feat(comparisonStore): replace displayStore with comparisonStore that has only the logic related to ComparisonSlider
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
export { displayedFontsStore } from './store';
|
|
||||||
@@ -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<UnifiedFont | undefined>(undefined);
|
|
||||||
|
|
||||||
#fontB = $state<UnifiedFont | undefined>(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();
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { displayedFontsStore } from './displayedFontsStore.svelte';
|
|
||||||
@@ -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<ComparisonState>('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<UnifiedFont | undefined>();
|
||||||
|
#fontB = $state<UnifiedFont | undefined>();
|
||||||
|
#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();
|
||||||
Reference in New Issue
Block a user