Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
import { useState, useEffect, useCallback } from 'react';
const STORAGE_KEY_PREFIX = 'widget-settings-';
export interface WidgetConfig {
refreshRate: number;
accentColor: 'primary' | 'accent' | 'destructive' | 'orange';
showHeader: boolean;
expanded: boolean;
opacity: number;
}
interface UseWidgetSettingsOptions<T> {
widgetId: string;
defaultConfig: WidgetConfig;
defaultSettings: T;
}
interface StoredWidgetData<T> {
config: WidgetConfig;
settings: T;
lastUpdated: number;
}
export function useWidgetSettings<T extends Record<string, any>>({
widgetId,
defaultConfig,
defaultSettings,
}: UseWidgetSettingsOptions<T>) {
const storageKey = `${STORAGE_KEY_PREFIX}${widgetId}`;
// Load initial state from localStorage
const loadFromStorage = useCallback((): StoredWidgetData<T> | null => {
try {
const stored = localStorage.getItem(storageKey);
if (stored) {
return JSON.parse(stored);
}
} catch (error) {
console.warn(`[WidgetSettings] Failed to load settings for ${widgetId}:`, error);
}
return null;
}, [storageKey, widgetId]);
const [config, setConfigState] = useState<WidgetConfig>(() => {
const stored = loadFromStorage();
return stored?.config ?? defaultConfig;
});
const [settings, setSettingsState] = useState<T>(() => {
const stored = loadFromStorage();
return stored?.settings ?? defaultSettings;
});
// Save to localStorage whenever config or settings change
useEffect(() => {
const data: StoredWidgetData<T> = {
config,
settings,
lastUpdated: Date.now(),
};
try {
localStorage.setItem(storageKey, JSON.stringify(data));
} catch (error) {
console.warn(`[WidgetSettings] Failed to save settings for ${widgetId}:`, error);
}
}, [config, settings, storageKey, widgetId]);
const setConfig = useCallback((updates: Partial<WidgetConfig>) => {
setConfigState(prev => ({ ...prev, ...updates }));
}, []);
const setSettings = useCallback((updates: Partial<T>) => {
setSettingsState(prev => ({ ...prev, ...updates }));
}, []);
const resetToDefaults = useCallback(() => {
setConfigState(defaultConfig);
setSettingsState(defaultSettings);
try {
localStorage.removeItem(storageKey);
} catch (error) {
console.warn(`[WidgetSettings] Failed to remove settings for ${widgetId}:`, error);
}
}, [defaultConfig, defaultSettings, storageKey, widgetId]);
return {
config,
settings,
setConfig,
setSettings,
resetToDefaults,
};
}
// Utility to generate a stable widget ID
export function generateWidgetId(name: string, widgetType?: string): string {
const sanitized = name.toLowerCase().replace(/[^a-z0-9]/g, '-');
return widgetType ? `${widgetType}-${sanitized}` : sanitized;
}
// Utility to clear all widget settings
export function clearAllWidgetSettings(): void {
const keysToRemove: string[] = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key?.startsWith(STORAGE_KEY_PREFIX)) {
keysToRemove.push(key);
}
}
keysToRemove.forEach(key => localStorage.removeItem(key));
}
// Utility to export all widget settings
export function exportWidgetSettings(): Record<string, any> {
const settings: Record<string, any> = {};
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key?.startsWith(STORAGE_KEY_PREFIX)) {
try {
settings[key] = JSON.parse(localStorage.getItem(key) || '{}');
} catch {
// Skip invalid entries
}
}
}
return settings;
}
// Utility to import widget settings
export function importWidgetSettings(settings: Record<string, any>): void {
Object.entries(settings).forEach(([key, value]) => {
if (key.startsWith(STORAGE_KEY_PREFIX)) {
localStorage.setItem(key, JSON.stringify(value));
}
});
}