Skip to content
38 changes: 36 additions & 2 deletions packages/common/src/store/cache/collections/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export const ORDER_PLAYLIST_FAILED = 'ORDER_PLAYLIST_FAILED'
export const PUBLISH_PLAYLIST = 'PUBLISH_PLAYLIST'
export const PUBLISH_PLAYLIST_FAILED = 'PUBLISH_PLAYLIST_FAILED'

export const DUPLICATE_PLAYLIST = 'DUPLICATE_PLAYLIST'

/**
* @param initTrackId optional track id to pull artwork from.
*/
Expand Down Expand Up @@ -102,8 +104,17 @@ export function editPlaylistFailed(
return { type: EDIT_PLAYLIST_FAILED, error, params, metadata }
}

export function addTrackToPlaylist(trackId: ID, playlistId: ID) {
return { type: ADD_TRACK_TO_PLAYLIST, trackId, playlistId }
export function addTrackToPlaylist(
trackId: ID,
playlistId: ID,
options?: { silent?: boolean }
) {
return {
type: ADD_TRACK_TO_PLAYLIST,
trackId,
playlistId,
silent: options?.silent ?? false
}
}

export function addTrackToPlaylistFailed(
Expand Down Expand Up @@ -166,3 +177,26 @@ export function publishPlaylistFailed(
) {
return { type: PUBLISH_PLAYLIST_FAILED, error, params, metadata }
}

export function duplicatePlaylist({
sourcePlaylistId,
formFields,
trackIds,
source,
isAlbum
}: {
sourcePlaylistId: ID
formFields: Partial<Collection>
trackIds: ID[]
source: string
isAlbum?: boolean
}) {
return {
type: DUPLICATE_PLAYLIST,
sourcePlaylistId,
formFields,
trackIds,
source,
isAlbum: !!isAlbum
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ID } from '../../../../models'
import { createModal } from '../createModal'

export type AddTracksByUrlModalState = {
collectionId?: ID
isAlbum?: boolean
}

const addTracksByUrlModal = createModal<AddTracksByUrlModalState>({
reducerPath: 'AddTracksByUrlModal',
initialState: {
isOpen: false,
isAlbum: false
},
sliceSelector: (state) => state.ui.modals
})

export const {
hook: useAddTracksByUrlModal,
reducer: addTracksByUrlModalReducer,
actions: addTracksByUrlModalActions
} = addTracksByUrlModal
1 change: 1 addition & 0 deletions packages/common/src/store/ui/modals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ export * from './coin-success-modal'
export * from './fan-club-details-modal'
export * from './create-playlist-modal'
export * from './duplicate-playlist-modal'
export * from './add-tracks-by-url-modal'
3 changes: 2 additions & 1 deletion packages/common/src/store/ui/modals/parentSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export const initialState: BasicModalsState = {
VerificationSuccess: { isOpen: false },
VerificationError: { isOpen: false },
CreatePlaylistModal: { isOpen: false },
DuplicatePlaylistModal: { isOpen: false }
DuplicatePlaylistModal: { isOpen: false },
AddTracksByUrlModal: { isOpen: false }
}

const slice = createSlice({
Expand Down
4 changes: 3 additions & 1 deletion packages/common/src/store/ui/modals/reducers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Action, combineReducers, Reducer } from '@reduxjs/toolkit'

import { addCashModalReducer } from './add-cash-modal'
import { addTracksByUrlModalReducer } from './add-tracks-by-url-modal'
import { albumTrackRemoveConfirmationModalReducer } from './album-track-remove-confirmation-modal'
import { announcementModalReducer } from './announcement-modal'
import { artistPickModalReducer } from './artist-pick-modal'
Expand Down Expand Up @@ -96,7 +97,8 @@ const combinedReducers = combineReducers({
CoinSuccessModal: coinSuccessModalReducer,
FanClubDetailsModal: fanClubDetailsModalReducer,
CreatePlaylistModal: createPlaylistModalReducer,
DuplicatePlaylistModal: duplicatePlaylistModalReducer
DuplicatePlaylistModal: duplicatePlaylistModalReducer,
AddTracksByUrlModal: addTracksByUrlModalReducer
})

/**
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/store/ui/modals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export type Modals =
| 'VerificationError'
| 'CreatePlaylistModal'
| 'DuplicatePlaylistModal'
| 'AddTracksByUrlModal'

export type BasicModalsState = {
[modal in Modals]: BaseModalState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,13 @@ function* addTrackToPlaylistAsync(action: AddTrackToPlaylistAction) {

yield* put(event)

yield* put(
toast({
content: messages.addedTrack(playlist.is_album ? 'album' : 'playlist')
})
)
if (!action.silent) {
yield* put(
toast({
content: messages.addedTrack(playlist.is_album ? 'album' : 'playlist')
})
)
}
}

function* confirmAddTrackToPlaylist(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { cacheCollectionsActions, toastActions } from '@audius/common/store'
import { call, delay, put, take, takeEvery } from 'typed-redux-saga'

const { toast } = toastActions

const INTER_DISPATCH_DELAY_MS = 30

const messages = {
duplicated: (count: number, isAlbum: boolean) =>
`Duplicated ${isAlbum ? 'album' : 'playlist'} with ${count} ${
count === 1 ? 'track' : 'tracks'
}`,
duplicatedNoTracks: (isAlbum: boolean) =>
`Duplicated ${isAlbum ? 'album' : 'playlist'}`
}

export function* duplicatePlaylistSaga() {
yield* takeEvery(
cacheCollectionsActions.DUPLICATE_PLAYLIST,
duplicatePlaylistWorker
)
}

function* duplicatePlaylistWorker(
action: ReturnType<typeof cacheCollectionsActions.duplicatePlaylist>
) {
const { formFields, trackIds, source, isAlbum } = action
const initTrackId = trackIds.length > 0 ? trackIds[0] : null

const createAction = isAlbum
? cacheCollectionsActions.createAlbum
: cacheCollectionsActions.createPlaylist

yield* put(createAction(formFields, source, initTrackId, 'route'))

if (trackIds.length <= 1) {
if (trackIds.length === 0) {
yield* put(toast({ content: messages.duplicatedNoTracks(isAlbum) }))
} else {
yield* put(toast({ content: messages.duplicated(1, isAlbum) }))
}
return
}

const requestedAction = yield* take(
cacheCollectionsActions.CREATE_PLAYLIST_REQUESTED
)
const newPlaylistId = (requestedAction as unknown as { playlistId: number })
.playlistId

for (let i = 1; i < trackIds.length; i += 1) {
yield* put(
cacheCollectionsActions.addTrackToPlaylist(trackIds[i], newPlaylistId, {
silent: true
})
)
yield* delay(INTER_DISPATCH_DELAY_MS)
}

yield* call(function* () {
yield* put(
toast({ content: messages.duplicated(trackIds.length, isAlbum) })
)
})
}
3 changes: 2 additions & 1 deletion packages/web/src/common/store/cache/collections/webSagas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import commonSagas from './commonSagas'
import { createPlaylistRequestedSaga } from './createPlaylistRequestedSaga'
import { duplicatePlaylistSaga } from './duplicatePlaylistSaga'

export default function sagas() {
return [...commonSagas(), createPlaylistRequestedSaga]
return [...commonSagas(), createPlaylistRequestedSaga, duplicatePlaylistSaga]
}
Loading
Loading