Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
21 changes: 21 additions & 0 deletions packages/common/src/store/ui/modals/create-playlist-modal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createModal } from '../createModal'

export type CreatePlaylistModalState = {
isAlbum?: boolean
initTrackId?: number
}

const createPlaylistModal = createModal<CreatePlaylistModalState>({
reducerPath: 'CreatePlaylistModal',
initialState: {
isOpen: false,
isAlbum: false
},
sliceSelector: (state) => state.ui.modals
})

export const {
hook: useCreatePlaylistModal,
reducer: createPlaylistModalReducer,
actions: createPlaylistModalActions
} = createPlaylistModal
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createModal } from '../createModal'

export type DuplicatePlaylistModalState = {
isAlbum?: boolean
}

const duplicatePlaylistModal = createModal<DuplicatePlaylistModalState>({
reducerPath: 'DuplicatePlaylistModal',
initialState: {
isOpen: false,
isAlbum: false
},
sliceSelector: (state) => state.ui.modals
})

export const {
hook: useDuplicatePlaylistModal,
reducer: duplicatePlaylistModalReducer,
actions: duplicatePlaylistModalActions
} = duplicatePlaylistModal
3 changes: 3 additions & 0 deletions packages/common/src/store/ui/modals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ export * from './receive-tokens-modal'
export * from './send-tokens-modal'
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'
5 changes: 4 additions & 1 deletion packages/common/src/store/ui/modals/parentSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ export const initialState: BasicModalsState = {
CoinSuccessModal: { isOpen: false },
FanClubDetailsModal: { isOpen: false },
VerificationSuccess: { isOpen: false },
VerificationError: { isOpen: false }
VerificationError: { isOpen: false },
CreatePlaylistModal: { isOpen: false },
DuplicatePlaylistModal: { isOpen: false },
AddTracksByUrlModal: { isOpen: false }
}

const slice = createSlice({
Expand Down
8 changes: 7 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 All @@ -12,8 +13,10 @@ import { coinflowWithdrawModalReducer } from './coinflow-withdraw-modal'
import { connectedWalletsModalReducer } from './connected-wallets-modal'
import { chatBlastModalReducer } from './create-chat-blast-modal'
import { createChatModalReducer } from './create-chat-modal'
import { createPlaylistModalReducer } from './create-playlist-modal'
import { deleteTrackConfirmationModalReducer } from './delete-track-confirmation-modal'
import { downloadTrackArchiveModalReducer } from './download-track-archive-modal'
import { duplicatePlaylistModalReducer } from './duplicate-playlist-modal'
import { earlyReleaseConfirmationModalReducer } from './early-release-confirmation-modal'
import { editAccessConfirmationModalReducer } from './edit-access-confirmation-modal'
import { externalWalletSignUpModalReducer } from './external-wallet-sign-up-modal'
Expand Down Expand Up @@ -92,7 +95,10 @@ const combinedReducers = combineReducers({
ReceiveTokensModal: receiveTokensModalReducer,
SendTokensModal: sendTokensModalReducer,
CoinSuccessModal: coinSuccessModalReducer,
FanClubDetailsModal: fanClubDetailsModalReducer
FanClubDetailsModal: fanClubDetailsModalReducer,
CreatePlaylistModal: createPlaylistModalReducer,
DuplicatePlaylistModal: duplicatePlaylistModalReducer,
AddTracksByUrlModal: addTracksByUrlModalReducer
})

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/store/ui/modals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ export type Modals =
| 'CoinSuccessModal'
| 'VerificationSuccess'
| '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