Files
bitfielder/src/Storage.ts

188 lines
4.9 KiB
TypeScript

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<AppSettings>
): 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<AppSettings>): 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;
}
}
}