11import { useState , useEffect , useRef } from "react" ;
22import { albumArtStorage } from "../platform/storage" ;
33
4- // Cache to store loaded album arts in memory
5- const loadedAlbumArts = new Map < string , string > ( ) ;
6- // Pending load requests to avoid duplicate fetches
74const pendingLoads = new Map < string , Promise < string | null > > ( ) ;
85
9- /**
10- * Hook to lazily load album art for a single song
11- * Only fetches from IndexedDB when needed, uses in-memory cache
12- */
136export function useAlbumArt (
147 songId : string | undefined ,
158 hasAlbumArt : boolean = false ,
169) : string | undefined {
17- const [ albumArt , setAlbumArt ] = useState < string | undefined > ( ( ) => {
18- if ( songId && loadedAlbumArts . has ( songId ) ) {
19- return loadedAlbumArts . get ( songId ) ;
20- }
21- return undefined ;
22- } ) ;
10+ const [ albumArt , setAlbumArt ] = useState < string | undefined > ( ( ) =>
11+ songId ? albumArtStorage . get ( songId ) : undefined ,
12+ ) ;
2313
2414 useEffect ( ( ) => {
2515 if ( ! songId || ! hasAlbumArt ) {
2616 setAlbumArt ( undefined ) ;
2717 return ;
2818 }
2919
30- if ( loadedAlbumArts . has ( songId ) ) {
31- setAlbumArt ( loadedAlbumArts . get ( songId ) ) ;
20+ const cached = albumArtStorage . get ( songId ) ;
21+ if ( cached ) {
22+ setAlbumArt ( cached ) ;
3223 return ;
3324 }
3425
@@ -42,25 +33,16 @@ export function useAlbumArt(
4233 const loadPromise = albumArtStorage . load ( songId ) ;
4334 pendingLoads . set ( songId , loadPromise ) ;
4435
45- loadPromise
46- . then ( ( art ) => {
47- if ( art ) {
48- loadedAlbumArts . set ( songId , art ) ;
49- setAlbumArt ( art ) ;
50- }
51- } )
52- . finally ( ( ) => {
53- pendingLoads . delete ( songId ) ;
54- } ) ;
36+ loadPromise . then ( ( art ) => {
37+ if ( art ) setAlbumArt ( art ) ;
38+ } ) . finally ( ( ) => {
39+ pendingLoads . delete ( songId ) ;
40+ } ) ;
5541 } , [ songId , hasAlbumArt ] ) ;
5642
5743 return albumArt ;
5844}
5945
60- /**
61- * Hook to batch load album art for visible songs
62- * More efficient for lists - loads multiple arts in one IndexedDB transaction
63- */
6446export function useAlbumArtBatch (
6547 songs : Array < { id : string ; hasAlbumArt ?: boolean } > ,
6648) : Map < string , string > {
@@ -71,80 +53,30 @@ export function useAlbumArtBatch(
7153 if ( songs . length === 0 ) return ;
7254
7355 const toLoad = songs . filter (
74- ( song ) =>
75- song . hasAlbumArt &&
76- ! loadedAlbumArts . has ( song . id ) &&
77- ! loadedRef . current . has ( song . id ) ,
56+ ( song ) => song . hasAlbumArt && ! albumArtStorage . has ( song . id ) && ! loadedRef . current . has ( song . id ) ,
7857 ) ;
7958
8059 if ( toLoad . length === 0 ) {
8160 const cached = new Map < string , string > ( ) ;
8261 for ( const song of songs ) {
83- if ( loadedAlbumArts . has ( song . id ) ) {
84- cached . set ( song . id , loadedAlbumArts . get ( song . id ) ! ) ;
85- }
86- }
87- if ( cached . size > 0 ) {
88- setAlbumArts ( cached ) ;
62+ const art = albumArtStorage . get ( song . id ) ;
63+ if ( art ) cached . set ( song . id , art ) ;
8964 }
65+ if ( cached . size > 0 ) setAlbumArts ( cached ) ;
9066 return ;
9167 }
9268
9369 toLoad . forEach ( ( song ) => loadedRef . current . add ( song . id ) ) ;
94-
95- albumArtStorage
96- . loadBatch ( toLoad . map ( ( s ) => s . id ) )
97- . then ( ( loaded ) => {
98- loaded . forEach ( ( art , songId ) => {
99- loadedAlbumArts . set ( songId , art ) ;
100- } ) ;
101-
102- const allArts = new Map < string , string > ( ) ;
103- for ( const song of songs ) {
104- if ( loadedAlbumArts . has ( song . id ) ) {
105- allArts . set ( song . id , loadedAlbumArts . get ( song . id ) ! ) ;
106- }
107- }
108- setAlbumArts ( allArts ) ;
109- } ) ;
70+ albumArtStorage . loadBatch ( toLoad . map ( ( s ) => s . id ) ) . then ( ( loaded ) => {
71+ const allArts = new Map < string , string > ( ) ;
72+ for ( const song of songs ) {
73+ const art = albumArtStorage . get ( song . id ) ;
74+ if ( art ) allArts . set ( song . id , art ) ;
75+ }
76+ setAlbumArts ( allArts ) ;
77+ } ) ;
11078 } , [ songs ] ) ;
11179
11280 return albumArts ;
11381}
11482
115- /**
116- * Get album art directly from cache without loading
117- * Returns undefined if not in cache
118- */
119- export function getAlbumArtFromCache ( songId : string ) : string | undefined {
120- return loadedAlbumArts . get ( songId ) ;
121- }
122-
123- /**
124- * Preload album art for songs (useful for current/next songs)
125- */
126- export async function preloadAlbumArt ( songIds : string [ ] ) : Promise < void > {
127- const toLoad = songIds . filter ( ( id ) => ! loadedAlbumArts . has ( id ) ) ;
128- if ( toLoad . length === 0 ) return ;
129-
130- const loaded = await albumArtStorage . loadBatch ( toLoad ) ;
131- loaded . forEach ( ( art , songId ) => {
132- loadedAlbumArts . set ( songId , art ) ;
133- } ) ;
134- }
135-
136- /**
137- * Clear album art cache to free memory
138- * Call this when switching views or when memory pressure is high
139- */
140- export function clearAlbumArtCache ( ) : void {
141- loadedAlbumArts . clear ( ) ;
142- albumArtStorage . clearCache ( ) ;
143- }
144-
145- /**
146- * Set album art in cache directly (used when importing new songs)
147- */
148- export function setAlbumArtInCache ( songId : string , albumArt : string ) : void {
149- loadedAlbumArts . set ( songId , albumArt ) ;
150- }
0 commit comments