Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 68 additions & 1 deletion apps/desktop/src-tauri/src/deeplink_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use tauri::{AppHandle, Manager, Url};
use tracing::trace;

use crate::{App, ArcLock, recording::StartRecordingInputs, windows::ShowCapWindow};
use crate::{App, ArcLock, recording::{InProgressRecording, StartRecordingInputs}, windows::ShowCapWindow};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
Expand All @@ -26,6 +26,22 @@ pub enum DeepLinkAction {
mode: RecordingMode,
},
StopRecording,
PauseRecording,
ResumeRecording,
TogglePauseRecording,
SetMicrophone {
label: Option<String>,
},
/// Sets the active camera input for the current recording.
///
/// **Note on field naming**: The JSON key exposed in the deep-link URL is `camera`
/// (e.g. `cap-desktop://action?value={"set_camera":{"camera":<id>}}`), which maps
/// to the `id` parameter of the underlying `set_camera_input` Tauri command.
/// This divergence is intentional to keep the deep-link API readable; the call
/// site passes `camera` positionally so the mapping is correct at runtime.
SetCamera {
camera: Option<DeviceOrModelID>,
},
Comment on lines +29 to +44
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 SetCamera field name diverges from underlying command parameter

The struct variant uses camera: Option<DeviceOrModelID> while the underlying set_camera_input command names the same parameter id. The call site is correct (camera is passed positionally), but the JSON key exposed in the deep-link URL will be camera (due to rename_all = "snake_case"), whereas anyone reading set_camera_input's signature would expect id. A brief doc-comment on the variant clarifying the mapping would help future contributors and Raycast extension maintainers.

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

Comment:
**`SetCamera` field name diverges from underlying command parameter**

The struct variant uses `camera: Option<DeviceOrModelID>` while the underlying `set_camera_input` command names the same parameter `id`. The call site is correct (`camera` is passed positionally), but the JSON key exposed in the deep-link URL will be `camera` (due to `rename_all = "snake_case"`), whereas anyone reading `set_camera_input`'s signature would expect `id`. A brief doc-comment on the variant clarifying the mapping would help future contributors and Raycast extension maintainers.

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

OpenEditor {
project_path: PathBuf,
},
Expand Down Expand Up @@ -147,6 +163,57 @@ impl DeepLinkAction {
DeepLinkAction::StopRecording => {
crate::recording::stop_recording(app.clone(), app.state()).await
}
DeepLinkAction::PauseRecording => {
crate::recording::pause_recording(app.clone(), app.state()).await
}
DeepLinkAction::ResumeRecording => {
crate::recording::resume_recording(app.clone(), app.state()).await
}
DeepLinkAction::TogglePauseRecording => {
crate::recording::toggle_pause_recording(app.clone(), app.state()).await
}
DeepLinkAction::SetMicrophone { label } => {
// `set_mic_input` only rewires the active audio feed for Studio-mode
// recordings. For other modes (Instant/Segment) or when no recording is
// in progress, the call updates `selected_mic_label` and returns `Ok(())`
// without changing the live audio path. External callers (e.g. the Raycast
// extension) should be aware that the change takes effect at the *next*
// Studio recording start if no Studio session is currently active.
let is_studio = matches!(
app.state::<crate::ArcLock<crate::App>>()
.read()
.await
.current_recording(),
Some(InProgressRecording::Studio { .. })
);
if !is_studio {
tracing::warn!(
"SetMicrophone deeplink: no active Studio recording; \
microphone preference saved but audio path not immediately updated"
);
}
crate::set_mic_input(app.state(), label).await
Comment on lines +175 to +195
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 SetMicrophone silently succeeds outside Studio recordings

set_mic_input only updates the live mic feed for InProgressRecording::Studio mode; for other recording modes (e.g., Instant/Segment) the function updates selected_mic_label but does NOT rewire the active recording's audio input. A caller (e.g., the Raycast extension) will receive Ok(()) even when the microphone wasn't actually switched mid-recording. The same asymmetry exists for SetCamera. This matches the in-app UI's behaviour, but it may be surprising for external callers relying on these deeplinks for real-time control. Consider emitting a warning or returning an informational status in those cases.

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

Comment:
**`SetMicrophone` silently succeeds outside Studio recordings**

`set_mic_input` only updates the live mic feed for `InProgressRecording::Studio` mode; for other recording modes (e.g., Instant/Segment) the function updates `selected_mic_label` but does NOT rewire the active recording's audio input. A caller (e.g., the Raycast extension) will receive `Ok(())` even when the microphone wasn't actually switched mid-recording. The same asymmetry exists for `SetCamera`. This matches the in-app UI's behaviour, but it may be surprising for external callers relying on these deeplinks for real-time control. Consider emitting a warning or returning an informational status in those cases.

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

}
DeepLinkAction::SetCamera { camera } => {
// Same caveat as SetMicrophone: camera switching via deeplink only
// affects the live feed for an active Studio recording. In other modes
// the preference is persisted but the physical capture source is not
// immediately swapped.
let is_studio = matches!(
app.state::<crate::ArcLock<crate::App>>()
.read()
.await
.current_recording(),
Some(InProgressRecording::Studio { .. })
);
if !is_studio {
tracing::warn!(
"SetCamera deeplink: no active Studio recording; \
camera preference saved but capture source not immediately updated"
);
}
crate::set_camera_input(app.clone(), app.state(), camera, None).await
}
DeepLinkAction::OpenEditor { project_path } => {
crate::open_project_from_path(Path::new(&project_path), app.clone())
}
Expand Down