feat(comparisonStore): add checkFontsLoading method to improve isLoading flag
This commit is contained in:
@@ -34,6 +34,7 @@ class ComparisonStore {
|
||||
#fontB = $state<UnifiedFont | undefined>();
|
||||
#sampleText = $state('The quick brown fox jumps over the lazy dog');
|
||||
#isRestoring = $state(true);
|
||||
#fontsReady = $state(false);
|
||||
#typography = createTypographyControlManager(DEFAULT_TYPOGRAPHY_CONTROLS_DATA, 'glyphdiff:comparison:typography');
|
||||
|
||||
constructor() {
|
||||
@@ -49,6 +50,7 @@ class ComparisonStore {
|
||||
|
||||
// If we already have a selection, do nothing
|
||||
if (this.#fontA && this.#fontB) {
|
||||
this.#checkFontsLoaded();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,6 +68,48 @@ class ComparisonStore {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if fonts are actually loaded in the browser at current weight.
|
||||
* Uses CSS Font Loading API to prevent FOUT.
|
||||
*/
|
||||
async #checkFontsLoaded() {
|
||||
if (!('fonts' in document)) {
|
||||
this.#fontsReady = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.#fontsReady = false;
|
||||
|
||||
const weight = this.#typography.weight;
|
||||
const size = this.#typography.renderedSize;
|
||||
const fontAName = this.#fontA?.name;
|
||||
const fontBName = this.#fontB?.name;
|
||||
|
||||
if (!fontAName || !fontBName) return;
|
||||
|
||||
try {
|
||||
// Step 1: Load fonts into memory
|
||||
await Promise.all([
|
||||
document.fonts.load(`${weight} ${size}px "${fontAName}"`),
|
||||
document.fonts.load(`${weight} ${size}px "${fontBName}"`),
|
||||
]);
|
||||
|
||||
// Step 2: Wait for browser to be ready to render
|
||||
await document.fonts.ready;
|
||||
|
||||
// Step 3: Force a layout/paint cycle (critical!)
|
||||
await new Promise(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(resolve); // Double rAF ensures paint completes
|
||||
});
|
||||
});
|
||||
|
||||
this.#fontsReady = true;
|
||||
} catch (error) {
|
||||
console.warn('[ComparisonStore] Font loading failed:', error);
|
||||
setTimeout(() => this.#fontsReady = true, 1000);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Restore state from persistent storage
|
||||
*/
|
||||
@@ -141,13 +185,12 @@ class ComparisonStore {
|
||||
* Check if both fonts are selected
|
||||
*/
|
||||
get isReady() {
|
||||
return !!this.#fontA && !!this.#fontB;
|
||||
return !!this.#fontA && !!this.#fontB && this.#fontsReady;
|
||||
}
|
||||
|
||||
get isLoading() {
|
||||
return this.#isRestoring;
|
||||
return this.#isRestoring || !this.#fontsReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public initializer (optional, as constructor starts it)
|
||||
* Kept for compatibility if manual re-init is needed
|
||||
|
||||
Reference in New Issue
Block a user