-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[Fix] Add Cap deeplinks and Raycast controls #1811
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
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "extends": ["@raycast"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| { | ||
| "$schema": "https://www.raycast.com/schemas/extension.json", | ||
| "name": "cap-raycast", | ||
| "title": "Cap", | ||
| "description": "Control Cap recordings with deeplinks.", | ||
| "icon": "command-icon.png", | ||
| "author": "Cap", | ||
| "license": "MIT", | ||
| "commands": [ | ||
| { | ||
| "name": "start-recording", | ||
| "title": "Start Recording", | ||
| "description": "Start a Cap recording with a display or window target.", | ||
| "mode": "view" | ||
| }, | ||
| { | ||
| "name": "stop-recording", | ||
| "title": "Stop Recording", | ||
| "description": "Stop the current Cap recording.", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "pause-recording", | ||
| "title": "Pause Recording", | ||
| "description": "Pause the current Cap recording.", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "resume-recording", | ||
| "title": "Resume Recording", | ||
| "description": "Resume the current Cap recording.", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "toggle-pause-recording", | ||
| "title": "Toggle Pause Recording", | ||
| "description": "Toggle pause for the current Cap recording.", | ||
| "mode": "no-view" | ||
| }, | ||
| { | ||
| "name": "set-microphone", | ||
| "title": "Set Microphone", | ||
| "description": "Set or clear Cap's microphone input.", | ||
| "mode": "view" | ||
| }, | ||
| { | ||
| "name": "set-camera", | ||
| "title": "Set Camera", | ||
| "description": "Set or clear Cap's camera input.", | ||
| "mode": "view" | ||
| }, | ||
| { | ||
| "name": "open-settings", | ||
| "title": "Open Settings", | ||
| "description": "Open Cap settings.", | ||
| "mode": "view" | ||
| } | ||
| ], | ||
| "dependencies": { | ||
| "@raycast/api": "^1.83.2" | ||
| }, | ||
| "devDependencies": { | ||
| "@raycast/eslint-config": "^1.0.11", | ||
| "@types/node": "^20.17.6", | ||
| "eslint": "^8.57.1", | ||
| "prettier": "^3.3.3", | ||
| "typescript": "^5.6.3" | ||
| }, | ||
| "scripts": { | ||
| "build": "ray build -e dist", | ||
| "dev": "ray develop", | ||
| "lint": "ray lint", | ||
| "fix-lint": "ray lint --fix" | ||
| } | ||
| } | ||
|
Comment on lines
+1
to
+75
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.
The Raycast manifest recommends declaring a Prompt To Fix With AIThis is a comment left during a code review.
Path: apps/raycast/package.json
Line: 1-75
Comment:
**Missing `platforms` field and `package-lock.json`**
The Raycast manifest recommends declaring a `platforms` field (e.g., `["macOS"]`) so users on other platforms are informed the extension is macOS-only. Additionally, Raycast's store CI builds extensions with `npm` using `package-lock.json`; without one the lockfile is missing and dependency versions aren't pinned for store validation.
How can I resolve this? If you propose a fix, please make it concise. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /// <reference types="@raycast/api"> | ||
|
|
||
| /* 🚧 🚧 🚧 | ||
| * This file is auto-generated from the extension's manifest. | ||
| * Do not modify manually. Instead, update the `package.json` file. | ||
| * 🚧 🚧 🚧 */ | ||
|
|
||
| /* eslint-disable @typescript-eslint/ban-types */ | ||
|
|
||
| type ExtensionPreferences = {} | ||
|
|
||
| /** Preferences accessible in all the extension's commands */ | ||
| declare type Preferences = ExtensionPreferences | ||
|
|
||
| declare namespace Preferences { | ||
| /** Preferences accessible in the `start-recording` command */ | ||
| export type StartRecording = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `stop-recording` command */ | ||
| export type StopRecording = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `pause-recording` command */ | ||
| export type PauseRecording = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `resume-recording` command */ | ||
| export type ResumeRecording = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `toggle-pause-recording` command */ | ||
| export type TogglePauseRecording = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `set-microphone` command */ | ||
| export type SetMicrophone = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `set-camera` command */ | ||
| export type SetCamera = ExtensionPreferences & {} | ||
| /** Preferences accessible in the `open-settings` command */ | ||
| export type OpenSettings = ExtensionPreferences & {} | ||
| } | ||
|
|
||
| declare namespace Arguments { | ||
| /** Arguments passed to the `start-recording` command */ | ||
| export type StartRecording = {} | ||
| /** Arguments passed to the `stop-recording` command */ | ||
| export type StopRecording = {} | ||
| /** Arguments passed to the `pause-recording` command */ | ||
| export type PauseRecording = {} | ||
| /** Arguments passed to the `resume-recording` command */ | ||
| export type ResumeRecording = {} | ||
| /** Arguments passed to the `toggle-pause-recording` command */ | ||
| export type TogglePauseRecording = {} | ||
| /** Arguments passed to the `set-microphone` command */ | ||
| export type SetMicrophone = {} | ||
| /** Arguments passed to the `set-camera` command */ | ||
| export type SetCamera = {} | ||
| /** Arguments passed to the `open-settings` command */ | ||
| export type OpenSettings = {} | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { open, showHUD } from "@raycast/api"; | ||
|
|
||
| const SCHEME = "cap-desktop://action"; | ||
|
|
||
| export type QueryParams = Record<string, string | boolean | undefined>; | ||
|
|
||
| export async function openCapAction(action: string, params: QueryParams = {}) { | ||
| const url = new URL(`${SCHEME}/${action}`); | ||
|
|
||
| for (const [key, value] of Object.entries(params)) { | ||
| if (value !== undefined && value !== "") | ||
| url.searchParams.set(key, String(value)); | ||
| } | ||
|
Comment on lines
+10
to
+13
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.
The guard Prompt To Fix With AIThis is a comment left during a code review.
Path: apps/raycast/src/cap.ts
Line: 10-13
Comment:
**`false` boolean values are always appended to URLs even when they are the server-side default**
The guard `value !== undefined && value !== ""` passes `false` booleans through, so `start-recording` always appends `system_audio=false` to the URL. In `parse_bool_param` the default is already `false`, so this is redundant. Consider also filtering out `false` unless the param is required.
How can I resolve this? If you propose a fix, please make it concise. |
||
|
|
||
| await open(url.toString()); | ||
| } | ||
|
|
||
| export async function runNoViewAction(action: string, hudTitle: string) { | ||
| await openCapAction(action); | ||
| await showHUD(hudTitle); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { Action, ActionPanel, Form, showToast, Toast } from "@raycast/api"; | ||
| import { openCapAction } from "./cap"; | ||
|
|
||
| type Values = { page?: string }; | ||
|
|
||
| export default function Command() { | ||
| async function submit(values: Values) { | ||
| await openCapAction("settings", { page: values.page?.trim() }); | ||
| await showToast({ | ||
| style: Toast.Style.Success, | ||
| title: "Opening Cap settings", | ||
| }); | ||
| } | ||
|
|
||
| return ( | ||
| <Form | ||
| actions={ | ||
| <ActionPanel> | ||
| <Action.SubmitForm title="Open Settings" onSubmit={submit} /> | ||
| </ActionPanel> | ||
| } | ||
| > | ||
| <Form.TextField | ||
| id="page" | ||
| title="Page" | ||
| placeholder="Optional settings page" | ||
| /> | ||
| </Form> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import { runNoViewAction } from "./cap"; | ||
| export default async function Command() { | ||
| await runNoViewAction("pause", "Pausing Cap recording"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import { runNoViewAction } from "./cap"; | ||
| export default async function Command() { | ||
| await runNoViewAction("resume", "Resuming Cap recording"); | ||
| } |
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.
parse_bool_paramonly accepts lowercase"true"/"false"Rust's
str::parse::<bool>()is case-sensitive and recognises exactly"true"and"false". Values like"1","0","True", or"yes"silently fall back todefault. For a URL-based API called by scripts or integrations outside the Raycast extension, this can cause unexpected silent misbehaviour.Prompt To Fix With AI