Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

[C-2108] Improve local image fetch #2826

Merged
merged 2 commits into from
Feb 13, 2023
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
10 changes: 5 additions & 5 deletions packages/mobile/src/components/audio/Audio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ import { useEffectOnce, usePrevious } from 'react-use'
import { DEFAULT_IMAGE_URL } from 'app/components/image/TrackImage'
import { getImageSourceOptimistic } from 'app/hooks/useContentNodeImage'
import { useIsOfflineModeEnabled } from 'app/hooks/useIsOfflineModeEnabled'
import { getLocalTrackImageSource } from 'app/hooks/useLocalImage'
import { useFeatureFlag } from 'app/hooks/useRemoteConfig'
import { apiClient } from 'app/services/audius-api-client'
import { audiusBackendInstance } from 'app/services/audius-backend-instance'
import {
DOWNLOAD_REASON_FAVORITES,
getLocalAudioPath
getLocalAudioPath,
getLocalTrackCoverArtPath
} from 'app/services/offline-downloader'
import {
getOfflineTrackStatus,
Expand Down Expand Up @@ -408,17 +408,17 @@ export const Audio = () => {
})
}

const localSource =
const localTrackImageSource =
isNotReachable && track
? await getLocalTrackImageSource(trackId)
? { uri: `file://${getLocalTrackCoverArtPath(trackId.toString())}` }
: undefined

const imageUrl =
getImageSourceOptimistic({
cid: track ? track.cover_art_sizes || track.cover_art : null,
user: trackOwner,
size: SquareSizes.SIZE_1000_BY_1000,
localSource
localSource: localTrackImageSource
})?.uri ?? DEFAULT_IMAGE_URL

return {
Expand Down
48 changes: 41 additions & 7 deletions packages/mobile/src/components/image/CollectionImage.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import type { Collection, Nullable, SquareSizes, User } from '@audius/common'
import { cacheUsersSelectors } from '@audius/common'
import type {
Collection,
ID,
Maybe,
Nullable,
SquareSizes,
User
} from '@audius/common'
import { reachabilitySelectors, cacheUsersSelectors } from '@audius/common'
import { useSelector } from 'react-redux'

import imageEmpty from 'app/assets/images/imageBlank2x.png'
import { useContentNodeImage } from 'app/hooks/useContentNodeImage'
import { useLocalCollectionImage } from 'app/hooks/useLocalImage'
import { getLocalCollectionCoverArtPath } from 'app/services/offline-downloader'
import { getCollectionDownloadStatus } from 'app/store/offline-downloads/selectors'
import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice'
import { useThemeColors } from 'app/utils/theme'

import type { FastImageProps } from './FastImage'
import { FastImage } from './FastImage'

const { getIsReachable } = reachabilitySelectors
const { getUser } = cacheUsersSelectors

type UseCollectionImageOptions = {
Expand All @@ -23,6 +33,28 @@ type UseCollectionImageOptions = {
user?: Pick<User, 'creator_node_endpoint'>
}

const useLocalCollectionImageUri = (collectionId: Maybe<ID>) => {
const collectionImageUri = useSelector((state) => {
if (!collectionId) return null

const isReachable = getIsReachable(state)
if (isReachable) return null

const collectionDownloadStatus = getCollectionDownloadStatus(
state,
collectionId
)
const isDownloaded =
collectionDownloadStatus === OfflineDownloadStatus.SUCCESS

if (!isDownloaded) return null

return `file://${getLocalCollectionCoverArtPath(collectionId.toString())}`
})

return collectionImageUri
}

export const useCollectionImage = (options: UseCollectionImageOptions) => {
const { collection, size, user } = options
const cid = collection
Expand All @@ -33,19 +65,21 @@ export const useCollectionImage = (options: UseCollectionImageOptions) => {
getUser(state, { id: collection?.playlist_owner_id })
)

const { value: localSource, loading } = useLocalCollectionImage(
collection?.playlist_id.toString()
const localCollectionImageUri = useLocalCollectionImageUri(
collection?.playlist_id
)

const contentNodeSource = useContentNodeImage({
cid,
size,
user: selectedUser ?? user ?? null,
fallbackImageSource: imageEmpty,
localSource
localSource: localCollectionImageUri
? { uri: localCollectionImageUri }
: null
})

return loading ? null : contentNodeSource
return contentNodeSource
}

type CollectionImageProps = UseCollectionImageOptions & Partial<FastImageProps>
Expand Down
42 changes: 34 additions & 8 deletions packages/mobile/src/components/image/TrackImage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import type { User, Track, Nullable, SquareSizes } from '@audius/common'
import { cacheUsersSelectors } from '@audius/common'
import type {
User,
Track,
Nullable,
SquareSizes,
ID,
Maybe
} from '@audius/common'
import { reachabilitySelectors, cacheUsersSelectors } from '@audius/common'
import { useSelector } from 'react-redux'

import imageEmpty from 'app/assets/images/imageBlank2x.png'
import { useContentNodeImage } from 'app/hooks/useContentNodeImage'
import { useLocalTrackImage } from 'app/hooks/useLocalImage'
import { getLocalTrackCoverArtPath } from 'app/services/offline-downloader'
import { getTrackDownloadStatus } from 'app/store/offline-downloads/selectors'
import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice'
import { useThemeColors } from 'app/utils/theme'

import type { FastImageProps } from './FastImage'
Expand All @@ -13,6 +22,7 @@ import { FastImage } from './FastImage'
export const DEFAULT_IMAGE_URL =
'https://download.audius.co/static-resources/preview-image.jpg'

const { getIsReachable } = reachabilitySelectors
const { getUser } = cacheUsersSelectors

type UseTrackImageOptions = {
Expand All @@ -23,25 +33,41 @@ type UseTrackImageOptions = {
user?: Pick<User, 'creator_node_endpoint'>
}

const useLocalTrackImageUri = (trackId: Maybe<ID>) => {
const trackImageUri = useSelector((state) => {
if (!trackId) return null

const isReachable = getIsReachable(state)
if (isReachable) return null

const trackDownloadStatus = getTrackDownloadStatus(state, trackId)
const isDownloaded = trackDownloadStatus === OfflineDownloadStatus.SUCCESS
if (!isDownloaded) return null

return `file://${getLocalTrackCoverArtPath(trackId.toString())}`
})

return trackImageUri
}

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

const selectedUser = useSelector((state) =>
getUser(state, { id: track?.owner_id })
)
const { value: localSource, loading } = useLocalTrackImage(
track?.track_id.toString()
)

const localTrackImageUri = useLocalTrackImageUri(track?.track_id)

const contentNodeSource = useContentNodeImage({
cid,
size,
user: user ?? selectedUser,
fallbackImageSource: imageEmpty,
localSource
localSource: localTrackImageUri ? { uri: localTrackImageUri } : null
})

return loading ? null : contentNodeSource
return contentNodeSource
}

type TrackImageProps = UseTrackImageOptions & Partial<FastImageProps>
Expand Down
75 changes: 0 additions & 75 deletions packages/mobile/src/hooks/useLocalImage.ts

This file was deleted.

8 changes: 8 additions & 0 deletions packages/mobile/src/store/offline-downloads/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ export const getTrackOfflineDownloadStatus =
(trackId?: number) => (state: AppState) =>
trackId ? state.offlineDownloads.trackStatus[trackId] : null

export const getTrackDownloadStatus = (state: AppState, trackId: ID) =>
state.offlineDownloads.trackStatus[trackId]

export const getCollectionOfflineDownloadStatus =
(collectionId?: CollectionId) => (state: AppState) =>
collectionId ? state.offlineDownloads.collectionStatus[collectionId] : null

export const getCollectionDownloadStatus = (
state: AppState,
collectionId: CollectionId
) => state.offlineDownloads.collectionStatus[collectionId]

export const getCollectionSyncStatus = (
state: AppState,
collectionId: CollectionId
Expand Down