import React from "react"; import { z } from "zod"; export const DEFAULT_BADGE_CACHE_EXPIRE_MS = 60 * 60 * 1000; // 1 hour export const DEFAULT_SHOW_COUNT_BADGE = false; const zSettingsSchema = z.object({ apiKey: z.string(), apiKeyId: z.string().optional(), address: z.string().optional().default("https://cloud.karakeep.app"), theme: z.enum(["light", "dark", "system"]).optional().default("system"), showCountBadge: z.boolean().default(DEFAULT_SHOW_COUNT_BADGE), useBadgeCache: z.boolean().default(true), badgeCacheExpireMs: z.number().min(0).default(DEFAULT_BADGE_CACHE_EXPIRE_MS), customHeaders: z.record(z.string(), z.string()).optional().default({}), }); const DEFAULT_SETTINGS: Settings = { apiKey: "", address: "https://cloud.karakeep.app", theme: "system", showCountBadge: DEFAULT_SHOW_COUNT_BADGE, useBadgeCache: true, badgeCacheExpireMs: DEFAULT_BADGE_CACHE_EXPIRE_MS, customHeaders: {}, }; export type Settings = z.infer; const STORAGE = chrome.storage.sync; export default function usePluginSettings() { const [settings, setSettingsInternal] = React.useState(DEFAULT_SETTINGS); const [isInit, setIsInit] = React.useState(false); React.useEffect(() => { if (!isInit) { getPluginSettings().then((settings) => { setSettingsInternal(settings); setIsInit(true); }); } const onChange = ( changes: Record, ) => { if (changes.settings === undefined) { return; } const parsedSettings = zSettingsSchema.safeParse( changes.settings.newValue, ); if (parsedSettings.success) { setSettingsInternal(parsedSettings.data); } }; STORAGE.onChanged.addListener(onChange); return () => { STORAGE.onChanged.removeListener(onChange); }; }, []); const setSettings = async (s: (_: Settings) => Settings) => { const newVal = s(settings); await STORAGE.set({ settings: newVal }); }; return { settings, setSettings, isPending: isInit }; } export async function getPluginSettings() { const parsedSettings = zSettingsSchema.safeParse( (await STORAGE.get("settings")).settings, ); if (parsedSettings.success) { return parsedSettings.data; } else { return DEFAULT_SETTINGS; } } export function subscribeToSettingsChanges( callback: (settings: Settings) => void, ) { STORAGE.onChanged.addListener((changes) => { if (changes.settings === undefined) { return; } const parsedSettings = zSettingsSchema.safeParse(changes.settings.newValue); if (parsedSettings.success) { callback(parsedSettings.data); } else { callback(DEFAULT_SETTINGS); } }); }