fix/initial-fonts-loading #35
@@ -1,3 +1,4 @@
|
|||||||
export * from './api';
|
export * from './api';
|
||||||
|
export * from './lib';
|
||||||
export * from './model';
|
export * from './model';
|
||||||
export * from './ui';
|
export * from './ui';
|
||||||
|
|||||||
@@ -14,15 +14,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type FontLoadRequestConfig,
|
||||||
type UnifiedFont,
|
type UnifiedFont,
|
||||||
|
appliedFontsManager,
|
||||||
fetchFontsByIds,
|
fetchFontsByIds,
|
||||||
fontStore,
|
fontStore,
|
||||||
|
getFontUrl,
|
||||||
} from '$entities/Font';
|
} from '$entities/Font';
|
||||||
import {
|
import {
|
||||||
DEFAULT_TYPOGRAPHY_CONTROLS_DATA,
|
DEFAULT_TYPOGRAPHY_CONTROLS_DATA,
|
||||||
createTypographyControlManager,
|
createTypographyControlManager,
|
||||||
} from '$features/SetupFont';
|
} from '$features/SetupFont';
|
||||||
import { createPersistentStore } from '$shared/lib';
|
import { createPersistentStore } from '$shared/lib';
|
||||||
|
import { untrack } from 'svelte';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage schema for comparison state
|
* Storage schema for comparison state
|
||||||
@@ -70,8 +74,37 @@ export class ComparisonStore {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.restoreFromStorage();
|
this.restoreFromStorage();
|
||||||
|
|
||||||
// Reactively set defaults if we aren't restoring and have no selection
|
// Reactively handle font loading and default selection
|
||||||
$effect.root(() => {
|
$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(() => {
|
$effect(() => {
|
||||||
// Wait until we are done checking storage
|
// Wait until we are done checking storage
|
||||||
if (this.#isRestoring) {
|
if (this.#isRestoring) {
|
||||||
@@ -80,24 +113,41 @@ export class ComparisonStore {
|
|||||||
|
|
||||||
// If we already have a selection, do nothing
|
// If we already have a selection, do nothing
|
||||||
if (this.#fontA && this.#fontB) {
|
if (this.#fontA && this.#fontB) {
|
||||||
this.#checkFontsLoaded();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if fonts are available to set as defaults
|
// Check if fonts are available to set as defaults
|
||||||
const fonts = fontStore.fonts;
|
const fonts = fontStore.fonts;
|
||||||
if (fonts.length >= 2) {
|
if (fonts.length >= 2) {
|
||||||
// Only set if we really have nothing (fallback)
|
// We need full objects with all URLs, so we trigger a batch fetch
|
||||||
if (!this.#fontA) this.#fontA = fonts[0];
|
// This is the "batch request" seen on initial load when storage is empty
|
||||||
if (!this.#fontB) this.#fontB = fonts[fonts.length - 1];
|
untrack(() => {
|
||||||
|
this.restoreDefaults([fonts[0].id, fonts[fonts.length - 1].id]);
|
||||||
// Sync defaults to storage so they persist if the user leaves
|
});
|
||||||
this.updateStorage();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Checks if fonts are actually loaded in the browser at current weight
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ import {
|
|||||||
vi.mock('$entities/Font', () => ({
|
vi.mock('$entities/Font', () => ({
|
||||||
fetchFontsByIds: vi.fn(),
|
fetchFontsByIds: vi.fn(),
|
||||||
fontStore: { fonts: [] },
|
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', () => ({
|
vi.mock('$features/SetupFont', () => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user