From 4627eb4615d52839148cc7825e096a171ece522a Mon Sep 17 00:00:00 2001 From: baiqing Date: Sat, 2 May 2026 10:36:13 +0800 Subject: [PATCH] =?UTF-8?q?fix(windows):=20=E5=90=AF=E5=8A=A8=20gate=20pol?= =?UTF-8?q?lHotkeyStatus=20=E5=8A=A0=2010s=20=E8=B6=85=E6=97=B6=20(closes?= =?UTF-8?q?=20#163)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows 上 OS 拒绝低层键盘 hook 安装(反作弊/EDR/UAC 拦)时, hotkey 永远 starting → 前端 while(!cancelled) 永不退出 → UI 卡 "正在启动" 灰屏。 加 50 × 200ms = 10s 上限:超时后强 setGate('ready'),让用户能进 Permissions 页看 hotkey_status.lastError 处理(页面已能显示错误 + 重试入口)。 非 Windows 路径不变。 测试: - npm run build ✅ --- openless-all/app/src/App.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/openless-all/app/src/App.tsx b/openless-all/app/src/App.tsx index 1aa7cea6..b1baac39 100644 --- a/openless-all/app/src/App.tsx +++ b/openless-all/app/src/App.tsx @@ -57,15 +57,28 @@ export function App({ isCapsule, isQa }: AppProps) { let cancelled = false; if (os === 'win') { + // 超时保护:50 次 × 200ms = 10s。hotkey hook 永远 starting(被反作弊 / EDR + // / UAC 拦)时不让 UI 死锁灰屏,过 10s 强 setGate('ready') 让用户进 + // Permissions 页看 hotkey_status.lastError 处理。详见 issue #163。 + const POLL_INTERVAL_MS = 200; + const POLL_MAX_ATTEMPTS = 50; const pollHotkeyStatus = async () => { - while (!cancelled) { + let attempts = 0; + while (!cancelled && attempts < POLL_MAX_ATTEMPTS) { + attempts += 1; const status = await getHotkeyStatus(); if (cancelled) return; if (status.state !== 'starting') { setGate('ready'); return; } - await new Promise(resolve => window.setTimeout(resolve, 200)); + await new Promise(resolve => window.setTimeout(resolve, POLL_INTERVAL_MS)); + } + if (!cancelled) { + console.warn( + `[startup] hotkey gate timed out after ${POLL_MAX_ATTEMPTS * POLL_INTERVAL_MS}ms; forcing ready so user can reach Permissions page` + ); + setGate('ready'); } }; void pollHotkeyStatus().catch(error => {