50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
// A small keyed cache behind the panel: the conversation index and the
|
|
// last threads land here so the next open paints before the network
|
|
// answers. localStorage when it exists, memory otherwise.
|
|
export interface PanelCache {
|
|
get: <T>(key: string) => T | null;
|
|
set: (key: string, value: unknown) => void;
|
|
}
|
|
|
|
const memory = new Map<string, string>();
|
|
|
|
function storage(): Pick<Storage, "getItem" | "setItem" | "removeItem"> {
|
|
try {
|
|
if (typeof localStorage !== "undefined") {
|
|
return localStorage;
|
|
}
|
|
} catch {
|
|
/* sandboxed */
|
|
}
|
|
return {
|
|
getItem: (key) => memory.get(key) ?? null,
|
|
removeItem: (key) => {
|
|
memory.delete(key);
|
|
},
|
|
setItem: (key, value) => {
|
|
memory.set(key, value);
|
|
},
|
|
};
|
|
}
|
|
|
|
export function panelCache(prefix: string): PanelCache {
|
|
const store = storage();
|
|
return {
|
|
get<T>(key: string): T | null {
|
|
try {
|
|
const raw = store.getItem(`${prefix}:${key}`);
|
|
return raw ? (JSON.parse(raw) as T) : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
},
|
|
set(key: string, value: unknown): void {
|
|
try {
|
|
store.setItem(`${prefix}:${key}`, JSON.stringify(value));
|
|
} catch {
|
|
store.removeItem(`${prefix}:${key}`);
|
|
}
|
|
},
|
|
};
|
|
}
|