feat(desktop): add cap:// deep links and minimal Raycast controls#1830
feat(desktop): add cap:// deep links and minimal Raycast controls#1830JYZ-LESLIE wants to merge 3 commits into
Conversation
|
Addressed the security findings in commit e13e954:
Validation note: Rust toolchain is unavailable in this runner, so I could not run cargo test locally here. |
| fn parses_cap_record_as_start_default_recording() { | ||
| let url = Url::parse("cap://record").expect("valid cap record url"); | ||
| let action = DeepLinkAction::try_from(&url).expect("cap record should parse"); | ||
| assert!(matches!(action, DeepLinkAction::StartDefaultRecording)); | ||
| } | ||
|
|
||
| #[test] | ||
| fn parses_cap_stop_as_stop_recording() { |
There was a problem hiding this comment.
parses_existing_action_format test will always fail
The match url.domain() block that precedes the JSON-parsing code has no arm that returns Ok — both arms always return Err(...), so the ? at the end short-circuits and the function exits with Err(Invalid) before it ever reaches query_pairs() or serde_json::from_str. For cap-desktop://action?value=..., url.domain() returns Some("action"), which falls through to the _ => Err(ActionParseFromUrlError::Invalid) arm. The test therefore panics at .expect("action deep link should parse"). Since Rust toolchain was unavailable when authoring this PR, this was not caught.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/deeplink_actions.rs
Line: 217-224
Comment:
**`parses_existing_action_format` test will always fail**
The `match url.domain()` block that precedes the JSON-parsing code has no arm that returns `Ok` — both arms always return `Err(...)`, so the `?` at the end short-circuits and the function exits with `Err(Invalid)` before it ever reaches `query_pairs()` or `serde_json::from_str`. For `cap-desktop://action?value=...`, `url.domain()` returns `Some("action")`, which falls through to the `_ => Err(ActionParseFromUrlError::Invalid)` arm. The test therefore panics at `.expect("action deep link should parse")`. Since Rust toolchain was unavailable when authoring this PR, this was not caught.
How can I resolve this? If you propose a fix, please make it concise.| .buttons(MessageDialogButtons::OkCancel) | ||
| .blocking_show(); | ||
|
|
There was a problem hiding this comment.
Silent error discard for mic/camera setup differs from
StartRecording path
set_mic_input and set_camera_input errors are swallowed with let _ =, so a recording can silently start without the user's saved microphone or camera. The StartRecording arm immediately below uses ? to propagate the same calls as hard errors — the inconsistency means default-recording failures are invisible while explicit-payload failures surface correctly.
| .buttons(MessageDialogButtons::OkCancel) | |
| .blocking_show(); | |
| crate::set_mic_input(state.clone(), settings.mic_name).await?; | |
| crate::set_camera_input(app.clone(), state.clone(), settings.camera_id, None) | |
| .await?; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/deeplink_actions.rs
Line: 131-133
Comment:
**Silent error discard for mic/camera setup differs from `StartRecording` path**
`set_mic_input` and `set_camera_input` errors are swallowed with `let _ =`, so a recording can silently start without the user's saved microphone or camera. The `StartRecording` arm immediately below uses `?` to propagate the same calls as hard errors — the inconsistency means default-recording failures are invisible while explicit-payload failures surface correctly.
```suggestion
crate::set_mic_input(state.clone(), settings.mic_name).await?;
crate::set_camera_input(app.clone(), state.clone(), settings.camera_id, None)
.await?;
```
How can I resolve this? If you propose a fix, please make it concise.| await showHUD("Cap recording started"); | ||
| } catch (error) { |
There was a problem hiding this comment.
showHUD fires before recording is confirmed
open("cap://record") dispatches the URL to the OS but returns as soon as the handoff completes — it does not wait for Cap Desktop to accept and act on the link. showHUD("Cap recording started") therefore always runs, even if Cap is not installed, is not yet launched, or encounters an internal error starting the recording. The same pattern applies in stop-recording.ts. Consider omitting the HUD (or replacing it with a neutral message like "Sent to Cap") since there is no acknowledgement channel from the app over this protocol.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/raycast/src/start-recording.ts
Line: 7-8
Comment:
**`showHUD` fires before recording is confirmed**
`open("cap://record")` dispatches the URL to the OS but returns as soon as the handoff completes — it does not wait for Cap Desktop to accept and act on the link. `showHUD("Cap recording started")` therefore always runs, even if Cap is not installed, is not yet launched, or encounters an internal error starting the recording. The same pattern applies in `stop-recording.ts`. Consider omitting the HUD (or replacing it with a neutral message like "Sent to Cap") since there is no acknowledgement channel from the app over this protocol.
How can I resolve this? If you propose a fix, please make it concise.|
Addressed the new Greptile review points in commit 6416043:
Validation note: Rust toolchain is unavailable in this runner, so I could not execute cargo tests locally here. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
/claim #28
Summary
This delivers a focused Raycast-control baseline for Cap Desktop (v0.3 architecture) with minimal surface area:
cap://record-> starts recording using the user’s saved defaultscap://stop-> stops active recordingcapcustom scheme in Tauri deep-link config.extensions/raycastwith three no-view commands:Why this scope
Issue #28 asks for fast start/stop flows from Raycast with defaults. Existing
cap-desktop://actionstart flow requires explicit capture payloads; this PR adds a simpler protocol path for keyboard-first invocation.Default-setting behavior
cap://recordreuses the app’s existing recording preferences fromRecordingSettingsStore:Validation notes
cap://record,cap://stop, and existingcap-desktop://actioncompatibility.cargo testlocally here.Greptile Summary
This PR adds two new
cap://deep-link routes (recordandstop) to the Tauri desktop app and ships a companion Raycast extension with three no-view commands (Start Recording, Stop Recording, Open Dashboard). Thecap://URL parsing is wired correctly next to the existingcap-desktop://handler and the scheme is registered intauri.conf.json.parses_existing_action_formatunit test added for backward-compat verification will fail: thematch url.domain()guard block returnsErr(...)on both arms (including theSome(\"action\")case), causing the?to short-circuit before the JSON parsing code is reached.StartDefaultRecordingsilently drops errors fromset_mic_input/set_camera_inputwithlet _ =, while the existingStartRecordingpath propagates them; a broken device will be skipped without any feedback.Confidence Score: 3/5
The new
cap://routing and Raycast extension work correctly end-to-end, but the broken unit test and silent device-error path should be resolved before merge.The
parses_existing_action_formattest will panic whencargo testis run because thecap-desktop://actionURL parsing code always short-circuits before reaching the JSON deserialization step. Additionally, mic and camera setup failures are silently ignored in theStartDefaultRecordingpath, meaning a recording can start without the user's saved audio/video devices with no indication that something went wrong.apps/desktop/src-tauri/src/deeplink_actions.rsneeds the most attention — both the broken test and the silent error handling are in that file.Important Files Changed
cap://recordandcap://stopscheme handling plus aStartDefaultRecordingaction; URL parsing for the new scheme is correct, but the addedparses_existing_action_formattest will fail and mic/camera errors are silently swallowed.capas an additional deep-link scheme alongsidecap-desktop; minimal and correct change.cap://record; HUD fires optimistically without confirmation from Cap Desktop.cap://stop; same optimistic HUD pattern as start-recording.Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "fix(desktop): harden raycast deep-link s..." | Re-trigger Greptile