diff --git a/packages/mobile/src/screens/feature-flag-override-screen/FeatureFlagOverrideScreen.tsx b/packages/mobile/src/screens/feature-flag-override-screen/FeatureFlagOverrideScreen.tsx
index ef7ac4407c1..da54269540d 100644
--- a/packages/mobile/src/screens/feature-flag-override-screen/FeatureFlagOverrideScreen.tsx
+++ b/packages/mobile/src/screens/feature-flag-override-screen/FeatureFlagOverrideScreen.tsx
@@ -127,6 +127,7 @@ const FeatureFlagScreen = () => {
diff --git a/packages/web/src/components/feature-flag-override-modal/FeatureFlagOverrideModal.tsx b/packages/web/src/components/feature-flag-override-modal/FeatureFlagOverrideModal.tsx
index 7b3cd2f9c8e..39000f9d1a3 100644
--- a/packages/web/src/components/feature-flag-override-modal/FeatureFlagOverrideModal.tsx
+++ b/packages/web/src/components/feature-flag-override-modal/FeatureFlagOverrideModal.tsx
@@ -127,6 +127,7 @@ export const FeatureFlagOverrideModal = () => {
) : null}
setFilter(e.target.value)}
value={filter}
diff --git a/packages/web/src/components/lineup/Lineup.tsx b/packages/web/src/components/lineup/Lineup.tsx
index d15261e6b57..e330070a6f0 100644
--- a/packages/web/src/components/lineup/Lineup.tsx
+++ b/packages/web/src/components/lineup/Lineup.tsx
@@ -9,22 +9,22 @@ import { useIsMobile } from 'hooks/useIsMobile'
import LineupProvider, { LineupProviderProps } from './LineupProvider'
import { LineupVariant } from './types'
-export type LineupWithoutTile = Omit<
+export type LineupProps = Omit<
LineupProviderProps,
'trackTile' | 'skeletonTile' | 'playlistTile'
>
-type LineupProps = LineupWithoutTile & { useSmallTiles?: boolean }
/** A lineup renders a LineupProvider, injecting different tiles
* depending on the client state.
*/
const Lineup = (props: LineupProps) => {
- const { useSmallTiles } = props
+ const { variant } = props
const isMobile = useIsMobile()
const trackTile =
- isMobile || useSmallTiles ? MobileTrackTile : DesktopTrackTile
- const playlistTile =
- isMobile || useSmallTiles ? MobilePlaylistTile : DesktopPlaylistTile
+ isMobile || variant === LineupVariant.SECTION
+ ? MobileTrackTile
+ : DesktopTrackTile
+ const playlistTile = isMobile ? MobilePlaylistTile : DesktopPlaylistTile
return (
{
if (variant === LineupVariant.MAIN || variant === LineupVariant.PLAYLIST) {
tileSize = TrackTileSize.LARGE
lineupStyle = styles.main
- } else if (variant === LineupVariant.SECTION) {
+ } else if (variant === LineupVariant.GRID) {
tileSize = TrackTileSize.SMALL
lineupStyle = styles.section
statSize = 'small'
diff --git a/packages/web/src/components/lineup/types.ts b/packages/web/src/components/lineup/types.ts
index 59462b0228c..2b8760586ac 100644
--- a/packages/web/src/components/lineup/types.ts
+++ b/packages/web/src/components/lineup/types.ts
@@ -1,6 +1,7 @@
export enum LineupVariant {
MAIN = 'main',
- SECTION = 'section',
+ GRID = 'grid',
CONDENSED = 'condensed',
- PLAYLIST = 'playlist'
+ PLAYLIST = 'playlist',
+ SECTION = 'section'
}
diff --git a/packages/web/src/components/track/mobile/BottomButtons.tsx b/packages/web/src/components/track/mobile/BottomButtons.tsx
index de7e04032fa..ade8e6a56bc 100644
--- a/packages/web/src/components/track/mobile/BottomButtons.tsx
+++ b/packages/web/src/components/track/mobile/BottomButtons.tsx
@@ -12,6 +12,7 @@ import FavoriteButton from 'components/alt-button/FavoriteButton'
import MoreButton from 'components/alt-button/MoreButton'
import RepostButton from 'components/alt-button/RepostButton'
import ShareButton from 'components/alt-button/ShareButton'
+import { useIsMobile } from 'hooks/useIsMobile'
import { useIsUSDCEnabled } from 'hooks/useIsUSDCEnabled'
import { GatedConditionsPill } from '../GatedConditionsPill'
@@ -39,9 +40,11 @@ type BottomButtonsProps = {
isMatrixMode: boolean
contentId: number
contentType: string
+ renderOverflow?: () => React.ReactNode
}
const BottomButtons = (props: BottomButtonsProps) => {
+ const isMobile = useIsMobile()
const isUSDCEnabled = useIsUSDCEnabled()
const isUSDCPurchase =
isUSDCEnabled && isContentUSDCPurchaseGated(props.streamConditions)
@@ -51,15 +54,18 @@ const BottomButtons = (props: BottomButtonsProps) => {
return null
}
- const moreButton = (
-
- )
+ const moreButton =
+ !isMobile && props.renderOverflow ? (
+ props.renderOverflow()
+ ) : (
+
+ )
// Stream conditions without access
if (!props.isLoading && props.streamConditions && !props.hasStreamAccess) {
diff --git a/packages/web/src/components/track/mobile/ConnectedTrackTile.tsx b/packages/web/src/components/track/mobile/ConnectedTrackTile.tsx
index 6c60a91b5b8..edf252d1b9f 100644
--- a/packages/web/src/components/track/mobile/ConnectedTrackTile.tsx
+++ b/packages/web/src/components/track/mobile/ConnectedTrackTile.tsx
@@ -25,10 +25,13 @@ import {
playerSelectors
} from '@audius/common/store'
import { Genre, route } from '@audius/common/utils'
+import { Box, IconButton, IconKebabHorizontal } from '@audius/harmony'
import { push as pushRoute } from 'connected-react-router'
import { connect } from 'react-redux'
import { Dispatch } from 'redux'
+import Menu from 'components/menu/Menu'
+import { OwnProps as TrackMenuProps } from 'components/menu/TrackMenu'
import { TrackTileProps } from 'components/track/types'
import { useFlag } from 'hooks/useRemoteConfig'
import { AppState } from 'store/types'
@@ -144,6 +147,7 @@ const ConnectedTrackTile = ({
getUserWithFallback(user)
const isOwner = user_id === currentUserId
+ const isArtistPick = showArtistPick && artist_pick_track_id === track_id
const { isEnabled: isNewPodcastControlsEnabled } = useFlag(
FeatureFlags.PODCAST_CONTROL_UPDATES_ENABLED,
@@ -195,6 +199,55 @@ const ConnectedTrackTile = ({
goToRoute(track?.permalink + '?showComments=true')
}
+ // We wanted to use mobile track tile on desktop, which means shimming in the desktop overflow
+ // menu whenever isMobile is false.
+ const renderOverflowMenu = () => {
+ const menu: Omit = {
+ extraMenuItems: [],
+ handle,
+ includeAddToPlaylist: !is_unlisted || isOwner,
+ includeAddToAlbum: isOwner && !ddexApp,
+ includeArtistPick: isOwner,
+ includeEdit: isOwner,
+ ddexApp: track?.ddex_app,
+ includeEmbed: !(is_unlisted || isStreamGated),
+ includeFavorite: hasStreamAccess,
+ includeRepost: hasStreamAccess,
+ includeShare: true,
+ includeTrackPage: true,
+ isArtistPick,
+ isDeleted: is_delete || user?.is_deactivated,
+ isFavorited: has_current_user_saved,
+ isOwner,
+ isReposted: has_current_user_reposted,
+ isUnlisted: is_unlisted,
+ trackId: track_id,
+ trackTitle: title,
+ genre: genre as Genre,
+ trackPermalink: permalink,
+ type: 'track'
+ }
+
+ return (
+
+ )
+ }
+
const onClickOverflow = (trackId: ID) => {
const isLongFormContent =
genre === Genre.PODCASTS || genre === Genre.AUDIOBOOKS
@@ -260,7 +313,7 @@ const ConnectedTrackTile = ({
fieldVisibility={field_visibility}
coSign={_co_sign}
// Artist Pick
- isArtistPick={showArtistPick && artist_pick_track_id === track_id}
+ isArtistPick={isArtistPick}
// Artist
artistHandle={handle}
artistName={name}
@@ -276,6 +329,7 @@ const ConnectedTrackTile = ({
toggleSave={toggleSave}
onShare={onShare}
onClickOverflow={onClickOverflow}
+ renderOverflow={renderOverflowMenu}
toggleRepost={toggleRepost}
makeGoToRepostsPage={makeGoToRepostsPage}
makeGoToFavoritesPage={makeGoToFavoritesPage}
diff --git a/packages/web/src/components/track/mobile/TrackTile.module.css b/packages/web/src/components/track/mobile/TrackTile.module.css
index bbaac1881de..c95066c01fb 100644
--- a/packages/web/src/components/track/mobile/TrackTile.module.css
+++ b/packages/web/src/components/track/mobile/TrackTile.module.css
@@ -10,7 +10,6 @@
display: flex;
padding: var(--harmony-unit-2);
border-radius: var(--harmony-unit-2);
- max-width: 400px;
cursor: pointer;
transition: all 0.2 ease-in-out;
user-select: none;
diff --git a/packages/web/src/components/track/mobile/TrackTile.tsx b/packages/web/src/components/track/mobile/TrackTile.tsx
index 6fc1e8506ef..006c7eddd27 100644
--- a/packages/web/src/components/track/mobile/TrackTile.tsx
+++ b/packages/web/src/components/track/mobile/TrackTile.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, MouseEvent } from 'react'
+import { useCallback, useEffect, MouseEvent, ReactNode } from 'react'
import { useFeatureFlag } from '@audius/common/hooks'
import {
@@ -74,6 +74,7 @@ type ExtraProps = {
hasPreview?: boolean
hasStreamAccess: boolean
trackId?: number
+ renderOverflow?: () => ReactNode
}
type CombinedProps = TrackTileProps & ExtraProps
@@ -209,7 +210,8 @@ const TrackTile = (props: CombinedProps) => {
containerClassName,
hasPreview = false,
title,
- source
+ source,
+ renderOverflow
} = props
const hideShare: boolean = props.fieldVisibility
@@ -515,6 +517,7 @@ const TrackTile = (props: CombinedProps) => {
toggleSave={onToggleSave}
onShare={onClickShare}
onClickOverflow={onClickOverflowMenu}
+ renderOverflow={renderOverflow}
onClickGatedUnlockPill={onClickPill}
isOwner={isOwner}
readonly={isReadonly}
diff --git a/packages/web/src/pages/ai-attributed-tracks-page/components/desktop/AiPage.tsx b/packages/web/src/pages/ai-attributed-tracks-page/components/desktop/AiPage.tsx
index 0f948562b51..405b93abbcc 100644
--- a/packages/web/src/pages/ai-attributed-tracks-page/components/desktop/AiPage.tsx
+++ b/packages/web/src/pages/ai-attributed-tracks-page/components/desktop/AiPage.tsx
@@ -3,7 +3,7 @@ import { IconRobot } from '@audius/harmony'
import cn from 'classnames'
import Header from 'components/header/desktop/Header'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import Page from 'components/page/Page'
import UserBadges from 'components/user-badges/UserBadges'
import { fullAiPage } from 'utils/route'
@@ -24,7 +24,7 @@ const messages = {
export type AiPageProps = {
title: string
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/ai-attributed-tracks-page/components/mobile/AiPage.tsx b/packages/web/src/pages/ai-attributed-tracks-page/components/mobile/AiPage.tsx
index 938fdff2afe..d4ef82a2bff 100644
--- a/packages/web/src/pages/ai-attributed-tracks-page/components/mobile/AiPage.tsx
+++ b/packages/web/src/pages/ai-attributed-tracks-page/components/mobile/AiPage.tsx
@@ -6,7 +6,7 @@ import cn from 'classnames'
import Header from 'components/header/mobile/Header'
import { HeaderContext } from 'components/header/mobile/HeaderContextProvider'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer'
import { useSubPageHeader } from 'components/nav/mobile/NavContext'
import UserBadges from 'components/user-badges/UserBadges'
@@ -27,7 +27,7 @@ const messages = {
export type AiPageProps = {
title: string
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/deleted-page/components/desktop/DeletedPage.tsx b/packages/web/src/pages/deleted-page/components/desktop/DeletedPage.tsx
index e15686ddf81..74e1b2d3892 100644
--- a/packages/web/src/pages/deleted-page/components/desktop/DeletedPage.tsx
+++ b/packages/web/src/pages/deleted-page/components/desktop/DeletedPage.tsx
@@ -12,7 +12,7 @@ import { Button, IconUser } from '@audius/harmony'
import { ArtistPopover } from 'components/artist/ArtistPopover'
import CoverPhoto from 'components/cover-photo/CoverPhoto'
import DynamicImage from 'components/dynamic-image/DynamicImage'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import NavBanner from 'components/nav-banner/NavBanner'
import Page from 'components/page/Page'
import { StatBanner } from 'components/stat-banner/StatBanner'
@@ -71,7 +71,7 @@ export type DeletedPageProps = {
playable: Playable
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/deleted-page/components/mobile/DeletedPage.tsx b/packages/web/src/pages/deleted-page/components/mobile/DeletedPage.tsx
index 8ca7aae2cde..f73d13951bf 100644
--- a/packages/web/src/pages/deleted-page/components/mobile/DeletedPage.tsx
+++ b/packages/web/src/pages/deleted-page/components/mobile/DeletedPage.tsx
@@ -11,7 +11,7 @@ import { Button, IconUser } from '@audius/harmony'
import { ArtistPopover } from 'components/artist/ArtistPopover'
import DynamicImage from 'components/dynamic-image/DynamicImage'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer'
import UserBadges from 'components/user-badges/UserBadges'
import { useCollectionCoverArt } from 'hooks/useCollectionCoverArt'
@@ -68,7 +68,7 @@ export type DeletedPageProps = {
playable: Playable
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/remixes-page/components/desktop/RemixesPage.tsx b/packages/web/src/pages/remixes-page/components/desktop/RemixesPage.tsx
index 60194a372c3..0ee15562369 100644
--- a/packages/web/src/pages/remixes-page/components/desktop/RemixesPage.tsx
+++ b/packages/web/src/pages/remixes-page/components/desktop/RemixesPage.tsx
@@ -4,7 +4,7 @@ import { IconRemix as IconRemixes } from '@audius/harmony'
import cn from 'classnames'
import Header from 'components/header/desktop/Header'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import Page from 'components/page/Page'
import UserBadges from 'components/user-badges/UserBadges'
import { fullTrackRemixesPage } from 'utils/route'
@@ -26,7 +26,7 @@ export type RemixesPageProps = {
count: number | null
originalTrack: Track | null
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToTrackPage: () => void
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/remixes-page/components/mobile/RemixesPage.tsx b/packages/web/src/pages/remixes-page/components/mobile/RemixesPage.tsx
index 2ddb3566430..ce733b8eb66 100644
--- a/packages/web/src/pages/remixes-page/components/mobile/RemixesPage.tsx
+++ b/packages/web/src/pages/remixes-page/components/mobile/RemixesPage.tsx
@@ -7,7 +7,7 @@ import cn from 'classnames'
import Header from 'components/header/mobile/Header'
import { HeaderContext } from 'components/header/mobile/HeaderContextProvider'
-import Lineup, { LineupWithoutTile } from 'components/lineup/Lineup'
+import Lineup, { LineupProps } from 'components/lineup/Lineup'
import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer'
import { useSubPageHeader } from 'components/nav/mobile/NavContext'
import UserBadges from 'components/user-badges/UserBadges'
@@ -30,7 +30,7 @@ export type RemixesPageProps = {
count: number | null
originalTrack: Track | null
user: User | null
- getLineupProps: () => LineupWithoutTile
+ getLineupProps: () => LineupProps
goToTrackPage: () => void
goToArtistPage: () => void
}
diff --git a/packages/web/src/pages/search-page-v2/search-results/TrackResults.tsx b/packages/web/src/pages/search-page-v2/search-results/TrackResults.tsx
index 985e97008f2..90e32670d04 100644
--- a/packages/web/src/pages/search-page-v2/search-results/TrackResults.tsx
+++ b/packages/web/src/pages/search-page-v2/search-results/TrackResults.tsx
@@ -137,9 +137,7 @@ export const TrackResults = (props: TrackResultsProps) => {
return (
{
const { trackId } = props
- const isMobile = useIsMobile()
+ const { isDesktop, isMobile } = useTrackPageSize()
const dispatch = useDispatch()
const remixesLineup = useSelector(getRemixesTracksLineup)
const currentQueueItem = useSelector(getCurrentQueueItem)
@@ -91,6 +92,11 @@ export const TrackRemixes = (props: TrackRemixesProrps) => {
const isCommentingEnabled = commentsFlagEnabled && !comments_disabled
const remixTrackIds = _remixes?.map(({ track_id }) => track_id) ?? null
+ const lineupVariant =
+ (isCommentingEnabled && isDesktop) || isMobile
+ ? LineupVariant.SECTION
+ : LineupVariant.CONDENSED
+
if (!remixTrackIds || !remixTrackIds.length) {
return null
}
@@ -99,16 +105,16 @@ export const TrackRemixes = (props: TrackRemixesProrps) => {
-
+
{messages.remixes}
@@ -116,7 +122,7 @@ export const TrackRemixes = (props: TrackRemixesProrps) => {
lineup={remixesLineup}
actions={remixesPageLineupActions}
count={Math.min(MAX_REMIXES_TO_DISPLAY, remixTrackIds.length)}
- variant={LineupVariant.CONDENSED}
+ variant={lineupVariant}
selfLoad
playingUid={currentQueueItem.uid}
playingSource={currentQueueItem.source}
@@ -127,7 +133,6 @@ export const TrackRemixes = (props: TrackRemixesProrps) => {
buffering={isBuffering}
playTrack={handlePlay}
pauseTrack={handlePause}
- useSmallTiles={isCommentingEnabled}
/>
{remixTrackIds.length > MAX_REMIXES_TO_DISPLAY ? (
diff --git a/packages/web/src/pages/track-page/components/desktop/TrackPage.tsx b/packages/web/src/pages/track-page/components/desktop/TrackPage.tsx
index 4f635e2dfb0..2ac1dc8ebf4 100644
--- a/packages/web/src/pages/track-page/components/desktop/TrackPage.tsx
+++ b/packages/web/src/pages/track-page/components/desktop/TrackPage.tsx
@@ -20,6 +20,7 @@ import { getTrackDefaults, emptyStringGuard } from 'pages/track-page/utils'
import { trackRemixesPage } from 'utils/route'
import { TrackRemixes } from '../TrackRemixes'
+import { useTrackPageSize } from '../useTrackPageSize'
import Remixes from './Remixes'
import styles from './TrackPage.module.css'
@@ -53,7 +54,6 @@ export type OwnProps = {
isPreview?: boolean
}) => void
goToAllRemixesPage: () => void
- goToParentRemixesPage: () => void
onHeroShare: (trackId: ID) => void
onHeroRepost: (isReposted: boolean, trackId: ID) => void
onFollow: () => void
@@ -87,7 +87,6 @@ const TrackPage = ({
trendingBadgeLabel,
onHeroPlay,
goToAllRemixesPage,
- goToParentRemixesPage,
onHeroShare,
onHeroRepost,
onSaveTrack,
@@ -105,6 +104,7 @@ const TrackPage = ({
play,
pause
}: OwnProps) => {
+ const { isDesktop, isMobile } = useTrackPageSize()
const { entries } = tracks
const isOwner = heroTrack?.owner_id === userId
const following = user?.does_current_user_follow ?? false
@@ -204,7 +204,7 @@ const TrackPage = ({
)
const renderOriginalTrackTitle = () => (
-
+
{messages.originalTrack}
)
@@ -216,7 +216,6 @@ const TrackPage = ({
color='default'
variant='title'
size='l'
- textAlign='left'
>{`${messages.moreBy} ${user?.name}`}
) : null
@@ -225,6 +224,11 @@ const TrackPage = ({
const hasRemixes =
fieldVisibility.remixes && remixTrackIds && remixTrackIds.length > 0
+ const lineupVariant =
+ (isCommentingEnabled && isDesktop) || isMobile
+ ? LineupVariant.SECTION
+ : LineupVariant.CONDENSED
+
return (
) : null}
diff --git a/packages/web/src/pages/track-page/components/useTrackPageSize.ts b/packages/web/src/pages/track-page/components/useTrackPageSize.ts
new file mode 100644
index 00000000000..cec5426dba2
--- /dev/null
+++ b/packages/web/src/pages/track-page/components/useTrackPageSize.ts
@@ -0,0 +1,7 @@
+import { useMedia } from 'react-use'
+
+export const useTrackPageSize = () => {
+ const isDesktop = useMedia('(min-width: 1054px)')
+ const isMobile = useMedia('(max-width: 768px)')
+ return { isDesktop, isMobile }
+}