refactor(Font): rename fontStore and appliedFontsManager

Both names were vague or overloaded:

- fontStore / FontStore -> fontCatalogStore / FontCatalogStore
  Three font-related stores live in this slice; the new name names the
  paginated catalog specifically.

- appliedFontsManager / AppliedFontsManager -> fontLifecycleManager /
  FontLifecycleManager
  "Applied" collided with the filter-side appliedFilterStore (different
  meaning). The class actually orchestrates a load-use-evict lifecycle
  with FontBufferCache + FontEvictionPolicy + FontLoadQueue
  collaborators, so "Manager" is justified. Companion types file moved
  alongside (appliedFonts.ts -> fontLifecycle.ts).

Directories, file basenames, factory (createFontStore ->
createFontCatalogStore), and the AppliedFontsManagerDeps interface all
renamed. All consumers (ComparisonView, SampleList, FontList,
FontApplicator, FontVirtualList, FilterAndSortFonts bindings,
createFontRowSizeResolver, mocks) updated.
This commit is contained in:
Ilia Mashkov
2026-05-24 20:00:43 +03:00
parent 07d044f4d6
commit 728380498b
38 changed files with 105 additions and 105 deletions
@@ -16,8 +16,8 @@
import {
type FontLoadRequestConfig,
type UnifiedFont,
appliedFontsManager,
fontStore,
fontCatalogStore,
fontLifecycleManager,
getFontUrl,
} from '$entities/Font';
import { typographySettingsStore } from '$features/AdjustTypography/model';
@@ -140,7 +140,7 @@ export class ComparisonStore {
});
if (configs.length > 0) {
appliedFontsManager.touch(configs);
fontLifecycleManager.touch(configs);
this.#checkFontsLoaded();
}
});
@@ -151,7 +151,7 @@ export class ComparisonStore {
return;
}
const fonts = fontStore.fonts;
const fonts = fontCatalogStore.fonts;
if (fonts.length >= 2) {
untrack(() => {
const id1 = fonts[0].id;
@@ -168,17 +168,17 @@ export class ComparisonStore {
const fb = this.#fontB;
const w = typographySettingsStore.weight;
if (fa) {
appliedFontsManager.pin(fa.id, w, fa.features?.isVariable);
fontLifecycleManager.pin(fa.id, w, fa.features?.isVariable);
}
if (fb) {
appliedFontsManager.pin(fb.id, w, fb.features?.isVariable);
fontLifecycleManager.pin(fb.id, w, fb.features?.isVariable);
}
return () => {
if (fa) {
appliedFontsManager.unpin(fa.id, w, fa.features?.isVariable);
fontLifecycleManager.unpin(fa.id, w, fa.features?.isVariable);
}
if (fb) {
appliedFontsManager.unpin(fb.id, w, fb.features?.isVariable);
fontLifecycleManager.unpin(fb.id, w, fb.features?.isVariable);
}
};
});
@@ -55,8 +55,8 @@ vi.mock('$entities/Font', async importOriginal => {
const actual = await importOriginal<typeof import('$entities/Font')>();
return {
...actual,
fontStore: { fonts: [] },
appliedFontsManager: {
fontCatalogStore: { fonts: [] },
fontLifecycleManager: {
touch: vi.fn(),
pin: vi.fn(),
unpin: vi.fn(),
@@ -85,8 +85,8 @@ vi.mock('$features/AdjustTypography/model', () => ({
}));
import {
appliedFontsManager,
fontStore,
fontCatalogStore,
fontLifecycleManager,
} from '$entities/Font';
import * as proxyFonts from '$entities/Font/api/proxy/proxyFonts';
import { ComparisonStore } from './comparisonStore.svelte';
@@ -100,7 +100,7 @@ describe('ComparisonStore', () => {
vi.clearAllMocks();
mockStorage._value = { fontAId: null, fontBId: null };
mockStorage._clear.mockClear();
(fontStore as any).fonts = [];
(fontCatalogStore as any).fonts = [];
// Default: fetchFontsByIds returns empty so tests that don't care don't hang
vi.spyOn(proxyFonts, 'fetchFontsByIds').mockResolvedValue([]);
@@ -155,7 +155,7 @@ describe('ComparisonStore', () => {
describe('Default Fallbacks', () => {
it('should update storage with default IDs when storage is empty', async () => {
(fontStore as any).fonts = [mockFontA, mockFontB];
(fontCatalogStore as any).fonts = [mockFontA, mockFontB];
vi.spyOn(proxyFonts, 'fetchFontsByIds').mockResolvedValue([mockFontA, mockFontB]);
new ComparisonStore();
@@ -212,12 +212,12 @@ describe('ComparisonStore', () => {
new ComparisonStore();
await vi.waitFor(() => {
expect(appliedFontsManager.pin).toHaveBeenCalledWith(
expect(fontLifecycleManager.pin).toHaveBeenCalledWith(
mockFontA.id,
400,
mockFontA.features?.isVariable,
);
expect(appliedFontsManager.pin).toHaveBeenCalledWith(
expect(fontLifecycleManager.pin).toHaveBeenCalledWith(
mockFontB.id,
400,
mockFontB.features?.isVariable,
@@ -238,12 +238,12 @@ describe('ComparisonStore', () => {
store.fontA = mockFontC;
await vi.waitFor(() => {
expect(appliedFontsManager.unpin).toHaveBeenCalledWith(
expect(fontLifecycleManager.unpin).toHaveBeenCalledWith(
mockFontA.id,
400,
mockFontA.features?.isVariable,
);
expect(appliedFontsManager.pin).toHaveBeenCalledWith(
expect(fontLifecycleManager.pin).toHaveBeenCalledWith(
mockFontC.id,
400,
mockFontC.features?.isVariable,
@@ -9,8 +9,8 @@ import {
FontVirtualList,
type UnifiedFont,
VIRTUAL_INDEX_NOT_LOADED,
appliedFontsManager,
fontStore,
fontCatalogStore,
fontLifecycleManager,
} from '$entities/Font';
import { getSkeletonWidth } from '$shared/lib/utils';
import {
@@ -36,7 +36,7 @@ function getVirtualIndex(fontId: string | undefined): number {
if (!fontId) {
return -1;
}
const idx = fontStore.fonts.findIndex(f => f.id === fontId);
const idx = fontCatalogStore.fonts.findIndex(f => f.id === fontId);
if (idx === -1) {
return VIRTUAL_INDEX_NOT_LOADED;
}
@@ -77,11 +77,11 @@ function handleSelect(font: UnifiedFont) {
/**
* Returns true once the font file is loaded (or errored) and safe to render.
* Called inside the template — Svelte 5 tracks the $state reads inside
* appliedFontsManager.getFontStatus(), so each row re-renders reactively
* fontLifecycleManager.getFontStatus(), so each row re-renders reactively
* when its file arrives.
*/
function isFontReady(font: UnifiedFont): boolean {
const status = appliedFontsManager.getFontStatus(
const status = fontLifecycleManager.getFontStatus(
font.id,
DEFAULT_FONT_WEIGHT,
font.features?.isVariable,
@@ -2,7 +2,7 @@
Component: Search
Typeface search input for the comparison view.
Writes through appliedFilterStore; the global bridge in $features/FilterAndSortFonts
propagates the value into fontStore.
propagates the value into fontCatalogStore.
-->
<script lang="ts">
import { appliedFilterStore } from '$features/FilterAndSortFonts';
@@ -7,9 +7,9 @@
<script lang="ts">
import {
FontVirtualList,
appliedFontsManager,
createFontRowSizeResolver,
fontStore,
fontCatalogStore,
fontLifecycleManager,
} from '$entities/Font';
import {
TypographyMenu,
@@ -57,17 +57,17 @@ const checkPosition = throttle(() => {
}, 100);
// Resolver recreated when typography values change. The returned closure reads
// appliedFontsManager.statuses (a SvelteMap) on every call, so any font status
// fontLifecycleManager.statuses (a SvelteMap) on every call, so any font status
// change triggers a full offsets recompute in createVirtualizer — no DOM snap.
const fontRowHeight = $derived.by(() =>
createFontRowSizeResolver({
getFonts: () => fontStore.fonts,
getFonts: () => fontCatalogStore.fonts,
getWeight: () => typographySettingsStore.weight,
getPreviewText: () => text,
getContainerWidth: () => containerWidth,
getFontSizePx: () => typographySettingsStore.renderedSize,
getLineHeightPx: () => typographySettingsStore.height * typographySettingsStore.renderedSize,
getStatus: key => appliedFontsManager.statuses.get(key),
getStatus: key => fontLifecycleManager.statuses.get(key),
contentHorizontalPadding: SAMPLER_CONTENT_PADDING_X,
chromeHeight: SAMPLER_CHROME_HEIGHT,
fallbackHeight: SAMPLER_FALLBACK_HEIGHT,
@@ -4,7 +4,7 @@
-->
<script lang="ts">
import { NavigationWrapper } from '$entities/Breadcrumb';
import { fontStore } from '$entities/Font';
import { fontCatalogStore } from '$entities/Font';
import type { ResponsiveManager } from '$shared/lib';
import { cn } from '$shared/lib';
import {
@@ -36,7 +36,7 @@ const responsive = getContext<ResponsiveManager>('responsive');
id="sample_set"
title="Sample Set"
headerTitle="visual_output"
headerSubtitle="items_total: {fontStore.pagination.total ?? 0}"
headerSubtitle="items_total: {fontCatalogStore.pagination.total ?? 0}"
headerAction={registerAction}
>
{#snippet headerContent()}