Skip to content

feat: confirmation dialog before stopping a recording - #12

Merged
dloomis merged 8 commits into
mainfrom
stop-recording-confirmation
Jul 17, 2026
Merged

feat: confirmation dialog before stopping a recording#12
dloomis merged 8 commits into
mainfrom
stop-recording-confirmation

Conversation

@nicw

@nicw nicw commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Problem

It's too easy to stop a recording: the main Stop Recording button (and its ⌘. shortcut) tore the session down on a single click, and accidental clicks mid-meeting kept ending sessions irreversibly (transcript finalizes, post-processing starts).

Change

The main Stop button now presents a standard alert — "Are you sure you want to stop recording?" — with Cancel as the default button (Return cancels) and a destructive Stop Recording button. Capture, transcription, and the timers keep running while the dialog is up; nothing stops until the explicit confirm.

Only the main button confirms. Deliberately unchanged:

Path Why
Silence prompt "Stop & Save" Already a confirmation
Notification "Stop Recording" action Mirror of the silence prompt
POST /sessions/stop Must stay scriptable; API/** untouched

Implementation: a small @Observable StopConfirmationModel owns the confirmation lifecycle (so it's unit-testable); ControlBar's shared onStop closure splits into onStopRequested (main button) and onStop (silence prompt); ContentView hosts the .alert and withdraws it via the existing isRunning onChange if the session ends through any other path (capture error, API stop, notification stop). A stale confirm racing a stop is a no-op via stopSession()'s existing re-entrance guard.

Spec and plan are included under docs/superpowers/.

Testing

  • 6 unit tests on the model (confirm fires exactly once; cancel/external-end fire nothing; a pinning test guards the deliberately-unguarded confirmStop() — SwiftUI clears the alert binding before running the button action, so adding guard isPresented would silently break every confirm).
  • Full suite: 100 tests in 18 suites, all passing.
  • Manual checklist on a live dev build: dialog presents mid-recording with the timer running behind it, Cancel resumes, confirm finalizes normally, Return cancels, silence prompt shows no second dialog, API stop withdraws the open dialog.

Known limitation (documented in the spec): Esc does not cancel — SwiftUI drops the cancel-role's implicit Esc equivalent when the button also carries .keyboardShortcut(.defaultAction), and a button holds one shortcut. We kept the verified Return-cancels-by-default behavior rather than trading it for Esc; bail-out is Return or clicking Cancel.

🤖 Generated with Claude Code

nicw and others added 8 commits July 13, 2026 11:01
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Accidental clicks mid-meeting were irreversibly ending sessions. The main
Stop button (and its Cmd-. shortcut) now presents 'Are you sure you want
to stop recording?' with Cancel as the default; the silence prompt,
notification action, and HTTP API still stop directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ts at boot

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… dead

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve ContentView.swift conflict: the isRunning onChange keeps both
main's APIServer state mirroring and the PR's stop-confirmation
withdrawal when the session ends through another path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dloomis
dloomis merged commit bf1f0fb into main Jul 17, 2026
@dloomis
dloomis deleted the stop-recording-confirmation branch July 17, 2026 21:39
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.

2 participants