feat(permissions): native drag-to-grant permission flow#3898
Conversation
398b436 to
8dd5dd7
Compare
|
@divanshu-go can you share video of the onboarding or when user remove screen permission while using the app? |
louis030195
left a comment
There was a problem hiding this comment.
apps/screenpipe-app-tauri/lib/utils/permission-flow.ts:123 — wrap in try/catch? on win/linux this will throw and bypass fallback
@divanshu-go nice! did you test on windows/linux? since the plugin is mac-only, we should make sure it doesnt crash on other platforms
generated by the screenpipe pr-review pipe (https://screenpi.pe), not written by a human — reply and tag @louis030195 if it got something wrong.
02c25b7 to
b247714
Compare
louis030195
left a comment
There was a problem hiding this comment.
wow this is a masterclass of a pr @divanshu-go . super thorough test plan and edge cases handling. lgtm !
generated by the screenpipe pr-review pipe (https://screenpi.pe), not written by a human — reply and tag @louis030195 if it got something wrong.
- Hide drag panel when screenpipe becomes frontmost: call stopCurrentFlow() in the onFocusChanged handler so the panel is only visible in system settings, not alongside screenpipe's own windows - Poll even when document.hidden: added pollWhenHidden option to watchAuthorizationStatus and pass it true from watchUntilGrantedAndClose so the 1.5s interval keeps running while system settings occludes the screenpipe window — detects manual toggle grants without waiting for focus to return - Immediate post-drag grant check: after startFlow resolves, call authorizationState() immediately to detect grants on apps already in the settings list that were re-enabled via drag (native plugin skips its own close signal in this case) - Start watcher before startFlow: watchUntilGrantedAndClose now runs before await startFlow so a manual toggle while the drag panel is still open is caught by the 1.5s poller - Force-close flow resource on grant: stopActiveFlow now calls both stopCurrentFlow() (soft) and flow.close() (destroys Swift controller) ensuring the panel disappears even when the plugin's drag state machine is stuck - Reset stale TCC entry before drag: calls resetPermission before showing the drag panel so macOS does not reject the drop as a duplicate when screenpipe is already in the settings list but disabled
…vent - Gate VisionManager start on screen recording permission to prevent SCShareableContent from triggering native TCC dialog before onboarding - Gate UI recording start on accessibility permission; skip with warning when not yet granted - Add permission_needed event (Rust → engine_events → frontend) so the recovery window can surface when capture is blocked at startup - Suppress permission_needed during active onboarding in handle_needed - Add prompt_permissions param to start_ui_recording: CLI passes true (native TCC dialogs expected), Tauri passes cfg!(debug_assertions) so dev builds get the native dialog fallback when dragflow unavailable - Fix check_screen_recording_tauri: debug builds use full probe chain on macOS 15+ (capture_probe safe in dev), release skips it to avoid the false-positive from own-window compositor change in Sequoia - Add com.apple.security.automation.apple-events entitlement so the Automation TCC prompt surfaces for browser URL capture
…macOS target - Reintroduced the tauri-plugin-permission-flow for macOS, ensuring it is only initialized on that platform. - Removed the global initialization from the main application setup to streamline platform-specific configurations.
5ab1bae to
e7d35d4
Compare
e7d35d4 to
a2f11ce
Compare
tauri-plugin-permission-flow failed to compile on Windows/Linux because the non-macOS stub handle wasn't generic over the runtime nor a `tauri::Resource`, and the macOS-only `permission_flow` error variants weren't cfg-gated. Point the dependency at the fixed fork commit so non-macOS builds succeed.
Onboardingresult1780942224.mp4Permission Recoveryresult1781036366.mp4 |
louis030195
left a comment
There was a problem hiding this comment.
great work! @divanshu-go windows/linux builds passing now is amazing. ill merge when CI is green
generated by the screenpipe pr-review pipe (https://screenpi.pe), not written by a human — reply and tag @louis030195 if it got something wrong.
Description
Instead of just opening System Settings and hoping the user figures it out, screenpipe now shows a floating panel with the app icon the user can drag directly into the settings list. This covers accessibility, screen recording, and input monitoring. Calendar and microphone still use the native system prompt.
On top of the drag panel, the capture pipeline now gates on TCC status at startup — VisionManager and UI recording no longer start until the required permissions are granted, which prevents macOS from showing its own raw TCC padlock dialogs before onboarding runs.
What changed
New
permission-flow.ts— wraps the native macOS drag panel plugin and all the screenpipe-specific controller logic in one fileAll permission buttons, banners, onboarding, and recovery screens now go through the new flow
New Tauri command
set_window_always_on_top_native— drops screenpipe below System Settings during the grant so it doesn't block the UIStartup capture gate (
capture_session.rs): VisionManager skips start when screen recording is not yet granted; UI recording skips start when accessibility is not yet granted. Both emit apermission_neededevent instead.spawn_screenpipeis called again from onboarding after the user grants access.permission_neededevent (screenpipe-events,engine_events,use-permission-monitor): new event emitted by the Rust capture layer when capture is blocked. Flows Rust → engine_events → frontend. The frontend hook shows the recovery window when received outside onboarding/recovery paths. Suppressed during active onboarding so it doesn't interfere with the normal flow.Accessibility included in recovery "all ok" check (
permission-recovery/page.tsx): the recovery page no longer restarts screenpipe until screen recording, microphone, AND accessibility are all granted on macOS.Tauri-specific screen recording probe (
check_screen_recording_tauri): release builds on macOS 15+ use preflight-only — Apple changedCGWindowListCreateImageto return the app's own windows without Screen Recording permission (false positive). Debug builds use the fullpreflight || capture_probechain since devs already have permissions and benefit from the false-negative protection.CLI
prompt_permissions:start_ui_recordinggains aprompt_permissionsbool. CLI passestrueso native TCC dialogs appear as expected in a terminal. Tauri passescfg!(debug_assertions)— release builds defer to the drag panel, dev builds use the native dialog as fallback since dragflow doesn't work in dev mode.Edge cases fixed
Panel wouldn't close when app was already in the settings list.
macOS rejects duplicate drag-drops, so the plugin never got a "drop accepted" signal. We now clear the TCC entry before showing the panel so the drag always lands clean.
Panel stayed open after user manually toggled the permission.
Two issues here. While System Settings is open, the screenpipe window is occluded and polling was paused. Also, the watcher only started after the drag finished, so mid-drag toggles were missed entirely. Fixed by polling through occlusion and starting the watcher before the drag begins.
Panel showed on screenpipe windows, not just System Settings.
The native plugin tracks the host app and shows the panel whenever screenpipe is frontmost. Fixed by calling
stopCurrentFlow()the moment screenpipe regains focus.System Settings hidden behind screenpipe — screenpipe runs always-on-top, which blocked System Settings from appearing in front. Fixed by temporarily dropping the window level when opening settings and restoring it when screenpipe refocuses.
Native TCC padlock dialog appearing before onboarding on macOS 15+.
SCShareableContent::current()(called inside VisionManager startup) triggers Apple's native TCC dialog if screen recording hasn't been granted yet — even before the user reaches the permission step. Fixed by gating VisionManager and UI recording on TCC status before any ScreenCaptureKit API is touched.CGWindowListCreateImagefalse positive on macOS 15+ Tauri.Apple changed this API in Sequoia to return the app's own windows even without Screen Recording permission, making our 1×1 capture probe always return non-NULL. Fixed by splitting into
check_screen_recording()(CLI — always uses full probe chain) andcheck_screen_recording_tauri()(Tauri release on macOS 15+ — preflight-only; dev builds still use full chain).Test plan
permission_neededfires → recovery window appears ✓permission_neededfires → recovery window does NOT appear ✓