diff --git a/packages/common/src/api/tan-query/comments/index.ts b/packages/common/src/api/tan-query/comments/index.ts index e0cca9a48c3..12278377c7a 100644 --- a/packages/common/src/api/tan-query/comments/index.ts +++ b/packages/common/src/api/tan-query/comments/index.ts @@ -2,6 +2,7 @@ export * from './types' export * from './utils' export * from './useUserComments' export * from './useTrackComments' +export * from './useTimestampedComments' export * from './useComment' export * from './useComments' export * from './useTrackCommentCount' diff --git a/packages/mobile/src/components/now-playing-drawer/useTimestampedComments.ts b/packages/common/src/api/tan-query/comments/useTimestampedComments.ts similarity index 90% rename from packages/mobile/src/components/now-playing-drawer/useTimestampedComments.ts rename to packages/common/src/api/tan-query/comments/useTimestampedComments.ts index ea6863c240b..ad1ee72adde 100644 --- a/packages/mobile/src/components/now-playing-drawer/useTimestampedComments.ts +++ b/packages/common/src/api/tan-query/comments/useTimestampedComments.ts @@ -1,7 +1,8 @@ import { useMemo } from 'react' -import { useTrackComments } from '@audius/common/api' -import type { Comment, ID } from '@audius/common/models' +import type { Comment, ID } from '~/models' + +import { useTrackComments } from './useTrackComments' const PAGE_SIZE = 50 // GetTrackCommentsSortMethodEnum.Timestamp diff --git a/packages/common/src/services/remote-config/feature-flags.ts b/packages/common/src/services/remote-config/feature-flags.ts index fab3d5a4901..33bb76af67c 100644 --- a/packages/common/src/services/remote-config/feature-flags.ts +++ b/packages/common/src/services/remote-config/feature-flags.ts @@ -18,7 +18,8 @@ export enum FeatureFlags { QUEUE_NEW_FEATURE_BADGE = 'queue_new_feature_badge', WEEKLY_ROTATION = 'weekly_rotation', TRACK_ROWS = 'track_rows', - NOW_PLAYING_COMMENTS = 'now_playing_comments' + NOW_PLAYING_COMMENTS = 'now_playing_comments', + TRACK_TILE_WAVEFORM = 'track_tile_waveform' } type FlagDefaults = Record @@ -28,7 +29,8 @@ export const environmentFlagDefaults: Record< Partial > = { development: { - [FeatureFlags.FAN_CLUB_TEXT_POST_POSTING]: true + [FeatureFlags.FAN_CLUB_TEXT_POST_POSTING]: true, + [FeatureFlags.TRACK_TILE_WAVEFORM]: true }, production: {} } @@ -59,5 +61,7 @@ export const flagDefaults: FlagDefaults = { [FeatureFlags.TRACK_ROWS]: false, // Timestamped comments as markers and bubbles on the Now Playing scrubber. // Default on; the remote flag is the kill switch. - [FeatureFlags.NOW_PLAYING_COMMENTS]: true + [FeatureFlags.NOW_PLAYING_COMMENTS]: true, + // Waveform with timestamped comment avatars on desktop web track tiles. + [FeatureFlags.TRACK_TILE_WAVEFORM]: false } diff --git a/packages/mobile/src/components/now-playing-drawer/CommentBubble.tsx b/packages/mobile/src/components/now-playing-drawer/CommentBubble.tsx index f9547c4aa14..765055fd0ec 100644 --- a/packages/mobile/src/components/now-playing-drawer/CommentBubble.tsx +++ b/packages/mobile/src/components/now-playing-drawer/CommentBubble.tsx @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useUser } from '@audius/common/api' +import type { TimestampedComment } from '@audius/common/api' import type { ID } from '@audius/common/models' import { playbackSelectors } from '@audius/common/store' import { Dimensions, Pressable, View } from 'react-native' @@ -13,8 +14,6 @@ import { useCommentDrawer } from 'app/components/comments/CommentDrawerContext' import { ProfilePicture } from 'app/components/core' import { useNavigation } from 'app/hooks/useNavigation' -import type { TimestampedComment } from './useTimestampedComments' - const { getSeek, getSeekCounter } = playbackSelectors const messages = { diff --git a/packages/mobile/src/components/now-playing-drawer/NowPlayingDrawer.tsx b/packages/mobile/src/components/now-playing-drawer/NowPlayingDrawer.tsx index a217ed0b090..8681e30f751 100644 --- a/packages/mobile/src/components/now-playing-drawer/NowPlayingDrawer.tsx +++ b/packages/mobile/src/components/now-playing-drawer/NowPlayingDrawer.tsx @@ -8,7 +8,7 @@ import { useState } from 'react' -import { useUser } from '@audius/common/api' +import { useUser, useTimestampedComments } from '@audius/common/api' import { useCurrentTrack, useFeatureFlag } from '@audius/common/hooks' import { FeatureFlags } from '@audius/common/services' import { playbackActions, playbackSelectors } from '@audius/common/store' @@ -60,7 +60,6 @@ import { TitleBar } from './TitleBar' import { TrackInfo } from './TrackInfo' import { PLAY_BAR_HEIGHT } from './constants' import { useCurrentTrackDuration } from './useCurrentTrackDuration' -import { useTimestampedComments } from './useTimestampedComments' const { seekTo: seek, reset, next, previous } = playbackActions const { getPlaying, getTrackId, getCounter, getBuffering } = playbackSelectors diff --git a/packages/web/src/components/track/desktop/TrackTile.tsx b/packages/web/src/components/track/desktop/TrackTile.tsx index 04908f19b44..0091b81fd57 100644 --- a/packages/web/src/components/track/desktop/TrackTile.tsx +++ b/packages/web/src/components/track/desktop/TrackTile.tsx @@ -1,13 +1,14 @@ import { useCallback, useEffect, MouseEvent } from 'react' import { useCurrentUserId, useTrack, useUser } from '@audius/common/api' -import { useGatedContentAccess } from '@audius/common/hooks' +import { useFeatureFlag, useGatedContentAccess } from '@audius/common/hooks' import { ShareSource, RepostSource, FavoriteSource, ID } from '@audius/common/models' +import { FeatureFlags } from '@audius/common/services' import { tracksSocialActions, shareModalUIActions, @@ -51,6 +52,7 @@ import { TrackTileSize } from '../types' import styles from './TrackTile.module.css' import { TrackTileDuration } from './TrackTileDuration' +import { TrackTileWaveform } from './TrackTileWaveform' const { requestOpen: requestOpenShareModal } = shareModalUIActions const { repostTrack, undoRepostTrack, saveTrack, unsaveTrack } = @@ -62,6 +64,8 @@ const { getPlaying } = playbackSelectors +const WAVEFORM_ARTWORK_SIZE = 176 + // Props from ConnectedTrackTile export type TrackTileProps = { id: ID @@ -139,7 +143,9 @@ export const TrackTile = ({ permalink, _co_sign: coSign, has_current_user_reposted: isReposted, - has_current_user_saved: isFavorited + has_current_user_saved: isFavorited, + duration, + comment_count: commentCount } = trackWithFallback const isArtistPick = partialUser?.artist_pick_track_id === trackId @@ -148,6 +154,21 @@ export const TrackTile = ({ useGatedContentAccess(trackWithFallback) const loading = isLoading || isFetchingNFTAccess || isPending + const { isEnabled: isWaveformEnabled } = useFeatureFlag( + FeatureFlags.TRACK_TILE_WAVEFORM + ) + const showWaveform = + isWaveformEnabled && + size === TrackTileSize.LARGE && + !loading && + duration > 0 + // With the waveform the right column is ~176px tall; the artwork matches it. + const artworkSize = showWaveform + ? WAVEFORM_ARTWORK_SIZE + : size === TrackTileSize.LARGE + ? 128 + : 108 + const [, setLockedContentVisibility] = useModalState('LockedContent') useEffect(() => { @@ -319,7 +340,12 @@ export const TrackTile = ({ disableActions && { opacity: 0.5, pointerEvents: 'none' }, { cursor: canClickTile ? 'pointer' : 'default', - height: size === TrackTileSize.LARGE ? 144 : 128, + // The waveform tile is taller; its height comes from the content. + height: showWaveform + ? undefined + : size === TrackTileSize.LARGE + ? 144 + : 128, containerType: 'inline-size', '&:hover .artworkIcon': { opacity: 0.75 }, '&:hover': { transform: 'scale(1.004)' }, @@ -343,10 +369,7 @@ export const TrackTile = ({ )} {/* Track tile image */} - +