ai-chatbot/lib/canvas-image-toolbar-preferences.ts

75 lines
1.8 KiB
TypeScript

"use client";
import { useSyncExternalStore } from "react";
export const IMAGE_TOOLBAR_STORAGE_KEY = "canvas.image-toolbar.v1";
const CHANGE_EVENT = "canvas-image-toolbar-preferences";
export type ImageToolbarPreferences = {
pinnedKeys: string[];
showNames: boolean;
};
export function parseImageToolbarPreferences(
raw: string | null
): ImageToolbarPreferences | null {
if (!raw) return null;
try {
const value = JSON.parse(raw);
if (
!value ||
!Array.isArray(value.pinnedKeys) ||
typeof value.showNames !== "boolean"
)
return null;
return {
pinnedKeys: [
...new Set<string>(
value.pinnedKeys.filter(
(key: unknown) => typeof key === "string" && key.length < 80
)
),
],
showNames: value.showNames,
};
} catch {
return null;
}
}
function snapshot() {
try {
return window.localStorage.getItem(IMAGE_TOOLBAR_STORAGE_KEY);
} catch {
return null;
}
}
function subscribe(listener: () => void) {
const onStorage = (event: StorageEvent) => {
if (!event.key || event.key === IMAGE_TOOLBAR_STORAGE_KEY) listener();
};
window.addEventListener("storage", onStorage);
window.addEventListener(CHANGE_EVENT, listener);
return () => {
window.removeEventListener("storage", onStorage);
window.removeEventListener(CHANGE_EVENT, listener);
};
}
export function useImageToolbarPreferences() {
const raw = useSyncExternalStore(subscribe, snapshot, () => null);
return parseImageToolbarPreferences(raw);
}
export function saveImageToolbarPreferences(
preferences: ImageToolbarPreferences
) {
try {
window.localStorage.setItem(
IMAGE_TOOLBAR_STORAGE_KEY,
JSON.stringify(preferences)
);
window.dispatchEvent(new Event(CHANGE_EVENT));
return true;
} catch {
return false;
}
}