Skip to content

Commit

Permalink
Client uses cids in requests to CN for images (#3882)
Browse files Browse the repository at this point in the history
  • Loading branch information
michellebrier committed Aug 23, 2023
1 parent 7974acc commit 1e0c335
Show file tree
Hide file tree
Showing 28 changed files with 144 additions and 42 deletions.
2 changes: 2 additions & 0 deletions packages/common/src/models/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export type CollectionMetadata = {
playlist_id: ID
cover_art: CID | null
cover_art_sizes: Nullable<CID>
cover_art_cids?: Nullable<CoverArtSizes>
permalink?: string
playlist_name: string
playlist_owner_id: ID
Expand Down Expand Up @@ -105,4 +106,5 @@ export type SmartCollection = {
export type CollectionImage = {
cover_art: Nullable<CID>
cover_art_sizes: Nullable<CID>
cover_art_cids?: Nullable<CoverArtSizes>
}
6 changes: 5 additions & 1 deletion packages/common/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export type TrackMetadata = {
track_segments: TrackSegment[]
cover_art: Nullable<CID>
cover_art_sizes: Nullable<CID>
cover_art_cids?: Nullable<CoverArtSizes>
is_unlisted: boolean
is_available: boolean
is_premium: boolean
Expand Down Expand Up @@ -267,4 +268,7 @@ export type StemUserTrack = UserTrack & Required<Pick<Track, 'stem_of'>>
export type RemixTrack = Track & Required<Pick<Track, 'remix_of'>>
export type RemixUserTrack = UserTrack & Required<Pick<Track, 'remix_of'>>

export type TrackImage = Pick<Track, 'cover_art' | 'cover_art_sizes'>
export type TrackImage = Pick<
Track,
'cover_art' | 'cover_art_sizes' | 'cover_art_cids'
>
4 changes: 4 additions & 0 deletions packages/common/src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export type UserMetadata = {
repost_count: number
track_count: number
cover_photo_sizes: Nullable<CID>
cover_photo_cids?: Nullable<CoverPhotoSizes>
profile_picture_sizes: Nullable<CID>
profile_picture_cids?: Nullable<ProfilePictureSizes>
metadata_multihash: Nullable<CID>
erc_wallet: WalletAddress
spl_wallet: Nullable<SolanaWalletAddress>
Expand Down Expand Up @@ -81,8 +83,10 @@ export type UserImage = Pick<
User,
| 'cover_photo'
| 'cover_photo_sizes'
| 'cover_photo_cids'
| 'profile_picture'
| 'profile_picture_sizes'
| 'profile_picture_cids'
>

export type UserMultihash = Pick<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ export const makeUser = (
current_user_followee_follow_count,
does_current_user_follow,
user_id: decodedUserId,
cover_photo: user.cover_photo_sizes || user.cover_photo_legacy,
profile_picture: user.profile_picture_sizes || user.profile_picture_legacy,
cover_photo: user.cover_photo_legacy,
profile_picture: user.profile_picture_legacy,
metadata_multihash: user.metadata_multihash || null,
supporter_count,
supporting_count,
Expand Down Expand Up @@ -454,6 +454,7 @@ export const makeStemTrack = (stem: APIStem): StemTrackMetadata | undefined => {
track_segments: [],
cover_art: null,
cover_art_sizes: null,
cover_art_cids: null,
is_unlisted: false,
stem_of: {
parent_track_id: parentId,
Expand Down
4 changes: 4 additions & 0 deletions packages/common/src/services/audius-api-client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ export type APIUser = {
handle_lc: string
updated_at: string
cover_photo_sizes: Nullable<CID>
cover_photo_cids: Nullable<CoverPhotoSizes>
cover_photo_legacy: Nullable<CID>
profile_picture_sizes: Nullable<CID>
profile_picture_cids: Nullable<ProfilePictureSizes>
profile_picture_legacy: Nullable<CID>
metadata_multihash: Nullable<CID>
erc_wallet: WalletAddress
Expand Down Expand Up @@ -115,6 +117,7 @@ export type APITrack = {
created_at: string
credits_splits: Nullable<string>
cover_art_sizes: string
cover_art_cids: Nullable<CoverArtSizes>
download: Download
isrc: Nullable<string>
license: Nullable<License>
Expand Down Expand Up @@ -191,6 +194,7 @@ export type APIPlaylist = {
track_count: number
cover_art: Nullable<string>
cover_art_sizes: Nullable<string>
cover_art_cids: Nullable<CoverArtSizes>
}

export type APISearchPlaylist = Omit<
Expand Down
25 changes: 20 additions & 5 deletions packages/common/src/services/audius-backend/AudiusBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,28 @@ export const audiusBackend = ({
}
}

async function fetchImageCID(cid: CID, size?: SquareSizes | WidthSizes) {
const cidFileName = size ? `${cid}/${size}.jpg` : `${cid}.jpg`
async function fetchImageCID(
cid: CID,
size?: SquareSizes | WidthSizes,
cidMap: Nullable<{ [key: string]: string }> = null
) {
let cidFileName = size ? `${cid}/${size}.jpg` : `${cid}.jpg`
// For v2 CIDs (aka job IDs), cidMap contains cids for each
// image variant. Use the CID for the desired image
// size from this map to accurately select the preferred
// rendezvous node to query.
if (size && cidMap && cidMap[size]) {
cidFileName = cidMap[size]
}
if (CIDCache.has(cidFileName)) {
return CIDCache.get(cidFileName) as string
}

const storageNodeSelector = await getStorageNodeSelector()
const storageNodes = storageNodeSelector.getNodes(cid)
// Only rendezvous hash the cid for extremely old legacy
// images that do not have size variants
const cidToHash = size ? cidFileName : cid
const storageNodes = storageNodeSelector.getNodes(cidToHash)
for (const storageNode of storageNodes) {
const imageUrl = `${storageNode}/content/${cidFileName}`

Expand All @@ -495,11 +509,12 @@ export const audiusBackend = ({

async function getImageUrl(
cid: Nullable<CID>,
size?: SquareSizes | WidthSizes
size?: SquareSizes | WidthSizes,
cidMap: Nullable<{ [key: string]: string }> = null
) {
if (!cid) return ''
try {
return await fetchImageCID(cid, size)
return await fetchImageCID(cid, size, cidMap)
} catch (e) {
console.error(e)
return ''
Expand Down
5 changes: 3 additions & 2 deletions packages/common/src/utils/updatePlaylistArtwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ export const updatePlaylistArtwork = async (
} else {
const trackUrls = await Promise.all(
tracksForImage.map(async (track) => {
const { cover_art_sizes, cover_art } = track
const { cover_art_cids, cover_art_sizes, cover_art } = track
return await context.audiusBackend.getImageUrl(
cover_art_sizes ?? cover_art,
SquareSizes.SIZE_1000_BY_1000
SquareSizes.SIZE_1000_BY_1000,
cover_art_cids
)
})
)
Expand Down
3 changes: 2 additions & 1 deletion packages/mobile/src/components/audio/GoogleCast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export const useChromecast = () => {
if (client && track && owner && streamingUri) {
const imageUrl = await audiusBackendInstance.getImageUrl(
track.cover_art_sizes,
SquareSizes.SIZE_1000_BY_1000
SquareSizes.SIZE_1000_BY_1000,
track.cover_art_cids
)

client.loadMedia({
Expand Down
4 changes: 3 additions & 1 deletion packages/mobile/src/components/image/CollectionImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type UseCollectionImageOptions = {
Collection | SearchPlaylist,
| 'playlist_id'
| 'cover_art_sizes'
| 'cover_art_cids'
| 'cover_art'
| 'playlist_owner_id'
| '_cover_art_sizes'
Expand Down Expand Up @@ -74,7 +75,8 @@ export const useCollectionImage = (options: UseCollectionImageOptions) => {
cid,
size,
fallbackImageSource: imageEmpty,
localSource: localSourceUri ? { uri: localSourceUri } : null
localSource: localSourceUri ? { uri: localSourceUri } : null,
cidMap: collection?.cover_art_cids
})

return contentNodeSource
Expand Down
10 changes: 8 additions & 2 deletions packages/mobile/src/components/image/TrackImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ type UseTrackImageOptions = {
track: Nullable<
Pick<
Track | SearchTrack,
'track_id' | 'cover_art_sizes' | 'cover_art' | '_cover_art_sizes'
| 'track_id'
| 'cover_art_sizes'
| 'cover_art_cids'
| 'cover_art'
| '_cover_art_sizes'
>
>
size: SquareSizes
Expand All @@ -53,6 +57,7 @@ const useLocalTrackImageUri = (trackId: Maybe<ID>) => {

export const useTrackImage = ({ track, size }: UseTrackImageOptions) => {
const cid = track ? track.cover_art_sizes || track.cover_art : null

const optimisticCoverArt = track?._cover_art_sizes?.OVERRIDE

const localTrackImageUri = useLocalTrackImageUri(track?.track_id)
Expand All @@ -62,7 +67,8 @@ export const useTrackImage = ({ track, size }: UseTrackImageOptions) => {
cid,
size,
fallbackImageSource: imageEmpty,
localSource: localSourceUri ? { uri: localSourceUri } : null
localSource: localSourceUri ? { uri: localSourceUri } : null,
cidMap: track?.cover_art_cids
})

return contentNodeSource
Expand Down
11 changes: 9 additions & 2 deletions packages/mobile/src/components/image/UserCoverImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ const interpolateImageTranslate = (animatedValue: Animated.Value) =>
})

type CoverImageUser = Nullable<
Pick<User, 'cover_photo_sizes' | 'cover_photo' | 'updatedCoverPhoto'>
Pick<
User,
| 'cover_photo_sizes'
| 'cover_photo_cids'
| 'cover_photo'
| 'updatedCoverPhoto'
>
>

export const useUserCoverImage = (user: CoverImageUser) => {
Expand All @@ -34,7 +40,8 @@ export const useUserCoverImage = (user: CoverImageUser) => {
const contentNodeImage = useContentNodeImage({
cid,
size: WidthSizes.SIZE_640,
fallbackImageSource: imageCoverPhotoBlank
fallbackImageSource: imageCoverPhotoBlank,
cidMap: user?.cover_photo_cids
})

if (user?.updatedCoverPhoto) {
Expand Down
8 changes: 6 additions & 2 deletions packages/mobile/src/components/image/UserImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ type UseUserImageOptions = {
user: Nullable<
Pick<
User,
'profile_picture_sizes' | 'profile_picture' | 'updatedProfilePicture'
| 'profile_picture_sizes'
| 'profile_picture_cids'
| 'profile_picture'
| 'updatedProfilePicture'
>
>
size: SquareSizes
Expand All @@ -22,7 +25,8 @@ export const useUserImage = ({ user, size }: UseUserImageOptions) => {
const contentNodeImage = useContentNodeImage({
cid,
size,
fallbackImageSource: profilePicEmpty
fallbackImageSource: profilePicEmpty,
cidMap: user?.profile_picture_cids
})

if (user?.updatedProfilePicture) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const messages = {
type ShareToStoryStickerProps = {
track: Pick<
Track,
| 'cover_art_cids'
| 'cover_art_sizes'
| 'cover_art'
| 'owner_id'
Expand Down
21 changes: 16 additions & 5 deletions packages/mobile/src/hooks/useContentNodeImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,29 @@ export const createAllImageSources = ({
cid,
endpoints,
size,
localSource
localSource,
cidMap = null
}: {
cid: Nullable<CID>
endpoints: string[]
size: SquareSizes | WidthSizes
localSource?: ImageURISource | null
cidMap?: Nullable<{ [key: string]: string }>
}) => {
if (!cid || !endpoints) {
return []
}
let cidForSize: Nullable<string> = null
if (cidMap && cidMap[size]) {
cidForSize = cidMap[size]
}

const newImageSources = createImageSourcesForEndpoints({
endpoints,
createUri: (endpoint) => `${endpoint}/content/${cid}/${size}.jpg`
createUri: (endpoint) =>
cidForSize
? `${endpoint}/content/${cidForSize}`
: `${endpoint}/content/${cid}/${size}.jpg`
})

// These can be removed when all the data on Content Node has
Expand Down Expand Up @@ -96,6 +105,7 @@ type UseContentNodeImageOptions = {
size: SquareSizes | WidthSizes
fallbackImageSource: ImageSourcePropType
localSource?: ImageURISource | null
cidMap?: Nullable<{ [key: string]: string }>
}

/**
Expand All @@ -113,7 +123,7 @@ type UseContentNodeImageOptions = {
export const useContentNodeImage = (
options: UseContentNodeImageOptions
): ContentNodeImageSource => {
const { cid, size, fallbackImageSource, localSource } = options
const { cid, size, fallbackImageSource, localSource, cidMap } = options
const [imageSourceIndex, setImageSourceIndex] = useState(0)
const [failedToLoad, setFailedToLoad] = useState(false)
const { storageNodeSelector } = useAppContext()
Expand All @@ -130,9 +140,10 @@ export const useContentNodeImage = (
cid,
endpoints,
localSource,
size
size,
cidMap
})
}, [cid, endpoints, localSource, size])
}, [cid, endpoints, localSource, size, cidMap])

const handleError = useCallback(() => {
if (imageSourceIndex < imageSources.length - 1) {
Expand Down
3 changes: 2 additions & 1 deletion packages/mobile/src/models/Collection.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { CID, Nullable } from '@audius/common'
import type { CID, CoverArtSizes, Nullable } from '@audius/common'

export type CollectionImage = {
cover_art: Nullable<CID>
cover_art_sizes: Nullable<CID>
cover_art_cids: Nullable<CoverArtSizes>
}
5 changes: 4 additions & 1 deletion packages/mobile/src/models/Track.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import type { Track } from '@audius/common'

export type TrackImage = Pick<Track, 'cover_art' | 'cover_art_sizes'>
export type TrackImage = Pick<
Track,
'cover_art' | 'cover_art_sizes' | 'cover_art_cids'
>
2 changes: 2 additions & 0 deletions packages/mobile/src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ export type UserImage = Pick<
User,
| 'cover_photo'
| 'cover_photo_sizes'
| 'cover_photo_cids'
| 'profile_picture'
| 'profile_picture_sizes'
| 'profile_picture_cids'
>

export type UserMultihash = Pick<
Expand Down
1 change: 1 addition & 0 deletions packages/mobile/src/screens/profile-screen/CoverPhoto.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const CoverPhoto = ({ scrollY }: { scrollY?: Animated.Value }) => {
const styles = useStyles()
const user = useSelectProfile([
'user_id',
'cover_photo_cids',
'cover_photo_sizes',
'cover_photo',
'creator_node_endpoint',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const ProfilePicture = (props: Partial<ProfilePictureProps>) => {
const profile = useSelectProfile([
'user_id',
'profile_picture',
'profile_picture_cids',
'profile_picture_sizes',
'creator_node_endpoint',
'updatedProfilePicture'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,15 @@ function* downloadCollectionAsync(
}

function* downloadCollectionCoverArt(collection: CollectionMetadata) {
const { cover_art_sizes, cover_art, playlist_id } = collection
const { cover_art_cids, cover_art_sizes, cover_art, playlist_id } = collection
const cid = cover_art_sizes ?? cover_art
const storageNodeSelector = yield* call(getStorageNodeSelector)

const imageSources = createAllImageSources({
cid,
endpoints: cid ? storageNodeSelector.getNodes(cid) : [],
size: SquareSizes.SIZE_1000_BY_1000
size: SquareSizes.SIZE_1000_BY_1000,
cidMap: cover_art_cids
})

const coverArtUris = imageSources.map(({ uri }) => uri).filter(removeNullable)
Expand Down

0 comments on commit 1e0c335

Please sign in to comment.