Skip to content

Allow clearing recording shortcuts#86

Closed
tkonya wants to merge 230 commits into
matthartman:mainfrom
getBanyan:feature/clearable-shortcuts
Closed

Allow clearing recording shortcuts#86
tkonya wants to merge 230 commits into
matthartman:mainfrom
getBanyan:feature/clearable-shortcuts

Conversation

@tkonya

@tkonya tkonya commented Apr 22, 2026

Copy link
Copy Markdown

Summary

Adds the ability to clear any of the three configurable recording shortcuts (Hold to Record, Toggle Recording, and Context Bundler), so users who don't want a given feature bound to a hotkey can remove the binding entirely. Previously these were required to always hold some chord.

Two ways to clear, both standard macOS patterns:

  • A small × button rendered inline next to the chord in Settings (visible only when a chord is bound).
  • Pressing Delete/Backspace while the recorder is in capture mode (alongside existing Escape to cancel).

Implementation notes

  • ChordBindingStore now exposes a tri-state BindingState (unset/cleared/set(KeyChord)) and a dedicated clearBinding(for:). A separate UserDefaults flag marks an action as explicitly cleared, which keeps first-run default fallbacks working — a newly-installed user still gets the default chord, but a user who cleared their binding stays cleared across relaunches.
  • AppState's three chord properties become KeyChord?. Cleared actions are simply omitted from the dict handed to HotkeyMonitor, so no hotkey registers for them.
  • ShortcutRecorderView accepts KeyChord?, shows "None" when unbound, renders an xmark.circle.fill clear button when bound, and handles Delete during capture to clear (keyCode 51 with no captured keys).

No format or persistence migration needed for existing users — previously-stored chord data continues to decode as .set(chord).

Test plan

  • Project builds in Xcode 16+
  • ChordBindingStoreTests pass (new coverage for .unset, persisted .cleared, re-set after clear, and "cleared != duplicate")
  • Existing GhostPepperTests pass (shortcut-related tests compare KeyChord? against KeyChord — relying on Swift's optional equality)
  • Fresh install: defaults still populate for all three shortcuts
  • Click × next to a bound shortcut → button shows "None", hotkey stops firing, state persists across relaunch
  • Click the chord button, press Delete → same result
  • Click the chord button, press Escape → cancels without clearing
  • Re-record a chord on a cleared action → works, the previously-bound chord (now cleared) is not treated as a duplicate

matthartman and others added 30 commits March 23, 2026 14:53
Models section shows each model with loaded/not loaded status.
Taller settings window (580px) to fit all sections.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows when any model isn't loaded. Downloads WhisperKit and/or
cleanup models directly from Settings — no need to re-run onboarding.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LLM.swift's bundled llama.cpp doesn't support Qwen3/3.5 architecture.
Reverted to Qwen 2.5 1.5B + 3B which work reliably.
Will upgrade when LLM.swift updates its llama.cpp.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Info.plist was still at v1.1 so Sparkle thought the "update"
was the same version. Now properly at v1.3 build 4.
Fixes #2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Improve post-paste learning via Accessibility
Picker in Settings under Input section. Switching models triggers
re-download and reload. Default remains small.en for accuracy.
tiny.en is ~75 MB and much faster for shorter recordings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…oggle)

Matches the original Ghost Pepper behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Input Monitoring prompt doesn't reliably show the system dialog
for debug-signed apps. Now attempts to start the hotkey monitor
even without it — Accessibility alone is sufficient for Control key.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixed codesign verification failure reported in #4.
Now verifies signature after extracting from DMG before release.

Also includes: speech model picker, default Control shortcuts,
non-blocking Input Monitoring check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
macOS kills the app after Screen Recording is granted but doesn't
relaunch it. Now spawns a background process that reopens the app
after 3 seconds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace no-audio modal with status pill
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses #5 — users should know about local transcript log
and auto-launch behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
File-based logging was replaced by in-memory DebugLogStore.
Nothing is written to disk. Updated disclosure accordingly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
No longer blocks Continue button. Shown as "(optional)" with
a bordered (not prominent) Enable button. Users can skip it
and enable later in Settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matches WhisperFlow and other dictation tools.
Toggle is Right Command + Right Option + Space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Supports Spanish and 90+ other languages. Same size as small.en.
Users can tweak the cleanup prompt for their language's filler words.
Addresses #6.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
obra and others added 27 commits April 17, 2026 15:50
Reduce transcription latency and improve speaker tagging
…idebar, detect meeting name & attendees

- Inline summary prompt editor with model picker on Summary tab (click "Customize")
- "Imported from Granola" badge on imported meeting files
- Granola files show green import icon in sidebar, no speaker badges on transcript
- Resizable sidebar (drag divider, 160-400px range)
- Sidebar open by default when Meetings window opens
- "Detect" button grabs meeting name from Zoom/Teams window title + OCR attendees
- Auto-detect scans known meeting apps even for manual recordings
- Attendee OCR retries at 3s, 15s, 30s, 60s to catch late joiners
- Attendees accumulate across retries (no duplicates)
- Title auto-update only marks as done on success (retries on failure)
- "Zoom Meeting" cleaned from window titles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rowser meetings

- Test dictation now uses selected mic (was always using system default)
- Settings mic picker initializes from saved selection, not system default
- Detect button activates meeting app (including browsers) before OCR
- Added browser bundle IDs (Brave, Chrome, Arc, Safari, Firefox) for Google Meet detection
- Falls back to frontmost non-Ghost Pepper app if no known meeting app found
- Attendee chips UI instead of plain text
- Debug logging for attendee OCR capture
- Cleaned "Zoom Meeting" from window titles

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- One-time migration: enables meetingTranscriptEnabled for existing users
  (detects update by checking if selectedCleanupModelKind exists but
  meetingTranscriptEnabled was never set)
- Shows "What's New" NSAlert on first launch after update with
  "Open Meetings" and "Got It" buttons
- Persists hasSeenMeetingTranscriptAnnouncement to only show once
- Fix: Settings mic picker initializes from saved selection, not system default
- Fix: test dictation targets selected mic device
- Fix: prioritize native Zoom over browsers for Detect button
- Fix: filter out ZM_ internal Zoom windows from title detection
- Fix: strip pronouns from attendee names (she/her, he/him, they/them)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- UpdaterController checks appcast XML 15s after launch to compare versions
- Menu bar dropdown shows 'Update Available — Install Now' in orange when update found
- Sparkle still handles the actual update dialog and installation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ler shortcuts

Users can now remove the binding for any configurable shortcut, so the
associated functionality can be disabled entirely.

- ChordBindingStore: new BindingState enum (unset/cleared/set) and a
  dedicated clearBinding(for:) so we can tell "first-run" apart from
  "user explicitly cleared" and keep defaults for the former.
- AppState: chord properties become optional; updateShortcut accepts
  KeyChord?; HotkeyMonitor simply receives a dict that omits cleared
  actions.
- ShortcutRecorderView: shows "None" when cleared, renders an inline
  × button next to the chord when bound, and accepts Delete/Backspace
  during recording to clear the binding (alongside Escape to cancel).
@tkonya tkonya marked this pull request as ready for review April 22, 2026 14:05
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.

6 participants