From 6187fe9388e70e9bd020e1c9d4e71d40251cde6f Mon Sep 17 00:00:00 2001 From: Daffie Date: Sat, 11 Jul 2026 04:28:41 +0000 Subject: [PATCH 1/4] Stop pausing the render loop and remove GPU layer hacks that hurt performance --- webui/src/lib/Universe.svelte | 33 +++++--------------------- webui/src/lib/components/Window.svelte | 8 +++---- 2 files changed, 9 insertions(+), 32 deletions(-) diff --git a/webui/src/lib/Universe.svelte b/webui/src/lib/Universe.svelte index 976fce2..7a8e7e5 100644 --- a/webui/src/lib/Universe.svelte +++ b/webui/src/lib/Universe.svelte @@ -63,16 +63,11 @@ let scale = initialScale; let targetScale = initialScale; - let tickerIdle = false; - let lastActivity = performance.now(); - const IDLE_TIMEOUT = 1200; - function wake() { - lastActivity = performance.now(); - if (tickerIdle && app) { - tickerIdle = false; - app.ticker.start(); - } - } + // the ticker used to stop entirely after a period of inactivity to save + // CPU, but starting/stopping it raced with PixiJS's resize handling and + // caused black rendering artifacts; keeping it always running is more + // reliable, so this is now a no-op kept for existing call sites + function wake() {} let velX = 0; let velY = 0; @@ -239,11 +234,7 @@ backgroundColor: 0x000000, antialias: false, resolution: window.devicePixelRatio * resLevels[resIndex], - autoDensity: true, - // keep the last rendered frame in the canvas buffer; without this the - // browser can discard it while the ticker is idle-paused, causing - // black flickering whenever the page recomposites - preserveDrawingBuffer: true + autoDensity: true }); container.appendChild(app.canvas); resButtonText = `res x${resLevels[resIndex]}`; @@ -1129,18 +1120,6 @@ fpsLast = now; } - const isAnimating = - flying || - inertiaActive || - Math.abs(scale - targetScale) > 1e-4 || - warps.length > 0 || - dragging; - if (isAnimating) { - lastActivity = now; - } else if (now - lastActivity > IDLE_TIMEOUT) { - tickerIdle = true; - app.ticker.stop(); - } }); }); diff --git a/webui/src/lib/components/Window.svelte b/webui/src/lib/components/Window.svelte index e1bd8eb..1b2b59a 100644 --- a/webui/src/lib/components/Window.svelte +++ b/webui/src/lib/components/Window.svelte @@ -283,8 +283,6 @@ font-family: var(--t-font-body); transform: scale(var(--ui-scale)); transform-origin: top left; - will-change: transform; - backface-visibility: hidden; } .panel :global(.unscaled) { transform: scale(calc(1 / var(--ui-scale))); @@ -295,9 +293,9 @@ .panel .body { overflow: auto; /* scrolling inside a scaled ancestor (.panel has transform: scale()) - makes Chromium/Firefox mis-rasterize tiles during scroll+resize, - showing up as black boxes; forcing its own compositing layer fixes it */ - will-change: transform; + can make Chromium/Firefox mis-rasterize tiles; contain: paint keeps + repaint scoped to this element instead of leaking into siblings */ + contain: paint; /* fill exactly the space left under the header so the bottom of the content is never clipped by the panel's overflow: hidden */ flex: 1 1 auto; From 4204a6c213000ba3bc9ca86db7e7a789c4afb212 Mon Sep 17 00:00:00 2001 From: Daffie Date: Sat, 11 Jul 2026 04:30:10 +0000 Subject: [PATCH 2/4] Revert compositing layer changes --- webui/src/lib/Universe.svelte | 27 +++++++++++++++++++++----- webui/src/lib/components/Window.svelte | 6 +----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/webui/src/lib/Universe.svelte b/webui/src/lib/Universe.svelte index 7a8e7e5..a5852f2 100644 --- a/webui/src/lib/Universe.svelte +++ b/webui/src/lib/Universe.svelte @@ -63,11 +63,16 @@ let scale = initialScale; let targetScale = initialScale; - // the ticker used to stop entirely after a period of inactivity to save - // CPU, but starting/stopping it raced with PixiJS's resize handling and - // caused black rendering artifacts; keeping it always running is more - // reliable, so this is now a no-op kept for existing call sites - function wake() {} + let tickerIdle = false; + let lastActivity = performance.now(); + const IDLE_TIMEOUT = 1200; + function wake() { + lastActivity = performance.now(); + if (tickerIdle && app) { + tickerIdle = false; + app.ticker.start(); + } + } let velX = 0; let velY = 0; @@ -1120,6 +1125,18 @@ fpsLast = now; } + const isAnimating = + flying || + inertiaActive || + Math.abs(scale - targetScale) > 1e-4 || + warps.length > 0 || + dragging; + if (isAnimating) { + lastActivity = now; + } else if (now - lastActivity > IDLE_TIMEOUT) { + tickerIdle = true; + app.ticker.stop(); + } }); }); diff --git a/webui/src/lib/components/Window.svelte b/webui/src/lib/components/Window.svelte index 1b2b59a..d9f8f0f 100644 --- a/webui/src/lib/components/Window.svelte +++ b/webui/src/lib/components/Window.svelte @@ -292,10 +292,6 @@ } .panel .body { overflow: auto; - /* scrolling inside a scaled ancestor (.panel has transform: scale()) - can make Chromium/Firefox mis-rasterize tiles; contain: paint keeps - repaint scoped to this element instead of leaking into siblings */ - contain: paint; /* fill exactly the space left under the header so the bottom of the content is never clipped by the panel's overflow: hidden */ flex: 1 1 auto; @@ -316,7 +312,7 @@ user-select: none; font-family: var(--t-font-mono); font-size: 0.78rem; - font-weight: 200; + font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase; color: var(--t-primary-text); From 7b81fe940e682e944b439c81af09f732b8cffb35 Mon Sep 17 00:00:00 2001 From: Daffie Date: Sat, 11 Jul 2026 04:44:20 +0000 Subject: [PATCH 3/4] Restore accent color, layout, and readability changes --- webui/src/app.css | 6 +++--- webui/src/lib/components/InfoPanel.svelte | 2 +- webui/src/lib/components/SearchPanel.svelte | 15 +++++++-------- webui/src/lib/components/SearchResults.svelte | 4 ---- webui/src/lib/components/TriPill.svelte | 1 - webui/src/lib/components/Window.svelte | 2 ++ webui/src/routes/+page.svelte | 2 +- 7 files changed, 14 insertions(+), 18 deletions(-) diff --git a/webui/src/app.css b/webui/src/app.css index 389522e..94fa9d1 100644 --- a/webui/src/app.css +++ b/webui/src/app.css @@ -7,9 +7,9 @@ --t-surface-high: #1e3350; --t-border: #345070; --t-text: #e3edff; - --t-text-dim: #b7cbe8; - --t-primary: #7c8bff; - --t-primary-text: #eceaff; + --t-text-dim: #f2f7ff; + --t-primary: #4fae82; + --t-primary-text: #d9f5e6; --t-on-primary: #0a0e2e; --t-secondary: #bcff5f; --t-error: #ff6b6b; diff --git a/webui/src/lib/components/InfoPanel.svelte b/webui/src/lib/components/InfoPanel.svelte index c5f7cf2..e9c4d20 100644 --- a/webui/src/lib/components/InfoPanel.svelte +++ b/webui/src/lib/components/InfoPanel.svelte @@ -67,7 +67,7 @@ } - + {#key JSON.stringify(info)} diff --git a/webui/src/lib/components/SearchPanel.svelte b/webui/src/lib/components/SearchPanel.svelte index dcffde1..8133412 100644 --- a/webui/src/lib/components/SearchPanel.svelte +++ b/webui/src/lib/components/SearchPanel.svelte @@ -16,7 +16,7 @@ import { onMount, onDestroy } from 'svelte'; export let left = 200; - export let top = 10; + export let top = 56; export let search_results: SearchResult | null = null; export let universe_data: UniverseData; export let hidden = false; @@ -721,7 +721,6 @@ } .input::placeholder { color: var(--t-text-dim); - opacity: 0.8; } .select option { background: var(--t-surface-high); @@ -788,7 +787,7 @@ .pill-wrap { display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(3, minmax(min-content, 1fr)); gap: 0.4rem; } .pill-wrap :global(.tri-pill) { @@ -796,21 +795,21 @@ justify-content: flex-start; } .form.md .pill-wrap { - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(3, minmax(min-content, 1fr)); } .form.sm .pill-wrap { - grid-template-columns: repeat(3, minmax(0, 1fr)); + grid-template-columns: repeat(3, minmax(min-content, 1fr)); } .form.xs .pill-wrap { - grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-template-columns: repeat(2, minmax(min-content, 1fr)); } .star-grid { display: grid; - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(3, minmax(min-content, 1fr)); gap: 0.3rem; } .form.md .star-grid { - grid-template-columns: repeat(3, 1fr); + grid-template-columns: repeat(3, minmax(min-content, 1fr)); } .form.sm .star-grid { grid-template-columns: repeat(3, 1fr); diff --git a/webui/src/lib/components/SearchResults.svelte b/webui/src/lib/components/SearchResults.svelte index 22b423d..edf1b10 100644 --- a/webui/src/lib/components/SearchResults.svelte +++ b/webui/src/lib/components/SearchResults.svelte @@ -413,12 +413,10 @@ display: flex; gap: 0.8rem; font-size: 0.72rem; - opacity: 0.8; margin: -0.3rem 0 0.4rem; } .empty { font-size: 0.8rem; - opacity: 0.7; padding: 0.25rem 0; } .row { @@ -456,12 +454,10 @@ .row .type, .row .size { font-size: 0.7rem; - opacity: 0.85; } .row .coord { font-size: 0.75rem; font-family: monospace; - opacity: 0.8; margin-right: 0.35rem; } .row .size { diff --git a/webui/src/lib/components/TriPill.svelte b/webui/src/lib/components/TriPill.svelte index 63d7136..c079201 100644 --- a/webui/src/lib/components/TriPill.svelte +++ b/webui/src/lib/components/TriPill.svelte @@ -72,7 +72,6 @@ display: flex; align-items: center; justify-content: center; - opacity: 0.9; } .tri-pill-check svg { width: 0.85rem; diff --git a/webui/src/lib/components/Window.svelte b/webui/src/lib/components/Window.svelte index d9f8f0f..de4d6d9 100644 --- a/webui/src/lib/components/Window.svelte +++ b/webui/src/lib/components/Window.svelte @@ -11,6 +11,7 @@ export let minHeight: number | undefined = undefined; export let maxHeight: number | undefined = undefined; export let autoWidth = false; + export let zIndex = 900; let startX = 0; let startY = 0; @@ -226,6 +227,7 @@ style:height={collapsed ? headerHeight + 'px' : height ? height + 'px' : undefined} style:min-height={collapsed ? headerHeight + 'px' : minHeight ? minHeight + 'px' : undefined} style:max-height={collapsed ? headerHeight + 'px' : maxHeight ? maxHeight + 'px' : undefined} + style:z-index={zIndex} >