Deeplinks: pause/resume/restart recording + switch mic/camera#1621
Deeplinks: pause/resume/restart recording + switch mic/camera#1621wh0amibjm wants to merge 5 commits intoCapSoftware:mainfrom
Conversation
| crate::recording::toggle_pause_recording(app.clone(), app.state()).await | ||
| } | ||
| DeepLinkAction::RestartRecording => { | ||
| crate::recording::restart_recording(app.clone(), app.state()).await |
There was a problem hiding this comment.
restart_recording returns Result<RecordingAction, String> but this match arm must return Result<(), String>. The existing StartRecording action (line 152-154) and hotkeys.rs:156-158 both use .map(|_| ()) to convert the return type.
| crate::recording::restart_recording(app.clone(), app.state()).await | |
| crate::recording::restart_recording(app.clone(), app.state()).await.map(|_| ()) |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/deeplink_actions.rs
Line: 169
Comment:
`restart_recording` returns `Result<RecordingAction, String>` but this match arm must return `Result<(), String>`. The existing `StartRecording` action (line 152-154) and hotkeys.rs:156-158 both use `.map(|_| ())` to convert the return type.
```suggestion
crate::recording::restart_recording(app.clone(), app.state()).await.map(|_| ())
```
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Addressed in commit e02ac71 — RestartRecording now maps Result<RecordingAction, String> to Result<(), String> with .map(|_| ()).
| .map(|_| ()) | ||
| } | ||
| DeepLinkAction::SwitchMicrophone { mic_label } => { | ||
| crate::set_mic_input(app.state(), mic_label).await |
There was a problem hiding this comment.
Nit: it’s a bit easier to follow (and a little less inference-dependent) if this matches the StartRecording pattern and makes the state type explicit.
| crate::set_mic_input(app.state(), mic_label).await | |
| crate::set_mic_input(app.state::<ArcLock<App>>(), mic_label).await |
There was a problem hiding this comment.
Addressed in 7bd37b3: SwitchMicrophone now treats empty/whitespace labels as unset (None) and uses explicit app.state::<ArcLock<App>>().
| DeepLinkAction::PauseRecording => { | ||
| crate::recording::pause_recording(app.clone(), app.state()).await | ||
| } |
There was a problem hiding this comment.
For deeplinks, do you want pause/resume/toggle to behave like StopRecording and error when there’s no active recording? Right now these will succeed silently when nothing is recording.
| DeepLinkAction::PauseRecording => { | |
| crate::recording::pause_recording(app.clone(), app.state()).await | |
| } | |
| DeepLinkAction::PauseRecording => { | |
| let state = app.state::<ArcLock<App>>(); | |
| if state.read().await.current_recording().is_none() { | |
| return Err("Recording not in progress".to_string()); | |
| } | |
| crate::recording::pause_recording(app.clone(), state).await | |
| } |
| .map(|_| ()) | ||
| } | ||
| DeepLinkAction::SwitchMicrophone { mic_label } => { | ||
| crate::set_mic_input(app.state(), mic_label).await |
There was a problem hiding this comment.
Small robustness thing: treat empty mic labels as None so callers that send "" don’t end up trying to select a non-existent device.
| crate::set_mic_input(app.state(), mic_label).await | |
| crate::set_mic_input(app.state(), mic_label.filter(|label| !label.trim().is_empty())).await |
There was a problem hiding this comment.
Addressed in 7bd37b3: SwitchMicrophone now treats empty/whitespace labels as unset (None) and uses explicit app.state::<ArcLock<App>>().
|
Correction (escaped markdown got mangled in previous comment): Follow-up pushed in
Validation attempt:
|
|
Pushed follow-up
Validation note:
|
| .await | ||
| } | ||
| DeepLinkAction::SwitchCamera { camera } => { | ||
| crate::set_camera_input(app.clone(), app.state(), camera, None).await |
There was a problem hiding this comment.
Minor robustness: mirror the mic label handling and treat an empty DeviceID("") as unset so it doesn't trigger 3 init retries.
| crate::set_camera_input(app.clone(), app.state(), camera, None).await | |
| let camera = camera.filter(|id| match id { | |
| DeviceOrModelID::DeviceID(device_id) => !device_id.trim().is_empty(), | |
| DeviceOrModelID::ModelID(_) => true, | |
| }); | |
| crate::set_camera_input(app.clone(), app.state(), camera, None).await |
| let error = DeepLinkAction::try_from(&url).expect_err("signin deeplink is not action"); | ||
| assert!(matches!(error, ActionParseFromUrlError::NotAction)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Nice to have: quick parse smoke tests for the other new actions, just to guard the serde rename plumbing.
| } | |
| #[test] | |
| fn parses_restart_recording_action() { | |
| let url = action_url(r#""restart_recording""#); | |
| let action = DeepLinkAction::try_from(&url).expect("parse restart action"); | |
| assert!(matches!(action, DeepLinkAction::RestartRecording)); | |
| } | |
| #[test] | |
| fn parses_switch_camera_action() { | |
| let url = action_url(r#"{"switch_camera":{"camera":{"DeviceID":"camera-1"}}}"#); | |
| let action = DeepLinkAction::try_from(&url).expect("parse switch camera action"); | |
| match action { | |
| DeepLinkAction::SwitchCamera { camera } => { | |
| assert!(camera.is_some()); | |
| } | |
| other => panic!("unexpected action: {other:?}"), | |
| } | |
| } | |
| } |
Follow-up implementation for #1540.
Proposed Changes
cap-desktop://action?value=...legacy JSON/string format):PauseRecording,ResumeRecording,TogglePauseRecording,RestartRecordingSwitchMicrophone(by label)SwitchCamera"Recording not in progress"when no active recording existsrestart_recording() -> Result<RecordingAction, String>intoResult<(), String>to match the deeplink executor return type.Proof
apps/desktop/src-tauri/src/deeplink_actions.rs:PauseRecordingSwitchMicrophonepayload decodingcap-desktop://signin?...)Local note: running the full
cap-desktoptest target on this machine is currently blocked by missing full Xcode toolchain (xcodebuild), but the change is isolated to deeplink action parsing/execution and follows existingrecording::*APIs.Checklist