2026-06-14 18:36:28 +08:00
|
|
|
import { useSyncExternalStore } from "react";
|
|
|
|
|
|
|
|
|
|
const STORAGE_KEY = "snapotter-recent-tools";
|
|
|
|
|
const MAX_RECENT = 5;
|
2026-06-14 20:31:49 +08:00
|
|
|
const EMPTY: string[] = [];
|
2026-06-14 18:36:28 +08:00
|
|
|
|
|
|
|
|
let listeners: Array<() => void> = [];
|
2026-06-14 20:31:49 +08:00
|
|
|
let cachedRaw: string | null = null;
|
|
|
|
|
let cachedParsed: string[] = EMPTY;
|
2026-06-14 18:36:28 +08:00
|
|
|
|
|
|
|
|
function getSnapshot(): string[] {
|
2026-06-14 20:31:49 +08:00
|
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
|
|
|
if (raw !== cachedRaw) {
|
|
|
|
|
cachedRaw = raw;
|
|
|
|
|
try {
|
|
|
|
|
cachedParsed = raw ? JSON.parse(raw) : EMPTY;
|
|
|
|
|
} catch {
|
|
|
|
|
cachedParsed = EMPTY;
|
|
|
|
|
}
|
2026-06-14 18:36:28 +08:00
|
|
|
}
|
2026-06-14 20:31:49 +08:00
|
|
|
return cachedParsed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getServerSnapshot(): string[] {
|
|
|
|
|
return EMPTY;
|
2026-06-14 18:36:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function subscribe(listener: () => void) {
|
|
|
|
|
listeners.push(listener);
|
|
|
|
|
return () => {
|
|
|
|
|
listeners = listeners.filter((l) => l !== listener);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function recordRecentTool(toolId: string) {
|
|
|
|
|
const current = getSnapshot();
|
|
|
|
|
const updated = [toolId, ...current.filter((id) => id !== toolId)].slice(0, MAX_RECENT);
|
|
|
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
|
2026-06-14 20:31:49 +08:00
|
|
|
cachedRaw = null;
|
2026-06-15 15:20:16 +08:00
|
|
|
for (const l of listeners) l();
|
2026-06-14 18:36:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useRecentTools(): string[] {
|
2026-06-14 20:31:49 +08:00
|
|
|
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
2026-06-14 18:36:28 +08:00
|
|
|
}
|