From 8cc83f1e08dd02a3e7fd48757c8698644cfe549d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=95=E6=9F=8F=E9=9D=92?= Date: Mon, 15 Jun 2026 21:47:16 +0800 Subject: [PATCH] =?UTF-8?q?perf(less-computer-glow):=20=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E6=97=B6=E5=8D=B8=E8=BD=BD=E5=85=A8=E5=B1=8F=E5=8F=91=E5=85=89?= =?UTF-8?q?=E5=B1=82=EF=BC=8C=E6=B6=88=E9=99=A4=E7=A9=BA=E9=97=B2=20GPU=20?= =?UTF-8?q?=E5=8D=A0=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit issue #470:彩虹描边 glow 是全屏 transparent 浮层 + 4 条无限动画(lcg-spin/breathe/ spin-reverse/flow)。原组件无状态无监听,窗口 .hide() 后 webview 仍持续合成发光层、 跑满 4 条动画,GPU 永不释放(Windows 尤其不释放)。 改为后端 show/hide 主动 emit `less-computer-glow:active` 驱动可见状态(不依赖在隐藏 窗口上失灵的 WebView2 visibilitychange):可见时渲染与原来完全一致的 DOM(视觉零变化), 不可见时返回 null 卸载发光层 → 零 GPU。另加 document.hidden 二级兜底(只停不启)。 注:glow 当前为 macOS-only(Windows show/hide 是 no-op),本修复消除 macOS 隐藏态泄漏, 并让组件具备跨平台「隐藏即零 GPU」安全性,为后续 Windows 重启用铺路。 --- openless-all/app/src-tauri/src/lib.rs | 5 +++ .../app/src/pages/LessComputerGlow.tsx | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/openless-all/app/src-tauri/src/lib.rs b/openless-all/app/src-tauri/src/lib.rs index f358e62b..dc3e125a 100644 --- a/openless-all/app/src-tauri/src/lib.rs +++ b/openless-all/app/src-tauri/src/lib.rs @@ -2181,6 +2181,8 @@ pub(crate) fn show_less_computer_glow(app: &AppHandle) { } // 点击穿透:纯视觉浮层,绝不拦截鼠标。 let _ = window.set_ignore_cursor_events(true); + // issue #470:通知 glow 前端「可见」,恢复发光动画(隐藏时会 emit(false) 卸载发光层以释放 GPU)。 + let _ = window.emit("less-computer-glow:active", true); let window_clone = window.clone(); let _ = app.run_on_main_thread(move || { use objc2::msg_send; @@ -2215,6 +2217,9 @@ pub(crate) fn show_less_computer_glow(_app: &AppHandle) {} #[cfg(target_os = "macos")] pub(crate) fn hide_less_computer_glow(app: &AppHandle) { if let Some(window) = app.get_webview_window("less-computer-glow") { + // issue #470:先通知前端「不可见」卸载全屏发光层(4 条无限动画),webview 隐藏后即零 GPU; + // 否则 .hide() 后 webview 仍持续合成发光层(Windows 尤其不释放动画)。 + let _ = window.emit("less-computer-glow:active", false); let _ = window.hide(); } } diff --git a/openless-all/app/src/pages/LessComputerGlow.tsx b/openless-all/app/src/pages/LessComputerGlow.tsx index 2214c319..cd79ccaf 100644 --- a/openless-all/app/src/pages/LessComputerGlow.tsx +++ b/openless-all/app/src/pages/LessComputerGlow.tsx @@ -2,6 +2,8 @@ // 只画贴边光带,不铺暗场;彩色弧段沿边缘流动,模拟 Apple Intelligence 的粗细变化。 // 纯视觉:pointer-events:none,后端再 set_ignore_cursor_events(true)。仅 macOS 显示。 +import { useEffect, useState } from 'react'; + const glowCss = ` @property --lcg-angle { syntax: ''; initial-value: 0deg; inherits: false; } @keyframes lcg-spin { to { --lcg-angle: 360deg; } } @@ -93,6 +95,35 @@ if (typeof document !== 'undefined' && !document.getElementById('less-computer-g } export function LessComputerGlow() { + // issue #470:窗口 .hide() 后 webview 不会自动停掉这 4 条无限动画(Windows 尤其不释放), + // 全屏发光层持续占 GPU 合成。改由后端 show/hide 主动 emit 可见状态驱动:不可见时直接卸载 + // 发光层(无元素 → 零 GPU),可见时原样渲染——显示时视觉零变化。 + const [active, setActive] = useState(true); + useEffect(() => { + let cancelled = false; + let unlisten: (() => void) | undefined; + void import('@tauri-apps/api/event').then(({ listen }) => { + if (cancelled) return; + void listen('less-computer-glow:active', (e) => { + setActive(Boolean(e.payload)); + }).then((un) => { + if (cancelled) un(); + else unlisten = un; + }); + }); + // 二级兜底:页面被标记为隐藏时也停(只停不启,绝不误关正在显示的发光)。 + const onVisibility = () => { + if (document.hidden) setActive(false); + }; + document.addEventListener('visibilitychange', onVisibility); + return () => { + cancelled = true; + unlisten?.(); + document.removeEventListener('visibilitychange', onVisibility); + }; + }, []); + + if (!active) return null; return (