From d72258c68ea17c7ac868478c11db6477b15e649e Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Sat, 14 Aug 2021 17:46:16 +0900 Subject: [PATCH] move album to cover art mapping to music --- app/hooks/music.ts | 4 +- app/models/music.ts | 4 +- app/state/cache.ts | 86 +++---------------------------------------- app/state/music.ts | 73 ++++++++++++++++++++++++++++++++++++ app/state/settings.ts | 4 +- 5 files changed, 85 insertions(+), 86 deletions(-) diff --git a/app/hooks/music.ts b/app/hooks/music.ts index 77fb0c4..b7759d9 100644 --- a/app/hooks/music.ts +++ b/app/hooks/music.ts @@ -1,4 +1,4 @@ -import { CacheFileTypeKey } from '@app/models/music' +import { CacheItemTypeKey } from '@app/models/music' import { selectCache } from '@app/state/cache' import { selectMusic } from '@app/state/music' import { selectSettings } from '@app/state/settings' @@ -64,7 +64,7 @@ export const useStarred = (id: string, type: string) => { ) } -const useFileRequest = (key: CacheFileTypeKey, id: string) => { +const useFileRequest = (key: CacheItemTypeKey, id: string) => { const file = useStore( useCallback( (store: Store) => { diff --git a/app/models/music.ts b/app/models/music.ts index 48b470f..443c044 100644 --- a/app/models/music.ts +++ b/app/models/music.ts @@ -80,13 +80,13 @@ export type ListableItem = Song | AlbumListItem | Artist | PlaylistListItem export type HomeLists = { [key: string]: AlbumListItem[] } -export enum CacheFileType { +export enum CacheItemType { coverArt, artistArt, song, } -export type CacheFileTypeKey = keyof typeof CacheFileType +export type CacheItemTypeKey = keyof typeof CacheItemType export type CacheFile = { path: string diff --git a/app/state/cache.ts b/app/state/cache.ts index 9784480..b4b1216 100644 --- a/app/state/cache.ts +++ b/app/state/cache.ts @@ -1,4 +1,4 @@ -import { CacheFile, CacheFileTypeKey, CacheRequest, Song } from '@app/models/music' +import { CacheFile, CacheItemTypeKey, CacheRequest } from '@app/models/music' import PromiseQueue from '@app/util/PromiseQueue' import produce from 'immer' import RNFS from 'react-native-fs' @@ -9,9 +9,9 @@ const imageDownloadQueue = new PromiseQueue(10) export type CacheDownload = CacheFile & CacheRequest -export type CacheDirsByServer = Record> -export type CacheFilesByServer = Record>> -export type CacheRequestsByServer = Record>> +export type CacheDirsByServer = Record> +export type CacheFilesByServer = Record>> +export type CacheRequestsByServer = Record>> // export type CacheItemsDb = Record< // string, @@ -24,7 +24,7 @@ export type CacheRequestsByServer = Record export type CacheSlice = { - cacheItem: (key: CacheFileTypeKey, itemId: string, url: string | (() => string | Promise)) => Promise + cacheItem: (key: CacheItemTypeKey, itemId: string, url: string | (() => string | Promise)) => Promise // cache: CacheItemsDb cacheDirs: CacheDirsByServer @@ -32,19 +32,11 @@ export type CacheSlice = { cacheRequests: CacheRequestsByServer getCoverArtPath: (coverArt: string) => Promise - - albumCoverArt: { [id: string]: string | undefined } - albumCoverArtRequests: { [id: string]: Promise } - fetchAlbumCoverArt: (id: string) => Promise - getAlbumCoverArt: (id: string | undefined) => Promise - mapSongCoverArtFromAlbum: (songs: Song[]) => Promise } export const selectCache = { - getCoverArtPath: (store: CacheSlice) => store.getCoverArtPath, cacheItem: (store: CacheSlice) => store.cacheItem, - - fetchAlbumCoverArt: (store: CacheSlice) => store.fetchAlbumCoverArt, + getCoverArtPath: (store: CacheSlice) => store.getCoverArtPath, } export const createCacheSlice = (set: SetState, get: GetState): CacheSlice => ({ @@ -138,70 +130,4 @@ export const createCacheSlice = (set: SetState, get: GetState): Ca await get().cacheItem('coverArt', coverArt, () => client.getCoverArtUri({ id: coverArt })) return get().cacheFiles[activeServerId].coverArt[coverArt].path }, - - albumCoverArt: {}, - albumCoverArtRequests: {}, - - fetchAlbumCoverArt: async id => { - const client = get().client - if (!client) { - return - } - - const inProgress = get().albumCoverArtRequests[id] - if (inProgress !== undefined) { - return await inProgress - } - - const promise = new Promise(async resolve => { - try { - const response = await client.getAlbum({ id }) - set( - produce(state => { - state.albumCoverArt[id] = response.data.album.coverArt - }), - ) - } finally { - resolve() - } - }).then(() => { - set( - produce(state => { - delete state.albumCoverArtRequests[id] - }), - ) - }) - set( - produce(state => { - state.albumCoverArtRequests[id] = promise - }), - ) - - return await promise - }, - - getAlbumCoverArt: async id => { - if (!id) { - return - } - - const existing = get().albumCoverArt[id] - if (existing) { - return existing - } - - await get().fetchAlbumCoverArt(id) - return get().albumCoverArt[id] - }, - - mapSongCoverArtFromAlbum: async songs => { - const mapped: Song[] = [] - for (const s of songs) { - mapped.push({ - ...s, - coverArt: await get().getAlbumCoverArt(s.albumId), - }) - } - return mapped - }, }) diff --git a/app/state/music.ts b/app/state/music.ts index 56bf653..7ccd650 100644 --- a/app/state/music.ts +++ b/app/state/music.ts @@ -14,6 +14,7 @@ import { PlaylistListItem, PlaylistWithSongs, SearchResults, + Song, } from '@app/models/music' import { Store } from '@app/state/store' import { GetAlbumList2Type, StarParams } from '@app/subsonic/params' @@ -65,6 +66,12 @@ export type MusicSlice = { starredAlbums: { [id: string]: boolean } starredArtists: { [id: string]: boolean } starItem: (id: string, type: string, unstar?: boolean) => Promise + + albumIdCoverArt: { [id: string]: string | undefined } + albumIdCoverArtRequests: { [id: string]: Promise } + fetchAlbumCoverArt: (id: string) => Promise + getAlbumCoverArt: (id: string | undefined) => Promise + mapSongCoverArtFromAlbum: (songs: Song[]) => Promise } export const selectMusic = { @@ -429,4 +436,70 @@ export const createMusicSlice = (set: SetState, get: GetState): Mu setStarred(unstar) } }, + + albumIdCoverArt: {}, + albumIdCoverArtRequests: {}, + + fetchAlbumCoverArt: async id => { + const client = get().client + if (!client) { + return + } + + const inProgress = get().albumIdCoverArtRequests[id] + if (inProgress !== undefined) { + return await inProgress + } + + const promise = new Promise(async resolve => { + try { + const response = await client.getAlbum({ id }) + set( + produce(state => { + state.albumIdCoverArt[id] = response.data.album.coverArt + }), + ) + } finally { + resolve() + } + }).then(() => { + set( + produce(state => { + delete state.albumIdCoverArtRequests[id] + }), + ) + }) + set( + produce(state => { + state.albumIdCoverArtRequests[id] = promise + }), + ) + + return await promise + }, + + getAlbumCoverArt: async id => { + if (!id) { + return + } + + const existing = get().albumIdCoverArt[id] + if (existing) { + return existing + } + + await get().fetchAlbumCoverArt(id) + return get().albumIdCoverArt[id] + }, + + mapSongCoverArtFromAlbum: async songs => { + const mapped: Song[] = [] + for (const s of songs) { + mapped.push({ + ...s, + coverArt: await get().getAlbumCoverArt(s.albumId), + }) + } + return mapped + }, }) diff --git a/app/state/settings.ts b/app/state/settings.ts index d4a57b9..9995ffa 100644 --- a/app/state/settings.ts +++ b/app/state/settings.ts @@ -1,4 +1,4 @@ -import { CacheFileType } from '@app/models/music' +import { CacheItemType } from '@app/models/music' import { AppSettings, Server } from '@app/models/settings' import { Store } from '@app/state/store' import { SubsonicApiClient } from '@app/subsonic/api' @@ -50,7 +50,7 @@ export const createSettingsSlice = (set: SetState, get: GetState): return } - for (const type in CacheFileType) { + for (const type in CacheItemType) { await mkdir(`${RNFS.DocumentDirectoryPath}/servers/${id}/${type}`) }