Skip to content

feat: confirm recordings without a microphone - #2047

Merged
richiemcilroy merged 2 commits into
mainfrom
feature/no-microphone-recording-warning
Jul 28, 2026
Merged

feat: confirm recordings without a microphone#2047
richiemcilroy merged 2 commits into
mainfrom
feature/no-microphone-recording-warning

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Jul 28, 2026

Copy link
Copy Markdown
Member

Summary

  • add an enabled-by-default General Settings preference requiring confirmation before recording without an available selected microphone
  • show an anchored picker warning and a native confirmation for direct Studio/Instant shortcuts
  • preserve existing behavior for screenshots, automation/deep links, valid microphones, and users who disable the preference

Validation

  • pnpm exec biome check on the five touched TypeScript files
  • desktop TypeScript type check
  • 12 focused Vitest tests
  • cargo fmt --all -- --check
  • cargo check -p cap-desktop
  • 3 focused hotkey unit tests
  • isolated diff integrity checks

Runtime UI smoke testing was not performed because the shared desktop runtime was owned by another active session.

Greptile Summary

Adds an enabled-by-default recording safety preference for missing microphones.

  • Adds persisted settings and shared decision logic for microphone confirmation.
  • Shows a picker warning before Studio or Instant recording without an available selected microphone.
  • Adds native confirmation for direct recording hotkeys while preserving active-recording and screenshot behavior.
  • Adds focused TypeScript and Rust tests for the new decision logic.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/desktop/src-tauri/src/hotkeys.rs Adds microphone availability checks and native confirmation before direct Studio or Instant hotkey starts.
apps/desktop/src/routes/(window-chrome)/settings/general.tsx Adds the persisted General Settings toggle and optimistic update rollback.
apps/desktop/src/routes/target-select-overlay.tsx Adds the anchored no-microphone warning and explicitly displays “Preparing...” while required queries initially load.
apps/desktop/src/store.ts Defines the defaulted persisted recording-start safety store and query integration.
apps/desktop/src/utils/general-settings.ts Defines the safety preference shape, defaults, and recording-mode confirmation predicate.
apps/desktop/src/utils/general-settings.test.ts Covers enabled, disabled, microphone-available, and screenshot decision cases.

Reviews (2): Last reviewed commit: "fix: show recording start loading state" | Re-trigger Greptile

@cursor

cursor Bot commented Jul 28, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Comment thread apps/desktop/src/routes/target-select-overlay.tsx Outdated

Copy link
Copy Markdown
Member Author

hey @greptileai, please re-review the PR

}
};

const handleRecordingStartSafetyChange = async (value: boolean) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor edge case: if the user toggles this quickly, multiple recordingStartSafetyStore.set(...) calls can overlap and resolve out-of-order (older write finishing last), leaving the persisted value different from the last toggle. Might be worth serializing writes (promise chain) or disabling the toggle while a save is in-flight so the last intent wins deterministically.

// This webview is hidden by now, so the toast is a
// best-effort extra — the visible feedback comes from the
// backend's StartFailed event toasted in the main window.
if (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The msg.includes(...) checks here are a bit brittle (string-matching on error text). If the backend can return a structured error code, it’d be more resilient to key off that; otherwise, consider centralizing these substrings as constants so the UI + backend stay in sync.

let _ = sender.send(confirmed);
});

receiver.await.unwrap_or(false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor robustness: if the dialog callback never fires (plugin failure, window closes, etc), this await will hang the hotkey task. Consider adding a timeout and treating it as cancel.

Suggested change
receiver.await.unwrap_or(false)
tokio::time::timeout(std::time::Duration::from_secs(60), receiver)
.await
.ok()
.and_then(Result::ok)
.unwrap_or(false)

@richiemcilroy
richiemcilroy merged commit 7e7ef19 into main Jul 28, 2026
23 of 24 checks passed
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.

1 participant