import { create } from 'zustand'; import { persist, createJSONStorage } from 'zustand/middleware'; import { DEFAULT_COVER_CACHE_STRATEGY, coverStrategyFromLegacyPrefetch, type CoverCacheStrategy, } from '../utils/library/coverStrategy'; import { useAuthStore } from './authStore'; import { serverIndexKeyFromUrl } from '../utils/server/serverIndexKey'; import type { ServerProfile } from './authStoreTypes'; const resolveStrategyKey = (serverId: string): string => { const server = useAuthStore.getState().servers.find(s => s.id === serverId); if (!server) return serverId; return serverIndexKeyFromUrl(server.url) || serverId; }; function readLegacyGlobalStrategy(): CoverCacheStrategy | null { try { const raw = localStorage.getItem('psysonic-auth'); if (!raw) return null; const parsed = JSON.parse(raw) as { state?: { coverPrefetchStrategy?: string } }; const legacy = parsed?.state?.coverPrefetchStrategy; if (!legacy) return null; return coverStrategyFromLegacyPrefetch(legacy); } catch { return null; } } interface CoverStrategyState { strategy: CoverCacheStrategy; strategyByServer: Record; setStrategy: (strategy: CoverCacheStrategy) => void; setServerStrategy: (serverId: string, strategy: CoverCacheStrategy) => void; clearServerOverrides: (serverId: string) => void; migrateServerOverrides: (servers: ServerProfile[]) => void; getStrategyForServer: (serverId: string | null | undefined) => CoverCacheStrategy; } export const useCoverStrategyStore = create()( persist( (set, get) => ({ strategy: DEFAULT_COVER_CACHE_STRATEGY, strategyByServer: {}, setStrategy: strategy => set({ strategy }), setServerStrategy: (serverId, strategy) => set(s => ({ strategyByServer: { ...s.strategyByServer, [resolveStrategyKey(serverId)]: strategy }, })), clearServerOverrides: (serverId) => set(s => { const key = resolveStrategyKey(serverId); const { [serverId]: _, [key]: __, ...strategyByServer } = s.strategyByServer; return { strategyByServer }; }), migrateServerOverrides: (servers) => set(s => { if (servers.length === 0) return {}; let changed = false; const strategyByServer = { ...s.strategyByServer }; for (const server of servers) { const key = serverIndexKeyFromUrl(server.url) || server.id; if (key === server.id) continue; const legacyStrategy = strategyByServer[server.id]; const nextStrategy = strategyByServer[key]; if (legacyStrategy !== undefined && nextStrategy !== undefined) { delete strategyByServer[server.id]; changed = true; } else if (legacyStrategy !== undefined && nextStrategy === undefined) { strategyByServer[key] = legacyStrategy; delete strategyByServer[server.id]; changed = true; } } return changed ? { strategyByServer } : {}; }), getStrategyForServer: serverId => { if (!serverId) return DEFAULT_COVER_CACHE_STRATEGY; const key = resolveStrategyKey(serverId); return get().strategyByServer[key] ?? get().strategyByServer[serverId] ?? get().strategy; }, }), { name: 'psysonic-cover-cache-strategy', storage: createJSONStorage(() => localStorage), version: 1, migrate: (persisted, version) => { const fallback = { strategy: DEFAULT_COVER_CACHE_STRATEGY, strategyByServer: {} as Record, }; if (version < 1) { const legacyGlobal = readLegacyGlobalStrategy(); const old = persisted as { strategy?: CoverCacheStrategy; strategyByServer?: Record }; return { strategy: legacyGlobal ?? old.strategy ?? fallback.strategy, strategyByServer: old.strategyByServer ?? fallback.strategyByServer, }; } const current = persisted as Partial; return { strategy: current.strategy ?? fallback.strategy, strategyByServer: current.strategyByServer ?? fallback.strategyByServer, }; }, partialize: s => ({ strategy: s.strategy, strategyByServer: s.strategyByServer, }), }, ), );