From 8bf4485a758327e0f0630de5e083482940790ce6 Mon Sep 17 00:00:00 2001 From: Melody Ruch <396921921@qq.com> Date: Sat, 15 Aug 2026 14:45:41 +0800 Subject: [PATCH] fix(grid): remeasure headers after configured font loads --- apps/desktop/src/components/grid/DataGrid.vue | 23 ++++++++++++++++++- .../app-tests/dataGridFontSettings.test.ts | 7 +++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 1745eb406f..24b783c429 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -2097,9 +2097,30 @@ const columnWidthDensity = computed(() => settingsStore.editorSettings.columnWid const tableFontFamily = computed(() => settingsStore.editorSettings.tableFontFamily); const columnWidthCacheKey = computed(() => props.cacheKey?.trim() || undefined); const columnStructureSignature = computed(() => createDataGridColumnStructureSignature(props.result.columns, props.result.column_types)); -const columnHeaderMeasurementKey = computed(() => [tableFontSize.value, tableFontFamily.value]); +// Bumped once the configured header font is ready, so widths measured against a temporary fallback +// font get re-measured without reacting to unrelated fonts loaded elsewhere in the application. +const dataGridFontReadyTick = ref(0); +const columnHeaderMeasurementKey = computed(() => [tableFontSize.value, tableFontFamily.value, dataGridFontReadyTick.value]); let columnHeaderMeasureContext: CanvasRenderingContext2D | null | undefined; +if (typeof document !== "undefined" && document.fonts) { + let fontLoadRequestId = 0; + watch( + [tableFontSize, tableFontFamily], + async ([fontSize, fontFamily]) => { + const requestId = ++fontLoadRequestId; + try { + await document.fonts.load(`600 ${fontSize}px ${fontFamily}`); + } catch { + return; + } + if (requestId === fontLoadRequestId) dataGridFontReadyTick.value++; + }, + { immediate: true }, + ); + onUnmounted(() => fontLoadRequestId++); +} + function measureColumnHeaderText(text: string): number | undefined { if (typeof document === "undefined") return undefined; if (columnHeaderMeasureContext === undefined) columnHeaderMeasureContext = document.createElement("canvas").getContext("2d"); diff --git a/packages/app-tests/dataGridFontSettings.test.ts b/packages/app-tests/dataGridFontSettings.test.ts index de2bb8ae55..e7af36580f 100644 --- a/packages/app-tests/dataGridFontSettings.test.ts +++ b/packages/app-tests/dataGridFontSettings.test.ts @@ -14,11 +14,16 @@ test("applies the configured result grid font to DOM and canvas renderers", () = }); test("invalidates grid measurements and canvas rendering when the result font changes", () => { - assert.match(dataGridSource, /columnHeaderMeasurementKey = computed\(\(\) => \[tableFontSize\.value, tableFontFamily\.value\]\)/); + assert.match(dataGridSource, /columnHeaderMeasurementKey = computed\(\(\) => \[tableFontSize\.value, tableFontFamily\.value, dataGridFontReadyTick\.value\]\)/); assert.match(dataGridSource, /columnHeaderMeasureContext\.font = `600 \$\{tableFontSize\.value\}px \$\{tableFontFamily\.value\}`/); assert.match(dataGridSource, /canvasRenderStyleKey = computed\(\(\) => `[^`]*\$\{tableFontFamily\.value\}:\$\{tableFontSize\.value\}:\$\{!!saveError\.value\}`\)/); }); +test("waits only for the configured result font before remeasuring headers", () => { + assert.match(dataGridSource, /document\.fonts\.load\(`600 \$\{fontSize\}px \$\{fontFamily\}`\)/); + assert.doesNotMatch(dataGridSource, /document\.fonts\.addEventListener\("loadingdone"/); +}); + test("places the result grid font beside the interface font in appearance settings", () => { const editorSectionStart = settingsDialogSource.indexOf(`activeSettingsTab === 'editor'`); const appearanceSectionStart = settingsDialogSource.indexOf(`activeSettingsTab === 'appearance'`);