From d02c8d281a7e76cd9182ef04f0e43694376eab5d Mon Sep 17 00:00:00 2001 From: patrick Date: Wed, 13 May 2026 18:12:21 -0400 Subject: [PATCH] feat: add pipeline store - Global pipeline configuration - Built-in and user presets - localStorage persistence - Preset CRUD operations Co-Authored-By: Claude --- src/lib/stores/pipeline.svelte.ts | 156 ++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/lib/stores/pipeline.svelte.ts diff --git a/src/lib/stores/pipeline.svelte.ts b/src/lib/stores/pipeline.svelte.ts new file mode 100644 index 0000000..08aacf7 --- /dev/null +++ b/src/lib/stores/pipeline.svelte.ts @@ -0,0 +1,156 @@ +import { + type PipelineConfig, + type PipelinePreset, + DEFAULT_PIPELINE_CONFIG, + BUILT_IN_PRESETS, + clonePipelineConfig +} from '$lib/types'; + +const STORAGE_KEY = '2eink-pipeline-presets'; + +function createPipelineStore() { + let globalConfig = $state(clonePipelineConfig(DEFAULT_PIPELINE_CONFIG)); + let selectedPresetId = $state('default'); + let userPresets = $state([]); + + const allPresets = $derived([...BUILT_IN_PRESETS, ...userPresets]); + + const selectedPreset = $derived( + allPresets.find((p) => p.id === selectedPresetId) ?? null + ); + + const isModified = $derived(() => { + if (!selectedPreset) return true; + return JSON.stringify(globalConfig) !== JSON.stringify(selectedPreset.config); + }); + + function loadPresets(): void { + if (typeof window === 'undefined') return; + try { + const stored = localStorage.getItem(STORAGE_KEY); + if (stored) { + userPresets = JSON.parse(stored); + } + } catch { + console.warn('Failed to load pipeline presets'); + } + } + + function savePresets(): void { + if (typeof window === 'undefined') return; + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(userPresets)); + } catch { + console.warn('Failed to save pipeline presets'); + } + } + + function selectPreset(presetId: string): void { + const preset = allPresets.find((p) => p.id === presetId); + if (preset) { + globalConfig = clonePipelineConfig(preset.config); + selectedPresetId = presetId; + } + } + + function updateConfig(updates: Partial): void { + globalConfig = { ...globalConfig, ...updates }; + } + + function updateStep( + step: K, + updates: Partial + ): void { + globalConfig = { + ...globalConfig, + [step]: { ...globalConfig[step], ...updates } + }; + } + + function saveAsPreset(name: string): PipelinePreset { + const id = `user-${Date.now()}`; + const preset: PipelinePreset = { + id, + name, + config: clonePipelineConfig(globalConfig), + isBuiltIn: false + }; + + userPresets = [...userPresets, preset]; + selectedPresetId = id; + savePresets(); + + return preset; + } + + function updatePreset(presetId: string): void { + const index = userPresets.findIndex((p) => p.id === presetId); + if (index === -1) return; + + userPresets = userPresets.map((p) => + p.id === presetId ? { ...p, config: clonePipelineConfig(globalConfig) } : p + ); + savePresets(); + } + + function deletePreset(presetId: string): void { + const preset = userPresets.find((p) => p.id === presetId); + if (!preset || preset.isBuiltIn) return; + + userPresets = userPresets.filter((p) => p.id !== presetId); + if (selectedPresetId === presetId) { + selectPreset('default'); + } + savePresets(); + } + + function renamePreset(presetId: string, newName: string): void { + userPresets = userPresets.map((p) => (p.id === presetId ? { ...p, name: newName } : p)); + savePresets(); + } + + function resetToDefault(): void { + selectPreset('default'); + } + + function getEffectiveConfig(imageOverride: PipelineConfig | null): PipelineConfig { + return imageOverride ?? globalConfig; + } + + if (typeof window !== 'undefined') { + loadPresets(); + } + + return { + get globalConfig() { + return globalConfig; + }, + get selectedPresetId() { + return selectedPresetId; + }, + get selectedPreset() { + return selectedPreset; + }, + get allPresets() { + return allPresets; + }, + get userPresets() { + return userPresets; + }, + get isModified() { + return isModified; + }, + selectPreset, + updateConfig, + updateStep, + saveAsPreset, + updatePreset, + deletePreset, + renamePreset, + resetToDefault, + getEffectiveConfig, + loadPresets + }; +} + +export const pipelineStore = createPipelineStore();