188 lines
4.9 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
}
|