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
6 changes: 4 additions & 2 deletions packages/common/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,10 @@ export type TrackMetadata = {
is_available: boolean
/**
* Whether the API will serve audio for this track. The API sets it to false
* when the track is deleted or its owner is no longer active (a self
* deactivation or a trusted-notifier delist). Optional because not every
* when the track is deleted, when its owner is no longer active (a self
* deactivation or a trusted-notifier delist), or when the row carries no
* track_cid - an upload that transcoded fine but was indexed without the cid
* pointing at the audio, leaving nothing to play. Optional because not every
* track source populates it, so treat `undefined` as "no opinion" rather
* than as "not streamable".
*/
Expand Down
8 changes: 5 additions & 3 deletions packages/common/src/utils/trackAvailability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ type MaybeTrack = Pick<TrackMetadata, 'is_delete' | 'is_streamable'> &
* Whether a track should be shown as no longer available.
*
* The API reports this via `is_streamable`, which it sets to false when the
* track is deleted or its owner is no longer active - either because the
* track is deleted, when its owner is no longer active - either because the
* artist deactivated their own account or because the account was delisted by
* the trusted notifier. Deleted tracks are excluded here because they have
* their own, more specific "deleted by artist" treatment.
* the trusted notifier - or when the row has no track_cid, an upload that was
* indexed without the cid pointing at its audio. Deleted tracks are excluded
* here because they have their own, more specific "deleted by artist"
* treatment.
*
* The check is an explicit `=== false` on purpose: not every track source
* populates `is_streamable`, and an absent field must not be read as
Expand Down
7 changes: 7 additions & 0 deletions packages/mobile/src/components/share-drawer/ShareDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,18 @@ export const ShareDrawer = NiceModal.create(() => {
}
}, [dispatch, content, source])

// The story platforms build a video out of the track's audio, so a track with
// nothing to play cannot be shared to them. `is_streamable` is false for an
// upload that was indexed without its track_cid: the stream URL 404s, ffmpeg
// fails on it, and the user gets a bare "something went wrong" with no idea
// why. Compare against `false` explicitly - an absent field means the source
// did not populate it, not that the track is broken.
const isShareableTrack =
content?.type === 'track' &&
!content.track.is_unlisted &&
!content.track.is_invalid &&
!content.track.is_delete &&
content.track.is_streamable !== false &&
!isStreamGatedTrack

const performActionAndClose = useCallback(
Expand Down
27 changes: 18 additions & 9 deletions packages/mobile/src/components/share-drawer/useShareToStory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,16 +366,25 @@ export const useShareToStory = ({
// For simplicity, assume that calculating dominant colors and generating the sticker takes 20% of the total loading time:
dispatch(setProgress(20))

const { data, signature } =
await audiusBackendInstance.signGatedContentRequest({
sdk
// Nothing here was guarded before, so a rejection - a failed signature,
// an SDK that never initialized - escaped as an unhandled promise
// rejection: no toast, and the progress drawer left spinning forever.
let streamMp3Url: string
try {
const { data, signature } =
await audiusBackendInstance.signGatedContentRequest({
sdk
})
streamMp3Url = await sdk.tracks.getTrackStreamUrl({
trackId: Id.parse(content.track.track_id),
userId: OptionalId.parse(userId),
userSignature: signature,
userData: data
})
const streamMp3Url = await sdk.tracks.getTrackStreamUrl({
trackId: Id.parse(content.track.track_id),
userId: OptionalId.parse(userId),
userSignature: signature,
userData: data
})
} catch (e) {
handleError(platform, e, 'Error at resolve stream url step')
return
}
const storyVideoPath = path.join(
RNFS.TemporaryDirectoryPath,
`storyVideo-${uuid()}.mp4`
Expand Down
Loading