Skip to content

Commit 3469c89

Browse files
dylanjefferssabrina
and
sabrina
authored
[C-2852 PLAT-1094 PLAT-1093] Add fetch collection by permalink (#3751)
Co-authored-by: sabrina <[email protected]>
1 parent bb99113 commit 3469c89

File tree

37 files changed

+426
-302
lines changed

37 files changed

+426
-302
lines changed

packages/common/src/services/audius-api-client/ResponseAdapter.ts

-1
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,6 @@ export const makePlaylist = (
370370
track_count,
371371
total_play_count,
372372
playlist_contents: playlistContents,
373-
permalink: 'response-adapter-permalink',
374373

375374
// Fields to prune
376375
id: undefined,

packages/common/src/services/remote-config/feature-flags.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export enum FeatureFlags {
4646
AI_ATTRIBUTION = 'ai_attribution',
4747
DEVELOPER_APPS_PAGE = 'developer_apps_page',
4848
UPLOAD_REDESIGN_ENABLED = 'upload_redesign_enabled',
49-
USDC_PURCHASES = 'usdc_purchases'
49+
USDC_PURCHASES = 'usdc_purchases',
50+
NEW_PLAYLIST_ROUTES = 'new_playlist_routes'
5051
}
5152

5253
type FlagDefaults = Record<FeatureFlags, boolean>
@@ -108,5 +109,6 @@ export const flagDefaults: FlagDefaults = {
108109
[FeatureFlags.AI_ATTRIBUTION]: false,
109110
[FeatureFlags.DEVELOPER_APPS_PAGE]: false,
110111
[FeatureFlags.UPLOAD_REDESIGN_ENABLED]: false,
111-
[FeatureFlags.USDC_PURCHASES]: false
112+
[FeatureFlags.USDC_PURCHASES]: false,
113+
[FeatureFlags.NEW_PLAYLIST_ROUTES]: false
112114
}

packages/common/src/store/account/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type AccountCollection = {
88
name: string
99
is_album: boolean
1010
user: { id: ID; handle: string }
11+
permalink: string
1112
}
1213

1314
type AccountPayload<Profile> = {

packages/web/src/common/store/cache/collections/createPlaylistSaga.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { call, put, select, takeLatest } from 'typed-redux-saga'
2626
import { make } from 'common/store/analytics/actions'
2727
import { addPlaylistsNotInLibrary } from 'common/store/playlist-library/sagas'
2828
import { ensureLoggedIn } from 'common/utils/ensureLoggedIn'
29-
import { playlistPage } from 'utils/route'
29+
import { collectionPage } from 'utils/route'
3030
import { waitForWrite } from 'utils/sagaHelpers'
3131

3232
import { reformat } from './utils'
@@ -97,7 +97,11 @@ function* optimisticallySavePlaylist(
9797
: []
9898
}
9999
playlist.track_count = initTrack ? 1 : 0
100-
playlist.permalink = playlistPage(handle, playlist.playlist_name, playlistId)
100+
playlist.permalink = collectionPage(
101+
handle,
102+
playlist.playlist_name,
103+
playlistId
104+
)
101105
if (playlist.artwork) {
102106
playlist._cover_art_sizes = {
103107
...playlist._cover_art_sizes,
@@ -128,7 +132,8 @@ function* optimisticallySavePlaylist(
128132
id: playlistId,
129133
name: playlist.playlist_name as string,
130134
is_album: false,
131-
user: { id: user_id, handle }
135+
user: { id: user_id, handle },
136+
permalink: playlist?.permalink
132137
})
133138
)
134139

packages/web/src/common/store/pages/collection/sagas.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,10 @@ function* watchFetchCollection() {
5151
yield put(fetchCollectionFailed())
5252
return
5353
}
54-
const collection = collections[collectionId]
54+
const identifier = collectionId || permalink
55+
const collection = collections[identifier]
5556
const userUid = makeUid(Kind.USERS, collection.playlist_owner_id)
56-
const collectionUid = collectionUids[collectionId]
57+
const collectionUid = collectionUids[identifier]
5758
if (collection) {
5859
yield put(
5960
cacheActions.subscribe(Kind.USERS, [

packages/web/src/common/store/social/collections/sagas.ts

+10-13
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
addPlaylistsNotInLibrary,
3131
removePlaylistFromLibrary
3232
} from 'common/store/playlist-library/sagas'
33-
import { albumPage, audioNftPlaylistPage, playlistPage } from 'utils/route'
33+
import { audioNftPlaylistPage, collectionPage } from 'utils/route'
3434
import { waitForWrite } from 'utils/sagaHelpers'
3535

3636
import watchCollectionErrors from './errorSagas'
@@ -378,7 +378,8 @@ export function* saveCollectionAsync(
378378
id: collection.playlist_id,
379379
name: collection.playlist_name,
380380
is_album: collection.is_album,
381-
user: { id: user.user_id, handle: user.handle }
381+
user: { id: user.user_id, handle: user.handle },
382+
permalink: collection.permalink || ''
382383
})
383384
)
384385

@@ -570,17 +571,13 @@ export function* watchShareCollection() {
570571
const user = yield* select(getUser, { id: collection.playlist_owner_id })
571572
if (!user) return
572573

573-
const link = collection.is_album
574-
? albumPage(
575-
user.handle,
576-
collection.playlist_name,
577-
collection.playlist_id
578-
)
579-
: playlistPage(
580-
user.handle,
581-
collection.playlist_name,
582-
collection.playlist_id
583-
)
574+
const link = collectionPage(
575+
user.handle,
576+
collection.playlist_name,
577+
collection.playlist_id,
578+
collection.permalink,
579+
collection.is_album
580+
)
584581

585582
const share = yield* getContext('share')
586583
share(link, formatShareText(collection.playlist_name, user.name))

packages/web/src/components/add-to-playlist/desktop/AddToPlaylistModal.tsx

+8-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { Tooltip } from 'components/tooltip'
2424
import { useCollectionCoverArt } from 'hooks/useCollectionCoverArt'
2525
import { useFlag } from 'hooks/useRemoteConfig'
2626
import { AppState } from 'store/types'
27-
import { playlistPage } from 'utils/route'
27+
import { collectionPage } from 'utils/route'
2828

2929
import styles from './AddToPlaylistModal.module.css'
3030
const { getTrackId, getTrackTitle, getTrackIsUnlisted } =
@@ -102,7 +102,13 @@ const AddToPlaylistModal = () => {
102102
if (account && trackTitle) {
103103
toast({
104104
content: messages.addedToast,
105-
link: playlistPage(account.handle, trackTitle, playlist.playlist_id),
105+
link: collectionPage(
106+
account.handle,
107+
trackTitle,
108+
playlist.playlist_id,
109+
playlist.permalink,
110+
playlist.is_album
111+
),
106112
linkText: messages.view
107113
})
108114
}

packages/web/src/components/card/desktop/CollectionArtCard.tsx

+16-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Dispatch } from 'redux'
1616
import { ReactComponent as IconKebabHorizontal } from 'assets/img/iconKebabHorizontal.svg'
1717
import { ArtistPopover } from 'components/artist/ArtistPopover'
1818
import DynamicImage from 'components/dynamic-image/DynamicImage'
19+
import { CollectionMenuProps } from 'components/menu/CollectionMenu'
1920
import Menu from 'components/menu/Menu'
2021
import PerspectiveCard from 'components/perspective-card/PerspectiveCard'
2122
import RepostFavoritesStats, {
@@ -31,7 +32,7 @@ import {
3132
UserListEntityType
3233
} from 'store/application/ui/userListModal/types'
3334
import { AppState } from 'store/types'
34-
import { playlistPage, albumPage, profilePage } from 'utils/route'
35+
import { collectionPage, profilePage } from 'utils/route'
3536
import { withNullGuard } from 'utils/withNullGuard'
3637

3738
import styles from './CollectionArtCard.module.css'
@@ -84,25 +85,31 @@ const CollectionArtCard = g(
8485
has_current_user_reposted,
8586
has_current_user_saved,
8687
repost_count,
87-
save_count
88+
save_count,
89+
permalink
8890
} = collection
8991
const { user_id, name, handle } = user
9092

9193
const [isPerspectiveDisabled, setIsPerspectiveDisabled] = useState(false)
9294

9395
const goToCollection = useCallback(() => {
9496
if (isPerspectiveDisabled) return
95-
const link = is_album
96-
? albumPage(handle, playlist_name, playlist_id)
97-
: playlistPage(handle, playlist_name, playlist_id)
97+
const link = collectionPage(
98+
handle,
99+
playlist_name,
100+
playlist_id,
101+
permalink,
102+
is_album
103+
)
98104
goToRoute(link)
99105
}, [
100106
is_album,
101107
handle,
102108
playlist_name,
103109
playlist_id,
104110
goToRoute,
105-
isPerspectiveDisabled
111+
isPerspectiveDisabled,
112+
permalink
106113
])
107114

108115
const goToProfile = useCallback(() => {
@@ -144,8 +151,9 @@ const CollectionArtCard = g(
144151
isFavorited: has_current_user_saved,
145152
isReposted: has_current_user_reposted,
146153
metadata: collection,
147-
name: playlist_name
148-
}
154+
name: playlist_name,
155+
permalink: permalink || null
156+
} as unknown as CollectionMenuProps
149157

150158
return (
151159
<div className={cn(styles.card, className)}>

packages/web/src/components/collection/desktop/OverflowMenuButton.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { Button, ButtonType, IconKebabHorizontal } from '@audius/stems'
1212
import { useDispatch, useSelector } from 'react-redux'
1313

14+
import { CollectionMenuProps } from 'components/menu/CollectionMenu'
1415
import Menu from 'components/menu/Menu'
1516

1617
import styles from './CollectionHeader.module.css'
@@ -36,7 +37,8 @@ export const OverflowMenuButton = (props: OverflowMenuButtonProps) => {
3637
playlist_name,
3738
is_private,
3839
playlist_owner_id,
39-
has_current_user_saved
40+
has_current_user_saved,
41+
permalink
4042
} =
4143
(useSelector((state: CommonState) =>
4244
getCollection(state, { id: collectionId })
@@ -74,8 +76,9 @@ export const OverflowMenuButton = (props: OverflowMenuButtonProps) => {
7476
includeSave: false,
7577
includeVisitPage: false,
7678
isPublic: !is_private,
77-
extraMenuItems
78-
}
79+
extraMenuItems,
80+
permalink
81+
} as unknown as CollectionMenuProps
7982

8083
return (
8184
<Menu menu={overflowMenu}>

packages/web/src/components/duplicate-add-confirmation-modal/DuplicateAddConfirmationModal.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { useModalState } from 'common/hooks/useModalState'
2323
import { useSelector } from 'common/hooks/useSelector'
2424
import { ToastContext } from 'components/toast/ToastContext'
2525
import ToastLinkContent from 'components/toast/mobile/ToastLinkContent'
26-
import { playlistPage } from 'utils/route'
26+
import { collectionPage } from 'utils/route'
2727

2828
import styles from './DuplicateAddConfirmationModal.module.css'
2929

@@ -64,10 +64,12 @@ export const DuplicateAddConfirmationModal = () => {
6464
<ToastLinkContent
6565
text={messages.addedToast}
6666
linkText={messages.view}
67-
link={playlistPage(
67+
link={collectionPage(
6868
account.handle,
6969
playlist?.playlist_name,
70-
playlistId
70+
playlistId,
71+
playlist?.permalink,
72+
playlist?.is_album
7173
)}
7274
/>
7375
)
@@ -83,7 +85,9 @@ export const DuplicateAddConfirmationModal = () => {
8385
dispatch,
8486
account,
8587
toast,
86-
playlist?.playlist_name
88+
playlist?.playlist_name,
89+
playlist?.permalink,
90+
playlist?.is_album
8791
])
8892

8993
return (

packages/web/src/components/menu/CollectionMenu.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Dispatch } from 'redux'
1515
import * as embedModalActions from 'components/embed-modal/store/actions'
1616
import { open as openEditCollectionModal } from 'store/application/ui/editPlaylistModal/slice'
1717
import { AppState } from 'store/types'
18-
import { albumPage, playlistPage, profilePage } from 'utils/route'
18+
import { albumPage, collectionPage, profilePage } from 'utils/route'
1919
const { getUser } = cacheUsersSelectors
2020

2121
type PlaylistId = number
@@ -40,6 +40,7 @@ export type OwnProps = {
4040
playlistId: PlaylistId
4141
playlistName: string
4242
type: 'album' | 'playlist'
43+
permalink: string
4344
}
4445

4546
export type CollectionMenuProps = OwnProps &
@@ -81,7 +82,7 @@ const CollectionMenu = (props: CollectionMenuProps) => {
8182
extraMenuItems
8283
} = props
8384

84-
const routePage = type === 'album' ? albumPage : playlistPage
85+
const routePage = type === 'album' ? albumPage : collectionPage
8586
const shareMenuItem = {
8687
text: 'Share',
8788
onClick: () => {

packages/web/src/components/nav/desktop/PlaylistLibrary/PlaylistNavItem.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import { useDispatch } from 'react-redux'
88

99
import { useSelector } from 'utils/reducer'
10-
import { playlistPage } from 'utils/route'
10+
import { collectionPage } from 'utils/route'
1111

1212
import { CollectionNavItem } from './CollectionNavItem'
1313

@@ -34,9 +34,9 @@ export const PlaylistNavItem = (props: PlaylistNavItemProps) => {
3434
const playlistUrl = useSelector((state) => {
3535
const playlist = state.account.collections[playlistId]
3636
if (!playlist) return null
37-
const { name, user } = playlist
37+
const { name, user, permalink } = playlist
3838
const { handle } = user
39-
return playlistPage(handle, name, playlistId)
39+
return collectionPage(handle, name, playlistId, permalink)
4040
})
4141

4242
const hasPlaylistUpdate = useSelector(

packages/web/src/components/notification/Notification/utils.ts

+6-18
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,20 @@ import { Entity, EntityType } from '@audius/common'
22

33
import { audiusBackendInstance } from 'services/audius-backend/audius-backend-instance'
44
import { UserListEntityType } from 'store/application/ui/userListModal/types'
5-
import {
6-
albumPage,
7-
fullAlbumPage,
8-
fullPlaylistPage,
9-
fullTrackPage,
10-
playlistPage
11-
} from 'utils/route'
5+
import { fullCollectionPage, fullTrackPage, collectionPage } from 'utils/route'
126

137
export const getEntityLink = (entity: EntityType, fullRoute = false) => {
148
if (!entity.user) return ''
159
if ('track_id' in entity) {
1610
return fullRoute ? fullTrackPage(entity.permalink) : entity.permalink
17-
} else if (entity.user && entity.playlist_id && entity.is_album) {
18-
const getRoute = fullRoute ? fullAlbumPage : albumPage
11+
} else if (entity.user && entity.playlist_id) {
12+
const getRoute = fullRoute ? fullCollectionPage : collectionPage
1913
return getRoute(
2014
entity.user.handle,
2115
entity.playlist_name,
22-
entity.playlist_id
23-
)
24-
}
25-
if (entity.user) {
26-
const getRoute = fullRoute ? fullPlaylistPage : playlistPage
27-
return getRoute(
28-
entity.user.handle,
29-
entity.playlist_name,
30-
entity.playlist_id
16+
entity.playlist_id,
17+
entity.permalink,
18+
entity.is_album
3119
)
3220
}
3321
return ''

0 commit comments

Comments
 (0)