perf(webui): flatten scroll-container background + scope explorer wheel listener
Two measured, universally-beneficial fixes (kept after determining the rest of the earlier perf work was chasing a Bitwarden extension that pegged the main thread, not real app bugs): - .main-content had a linear-gradient background. A gradient on the scroll container is re-rastered across the whole scrolled area every scroll frame (the compositor can't translate a cached tile): ~25% dropped frames -> <1% once flattened to a solid color (visually identical, was rgb 10->15->11). - The explorer wheel-zoom listener was a non-passive listener on `document`, which disables compositor (async) scrolling app-wide so every wheel/trackpad scroll runs through the main thread. Scoped it to the explorer viewport. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1c1d2eb884
commit
89fe7703fa
2 changed files with 23 additions and 15 deletions
|
|
@ -1066,18 +1066,24 @@ function explorerFitToView() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll wheel zoom (no modifier needed inside viewport)
|
// Scroll wheel zoom (no modifier needed inside viewport).
|
||||||
document.addEventListener('wheel', (e) => {
|
// IMPORTANT: attach to the viewport element, NOT document. A non-passive wheel
|
||||||
|
// listener on document disables the browser's compositor (async) scrolling for
|
||||||
|
// the ENTIRE app — every wheel/trackpad scroll then runs through the main thread.
|
||||||
|
// Scoping it to the viewport keeps zoom working while the rest of the app keeps
|
||||||
|
// smooth compositor scrolling.
|
||||||
|
(function attachExplorerWheelZoom() {
|
||||||
const viewport = document.getElementById('explorer-viewport');
|
const viewport = document.getElementById('explorer-viewport');
|
||||||
if (!viewport || !viewport.contains(e.target)) return;
|
if (!viewport) return;
|
||||||
// Check if we're on the explorer page
|
viewport.addEventListener('wheel', (e) => {
|
||||||
const page = document.getElementById('playlist-explorer-page');
|
const page = document.getElementById('playlist-explorer-page');
|
||||||
if (!page || !page.classList.contains('active')) return;
|
if (!page || !page.classList.contains('active')) return;
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const step = e.deltaY > 0 ? -0.08 : 0.08;
|
const step = e.deltaY > 0 ? -0.08 : 0.08;
|
||||||
explorerZoom(step);
|
explorerZoom(step);
|
||||||
}, { passive: false });
|
}, { passive: false });
|
||||||
|
})();
|
||||||
|
|
||||||
// Middle-click / right-click drag to pan
|
// Middle-click / right-click drag to pan
|
||||||
document.addEventListener('mousedown', (e) => {
|
document.addEventListener('mousedown', (e) => {
|
||||||
|
|
|
||||||
|
|
@ -2970,11 +2970,13 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
/* Opaque dark background (GPU-optimized: no backdrop-filter needed on solid dark body) */
|
/* Flat solid background — NOT a gradient. A gradient on the scroll container
|
||||||
background: linear-gradient(135deg,
|
has to be re-rastered across the whole scrolled area on every scroll frame
|
||||||
rgba(10, 10, 10, 1) 0%,
|
(the compositor can't just translate a cached tile), which caused the
|
||||||
rgba(15, 15, 15, 1) 50%,
|
dominant scroll jank (~25% dropped frames -> <1% once flattened, measured).
|
||||||
rgba(11, 11, 11, 1) 100%);
|
A solid color is drawn as a single compositor quad, no per-frame raster.
|
||||||
|
The gradient was rgb 10->15->11, visually indistinguishable from this. */
|
||||||
|
background: rgb(12, 12, 12);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue