Skip to content
Merged
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
1 change: 1 addition & 0 deletions packages/common/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export * from './tan-query/authorized-apps/useRemoveAuthorizedApp'
export * from './tan-query/coins'

// Uploads
export * from './tan-query/upload/useUpload'
export * from './tan-query/upload/useUploadFiles'
export * from './tan-query/upload/useUploadStatus'
export * from './tan-query/upload/usePublishTracks'
Expand Down
30 changes: 16 additions & 14 deletions packages/common/src/api/tan-query/upload/usePublishCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ import {

type PublishCollectionContext = Pick<
QueryContextType,
'audiusSdk' | 'analytics' | 'dispatch'
'audiusSdk' | 'analytics' | 'dispatch' | 'reportToSentry'
> & {
userId?: number
wallet?: string
userId: number
wallet: string
}

type PublishCollectionParams = {
Expand All @@ -55,12 +55,13 @@ type PublishCollectionParams = {
const getPublishCollectionOptions = (context: PublishCollectionContext) =>
mutationOptions({
mutationFn: async (params: PublishCollectionParams) => {
const sdk = await context.audiusSdk()
if (!context.userId || !context.wallet) {
const { audiusSdk, userId, wallet } = context
const sdk = await audiusSdk()
if (!userId || !wallet) {
throw new Error('User ID and wallet are required to publish collection')
}
const userBank = await sdk.services.claimableTokensClient.deriveUserBank({
ethWallet: context.wallet,
ethWallet: wallet,
mint: 'USDC'
})

Expand Down Expand Up @@ -108,20 +109,20 @@ const getPublishCollectionOptions = (context: PublishCollectionContext) =>
: undefined
if (params.collectionMetadata.is_album) {
return await sdk.albums.createAlbum({
userId: Id.parse(context.userId),
userId: Id.parse(userId),
coverArtFile,
metadata: albumMetadataForCreateWithSDK(params.collectionMetadata),
trackIds: publishedTracks
.filter((t) => !t.error)
.filter((t) => t.trackId && !t.error)
.map((t) => t.trackId!)
})
} else {
return await sdk.playlists.createPlaylist({
userId: Id.parse(context.userId),
userId: Id.parse(userId),
coverArtFile,
metadata: playlistMetadataForCreateWithSDK(params.collectionMetadata),
trackIds: publishedTracks
.filter((t) => !t.error)
.filter((t) => t.trackId && !t.error)
.map((t) => t.trackId!)
})
}
Expand All @@ -131,7 +132,7 @@ const getPublishCollectionOptions = (context: PublishCollectionContext) =>
export const usePublishCollection = (
options?: Partial<ReturnType<typeof getPublishCollectionOptions>>
) => {
const { audiusSdk, analytics } = useQueryContext()
const { audiusSdk, analytics, reportToSentry } = useQueryContext()
const queryClient = useQueryClient()
const dispatch = useDispatch()
const { data: account = null } = useCurrentAccount()
Expand All @@ -143,10 +144,11 @@ export const usePublishCollection = (
...options,
...getPublishCollectionOptions({
audiusSdk,
userId,
wallet,
userId: userId!,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we throw an err above on missing userId/wallet, maybe should do the same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check inside the hook so that we don't error on render but error when you call the mutation

wallet: wallet!,
dispatch,
analytics
analytics,
reportToSentry
}),

onSuccess: async (playlist) => {
Expand Down
118 changes: 118 additions & 0 deletions packages/common/src/api/tan-query/upload/usePublishStems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { HashId, Id, type UploadResponse } from '@audius/sdk'
import { mutationOptions, useMutation } from '@tanstack/react-query'

import { trackMetadataForUploadToSdk } from '~/adapters'
import { StemCategory, Name } from '~/models'
import { ProgressStatus, uploadActions } from '~/store'
import type { TrackMetadataForUpload } from '~/store'

import { useCurrentUserId } from '../users/account/useCurrentUserId'
import { useQueryContext, type QueryContextType } from '../utils'

const { updateProgress } = uploadActions

type PublishStemsContext = Pick<
QueryContextType,
'audiusSdk' | 'analytics' | 'dispatch' | 'reportToSentry'
> & {
userId: number
}

type PublishStemsParams = {
clientId: string
parentTrackId: number
metadata: TrackMetadataForUpload
imageUploadResponse: UploadResponse
stemsUploadResponses: UploadResponse[]
}

export const publishStems = async (
context: PublishStemsContext,
params: PublishStemsParams
) => {
const {
userId,
audiusSdk,
dispatch,
analytics: { make, track }
} = context

if (!userId) {
throw new Error('User ID is required to publish stems')
}

const sdk = await audiusSdk()
return await Promise.all(
(params.metadata.stems ?? []).map(async (stem, index) => {
try {
const stemUploadResponse = params.stemsUploadResponses?.[index]
if (!stemUploadResponse) {
throw new Error(`No upload response found for stem ${index}`)
}
const metadata = {
...stem.metadata,
genre: params.metadata.genre,
is_downloadable: true,
stem_of: {
category: stem.category ?? StemCategory.OTHER,
parent_track_id: params.parentTrackId
}
}
const stemRes = await sdk.tracks.publishTrack({
userId: Id.parse(userId),
metadata: trackMetadataForUploadToSdk(metadata),
audioUploadResponse: stemUploadResponse,
imageUploadResponse: params.imageUploadResponse
})
dispatch(
updateProgress({
clientId: params.clientId,
stemIndex: index,
key: 'audio',
progress: { status: ProgressStatus.COMPLETE }
})
)
track(
make({
eventName: Name.STEM_COMPLETE_UPLOAD,
id: HashId.parse(stemRes.trackId),
parent_track_id: params.parentTrackId,
category: stem.category ?? StemCategory.OTHER
})
)
return { trackId: stemRes.trackId, error: null }
} catch (e) {
dispatch(
updateProgress({
clientId: params.clientId,
stemIndex: index,
key: 'audio',
progress: { status: ProgressStatus.ERROR }
})
)
console.error('Error publishing stem:', e)
return { trackId: null, error: e as Error }
}
})
)
}

const getPublishStemsOptions = (context: PublishStemsContext) =>
mutationOptions({
mutationFn: async (params: PublishStemsParams) =>
publishStems(context, params)
})

export const usePublishStems = (
options?: Partial<ReturnType<typeof getPublishStemsOptions>> & {
kind?: 'tracks' | 'album' | 'playlist'
}
) => {
const context = useQueryContext()
const { data: userId } = useCurrentUserId()

return useMutation({
...options,
...getPublishStemsOptions({ ...context, userId: userId! })
})
}
Loading
Loading