-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Bounty: Deeplinks support + Raycast Extension #1628
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
67cd96e
0ec5e67
b7770db
5738188
a16614c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,7 +30,7 @@ | |
| "updater": { "active": false, "pubkey": "" }, | ||
| "deep-link": { | ||
| "desktop": { | ||
| "schemes": ["cap-desktop"] | ||
| "schemes": ["cap-desktop", "cap"] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding the global |
||
| } | ||
| } | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| { | ||
| "$schema": "https://www.raycast.com/schemas/extension.json", | ||
| "name": "cap", | ||
| "title": "Cap", | ||
| "description": "Control Cap screen recording from Raycast", | ||
| "icon": "extension-icon.png", | ||
| "author": "cap", | ||
| "categories": ["Media", "Productivity"], | ||
| "license": "MIT", | ||
| "commands": [ | ||
| { | ||
| "name": "start-recording", | ||
| "title": "Start Recording", | ||
| "subtitle": "Cap", | ||
| "description": "Start a new Cap screen recording session", | ||
| "mode": "no-view", | ||
| "preferences": [ | ||
| { | ||
| "name": "captureType", | ||
| "title": "Capture Type", | ||
| "description": "Whether to capture a screen or a window", | ||
| "type": "dropdown", | ||
| "required": true, | ||
| "default": "screen", | ||
| "data": [ | ||
| { "title": "Screen", "value": "screen" }, | ||
| { "title": "Window", "value": "window" } | ||
| ] | ||
| }, | ||
| { | ||
| "name": "captureName", | ||
| "title": "Screen or Window Name", | ||
| "description": "Exact name of the screen or window to capture", | ||
| "type": "textfield", | ||
| "required": false, | ||
| "default": "" | ||
| }, | ||
| { | ||
| "name": "captureSystemAudio", | ||
| "title": "System Audio", | ||
| "description": "Capture system audio alongside the recording", | ||
| "type": "checkbox", | ||
| "required": false, | ||
| "default": false, | ||
| "label": "Capture system audio" | ||
| }, | ||
| { | ||
| "name": "recordingMode", | ||
| "title": "Recording Mode", | ||
| "description": "Instant shares immediately; Studio lets you edit first", | ||
| "type": "dropdown", | ||
| "required": false, | ||
| "default": "studio", | ||
| "data": [ | ||
| { "title": "Instant", "value": "instant" }, | ||
| { "title": "Studio", "value": "studio" } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "name": "stop-recording", | ||
| "title": "Stop Recording", | ||
| "subtitle": "Cap", | ||
| "description": "Stop the current Cap screen recording", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "pause-recording", | ||
| "title": "Pause Recording", | ||
| "subtitle": "Cap", | ||
| "description": "Pause the current Cap screen recording", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "resume-recording", | ||
| "title": "Resume Recording", | ||
| "subtitle": "Cap", | ||
| "description": "Resume the paused Cap screen recording", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "switch-microphone", | ||
| "title": "Switch Microphone", | ||
| "subtitle": "Cap", | ||
| "description": "Switch the active microphone used by Cap", | ||
| "mode": "view" | ||
| }, | ||
| { | ||
| "name": "switch-camera", | ||
| "title": "Switch Camera", | ||
| "subtitle": "Cap", | ||
| "description": "Switch the active camera used by Cap", | ||
| "mode": "view" | ||
| } | ||
| ], | ||
| "dependencies": { | ||
| "@raycast/api": "^1.68.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@raycast/utils": "^1.15.0", | ||
| "@types/node": "20.8.10", | ||
| "@types/react": "18.3.3", | ||
| "eslint": "^8.57.0", | ||
| "prettier": "^3.2.5", | ||
| "typescript": "^5.4.5" | ||
| }, | ||
| "scripts": { | ||
| "build": "ray build -e dist", | ||
| "dev": "ray develop", | ||
| "fix-lint": "ray lint --fix", | ||
| "lint": "ray lint", | ||
| "publish": "npx @raycast/api@latest publish" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { closeMainWindow, open, showHUD } from "@raycast/api"; | ||
|
|
||
| export default async function Command() { | ||
| await closeMainWindow(); | ||
| await open("cap://pause-recording"); | ||
| await showHUD("Pausing recording…"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { closeMainWindow, open, showHUD } from "@raycast/api"; | ||
|
|
||
| export default async function Command() { | ||
| await closeMainWindow(); | ||
| await open("cap://resume-recording"); | ||
| await showHUD("Resuming recording…"); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||||
| import { closeMainWindow, getPreferenceValues, open, showHUD } from "@raycast/api"; | ||||||
|
|
||||||
| interface Preferences { | ||||||
| captureType: "screen" | "window"; | ||||||
| captureName: string; | ||||||
| captureSystemAudio: boolean; | ||||||
| recordingMode: "instant" | "studio"; | ||||||
| } | ||||||
|
|
||||||
| export default async function Command() { | ||||||
| const prefs = getPreferenceValues<Preferences>(); | ||||||
|
|
||||||
| const captureName = prefs.captureName?.trim(); | ||||||
| if (!captureName) { | ||||||
| await showHUD("Set a screen/window name in Raycast preferences first"); | ||||||
| return; | ||||||
| } | ||||||
| const captureMode = | ||||||
| prefs.captureType === "window" | ||||||
| ? { window: captureName } | ||||||
| : { screen: captureName }; | ||||||
|
|
||||||
| const action = { | ||||||
| start_recording: { | ||||||
| capture_mode: captureMode, | ||||||
| camera: null, | ||||||
| mic_label: null, | ||||||
| capture_system_audio: prefs.captureSystemAudio ?? false, | ||||||
| mode: prefs.recordingMode ?? "instant", | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Prompt To Fix With AIThis is a comment left during a code review.
Path: apps/raycast-extension/src/start-recording.tsx
Line: 25
Comment:
`instant_capture` doesn't match the Rust `RecordingMode` enum values (`studio` or `instant`)
```suggestion
mode: prefs.recordingMode ?? "instant",
```
How can I resolve this? If you propose a fix, please make it concise. |
||||||
| }, | ||||||
| }; | ||||||
|
|
||||||
| const url = `cap://action?value=${encodeURIComponent(JSON.stringify(action))}`; | ||||||
|
|
||||||
| await closeMainWindow(); | ||||||
| await open(url); | ||||||
| await showHUD("Starting recording…"); | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { closeMainWindow, open, showHUD } from "@raycast/api"; | ||
|
|
||
| export default async function Command() { | ||
| await closeMainWindow(); | ||
| await open("cap://stop-recording"); | ||
| await showHUD("Stopping recording…"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { Action, ActionPanel, Form, closeMainWindow, open, showHUD } from "@raycast/api"; | ||
|
|
||
| interface Values { | ||
| id: string; | ||
| } | ||
|
|
||
| export default function Command() { | ||
| async function handleSubmit(values: Values) { | ||
| const id = values.id.trim(); | ||
| const url = id | ||
| ? `cap://switch-camera?id=${encodeURIComponent(id)}` | ||
| : "cap://switch-camera"; | ||
|
|
||
| await closeMainWindow(); | ||
| await open(url); | ||
| await showHUD(id ? `Switching camera to: ${id}` : "Disabling camera"); | ||
| } | ||
|
|
||
| return ( | ||
| <Form | ||
| actions={ | ||
| <ActionPanel> | ||
| <Action.SubmitForm title="Switch Camera" onSubmit={handleSubmit} /> | ||
| </ActionPanel> | ||
| } | ||
| > | ||
| <Form.TextField | ||
| id="id" | ||
| title="Camera ID" | ||
| placeholder="e.g. FaceTime HD Camera (leave blank to disable)" | ||
| autoFocus | ||
| /> | ||
| </Form> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { Action, ActionPanel, Form, closeMainWindow, open, showHUD } from "@raycast/api"; | ||
|
|
||
| interface Values { | ||
| label: string; | ||
| } | ||
|
|
||
| export default function Command() { | ||
| async function handleSubmit(values: Values) { | ||
| const label = values.label.trim(); | ||
| const url = label | ||
| ? `cap://switch-mic?label=${encodeURIComponent(label)}` | ||
| : "cap://switch-mic"; | ||
|
|
||
| await closeMainWindow(); | ||
| await open(url); | ||
| await showHUD(label ? `Switching microphone to: ${label}` : "Disabling microphone"); | ||
| } | ||
|
|
||
| return ( | ||
| <Form | ||
| actions={ | ||
| <ActionPanel> | ||
| <Action.SubmitForm title="Switch Microphone" onSubmit={handleSubmit} /> | ||
| </ActionPanel> | ||
| } | ||
| > | ||
| <Form.TextField | ||
| id="label" | ||
| title="Microphone Label" | ||
| placeholder="e.g. Built-in Microphone (leave blank to disable)" | ||
| autoFocus | ||
| /> | ||
| </Form> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "target": "ES2020", | ||
| "lib": ["ES2020"], | ||
| "module": "CommonJS", | ||
| "moduleResolution": "node", | ||
| "jsx": "react-jsx", | ||
| "strict": true, | ||
| "esModuleInterop": true, | ||
| "skipLibCheck": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "baseUrl": "." | ||
| }, | ||
| "include": ["src/**/*"] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DeviceOrModelIDis an externally-tagged enum (DeviceID/ModelID), so deserializing from a plain string will always fail. As-is,cap://switch-camera?id=<some id>likely resolves toid: Noneand disables the camera instead of switching.