75 lines
1.8 KiB
TypeScript
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;
|
|
}
|
|
}
|