Skip to content

fix(onboarding): require macOS Accessibility grant before first-run completes#703

Merged
appergb merged 1 commit into
betafrom
fix/onboarding-require-accessibility
Jun 17, 2026
Merged

fix(onboarding): require macOS Accessibility grant before first-run completes#703
appergb merged 1 commit into
betafrom
fix/onboarding-require-accessibility

Conversation

@appergb

@appergb appergb commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

User description

Problem

On macOS, first-run onboarding could complete after Microphone only and drop the user into the main UI without Accessibility granted — so the global hotkey silently does nothing and the app looks broken.

Cause

DesktopOnboarding gated completion on the hotkey capability flag requiresAccessibilityPermission:

const aOk = !requiresAccessibility || a === 'granted' || a === 'notApplicable';

That flag comes from an async IPC and is null while it loadsrequiresAccessibility is briefly falseaOk is true. If Microphone gets granted inside that window, refresh() calls onComplete() before Accessibility was ever requested. The accessibility step ({requiresAccessibility && …}) hadn't rendered yet either. Meanwhile App.tsx's startup gate always requires Accessibility, so the two disagreed.

Confirmed in source: macOS HotkeyCapability has requires_accessibility_permission: true (types.rs), but the TS fallback/mock default to false.

Fix (Onboarding.tsx, desktop path only)

  1. Gate on the real permission status, mirroring App.tsx — timing-independent, capability-flag-independent:
    const aOk = a === 'granted' || a === 'notApplicable';
    check_accessibility() returns granted/denied on macOS and notApplicable on Windows/Linux/Android, so this requires Accessibility exactly where it's needed.
  2. Show the Accessibility step whenever it's denied (a macOS-only state) in addition to the capability flag, so the step reliably appears even before/if the capability hasn't loaded.
  3. Drop the capability dependency from the grant button's disabled, so it's actionable in that same window.

Behavior

  • macOS: onboarding now stays until both Accessibility and Microphone are granted. No more "in the app but hotkey dead."
  • Windows / Linux / Android: Accessibility is notApplicableaOk true, step hidden → unchanged.

Test plan

  • npx tsc --noEmit — clean
  • macOS fresh-run (TCC reset): onboarding blocks until Accessibility granted; grant flow opens System Settings; completes only after both
  • Windows/Linux: onboarding unchanged (mic-only), CI build green

Base: beta.


PR Type

Bug fix


Description

  • Fix macOS onboarding completing without Accessibility granted

  • Gate completion on real permission status, not capability flag

  • Show Accessibility step when denied even before capability loads

  • Drop capability dependency from grant button disabled state


Diagram Walkthrough

flowchart LR
  A["Onboarding refresh()"] --> B["Check permissions"]
  B --> C{"Accessibility = granted or notApplicable?"}
  C -- "True" --> D{"Microphone = granted or notApplicable?"}
  D -- "True" --> E["onComplete()"]
  D -- "False" --> F["Wait for Mic grant"]
  C -- "False" --> G["Show Accessibility step"]
  G --> H["User grants Accessibility"]
  H --> B
Loading

File Walkthrough

Relevant files
Bug fix
Onboarding.tsx
Fix Accessibility permission gating and step visibility   

openless-all/app/src/components/Onboarding.tsx

  • Modified refresh() to gate completion on real accessibility permission
    status instead of requiresAccessibility flag
  • Changed rendering condition for Accessibility step to include
    accessibility === 'denied'
  • Removed capability?.requiresAccessibilityPermission from grant button
    disabled condition
  • Updated step index calculation to account for accessibility step when
    denied
+9/-4     

…ompletes

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).
@github-actions

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ No major issues detected

@appergb appergb merged commit f3467ae into beta Jun 17, 2026
5 checks passed
@appergb appergb deleted the fix/onboarding-require-accessibility branch June 17, 2026 09:41
appergb pushed a commit that referenced this pull request Jun 17, 2026
…ing accessibility gate

Bundles the two macOS UX fixes already merged into beta:
- #702 unify macOS shell top inset with sidebar/background surface
- #703 require macOS Accessibility grant before first-run onboarding completes

Version synced across package.json, package-lock.json, tauri.conf.json,
Cargo.toml, Cargo.lock. Local release build verified (1.3.10-2 installs and
runs; top bar seamless; first-run requires Accessibility).
appergb pushed a commit that referenced this pull request Jun 17, 2026
Re-cut of the 1.3.10-2 beta from the synced cloud beta branch (supersedes the
-2 pre-release, which was deleted). Identical code to 1.3.10-2 — version-number
bump only. Bundles #701 persistence split, #702 top-bar unification, #703
onboarding accessibility gate, on top of 1.3.10-1 audit fixes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant