refactor: extract magic constants — wave 3 (font lifecycle)

Promote font-loading scheduling and lifecycle tunables to named
module-level constants:

- comparisonStore: FONT_READY_FALLBACK_MS (1000ms) — UI unblock safety net
- fontLifecycleManager:
  - PURGE_INTERVAL_MS (60000) — periodic eviction sweep
  - IDLE_CALLBACK_TIMEOUT_MS (150) — requestIdleCallback timeout
  - SCHEDULE_FALLBACK_MS (16) — setTimeout fallback (~60fps)
  - YIELD_INTERVAL_MS (8) — parse-loop yield budget for non-Chromium
  - CRITICAL_FONT_WEIGHTS ([400, 700]) — data-saver allowlist
- FontEvictionPolicy: DEFAULT_FONT_TTL_MS (5 minutes)
- FontLoadQueue: FONT_LOAD_MAX_RETRIES (3)

No behavior changes — values preserved exactly. Class-private fields
that mirrored these constants are removed in favor of module scope.
This commit is contained in:
Ilia Mashkov
2026-05-24 21:13:38 +03:00
parent ccef3cf7bb
commit 2bb43797f0
4 changed files with 56 additions and 14 deletions
@@ -44,6 +44,13 @@ export type Side = 'A' | 'B';
const STORAGE_KEY = 'glyphdiff:comparison';
/**
* Max time the UI waits after a font-load failure before unblocking
* (#fontsReady = true). Acts as a safety net so a transient load error
* can't strand the comparison view in a permanent loading state.
*/
const FONT_READY_FALLBACK_MS = 1000;
// Persistent storage for selected comparison fonts
const storage = createPersistentStore<ComparisonState>(STORAGE_KEY, {
fontAId: null,
@@ -236,7 +243,7 @@ export class ComparisonStore {
this.#fontsReady = true;
} catch (error) {
console.warn('[ComparisonStore] Font loading failed:', error);
setTimeout(() => (this.#fontsReady = true), 1000);
setTimeout(() => (this.#fontsReady = true), FONT_READY_FALLBACK_MS);
}
}