fix(windows): 启动 gate pollHotkeyStatus 加 10s 超时 (closes #163)

Windows 上 OS 拒绝低层键盘 hook 安装(反作弊/EDR/UAC 拦)时,
hotkey 永远 starting → 前端 while(!cancelled) 永不退出 → UI 卡 "正在启动" 灰屏。

加 50 × 200ms = 10s 上限:超时后强 setGate('ready'),让用户能进 Permissions
页看 hotkey_status.lastError 处理(页面已能显示错误 + 重试入口)。

非 Windows 路径不变。

测试:
- npm run build ✅
This commit is contained in:
baiqing committed 2026-05-02 10:36:13 +08:00
1 parent 490b391022
commit 4627eb4615
1 file changed
+15 -2
+15 -2
View File
@@ -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 => {