diff --git a/src/features/DisplayFont/model/index.ts b/src/features/DisplayFont/model/index.ts deleted file mode 100644 index 5099f73..0000000 --- a/src/features/DisplayFont/model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { displayedFontsStore } from './store'; diff --git a/src/features/DisplayFont/model/store/displayedFontsStore.svelte.ts b/src/features/DisplayFont/model/store/displayedFontsStore.svelte.ts deleted file mode 100644 index e9d8b31..0000000 --- a/src/features/DisplayFont/model/store/displayedFontsStore.svelte.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { - type UnifiedFont, - selectedFontsStore, -} from '$entities/Font'; - -/** - * Store for displayed font samples - * - Handles shown text - * - Stores selected fonts for display - */ -export class DisplayedFontsStore { - #sampleText = $state('The quick brown fox jumps over the lazy dog'); - - #displayedFonts = $derived.by(() => { - return selectedFontsStore.all; - }); - - #fontA = $state(undefined); - - #fontB = $state(undefined); - - #hasAnySelectedFonts = $derived(this.#displayedFonts.length > 0); - - get fonts() { - return this.#displayedFonts; - } - - get fontA() { - return this.#fontA ?? this.#displayedFonts[0]; - } - - set fontA(font: UnifiedFont | undefined) { - this.#fontA = font; - } - - get fontB() { - return this.#fontB ?? this.#displayedFonts[1]; - } - - set fontB(font: UnifiedFont | undefined) { - this.#fontB = font; - } - - get text() { - return this.#sampleText; - } - - set text(text: string) { - this.#sampleText = text; - } - - get hasAnyFonts() { - return this.#hasAnySelectedFonts; - } - - getById(id: string): UnifiedFont | undefined { - return selectedFontsStore.getById(id); - } -} - -export const displayedFontsStore = new DisplayedFontsStore(); diff --git a/src/features/DisplayFont/model/store/index.ts b/src/features/DisplayFont/model/store/index.ts deleted file mode 100644 index 43bb021..0000000 --- a/src/features/DisplayFont/model/store/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { displayedFontsStore } from './displayedFontsStore.svelte'; diff --git a/src/widgets/ComparisonSlider/model/stores/comparisonStore.svelte.ts b/src/widgets/ComparisonSlider/model/stores/comparisonStore.svelte.ts new file mode 100644 index 0000000..503900f --- /dev/null +++ b/src/widgets/ComparisonSlider/model/stores/comparisonStore.svelte.ts @@ -0,0 +1,150 @@ +import { + type UnifiedFont, + fetchFontsByIds, + unifiedFontStore, +} from '$entities/Font'; +import { createPersistentStore } from '$shared/lib'; + +/** + * Storage schema for comparison state + */ +interface ComparisonState { + fontAId: string | null; + fontBId: string | null; +} + +// Persistent storage for selected comparison fonts +const storage = createPersistentStore('glyphdiff:comparison', { + fontAId: null, + fontBId: null, +}); + +/** + * Store for managing font comparison state + * - Persists selection to localStorage + * - Handles font fetching on initialization + * - Manages sample text + */ +class ComparisonStore { + #fontA = $state(); + #fontB = $state(); + #sampleText = $state('The quick brown fox jumps over the lazy dog'); + #isRestoring = $state(true); + + constructor() { + this.restoreFromStorage(); + + // Reactively set defaults if we aren't restoring and have no selection + $effect.root(() => { + $effect(() => { + // Wait until we are done checking storage + if (this.#isRestoring) { + return; + } + + // If we already have a selection, do nothing + if (this.#fontA && this.#fontB) { + return; + } + + // Check if fonts are available to set as defaults + const fonts = unifiedFontStore.fonts; + if (fonts.length >= 2) { + // Only set if we really have nothing (fallback) + if (!this.#fontA) this.#fontA = fonts[0]; + if (!this.#fontB) this.#fontB = fonts[fonts.length - 1]; + + // Sync defaults to storage so they persist if the user leaves + this.updateStorage(); + } + }); + }); + } + + /** + * Restore state from persistent storage + */ + async restoreFromStorage() { + this.#isRestoring = true; + const { fontAId, fontBId } = storage.value; + + if (fontAId && fontBId) { + try { + // Batch fetch the saved fonts + const fonts = await fetchFontsByIds([fontAId, fontBId]); + const loadedFontA = fonts.find((f: UnifiedFont) => f.id === fontAId); + const loadedFontB = fonts.find((f: UnifiedFont) => f.id === fontBId); + + if (loadedFontA && loadedFontB) { + this.#fontA = loadedFontA; + this.#fontB = loadedFontB; + } + } catch (error) { + console.warn('[ComparisonStore] Failed to restore fonts:', error); + } + } + + // Mark restoration as complete (whether success or fail) + this.#isRestoring = false; + } + + /** + * Update storage with current state + */ + private updateStorage() { + // Don't save if we are currently restoring (avoid race) + if (this.#isRestoring) return; + + storage.value = { + fontAId: this.#fontA?.id ?? null, + fontBId: this.#fontB?.id ?? null, + }; + } + + // --- Getters & Setters --- + + get fontA() { + return this.#fontA; + } + + set fontA(font: UnifiedFont | undefined) { + this.#fontA = font; + this.updateStorage(); + } + + get fontB() { + return this.#fontB; + } + + set fontB(font: UnifiedFont | undefined) { + this.#fontB = font; + this.updateStorage(); + } + + get text() { + return this.#sampleText; + } + + set text(value: string) { + this.#sampleText = value; + } + + /** + * Check if both fonts are selected + */ + get isReady() { + return !!this.#fontA && !!this.#fontB; + } + + /** + * Public initializer (optional, as constructor starts it) + * Kept for compatibility if manual re-init is needed + */ + initialize() { + if (!this.#isRestoring && !this.#fontA && !this.#fontB) { + this.restoreFromStorage(); + } + } +} + +export const comparisonStore = new ComparisonStore();