From ce319d8436425f665f69a177be82ac1929c4ef2b Mon Sep 17 00:00:00 2001 From: OA Hsiao Date: Tue, 23 Jun 2026 17:29:11 +0800 Subject: [PATCH] perf(analysis): virtualize the LOG viewer (render only visible lines) Opening was already fixed (single-insert), but an 80k-line log still kept ~250k DOM nodes, so scrolling and especially drag-selecting text lagged hard (selecting across content-visibility lines forces them all to lay out, which could lock up the renderer). Render only the lines near the viewport: a fixed-height window with top/bottom spacer divs holding the off-screen height; the rest never enter the DOM. The features that assumed every line was in the DOM are routed through the lines array + a windowed anaLineEl(idx): scroll-to-line, current line, bookmarks, find highlights, copy, line click. Markers for the minimap/levels are still scanned across all lines once (~45ms for 82k). content-visibility is removed. The viewer is now always nowrap (long lines scroll horizontally) because virtualization needs a fixed line height, so the word-wrap toggle button and its code/i18n are removed. PgUp/PgDn focus fix: the scroller (#anaScroll), which is never rebuilt, is the keyboard-focus target (tabindex=-1, focused on open and on click), so paging and arrows keep working after the window re-renders. Measured on a real 82,576-line log: opening stays fast and scroll/selection are smooth; selection no longer locks up. --- src/renderer/css/styles.css | 12 +- src/renderer/i18n/en.json | 1 - src/renderer/i18n/zh.json | 1 - src/renderer/index.html | 5 +- src/renderer/js/app.js | 280 ++++++++++++++++++++---------------- 5 files changed, 160 insertions(+), 139 deletions(-) diff --git a/src/renderer/css/styles.css b/src/renderer/css/styles.css index d78e2a9..4e7d047 100644 --- a/src/renderer/css/styles.css +++ b/src/renderer/css/styles.css @@ -931,12 +931,6 @@ input[type="date"] { outline-offset: -1px; } -/* Active state for the viewer word-wrap toggle. */ -#btnAnaWrap.on { - color: var(--accent); - background: color-mix(in srgb, var(--accent) 14%, transparent); -} - .ana-row { display: flex; align-items: center; @@ -1014,6 +1008,7 @@ input[type="date"] { height: 100%; overflow: auto; padding-right: 38px; + outline: none; } .ana-scroll::-webkit-scrollbar { @@ -1269,11 +1264,6 @@ body.ana-ruler-dragging .ana-ruler-view { .ana-line { display: flex; align-items: flex-start; - /* Skip layout/paint work for off-screen lines so scrolling a large log stays - smooth. `auto` lets the browser remember each line's real height once seen, - keeping the scrollbar stable; ~20px matches the 12.5px/1.55 line-height. */ - content-visibility: auto; - contain-intrinsic-size: auto 20px; } .ana-line:hover { diff --git a/src/renderer/i18n/en.json b/src/renderer/i18n/en.json index 2cda65c..d669ab0 100644 --- a/src/renderer/i18n/en.json +++ b/src/renderer/i18n/en.json @@ -75,7 +75,6 @@ "ana.hl.auto": "Auto", "ana.hl.none": "Off", "ana.copy": "Copy", - "ana.wrap.title": "Toggle word wrap", "ana.zoomIn.title": "Zoom in (Ctrl +)", "ana.zoomOut.title": "Zoom out (Ctrl -)", "ana.ai": "AI", diff --git a/src/renderer/i18n/zh.json b/src/renderer/i18n/zh.json index 77a44b2..7e0e188 100644 --- a/src/renderer/i18n/zh.json +++ b/src/renderer/i18n/zh.json @@ -75,7 +75,6 @@ "ana.hl.auto": "自動", "ana.hl.none": "關閉", "ana.copy": "複製", - "ana.wrap.title": "切換自動換行", "ana.zoomIn.title": "放大字級 (Ctrl +)", "ana.zoomOut.title": "縮小字級 (Ctrl -)", "ana.ai": "AI", diff --git a/src/renderer/index.html b/src/renderer/index.html index 8911ecc..494d565 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -244,9 +244,6 @@

檔案

檢視

- @@ -297,7 +294,7 @@

檢視

-
+