import { AppSettings } from './stores/appSettings'; import { STORAGE_KEYS, PERFORMANCE, DEFAULTS, ValueMode, } from './utils/constants'; export interface SavedShader { id: string; name: string; code: string; created: number; lastUsed: number; // Visual settings resolution?: number; fps?: number; renderMode?: string; valueMode?: ValueMode; uiOpacity?: number; hueShift?: number; } export class Storage { private static readonly SHADERS_KEY = STORAGE_KEYS.SHADERS; private static readonly SETTINGS_KEY = STORAGE_KEYS.SETTINGS; static saveShader( name: string, code: string, settings?: Partial ): SavedShader { const shaders = this.getShaders(); const id = this.generateId(); const timestamp = Date.now(); const shader: SavedShader = { id, name: name.trim() || `Shader ${shaders.length + 1}`, code, created: timestamp, lastUsed: timestamp, // Include settings if provided ...(settings && { resolution: settings.resolution, fps: settings.fps, renderMode: settings.renderMode, valueMode: settings.valueMode, uiOpacity: settings.uiOpacity, hueShift: settings.hueShift, }), }; shaders.push(shader); this.setShaders(shaders); return shader; } static getShaders(): SavedShader[] { try { const stored = localStorage.getItem(this.SHADERS_KEY); return stored ? JSON.parse(stored) : []; } catch (error) { console.error('Failed to load shaders:', error); return []; } } static deleteShader(id: string): void { const shaders = this.getShaders().filter((s) => s.id !== id); this.setShaders(shaders); } static updateShaderUsage(id: string): void { const shaders = this.getShaders(); const shader = shaders.find((s) => s.id === id); if (shader) { shader.lastUsed = Date.now(); this.setShaders(shaders); } } static renameShader(id: string, newName: string): void { const shaders = this.getShaders(); const shader = shaders.find((s) => s.id === id); if (shader) { shader.name = newName.trim() || shader.name; this.setShaders(shaders); } } private static setShaders(shaders: SavedShader[]): void { try { // Keep only the most recent shaders const sortedShaders = shaders .sort((a, b) => b.lastUsed - a.lastUsed) .slice(0, PERFORMANCE.MAX_SAVED_SHADERS); localStorage.setItem(this.SHADERS_KEY, JSON.stringify(sortedShaders)); } catch (error) { console.error('Failed to save shaders:', error); } } static saveSettings(settings: Partial): void { try { const current = this.getSettings(); const updated = { ...current, ...settings }; localStorage.setItem(this.SETTINGS_KEY, JSON.stringify(updated)); } catch (error) { console.error('Failed to save settings:', error); } } static getSettings(): AppSettings { try { const stored = localStorage.getItem(this.SETTINGS_KEY); const defaults: AppSettings = { resolution: DEFAULTS.RESOLUTION, fps: DEFAULTS.FPS, lastShaderCode: DEFAULTS.SHADER_CODE, renderMode: DEFAULTS.RENDER_MODE, valueMode: DEFAULTS.VALUE_MODE, uiOpacity: DEFAULTS.UI_OPACITY, }; return stored ? { ...defaults, ...JSON.parse(stored) } : defaults; } catch (error) { console.error('Failed to load settings:', error); return { resolution: DEFAULTS.RESOLUTION, fps: DEFAULTS.FPS, lastShaderCode: DEFAULTS.SHADER_CODE, renderMode: DEFAULTS.RENDER_MODE, valueMode: DEFAULTS.VALUE_MODE, uiOpacity: DEFAULTS.UI_OPACITY, }; } } static clearAll(): void { try { localStorage.removeItem(this.SHADERS_KEY); localStorage.removeItem(this.SETTINGS_KEY); } catch (error) { console.error('Failed to clear storage:', error); } } private static generateId(): string { return Date.now().toString(36) + Math.random().toString(36).substr(2); } static exportShaders(): string { const shaders = this.getShaders(); return JSON.stringify(shaders, null, 2); } static importShaders(jsonData: string): boolean { try { const imported = JSON.parse(jsonData) as SavedShader[]; if (!Array.isArray(imported)) { return false; } // Validate structure const valid = imported.every( (shader) => shader.id && shader.name && shader.code && typeof shader.created === 'number' && typeof shader.lastUsed === 'number' ); if (!valid) { return false; } const existing = this.getShaders(); const merged = [...existing, ...imported]; this.setShaders(merged); return true; } catch (error) { console.error('Failed to import shaders:', error); return false; } } }