diff --git a/apps/desktop/src-tauri/src/deeplink_actions.rs b/apps/desktop/src-tauri/src/deeplink_actions.rs index a1170284877..5cc330e4ca7 100644 --- a/apps/desktop/src-tauri/src/deeplink_actions.rs +++ b/apps/desktop/src-tauri/src/deeplink_actions.rs @@ -26,6 +26,15 @@ pub enum DeepLinkAction { mode: RecordingMode, }, StopRecording, + PauseRecording, + ResumeRecording, + TogglePauseRecording, + SwitchCamera { + camera: DeviceOrModelID, + }, + SwitchMic { + mic_label: String, + }, OpenEditor { project_path: PathBuf, }, @@ -147,6 +156,21 @@ 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::SwitchCamera { camera } => { + crate::set_camera_input(app.clone(), app.state(), Some(camera), None).await + } + DeepLinkAction::SwitchMic { mic_label } => { + crate::set_mic_input(app.state(), Some(mic_label)).await + } DeepLinkAction::OpenEditor { project_path } => { crate::open_project_from_path(Path::new(&project_path), app.clone()) } diff --git a/packages/raycast/package.json b/packages/raycast/package.json new file mode 100644 index 00000000000..2683790d3a6 --- /dev/null +++ b/packages/raycast/package.json @@ -0,0 +1,86 @@ +{ + "name": "cap-raycast", + "title": "Cap", + "description": "Control Cap recording from Raycast", + "icon": "icon.png", + "author": "CapSoftware", + "categories": [ + "Productivity", + "Media" + ], + "license": "MIT", + "commands": [ + { + "name": "start-recording", + "title": "Start Recording", + "description": "Start a new recording in Cap", + "mode": "no-view" + }, + { + "name": "stop-recording", + "title": "Stop Recording", + "description": "Stop current recording in Cap", + "mode": "no-view" + }, + { + "name": "pause-recording", + "title": "Pause Recording", + "description": "Pause current recording in Cap", + "mode": "no-view" + }, + { + "name": "resume-recording", + "title": "Resume Recording", + "description": "Resume current recording in Cap", + "mode": "no-view" + }, + { + "name": "toggle-pause", + "title": "Toggle Pause", + "description": "Toggle pause/resume for current recording", + "mode": "no-view" + }, + { + "name": "switch-camera", + "title": "Switch Camera", + "description": "Switch to a specific camera", + "mode": "no-view", + "arguments": [ + { + "name": "camera", + "placeholder": "Camera Name/ID", + "type": "text", + "required": true + } + ] + }, + { + "name": "switch-mic", + "title": "Switch Microphone", + "description": "Switch to a specific microphone", + "mode": "no-view", + "arguments": [ + { + "name": "mic", + "placeholder": "Microphone Label", + "type": "text", + "required": true + } + ] + } + ], + "dependencies": { + "@raycast/api": "^1.88.0" + }, + "devDependencies": { + "@types/node": "20.8.10", + "@types/react": "18.2.27", + "typescript": "^5.2.2" + }, + "scripts": { + "dev": "ray dev", + "fix-lint": "ray lint --fix", + "lint": "ray lint", + "publish": "npx @raycast/api@latest publish" + } +} diff --git a/packages/raycast/src/pause-recording.ts b/packages/raycast/src/pause-recording.ts new file mode 100644 index 00000000000..6d0906bc862 --- /dev/null +++ b/packages/raycast/src/pause-recording.ts @@ -0,0 +1,7 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +export default async function Command() { + await triggerAction("pause_recording"); + await showHUD("Pausing Cap Recording"); +} diff --git a/packages/raycast/src/resume-recording.ts b/packages/raycast/src/resume-recording.ts new file mode 100644 index 00000000000..6653994af66 --- /dev/null +++ b/packages/raycast/src/resume-recording.ts @@ -0,0 +1,7 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +export default async function Command() { + await triggerAction("resume_recording"); + await showHUD("Resuming Cap Recording"); +} diff --git a/packages/raycast/src/start-recording.ts b/packages/raycast/src/start-recording.ts new file mode 100644 index 00000000000..d6f16fb9737 --- /dev/null +++ b/packages/raycast/src/start-recording.ts @@ -0,0 +1,16 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +export default async function Command() { + // Trigger a standard recording. User can configure devices in the app. + await triggerAction({ + start_recording: { + capture_mode: { screen: "Main" }, + camera: null, + mic_label: null, + capture_system_audio: true, + mode: "instant" + } + }); + await showHUD("Starting Cap Recording"); +} diff --git a/packages/raycast/src/stop-recording.ts b/packages/raycast/src/stop-recording.ts new file mode 100644 index 00000000000..9e5444d8460 --- /dev/null +++ b/packages/raycast/src/stop-recording.ts @@ -0,0 +1,7 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +export default async function Command() { + await triggerAction("stop_recording"); + await showHUD("Stopping Cap Recording"); +} diff --git a/packages/raycast/src/switch-camera.ts b/packages/raycast/src/switch-camera.ts new file mode 100644 index 00000000000..65ed77f9ffb --- /dev/null +++ b/packages/raycast/src/switch-camera.ts @@ -0,0 +1,13 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +interface Arguments { + camera: string; +} + +export default async function Command(props: { arguments: Arguments }) { + const { camera } = props.arguments; + // We assume it's a DeviceID for simplicity in this Raycast command + await triggerAction({ switch_camera: { camera: { device_id: camera } } }); + await showHUD(`Switching Camera to ${camera}`); +} diff --git a/packages/raycast/src/switch-mic.ts b/packages/raycast/src/switch-mic.ts new file mode 100644 index 00000000000..e0d6cd7825f --- /dev/null +++ b/packages/raycast/src/switch-mic.ts @@ -0,0 +1,12 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +interface Arguments { + mic: string; +} + +export default async function Command(props: { arguments: Arguments }) { + const { mic } = props.arguments; + await triggerAction({ switch_mic: { mic_label: mic } }); + await showHUD(`Switching Microphone to ${mic}`); +} diff --git a/packages/raycast/src/toggle-pause.ts b/packages/raycast/src/toggle-pause.ts new file mode 100644 index 00000000000..fde7bfc0fc3 --- /dev/null +++ b/packages/raycast/src/toggle-pause.ts @@ -0,0 +1,7 @@ +import { triggerAction } from "./utils"; +import { showHUD } from "@raycast/api"; + +export default async function Command() { + await triggerAction("toggle_pause_recording"); + await showHUD("Toggling Cap Pause"); +} diff --git a/packages/raycast/src/utils.ts b/packages/raycast/src/utils.ts new file mode 100644 index 00000000000..f632e984caf --- /dev/null +++ b/packages/raycast/src/utils.ts @@ -0,0 +1,12 @@ +import { open, showHUD } from "@raycast/api"; + +export async function triggerAction(action: any) { + try { + const json = JSON.stringify(action); + const url = `cap-desktop://action?value=${encodeURIComponent(json)}`; + await open(url); + } catch (error) { + await showHUD("Failed to trigger Cap action"); + console.error(error); + } +}