import { useCallback, useEffect, useRef, useState } from 'react'; import { invoke } from '@tauri-apps/api/core'; import { createThumbnailRequestKey, startOwnedThumbnailGeneration, ThumbnailRequestGeneration, thumbnailIdsFromRequestKey, } from '../lib/thumbnailRequests'; import { windowAsyncScope } from '../lib/asyncOwnership'; /** * Per-id cache for cover thumbnails belonging to the supplied game ids. * Returns `null` until the value is known; returns the empty string when the * backend has nothing for the id, so callers can use the placeholder cover. */ export const useThumbnails = (ids: readonly string[]) => { const [thumbnails, setThumbnails] = useState>(new Map()); const thumbnailsRef = useRef(thumbnails); const requestKey = createThumbnailRequestKey(ids); useEffect(() => { const generation = new ThumbnailRequestGeneration( id => invoke('get_game_thumbnail', { gameId: id }), (id, url) => { const next = new Map(thumbnailsRef.current).set(id, url); thumbnailsRef.current = next; setThumbnails(next); }, ); const missingIds = thumbnailIdsFromRequestKey(requestKey) .filter(id => !thumbnailsRef.current.has(id)); return startOwnedThumbnailGeneration(windowAsyncScope, generation, missingIds); }, [requestKey]); const get = useCallback((id: string): string | null => { if (thumbnails.has(id)) return thumbnails.get(id) ?? ''; return null; }, [thumbnails]); return { get }; };