fix/initial-fonts-loading #35
@@ -14,15 +14,19 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
type FontLoadRequestConfig,
|
||||
type UnifiedFont,
|
||||
appliedFontsManager,
|
||||
fetchFontsByIds,
|
||||
fontStore,
|
||||
getFontUrl,
|
||||
} from '$entities/Font';
|
||||
import {
|
||||
DEFAULT_TYPOGRAPHY_CONTROLS_DATA,
|
||||
createTypographyControlManager,
|
||||
} from '$features/SetupFont';
|
||||
import { createPersistentStore } from '$shared/lib';
|
||||
import { untrack } from 'svelte';
|
||||
|
||||
/**
|
||||
* Storage schema for comparison state
|
||||
@@ -70,8 +74,37 @@ export class ComparisonStore {
|
||||
constructor() {
|
||||
this.restoreFromStorage();
|
||||
|
||||
// Reactively set defaults if we aren't restoring and have no selection
|
||||
// Reactively handle font loading and default selection
|
||||
$effect.root(() => {
|
||||
// Effect 1: Trigger font loading whenever selection or weight changes
|
||||
$effect(() => {
|
||||
const fa = this.#fontA;
|
||||
const fb = this.#fontB;
|
||||
const weight = this.#typography.weight;
|
||||
|
||||
if (!fa || !fb) return;
|
||||
|
||||
const configs: FontLoadRequestConfig[] = [];
|
||||
[fa, fb].forEach(f => {
|
||||
const url = getFontUrl(f, weight);
|
||||
if (url) {
|
||||
configs.push({
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
weight,
|
||||
url,
|
||||
isVariable: f.features?.isVariable,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (configs.length > 0) {
|
||||
appliedFontsManager.touch(configs);
|
||||
this.#checkFontsLoaded();
|
||||
}
|
||||
});
|
||||
|
||||
// Effect 2: Set defaults if we aren't restoring and have no selection
|
||||
$effect(() => {
|
||||
// Wait until we are done checking storage
|
||||
if (this.#isRestoring) {
|
||||
@@ -80,24 +113,41 @@ export class ComparisonStore {
|
||||
|
||||
// If we already have a selection, do nothing
|
||||
if (this.#fontA && this.#fontB) {
|
||||
this.#checkFontsLoaded();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if fonts are available to set as defaults
|
||||
const fonts = fontStore.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();
|
||||
// We need full objects with all URLs, so we trigger a batch fetch
|
||||
// This is the "batch request" seen on initial load when storage is empty
|
||||
untrack(() => {
|
||||
this.restoreDefaults([fonts[0].id, fonts[fonts.length - 1].id]);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default fonts by fetching full objects from the API
|
||||
*/
|
||||
private async restoreDefaults(ids: string[]) {
|
||||
this.#isRestoring = true;
|
||||
try {
|
||||
const fullFonts = await fetchFontsByIds(ids);
|
||||
if (fullFonts.length >= 2) {
|
||||
this.#fontA = fullFonts[0];
|
||||
this.#fontB = fullFonts[1];
|
||||
this.updateStorage();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[ComparisonStore] Failed to set defaults:', error);
|
||||
} finally {
|
||||
this.#isRestoring = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if fonts are actually loaded in the browser at current weight
|
||||
*
|
||||
|
||||
@@ -26,6 +26,12 @@ import {
|
||||
vi.mock('$entities/Font', () => ({
|
||||
fetchFontsByIds: vi.fn(),
|
||||
fontStore: { fonts: [] },
|
||||
appliedFontsManager: {
|
||||
touch: vi.fn(),
|
||||
getFontStatus: vi.fn(),
|
||||
ready: vi.fn(() => Promise.resolve()),
|
||||
},
|
||||
getFontUrl: vi.fn(() => 'http://example.com/font.woff2'),
|
||||
}));
|
||||
|
||||
vi.mock('$features/SetupFont', () => ({
|
||||
|
||||
Reference in New Issue
Block a user