feat: add Raycast recording controls#1867
Conversation
| mic_label: micLabel?.trim() || null, | ||
| }, | ||
| }, | ||
| micLabel ? "Switched microphone" : "Disabled microphone", |
There was a problem hiding this comment.
The toast title uses the raw
micLabel to decide between "Switched" and "Disabled", but the actual value sent to the desktop is micLabel?.trim() || null. If micLabel is a whitespace-only string (e.g., " "), the action sends null — disabling the microphone — while the toast claims "Switched microphone". The same pattern affects setCamera and startRecording.
| micLabel ? "Switched microphone" : "Disabled microphone", | |
| micLabel?.trim() ? "Switched microphone" : "Disabled microphone", |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/raycast/src/lib/deeplinks.ts
Line: 129
Comment:
The toast title uses the raw `micLabel` to decide between "Switched" and "Disabled", but the actual value sent to the desktop is `micLabel?.trim() || null`. If `micLabel` is a whitespace-only string (e.g., `" "`), the action sends `null` — disabling the microphone — while the toast claims "Switched microphone". The same pattern affects `setCamera` and `startRecording`.
```suggestion
micLabel?.trim() ? "Switched microphone" : "Disabled microphone",
```
How can I resolve this? If you propose a fix, please make it concise.| camera: deviceId?.trim() ? { DeviceID: deviceId.trim() } : null, | ||
| }, | ||
| }, | ||
| deviceId ? "Switched camera" : "Disabled camera", |
There was a problem hiding this comment.
Same toast/action mismatch for
setCamera: a whitespace-only deviceId evaluates as truthy here, so the toast says "Switched camera", but the action sends null (disabled camera) because deviceId?.trim() is falsy.
| deviceId ? "Switched camera" : "Disabled camera", | |
| deviceId?.trim() ? "Switched camera" : "Disabled camera", |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/raycast/src/lib/deeplinks.ts
Line: 140
Comment:
Same toast/action mismatch for `setCamera`: a whitespace-only `deviceId` evaluates as truthy here, so the toast says "Switched camera", but the action sends `null` (disabled camera) because `deviceId?.trim()` is falsy.
```suggestion
deviceId?.trim() ? "Switched camera" : "Disabled camera",
```
How can I resolve this? If you propose a fix, please make it concise.| <Form.Dropdown.Item value="screen" title="Screen" /> | ||
| <Form.Dropdown.Item value="window" title="Window" /> | ||
| </Form.Dropdown> | ||
| <Form.TextField id="targetName" title="Target Name" /> |
There was a problem hiding this comment.
Missing validation on target name field
targetName has no placeholder, info, or client-side guard, and submitting an empty string is silently sent to Cap Desktop where it fails with "No screen/window with name ''". The same gap exists in take-screenshot.tsx. Adding a validation callback on the form would surface the problem before the deeplink fires.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/raycast/src/start-recording.tsx
Line: 40
Comment:
**Missing validation on target name field**
`targetName` has no `placeholder`, `info`, or client-side guard, and submitting an empty string is silently sent to Cap Desktop where it fails with `"No screen/window with name ''"`. The same gap exists in `take-screenshot.tsx`. Adding a validation callback on the form would surface the problem before the deeplink fires.
How can I resolve this? If you propose a fix, please make it concise.
/claim #1540
Summary
Validation
cargo fmt --allpnpm exec biome check --write apps/raycast/package.json apps/raycast/tsconfig.json apps/raycast/src apps/raycast/README.md apps/raycast/assets/command-icon.png apps/raycast/.gitignorepnpm --dir apps/raycast exec tsc --noEmitpnpm --dir apps/raycast exec ray buildpnpm --dir apps/raycast exec ray lintcargo check -p cap-desktopis blocked on this machine before reaching this change becausecidrerequires full Xcode viaxcodebuild, while the active developer directory is Command Line Tools only.Greptile Summary
This PR adds Raycast extension commands for controlling Cap Desktop recordings via deeplinks, and extends the Rust deeplink action handler with pause/resume/toggle, screenshot, and device-switching actions. The
url.domain()→url.host_str()fix is a correctness improvement that prevents non-domain hostnames from being misclassified.deeplink_actions.rs: Adds six newDeepLinkActionvariants, awith_recording_paused_for_input_changehelper that correctly brackets input changes with pause/resume, and a test suite covering the new variants.apps/raycast/: New Raycast extension with four commands (control, start recording, screenshot, switch device); the shareddeeplinks.tslibrary mirrors the Rust action enum as TypeScript types and fires deeplinks viaopen().setMicrophoneandsetCameraindeeplinks.tscheck the raw (untrimmed) value when constructing the toast title, but trim before sending — a whitespace-only input shows a "Switched" toast while actually disabling the device.Confidence Score: 4/5
Safe to merge; the Rust changes are well-tested and correct, and the Raycast issues are confined to edge-case toast messaging and missing form validation.
The Rust backend changes are clean and well-covered by tests. The Raycast TypeScript layer has two small toast/action mismatches for whitespace-only inputs in setMicrophone and setCamera, and the recording/screenshot forms do not validate the target name field before firing the deeplink.
apps/raycast/src/lib/deeplinks.ts — toast title mismatch for whitespace inputs in setMicrophone and setCamera.
Important Files Changed
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat: add Raycast recording controls" | Re-trigger Greptile