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
5 changes: 1 addition & 4 deletions packages/common/src/adapters/track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
type Genre,
type Mood,
type NativeFile,
type TrackFilesMetadata,
HashId,
Id,
OptionalHashId,
Expand Down Expand Up @@ -235,9 +234,7 @@ export const stemTrackMetadataFromSDK = (
}
}

export const trackMetadataForUploadToSdk = (
input: TrackMetadataForUpload
): TrackFilesMetadata => ({
export const trackMetadataForUploadToSdk = (input: TrackMetadataForUpload) => ({
...camelcaseKeys(
pick(input, [
'license',
Expand Down
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
19 changes: 15 additions & 4 deletions packages/common/src/api/tan-query/tracks/useUpdateTrack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Id } from '@audius/sdk'
import { Id, type ProgressHandler } from '@audius/sdk'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useDispatch, useStore } from 'react-redux'

Expand Down Expand Up @@ -29,7 +29,9 @@ export type UpdateTrackParams = {
trackId: ID
userId: ID
metadata: Partial<TrackMetadataForUpload>
audioFile?: File
coverArtFile?: File
onProgress?: ProgressHandler
}

export const useUpdateTrack = () => {
Expand All @@ -44,7 +46,9 @@ export const useUpdateTrack = () => {
trackId,
userId,
metadata,
coverArtFile
audioFile,
coverArtFile,
onProgress
}: UpdateTrackParams) => {
const sdk = await audiusSdk()

Expand All @@ -56,12 +60,14 @@ export const useUpdateTrack = () => {
)

const response = await sdk.tracks.updateTrack({
coverArtFile: coverArtFile
audioFile: audioFile ? fileToSdk(audioFile, 'audio') : undefined,
imageFile: coverArtFile
? fileToSdk(coverArtFile, 'cover_art')
: undefined,
trackId: Id.parse(trackId),
userId: Id.parse(userId),
metadata: sdkMetadata
metadata: sdkMetadata,
onProgress
})

// TODO: migrate stem uploads to use tan-query
Expand Down Expand Up @@ -104,6 +110,11 @@ export const useUpdateTrack = () => {
// Return context with the previous track and metadata
return { previousTrack }
},
onSuccess: (_, params) => {
queryClient.invalidateQueries({
queryKey: getTrackQueryKey(params.trackId)
})
},
onError: (
error,
{ trackId, userId, metadata },
Expand Down
32 changes: 17 additions & 15 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 @@ -48,19 +48,20 @@ type PublishCollectionParams = {
clientId: string
metadata: TrackMetadataForUpload
audioUploadResponse: UploadResponse
artUploadResponse: UploadResponse
imageUploadResponse: UploadResponse
}[]
}

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!,
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