Skip to content

fix(desktop): improve deeplink action routing and control surface#1806

Open
JYZ-LESLIE wants to merge 2 commits into
CapSoftware:mainfrom
JYZ-LESLIE:codex/deeplink-quality-pass-1540
Open

fix(desktop): improve deeplink action routing and control surface#1806
JYZ-LESLIE wants to merge 2 commits into
CapSoftware:mainfrom
JYZ-LESLIE:codex/deeplink-quality-pass-1540

Conversation

@JYZ-LESLIE
Copy link
Copy Markdown

@JYZ-LESLIE JYZ-LESLIE commented May 12, 2026

/claim #1540

This is a focused desktop-side quality pass for the deeplink/Raycast control surface.

What changed

  • fixes cap-desktop://action?... parsing by using the deeplink host (host_str) so action links are no longer rejected
  • adds recording-control deeplink actions:
    • pause_recording
    • resume_recording
    • toggle_pause_recording
    • restart_recording
    • take_screenshot
    • set_microphone (with switch_microphone alias)
    • set_camera (with switch_camera alias)
    • refresh_raycast_device_cache
  • extracts shared capture-target resolution so start/screenshot flows use the same mapping logic
  • writes Raycast JSON artifacts:
    • raycast-device-cache.json
    • raycast-last-screenshot.json
  • keeps runtime responsive by moving device enumeration into spawn_blocking and writing files with async FS APIs
  • adds parser tests for action-host routing, nullable camera/mic payloads, capture payloads, and non-action deeplinks (cap-desktop://signin)

Notes

  • SetCamera uses skip_camera_window=true so deeplink-triggered device changes do not force camera preview UI popups.

Validation

  • Could not run cargo fmt / cargo test in this environment because Rust (cargo) is unavailable on the runner.
  • Added focused parser unit coverage in deeplink_actions.rs for the changed payload surface.

Demo

  • I cannot capture a desktop demo video from this headless environment. The PR includes deterministic parser tests and desktop-side action wiring only (no frontend-side behavior changes).

Greptile Summary

This PR fixes the long-standing url.domain()url.host_str() bug that caused all cap-desktop://action?... deeplinks to be rejected, and wires up eight new recording-control actions (pause_recording, resume_recording, toggle_pause_recording, restart_recording, take_screenshot, set_microphone/switch_microphone, set_camera/switch_camera, refresh_raycast_device_cache) to their existing Rust backend handlers.

  • The core URL-parsing fix is correct: host_str() is the right method for custom-scheme URLs and the NotAction guard now correctly passes through non-action links like cap-desktop://signin.
  • refresh_raycast_device_cache properly offloads blocking device-enumeration calls into spawn_blocking, and writes the cache/screenshot-result artifacts via tokio::fs; parser unit tests cover all new variants including serde aliases and nullable payloads.
  • capture_target_from_mode (shared by StartRecording and the new TakeScreenshot path) still calls list_displays() / list_windows() directly on the async runtime thread, inconsistent with the spawn_blocking discipline applied elsewhere in this PR.

Confidence Score: 4/5

Safe to merge; the URL-parsing fix and new action wiring are correct. The one issue (blocking OS calls in TakeScreenshot) mirrors a pre-existing pattern in StartRecording and will not cause data loss or crashes — it may only cause minor runtime latency on systems with many open windows.

The URL-parsing regression fix is well-scoped and correct. New actions delegate to existing, tested backend functions. The spawn_blocking discipline is applied in refresh_raycast_device_cache but not carried through to capture_target_from_mode, which is used by the new TakeScreenshot path — a quality inconsistency rather than a correctness problem.

apps/desktop/src-tauri/src/deeplink_actions.rs — specifically the TakeScreenshot arm and capture_target_from_mode

Important Files Changed

Filename Overview
apps/desktop/src-tauri/src/deeplink_actions.rs Adds 8 new recording-control deeplink actions, fixes action-host URL parsing (domain→host_str), extracts capture-target resolution into a shared helper, writes Raycast JSON artifacts, and adds parser tests. One inconsistency: capture_target_from_mode calls blocking OS APIs directly in the async executor for TakeScreenshot, while refresh_raycast_device_cache correctly wraps equivalent calls in spawn_blocking.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/desktop/src-tauri/src/deeplink_actions.rs:195-199
**Blocking OS calls on async thread in `TakeScreenshot`**

`capture_target_from_mode` calls `list_displays()` / `list_windows()` — synchronous system APIs — directly on the Tokio runtime thread. `refresh_raycast_device_cache` wraps the identical calls in `spawn_blocking` specifically to avoid stalling the runtime, but the same protection is missing here. On a system with many windows, `list_windows()` can take tens of milliseconds and will block the entire runtime thread for the duration.

Reviews (1): Last reviewed commit: "fix(desktop): improve deeplink action ro..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@brin-security-scanner brin-security-scanner Bot added contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis. labels May 12, 2026
Comment on lines +195 to +199
DeepLinkAction::TakeScreenshot { capture_mode } => {
let capture_target = capture_target_from_mode(capture_mode)?;
let path = crate::recording::take_screenshot(app.clone(), capture_target).await?;
write_raycast_screenshot_result(app, path).await
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blocking OS calls on async thread in TakeScreenshot

capture_target_from_mode calls list_displays() / list_windows() — synchronous system APIs — directly on the Tokio runtime thread. refresh_raycast_device_cache wraps the identical calls in spawn_blocking specifically to avoid stalling the runtime, but the same protection is missing here. On a system with many windows, list_windows() can take tens of milliseconds and will block the entire runtime thread for the duration.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/deeplink_actions.rs
Line: 195-199

Comment:
**Blocking OS calls on async thread in `TakeScreenshot`**

`capture_target_from_mode` calls `list_displays()` / `list_windows()` — synchronous system APIs — directly on the Tokio runtime thread. `refresh_raycast_device_cache` wraps the identical calls in `spawn_blocking` specifically to avoid stalling the runtime, but the same protection is missing here. On a system with many windows, `list_windows()` can take tens of milliseconds and will block the entire runtime thread for the duration.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🙋 Bounty claim contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant