Skip to content

feat(desktop): add settings toggle to disable UI animations and visual effects (#1853) - #2093

Open
Samarth1306w wants to merge 9 commits into
CapSoftware:mainfrom
Samarth1306w:feat/disable-animations-setting-toggle-1853
Open

feat(desktop): add settings toggle to disable UI animations and visual effects (#1853)#2093
Samarth1306w wants to merge 9 commits into
CapSoftware:mainfrom
Samarth1306w:feat/disable-animations-setting-toggle-1853

Conversation

@Samarth1306w

@Samarth1306w Samarth1306w commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #1853

Summary

Add user preference setting to toggle visual UI entry and selection animations in Cap Desktop.

  1. ****:
    • Added with attribute to .
  2. ****:
    • Added to TypeScript interface and helper.
  3. ****:
    • Added Disable visual animations under new Interface & Performance settings section.

Greptile Summary

This PR adds a desktop preference for disabling visual animations while also introducing unrelated CLI recording metadata, developer transcript, tray-hotkey, teleprompter, API rate-limit, and configurable OpenAI endpoint changes.

  • Persists and exposes the desktop disableAnimations setting.
  • Adds cap recordings info and a video metadata GET endpoint.
  • Adds developer transcript retrieval and tray accelerator labels.
  • Adjusts desktop/mobile teleprompter behavior and applies rate limiting to selected web APIs.
  • Adds OPENAI_BASE_URL support for compatible AI providers.

Confidence Score: 1/5

This PR is not safe to merge until the metadata authorization bypass, unusable transcript response, and trailing-slash CLI parsing failure are fixed.

The metadata API discloses protected video-derived content without applying the existing access policy, the developer transcript endpoint cannot deliver completed transcripts, and valid trailing-slash share URLs fail in the new CLI command.

Files Needing Attention: apps/web/app/api/video/metadata/route.ts, apps/web/app/api/developer/v1/[...route]/videos.ts, apps/cli/src/recordings.rs

Security Review

The new video metadata endpoint bypasses existing password and domain access policies for public videos, allowing unauthenticated disclosure of AI-generated titles, summaries, and chapters.

Important Files Changed

Filename Overview
apps/web/app/api/video/metadata/route.ts Adds metadata retrieval but bypasses established public-video access restrictions and repository API/type conventions.
apps/web/app/api/developer/v1/[...route]/videos.ts Adds a transcript endpoint that returns the raw video's S3 key rather than retrievable transcript data.
apps/cli/src/recordings.rs Adds recording metadata lookup, but trailing-slash share URLs are parsed as an empty video ID.
apps/desktop/src-tauri/src/general_settings.rs Adds a backward-compatible, default-false persisted disableAnimations field.
apps/desktop/src/routes/(window-chrome)/settings/general.tsx Adds the interface-performance settings toggle using the existing settings mutation path.
apps/desktop/src-tauri/src/hotkeys.rs Exposes accelerator formatting and refreshes the tray after hotkey updates.
apps/desktop/src-tauri/src/tray.rs Displays configured hotkeys beside relevant tray actions.
apps/mobile/src/recording/TeleprompterOverlay.tsx Preserves teleprompter progress during subsequent text layout measurements.
packages/env/server.ts Adds an optional validated base URL for OpenAI-compatible endpoints.
Prompt To Fix All With AI
### Issue 1
apps/web/app/api/video/metadata/route.ts:60-62
**Metadata bypasses video access policy**

When a public video is protected by a video or space password or an allowed-email-domain restriction, this owner-only check still returns its AI title, summary, and chapters to an unauthenticated caller. The endpoint needs to apply the same effective viewing policy as the share page. **How this was verified:** The new check was compared with the share-page policy, which verifies password candidates and other effective access rules even for public videos.

### Issue 2
apps/web/app/api/developer/v1/[...route]/videos.ts:158-164
**Transcript endpoint returns video key**

When a developer requests a transcript after processing completes, this response returns the raw video's `s3Key` rather than transcript content or a usable transcript location. Because transcripts are stored under a separate owner-based `transcription.vtt` path unavailable to the client, the caller cannot retrieve the completed transcript.

### Issue 3
apps/cli/src/recordings.rs:110-118
**Trailing slash empties video ID**

When a valid share URL ends with `/`, `rsplit('/').next()` returns an empty string, so the metadata request sends an empty `videoId` and the command fails with a 400 response. Parse the URL and select the final non-empty path segment, as the existing CLI ID parser does.

### Issue 4
apps/web/app/api/video/metadata/route.ts:43-57
**Route bypasses typed API conventions**

This new ad-hoc GET handler bypasses the repository's `HttpApi` endpoint pattern and casts persisted metadata through `Record<string, any>`. Using the standard typed contract and narrowing metadata from `unknown` would prevent unchecked shape drift from propagating into the response.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(desktop): add settings toggle to di..." | Re-trigger Greptile

Greptile also left 4 inline comments on this PR.

Context used (6)

@superagent-security

Copy link
Copy Markdown

🚨 Contributor flagged. Click here for more info: Superagent Dashboard

Comment on lines +60 to +62
if (!video.public && video.ownerId !== user?.id) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}

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.

P1 security Metadata bypasses video access policy

When a public video is protected by a video or space password or an allowed-email-domain restriction, this owner-only check still returns its AI title, summary, and chapters to an unauthenticated caller. The endpoint needs to apply the same effective viewing policy as the share page. How this was verified: The new check was compared with the share-page policy, which verifies password candidates and other effective access rules even for public videos.

Knowledge Base Used: Web App (apps/web)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/video/metadata/route.ts
Line: 60-62

Comment:
**Metadata bypasses video access policy**

When a public video is protected by a video or space password or an allowed-email-domain restriction, this owner-only check still returns its AI title, summary, and chapters to an unauthenticated caller. The endpoint needs to apply the same effective viewing policy as the share page. **How this was verified:** The new check was compared with the share-page policy, which verifies password candidates and other effective access rules even for public videos.

**Knowledge Base Used:** [Web App (apps/web)](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/web-app.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +158 to +164
return c.json({
data: {
id: video.id,
transcriptionStatus: video.transcriptionStatus,
s3Key: video.s3Key,
},
});

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.

P1 Transcript endpoint returns video key

When a developer requests a transcript after processing completes, this response returns the raw video's s3Key rather than transcript content or a usable transcript location. Because transcripts are stored under a separate owner-based transcription.vtt path unavailable to the client, the caller cannot retrieve the completed transcript.

Knowledge Base Used: Web App (apps/web)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/developer/v1/[...route]/videos.ts
Line: 158-164

Comment:
**Transcript endpoint returns video key**

When a developer requests a transcript after processing completes, this response returns the raw video's `s3Key` rather than transcript content or a usable transcript location. Because transcripts are stored under a separate owner-based `transcription.vtt` path unavailable to the client, the caller cannot retrieve the completed transcript.

**Knowledge Base Used:** [Web App (apps/web)](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/web-app.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +110 to +118
pub async fn info(url_or_id: String, format: OutputFormat) -> Result<(), String> {
let video_id = if url_or_id.contains('/') {
url_or_id
.rsplit('/')
.next()
.unwrap_or(&url_or_id)
.to_string()
} else {
url_or_id

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.

P1 Trailing slash empties video ID

When a valid share URL ends with /, rsplit('/').next() returns an empty string, so the metadata request sends an empty videoId and the command fails with a 400 response. Parse the URL and select the final non-empty path segment, as the existing CLI ID parser does.

Knowledge Base Used: Cap CLI (apps/cli)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/cli/src/recordings.rs
Line: 110-118

Comment:
**Trailing slash empties video ID**

When a valid share URL ends with `/`, `rsplit('/').next()` returns an empty string, so the metadata request sends an empty `videoId` and the command fails with a 400 response. Parse the URL and select the final non-empty path segment, as the existing CLI ID parser does.

**Knowledge Base Used:** [Cap CLI (`apps/cli`)](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/cli.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +43 to +57
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const videoId = searchParams.get("videoId");

if (!videoId) {
return Response.json({ error: "Missing videoId parameter" }, { status: 400 });
}

const query = await db().select().from(videos).where(eq(videos.id, videoId));

if (query.length === 0 || !query[0]) {
return Response.json({ error: "Video not found" }, { status: 404 });
}

const video = query[0];

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 Route bypasses typed API conventions

This new ad-hoc GET handler bypasses the repository's HttpApi endpoint pattern and casts persisted metadata through Record<string, any>. Using the standard typed contract and narrowing metadata from unknown would prevent unchecked shape drift from propagating into the response.

Context Used: AGENTS.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/video/metadata/route.ts
Line: 43-57

Comment:
**Route bypasses typed API conventions**

This new ad-hoc GET handler bypasses the repository's `HttpApi` endpoint pattern and casts persisted metadata through `Record<string, any>`. Using the standard typed contract and narrowing metadata from `unknown` would prevent unchecked shape drift from propagating into the response.

**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Settings toggles to disable screenshot animations and UI sound effects

2 participants