From d55967cca8785c7bb0ecdb33c66222fae120348f Mon Sep 17 00:00:00 2001 From: zipg Date: Sun, 28 Jun 2026 00:32:11 +0800 Subject: [PATCH] fix(canvas): fix premature text truncation in canvas grid cells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复 Canvas 单元格文本提前截断 * fix: 清理 Dremio 未使用连接 URL 判断 --------- Co-authored-by: staff --- .../connection/ConnectionDialog.vue | 5 ---- apps/desktop/src/components/grid/DataGrid.vue | 2 ++ .../desktop/src/lib/canvasDataGridRenderer.ts | 8 +++---- .../app-tests/canvasDataGridRenderer.test.ts | 23 +++++++++++++++++++ 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 packages/app-tests/canvasDataGridRenderer.test.ts diff --git a/apps/desktop/src/components/connection/ConnectionDialog.vue b/apps/desktop/src/components/connection/ConnectionDialog.vue index 8b45508da..b9b27c0f8 100644 --- a/apps/desktop/src/components/connection/ConnectionDialog.vue +++ b/apps/desktop/src/components/connection/ConnectionDialog.vue @@ -844,11 +844,6 @@ function dremioDefaultDriverClass(mode = dremioConnectionMode.value) { return mode === "legacy" ? DREMIO_LEGACY_JDBC_DRIVER_CLASS : DREMIO_ARROW_FLIGHT_SQL_JDBC_DRIVER_CLASS; } -function isDremioGeneratedDefaultConnectionUrl(value: string) { - const url = value.trim(); - return url === DREMIO_ARROW_FLIGHT_SQL_JDBC_URL || url === `${DREMIO_ARROW_FLIGHT_SQL_JDBC_URL}?useEncryption=false` || url === DREMIO_LEGACY_JDBC_URL; -} - function isDremioGeneratedDefaultDriverClass(value: string | undefined) { const driverClass = value?.trim() || ""; return !driverClass || driverClass === DREMIO_ARROW_FLIGHT_SQL_JDBC_DRIVER_CLASS || driverClass === DREMIO_LEGACY_JDBC_DRIVER_CLASS; diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index e4f50485b..b9ca3a094 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -4438,6 +4438,8 @@ const canvasDetailButtonCell = computed(() => { if (!useCanvasGridRows.value || isScrolling.value) return null; const target = hoveredDetailCell.value ?? quickDownloadMenuCell.value ?? (showCellDetail.value ? detailCell.value : null); if (!target || !cellDetailButtonVisible(target.rowIndex, target.col)) return null; + const editing = editingCell.value; + if (editing?.rowId === displayItems.value[target.rowIndex]?.id && editing.col === target.col) return null; const visibleColIdx = visibleColumnIndexes.value.indexOf(target.col); if (visibleColIdx < 0) return null; const rect = canvasCellViewportRect(target.rowIndex, visibleColIdx); diff --git a/apps/desktop/src/lib/canvasDataGridRenderer.ts b/apps/desktop/src/lib/canvasDataGridRenderer.ts index 16684f16e..a716633fc 100644 --- a/apps/desktop/src/lib/canvasDataGridRenderer.ts +++ b/apps/desktop/src/lib/canvasDataGridRenderer.ts @@ -93,7 +93,7 @@ export function clearFitCanvasTextCache(): void { fitCanvasTextCache.clear(); } -function fitCanvasText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number): string { +export function fitCanvasText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number): string { if (maxWidth <= 0) return ""; const font = ctx.font; const cacheKey = `${font}|${text}|${maxWidth}`; @@ -367,12 +367,10 @@ export function drawCanvasDataGrid(options: DrawCanvasDataGridOptions) { ctx.font = value === null ? italicFont : tabularFont; setCanvasNumericVariant(ctx, value === null ? "normal" : "tabular-nums"); const textLeft = alignCanvasPixel(x + 12, dpr); - const paddedMaxWidth = Math.max(0, x + colWidth - textLeft - 12); + const textMaxWidth = Math.max(0, x + colWidth - textLeft - 12); const isEditingThisCell = editingCell?.rowId === item.id && editingCell.col === actualColIdx; const displayText = isEditingThisCell ? "" : formatCell(value, actualColIdx); - const needsTruncation = ctx.measureText(displayText).width > paddedMaxWidth; - const textMaxWidth = needsTruncation ? Math.max(0, x + colWidth - textLeft) : paddedMaxWidth; - const text = isEditingThisCell ? displayText : fitCanvasText(ctx, displayText, textMaxWidth - 12); + const text = isEditingThisCell ? displayText : fitCanvasText(ctx, displayText, textMaxWidth); ctx.fillText(text, textLeft, textY); if (item.isDeleted && text) { const textWidth = Math.min(ctx.measureText(text).width, textMaxWidth); diff --git a/packages/app-tests/canvasDataGridRenderer.test.ts b/packages/app-tests/canvasDataGridRenderer.test.ts new file mode 100644 index 000000000..1a778d850 --- /dev/null +++ b/packages/app-tests/canvasDataGridRenderer.test.ts @@ -0,0 +1,23 @@ +import { strict as assert } from "node:assert"; +import { test } from "vitest"; +import { fitCanvasText } from "../../apps/desktop/src/lib/canvasDataGridRenderer.ts"; + +function measureContext(charWidth = 1): CanvasRenderingContext2D { + return { + font: "13px sans-serif", + measureText: (text: string) => ({ width: text.length * charWidth }), + } as CanvasRenderingContext2D; +} + +test("fitCanvasText keeps text that fits the available cell width", () => { + const ctx = measureContext(); + const text = "1234567890abcdefghijklmnopqrst"; + + assert.equal(fitCanvasText(ctx, text, text.length), text); +}); + +test("fitCanvasText truncates only when text exceeds the available cell width", () => { + const ctx = measureContext(); + + assert.equal(fitCanvasText(ctx, "1234567890", 8), "12345..."); +});