Skip to content

feat: Paste Last Transcription (clipboard-free) via hotkey + overlay#488

Merged
altic-dev merged 6 commits into
altic-dev:mainfrom
bloom-street:feature/paste-last-transcription
Jul 1, 2026
Merged

feat: Paste Last Transcription (clipboard-free) via hotkey + overlay#488
altic-dev merged 6 commits into
altic-dev:mainfrom
bloom-street:feature/paste-last-transcription

Conversation

@bloom-street

@bloom-street bloom-street commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Demo

CleanShot.2026-06-30.at.11.40.47.mp4

Shows assigning the shortcut in Settings → Shortcuts and re-pasting the last transcription into a focused field (clipboard untouched).

Description

Adds a "Paste Last Transcription" action that re-inserts the most recent transcription into the focused text field using FluidVoice's existing clipboard-free insertion path (TypingService standard mode). Unlike "Copy Last Transcription," it never writes to the system clipboard, so it works for users who intentionally keep Copy transcription to clipboard disabled. Useful when auto-insert drops the tail of a dictation or the text lands in the wrong place.

It's exposed two ways, both routed through a single ContentView.pasteLastDictationFromHistory():

  • A configurable global hotkey, unbound and disabled by default (opt-in; assigned in Settings, same default-off model as Command/Edit mode), so it never collides with an existing shortcut until the user sets one.
  • An item in the overlay actions menu beside the existing "Copy Last Transcription."

The action re-inserts the last entry's processedText (falling back to rawText), creates no new history entry, and does no reformatting — it's a faithful re-paste. It reuses resolveTypingTargetPID() / restoreFocusToRecordingTarget() so it targets the right field in both the hotkey case (insert at the current cursor) and the menu case (restore focus to the prior app first). It's ignored while a recording is in progress, and no-ops with a debug log when history is empty.

Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • 🧹 Chore
  • 📝 Documentation update

Related Issues

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac (macOS 26)
  • Ran linter locally: swiftlint --strict --config .swiftlint.yml Sources
  • Ran formatter locally: swiftformat --config .swiftformat Sources
  • Manually verified end-to-end on a signed local build: record shortcut → dictate → re-paste into a focused field with the clipboard untouched.

Added HotkeyShortcutTests cases covering the new setting's default (unbound + disabled) and persistence/clear round-trip.

Two fixes landed after exercising the feature on a real build:

  1. Shortcut-recording feedback (shortcutRow): the "press keys…" capture pill was gated on isRecording && enabledValue, so for an opt-in row whose toggle is still off, clicking "Change" started recording but kept showing "Not set" — it looked unresponsive. Now the pill shows whenever recording. Note: this also improves the existing Command Mode row (same helper), which had the same first-record blind spot — flagging in case that's unexpected.
  2. Modifier-held paste drop: the hotkey fires on key-down while its own modifiers are still held, so synthesized characters were interpreted by the target app as shortcuts and dropped. The paste now waits for the modifier keys to release before inserting.

Notes

  • Default-off / unbound by design. The hotkey ships with no binding and disabled; it activates only after the user records a shortcut in Settings → Shortcuts. This avoids clobbering app shortcuts (e.g. ⌘⇧V "paste & match style").
  • No new dependencies. Mirrors the existing Command/Cancel hotkey patterns; the manager reads the shortcut live from SettingsStore (like the Cancel shortcut), so there's no extra plumbing through the GlobalHotkeyManager initializer.
  • Backup/restore. The new shortcut + enabled flag are added to SettingsBackupPayload as optionals, so older backup files still decode.
  • Clipboard behavior unchanged. Honors the user's textInsertionMode: standard inserts with no clipboard involvement; reliablePaste uses the existing temporary-clipboard-then-restore mechanism. The independent copyTranscriptionToClipboard setting is untouched.

Screenshots / Video

See the Demo at the top — it walks through assigning the shortcut in Settings and re-pasting the last transcription into a focused field with the clipboard untouched.

…oard-free

Re-inserts the most recent transcription into the focused text field using
the existing clipboard-free insertion path (TypingService standard mode).
Unlike "Copy Last Transcription", it never writes to the system clipboard, so
it works for users who keep `copyTranscriptionToClipboard` disabled. Useful
when auto-insert drops the tail of a dictation or text lands in the wrong field.

Exposed two ways, both routed through ContentView.pasteLastDictationFromHistory():
- A configurable global hotkey, unbound and disabled by default (opt-in,
  assigned in Settings, mirroring the Command/Edit-mode default-off model).
  GlobalHotkeyManager reads the shortcut live from SettingsStore, like Cancel.
- An item in the overlay actions menu beside "Copy Last Transcription".

The action pastes the last entry's processedText (fallback rawText) verbatim:
no new history entry, no reformatting. It reuses resolveTypingTargetPID() /
restoreFocusToRecordingTarget() so it targets the right field for both the
hotkey (insert at cursor) and menu (restore prior focus) cases, is ignored
while recording, and no-ops with a debug log when history is empty.

The new shortcut + enabled flag are persisted and added to SettingsBackupPayload
as optionals (older backups still decode). Adds HotkeyShortcutTests coverage for
the default (unbound/disabled) and persistence/clear round-trip.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1bd57dbaa2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +2522 to +2524
let processed = last.processedText.trimmingCharacters(in: .whitespacesAndNewlines)
let raw = last.rawText.trimmingCharacters(in: .whitespacesAndNewlines)
let text = processed.isEmpty ? raw : processed

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve stored whitespace when re-pasting history

When continuous dictation spacing is enabled, ASRService.applyContinuousDictationFormatting deliberately saves boundary whitespace in processedText (for example a leading space before a word and a trailing space after it), but this new paste path trims both processedText and rawText before insertion. In that setting, re-pasting the latest entry no longer reproduces the text that was originally delivered and can concatenate words at the cursor, which contradicts the clipboard-free “faithful re-paste” behavior.

Useful? React with 👍 / 👎.

Comment on lines +657 to +663
// Check the "paste last transcription" shortcut (a one-shot action, like cancel).
if SettingsStore.shared.pasteLastTranscriptionShortcutEnabled,
let pasteShortcut = SettingsStore.shared.pasteLastTranscriptionHotkeyShortcut,
pasteShortcut.matches(keyCode: keyCode, modifiers: eventModifiers)
{
self.triggerPasteLastTranscription()
return nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Debounce repeated keyDown events for paste shortcut

This hotkey fires on every matching keyDown without tracking the press until keyUp or checking keyboardEventAutorepeat, unlike the recording-mode shortcuts below that guard with is...KeyPressed. If the user holds the configured paste shortcut long enough for macOS key repeat, the callback can run repeatedly and insert multiple copies of the same transcription while the physical shortcut is still down.

Useful? React with 👍 / 👎.

@bloom-street bloom-street marked this pull request as draft June 30, 2026 15:31
@altic-dev

Copy link
Copy Markdown
Owner

I am working on this as well! Would love ypur help here!! :)).

If you can send me a recording of it working and the settings page where you set the shortcut, I would much appreciate it and it would be easy for me to merge it. I just need to make sure that UI and UX looks okay and good before merging, other than that - amazing work

Two issues found while testing the feature on a real build:

1. Shortcut recording gave no feedback for opt-in (off-by-default) rows.
   In `shortcutRow`, the "press keys…" capture pill was gated on
   `isRecording && enabledValue`, so for a row whose toggle is still off
   (Command Mode, Paste Last Transcription) clicking "Change" started
   recording but kept showing "Not set" — it looked dead. Show the capture
   pill whenever recording, regardless of the enable toggle.

2. The paste hotkey fired on key-down while its own modifiers (e.g. ⌘⌃)
   were still physically held, so the synthesized characters were
   interpreted by the target app as modifier+key shortcuts and dropped
   (the insert "succeeded" but no text landed). Dictation never hits this
   because no keys are held by the time it types. Paste now waits (up to
   0.6s, polling 15ms) for the modifier keys to be released before
   inserting, so the text lands cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bloom-street bloom-street marked this pull request as ready for review June 30, 2026 16:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fc1ad7826

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +657 to +661
// Check the "paste last transcription" shortcut (a one-shot action, like cancel).
if SettingsStore.shared.pasteLastTranscriptionShortcutEnabled,
let pasteShortcut = SettingsStore.shared.pasteLastTranscriptionHotkeyShortcut,
pasteShortcut.matches(keyCode: keyCode, modifiers: eventModifiers)
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route modifier-only paste shortcuts through flagsChanged

The settings recorder accepts modifier-only shortcuts for this target (it creates a HotkeyShortcut from handleShortcutFlagsChangedEvent and then assigns .pasteLast), but the new paste action is only checked in the .keyDown path here. If a user records a modifier-only shortcut such as Right Option or Ctrl+Shift, macOS delivers it as .flagsChanged and the existing flagsChanged handlers cover the other shortcut types but not paste, so Settings can show the shortcut as enabled even though it never triggers.

Useful? React with 👍 / 👎.

@bloom-street

Copy link
Copy Markdown
Contributor Author

I updated the PR, There are a couple small issues, but it's all working now. I attached a video. I absolutely love this product from the sounds To the AI enhancement. This is by far the best mac app STT out there. Keep up the good work
https://github.com/user-attachments/assets/cc852e52-8a53-4490-a124-2ef7c61f78cd

Addresses issues found in a self-review of the feature:

- Abort instead of inserting if the modifier keys never release. The wait
  helper now returns whether the modifiers were released; if they're still
  held when the 0.6s timeout elapses (stuck/long-held key), the paste is
  aborted rather than typing a corrupted — possibly destructive (⌘W/⌘Q) —
  shortcut sequence. The user can simply retrigger.

- Ignore auto-repeat key-downs so holding the chord pastes once, not N times.
  The auto-repeat state is passed to triggerPasteLastTranscription, which now
  acts only on the initial press. (Passed as an argument rather than branching
  in the already-at-limit handleKeyEvent.)

- Guard the overlay entry point against pasting mid-recording. The asrService
  .isRunning check now lives inside pasteLastDictationFromHistory (re-checked
  after the modifier wait), so the overlay menu item is protected like the
  hotkey path and the trigger/insert TOCTOU window is closed.

- Restore backup symmetrically: the paste shortcut is now `if let`-guarded like
  its enabled flag, so restoring an older backup can't wipe a configured
  shortcut while leaving the feature flagged enabled.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08ba816869

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +2554 to +2555
if typingTarget.shouldRestoreOriginalFocus {
await self.restoreFocusToRecordingTarget()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid restoring stale focus for paste hotkey

When the paste action is invoked by the global hotkey while the user is still in the same app as the last dictation but has moved the cursor to a different field/window, resolveTypingTargetPID() returns the current PID with shouldRestoreOriginalFocus == true because it only compares against recordingTargetPID; this branch then calls restoreFocusToRecordingTarget(), which refocuses the old AX element captured at recording start. In that scenario the hotkey inserts into the previous dictation field rather than the currently focused field, so focus restoration should be reserved for the overlay/menu path or only when Fluid is frontmost.

Useful? React with 👍 / 👎.

@altic-dev

Copy link
Copy Markdown
Owner

Perfect - Once you fix the issues - I am merging this blindly ;)

bloom-street and others added 2 commits June 30, 2026 14:45
The earlier "abort if modifiers still held" guard timed out at 0.6s, so a
second/held press of the paste hotkey aborted with the transcript never
inserting ("only pastes once"). Make the wait generous (5s) so the paste
lands when the keys are released — including a held or quick repeated press —
and only abort if a modifier is genuinely stuck. Preserves the protection
against synthesizing text while modifiers are down.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Because the paste waits for the modifier keys to release, a quick double/triple
tap of the chord queued several Tasks that all inserted at once on release,
duplicating the transcription. Guard with a single in-flight flag (set before
the wait, cleared in a defer) so only one paste runs at a time, covering both
the hotkey and overlay entry points. Deliberate sequential pastes (press, it
lands, press again) still work since the flag clears when the paste completes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bloom-street

bloom-street commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

✅ Ready to merge — everything's working and tested

Since the demo video I did a full pass of manual testing plus a self‑review and fixed everything I found. The feature works end‑to‑end and is verified on a signed local build: assign a shortcut in Settings → Shortcuts, dictate, then re‑paste the last transcription into the focused field with the clipboard never touched.

Bugs found and fixed during testing/review:

  1. Couldn't assign the shortcut — the "press keys…" capture state wasn't shown for an off‑by‑default row, so clicking Change looked unresponsive. Now it shows while recording. (Also fixes the same first‑record blind spot on the existing Command Mode row.)
  2. Pasted text was dropped — the hotkey fires while its own modifiers (e.g. ⌘⌃) are still held, so the synthesized characters were swallowed as keyboard shortcuts. The paste now lands once the keys are released.
  3. "Only pasted once" — a held or second press aborted too eagerly; now it waits for the keys to release (generous timeout) and pastes reliably every time.
  4. Double‑paste on rapid re‑tap — a quick double‑tap could queue two inserts; now collapsed to one paste at a time (deliberate repeats still work).
  5. Auto‑repeat — holding the chord pasted N times; now fires once.
  6. Overlay menu paste — could fire mid‑recording; now guarded the same as the hotkey path.
  7. Backup restore — restoring an older backup could wipe a configured shortcut; now guarded symmetrically.

Quality: passes swiftlint --strict, builds clean, and I added HotkeyShortcutTests coverage for the new setting (default unbound/disabled + persistence). The clipboard‑free insertion honors the existing textInsertionMode — no clipboard involvement in standard mode.

One known limitation (noted in code): with macOS Sticky Keys, a latched modifier means inserting would corrupt the text, so the paste aborts safely rather than typing garbage.

Happy to squash to a single commit on merge if you'd prefer. Thanks again

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92e66dccb4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +2860 to +2862
if let pasteLastTranscriptionHotkeyShortcut = payload.pasteLastTranscriptionHotkeyShortcut {
self.pasteLastTranscriptionHotkeyShortcut = pasteLastTranscriptionHotkeyShortcut
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restore cleared paste shortcuts from backups

When restoring a backup created after this change with Paste Last Transcription left unbound, the synthesized encoder omits pasteLastTranscriptionHotkeyShortcut because it is nil, so this if let treats that current backup the same as a pre-feature backup and leaves any existing shortcut in UserDefaults. A user restoring an unbound/disabled configuration over a machine that previously had a paste shortcut will still see the old binding available to re-enable, so backup restore no longer faithfully restores this setting; the restore path needs a way to distinguish missing legacy fields from an intentionally nil shortcut or otherwise clear it for current backups.

Useful? React with 👍 / 👎.

Comment on lines +188 to +189
@State private var pasteLastTranscriptionHotkeyShortcut: HotkeyShortcut? = SettingsStore.shared.pasteLastTranscriptionHotkeyShortcut
@State private var isPasteLastTranscriptionShortcutEnabled: Bool = SettingsStore.shared.pasteLastTranscriptionShortcutEnabled

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Refresh paste shortcut state after backup restore

These new @State values are only initialized once, but reloadSettingsStateAfterBackupRestore() refreshes the other hotkey bindings after .settingsBackupDidRestore and does not refresh the paste shortcut or enabled flag. If a backup changes this shortcut while Preferences is open, the global hotkey manager reads the restored values from SettingsStore but the Settings UI keeps showing the old binding/toggle and can mislead the user; include these two states in the restore reload alongside the other shortcut states.

Useful? React with 👍 / 👎.

@altic-dev

Copy link
Copy Markdown
Owner

One final comment - does it reuse the same gotkey flow from the other items? Makin sure you can use all forms of shortcut for this like kyeboard, mouse etc just like the other ones!

Thanks

@bloom-street

Copy link
Copy Markdown
Contributor Author

Great question — yes, it reuses the existing shortcut machinery end‑to‑end, nothing bespoke. "Paste Last Transcription" goes through the same ShortcutRecordingTarget flow, the same shortcutRow recorder UI, the same HotkeyShortcut model, the same global event‑tap dispatch in GlobalHotkeyManager, and the same conflict detection as the other items.

On shortcut types, it matches the other secondary actions exactly:

  • Keyboard (key + any modifiers): fully supported — fires through the same keyDown path as Command Mode / Edit Mode / Cancel.
  • Mouse buttons: not accepted — but that's the app's existing design, not a gap in this PR. allowsMouseShortcut is true only for Primary Dictation, and the mouse branch of handleKeyEvent only ever matches primaryShortcuts. So Command Mode, Edit Mode, Cancel Recording, and Paste Last all restrict to keyboard (the recorder shows "Mouse clicks can only be assigned to Primary Dictation Shortcut"). Paste Last is consistent with the other secondary shortcuts here.
  • Modifier‑only (hold a bare modifier): Paste Last fires on key‑down like Cancel Recording, i.e. it's a one‑shot tap action. The hold‑to‑talk modes (Command/Edit/Prompt) additionally support modifier‑only bindings because they're press‑and‑hold; matching Cancel made sense for a one‑shot paste.

So it behaves "just like the other ones" (the non‑primary ones). If you'd actually like to open mouse buttons (or modifier‑only) up to the secondary actions app‑wide, that's a small tweak to allowsMouseShortcut + the mouse branch of handleKeyEvent — happy to add it here or as a follow‑up, just say the word.

Makes Paste Last as flexible as the Primary Dictation ("listen") button —
mappable to a mouse button (side buttons, modified clicks), not just the
keyboard. Adds .pasteLast to allowsMouseShortcut and wires a mouse-button
check into GlobalHotkeyManager: the mouse-down handling is extracted into
handleMouseShortcutDown/Up helpers (which also keeps handleKeyEvent under the
cyclomatic-complexity limit), the paste fires once on mouse-down (one-shot,
mirroring the keyboard path), and the paired mouse-up is swallowed so the
focused app never sees an orphaned up. The other secondary actions
(Command/Edit/Cancel) remain keyboard-only as before. Adds a test that the
paste setting round-trips a mouse shortcut.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bloom-street

Copy link
Copy Markdown
Contributor Author

Done — just pushed mouse‑button support for Paste Last (3b2dfe7), so it's now as flexible as the Primary Dictation button: you can map it to a mouse side‑button or a modified click, in addition to a keyboard shortcut.

Implementation notes:

  • Added .pasteLast to allowsMouseShortcut, so the recorder, conflict detection, and the modifier‑wait/in‑flight guards all apply to mouse shortcuts for free.
  • Pulled the mouse‑down/up handling in handleKeyEvent into small handleMouseShortcutDown/Up helpers (also keeps that method under the cyclomatic‑complexity limit). The paste fires once on mouse‑down (one‑shot, mirroring the keyboard path), and the paired mouse‑up is swallowed so the focused app never sees an orphaned up.
  • Left Command/Edit/Cancel keyboard‑only as before — I scoped this to Paste Last so it directly matches the primary button without quietly changing those. Happy to extend mouse to them too if you'd like, just say the word.
  • Added a test covering a mouse shortcut round‑tripping through the setting.

Builds clean, passes swiftlint --strict, tests green.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3b2dfe787f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1696 to +1701
if SettingsStore.shared.pasteLastTranscriptionShortcutEnabled,
let pasteShortcut = SettingsStore.shared.pasteLastTranscriptionHotkeyShortcut,
pasteShortcut.isMouseShortcut,
pasteShortcut.mouseButton == mouseButton
{
return true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Track paste mouse-down before swallowing mouse-up

Because this branch ignores both the release modifiers and whether the preceding mouse-down actually matched Paste Last, it also consumes releases for other uses of the same button. For example, if Primary Dictation is Ctrl+Mouse 4 and Paste Last is Option+Mouse 4 (a non-duplicate combination the conflict checker allows), the primary mouse-down starts recording but the mouse-up returns here before finishPrimaryShortcutPress(.mouse(...)), so hold/automatic mode can leave dictation running until the user stops it another way.

Useful? React with 👍 / 👎.

@altic-dev altic-dev merged commit 73928f2 into altic-dev:main Jul 1, 2026
1 check 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.

[✨ FEATURE] Paste Last Transcription (clipboard-free) via hotkey

2 participants