import { useState, useEffect, useCallback } from 'react' import { isCached, cacheStem } from '../utils/presetCache' const STEM_NAMES = ['guitar', 'drums', 'bass', 'synth', 'click_record'] /** * Checks IndexedDB for cached presets on mount, then background-fetches * any that are missing using the stateless /api/preset-stem endpoint. * * Returns cacheStatus: { [presetName]: 'cached' | 'loading' | 'uncached' } */ export function usePresetCache() { const [cacheStatus, setCacheStatus] = useState({}) const prefetchPreset = useCallback(async (presetName) => { setCacheStatus(prev => ({ ...prev, [presetName]: 'loading' })) try { const results = await Promise.all( STEM_NAMES.map(async (stemName) => { const response = await fetch(`/api/preset-stem/${presetName}/${stemName}`) if (!response.ok) return false const sampleRate = parseInt(response.headers.get('X-Sample-Rate')) const numChannels = parseInt(response.headers.get('X-Channels')) const numFrames = parseInt(response.headers.get('X-Frames')) const bytes = await response.arrayBuffer() await cacheStem(presetName, stemName, { bytes, sampleRate, numChannels, numFrames }) return true }) ) const allOk = results.every(Boolean) setCacheStatus(prev => ({ ...prev, [presetName]: allOk ? 'cached' : 'uncached' })) } catch { setCacheStatus(prev => ({ ...prev, [presetName]: 'uncached' })) } }, []) useEffect(() => { let cancelled = false async function init() { try { const res = await fetch('/api/presets') const { presets } = await res.json() if (cancelled || !presets?.length) return // Check which presets are already in IndexedDB const statuses = {} await Promise.all( presets.map(async (name) => { statuses[name] = (await isCached(name, STEM_NAMES)) ? 'cached' : 'uncached' }) ) if (cancelled) return setCacheStatus(statuses) // Background-fetch uncached presets one at a time to avoid saturating bandwidth for (const name of presets) { if (cancelled) break if (statuses[name] === 'uncached') { await prefetchPreset(name) } } } catch { // Prefetch is best-effort — silently fail } } init() return () => { cancelled = true } }, [prefetchPreset]) return { cacheStatus } }