mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
50 lines
2.2 KiB
TypeScript
50 lines
2.2 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react';
|
|
import { isNewer } from '@/utils/componentHelpers/appUpdaterHelpers';
|
|
import { fetchRegistry, getCachedRegistry, type Registry, type RegistryTheme } from '@/utils/themes/themeRegistry';
|
|
import { useInstalledThemesStore } from '@/store/installedThemesStore';
|
|
|
|
// Refresh the registry from source once per app launch (not just from the
|
|
// cache). This surfaces newly published themes and updates without the user
|
|
// having to hit the manual refresh in the Theme Store, and it feeds the
|
|
// sidebar update notice. Subsequent reads this session use the cache.
|
|
let sessionRefreshStarted = false;
|
|
|
|
/**
|
|
* Registry entries for installed community themes that have a newer version
|
|
* available. Returns the full registry theme (css path, version, metadata) so a
|
|
* caller can update in place. Seeds from the last-cached registry synchronously,
|
|
* then revalidates (forced on the first call this session). Recomputes when the
|
|
* installed set changes, so the list shrinks as the user updates themes.
|
|
*/
|
|
export function useThemeUpdates(): RegistryTheme[] {
|
|
const installed = useInstalledThemesStore(s => s.themes);
|
|
const [registry, setRegistry] = useState<Registry | null>(() => getCachedRegistry());
|
|
|
|
useEffect(() => {
|
|
let alive = true;
|
|
const opts = sessionRefreshStarted ? undefined : { force: true };
|
|
sessionRefreshStarted = true;
|
|
fetchRegistry(opts)
|
|
.then(r => { if (alive) setRegistry(r.registry); })
|
|
.catch(() => { /* offline: keep whatever the cache gave us */ });
|
|
return () => { alive = false; };
|
|
}, []);
|
|
|
|
return useMemo(() => {
|
|
if (!registry) return [];
|
|
const installedVersionById = new Map(installed.map(t => [t.id, t.version]));
|
|
return registry.themes.filter(rt => {
|
|
const current = installedVersionById.get(rt.id);
|
|
return current != null && isNewer(rt.version, current);
|
|
});
|
|
}, [registry, installed]);
|
|
}
|
|
|
|
/**
|
|
* Stable signature of an update set, used to remember a dismissal: the sidebar
|
|
* notice stays hidden until a new or bumped update changes this string.
|
|
*/
|
|
export function themeUpdateSignature(updates: Array<{ id: string; version: string }>): string {
|
|
return updates.map(u => `${u.id}@${u.version}`).sort().join(',');
|
|
}
|