From 18b88f51dea43b7c2e628e0e4ee6ecb50644b73f Mon Sep 17 00:00:00 2001 From: sim Date: Wed, 17 Jun 2026 17:24:32 +0800 Subject: [PATCH] fix(onboarding): require macOS Accessibility grant before first-run completes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On macOS the hotkey needs Accessibility, but first-run onboarding could finish after Microphone only and drop users into the main UI with a dead hotkey ("nothing happens when I press the key"). Cause: desktop onboarding gated completion on the hotkey *capability* flag (requiresAccessibilityPermission). That flag is null while the capability IPC loads, so requiresAccessibility was briefly false — if Mic got granted in that window, refresh() called onComplete() before Accessibility was ever requested. App.tsx's startup gate, by contrast, always requires Accessibility, so the two disagreed. Fix: gate completion on the real permission status, mirroring App.tsx — macOS returns granted/denied, every other platform returns notApplicable, so this is timing-independent and cross-platform safe. Also surface the Accessibility step whenever it is denied (macOS-only state) and drop the capability dependency from its grant button, so the step always appears and is actionable even before the capability finishes loading. No change on Windows/Linux/Android (Accessibility = notApplicable there). --- openless-all/app/src/components/Onboarding.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/openless-all/app/src/components/Onboarding.tsx b/openless-all/app/src/components/Onboarding.tsx index 249f1ba6..90ee702a 100644 --- a/openless-all/app/src/components/Onboarding.tsx +++ b/openless-all/app/src/components/Onboarding.tsx @@ -293,7 +293,12 @@ function DesktopOnboarding({ ]); setAccessibility(a); setMicrophone(m); - const aOk = !requiresAccessibility || a === 'granted' || a === 'notApplicable'; + // Gate on the real permission status — macOS returns granted/denied, other + // platforms return notApplicable. This must NOT depend on the hotkey + // capability flag: it is null while it loads, so trusting it let mic-only + // onboarding finish before we knew macOS needs Accessibility, dropping users + // into the app with a dead hotkey. Mirrors the gate in App.tsx. + const aOk = a === 'granted' || a === 'notApplicable'; const mOk = m === 'granted' || m === 'notApplicable'; if (aOk && mOk) { onComplete(); @@ -362,7 +367,7 @@ function DesktopOnboarding({ > - {requiresAccessibility && ( + {(requiresAccessibility || accessibility === 'denied') && ( )}