feat(history): copy entries via double-click/⌘C/menu + keyboard navigation#568
feat(history): copy entries via double-click/⌘C/menu + keyboard navigation#568Fe2-O3 wants to merge 11 commits into
Conversation
Central, unit-tested seam for what double-click/⌘C copy from the History list. Delegates to TranscriptionHistoryEntry.clipboardText. Refs altic-dev#566 [authored on non-Xcode host; pending build+test verification on studio]
Adds a count:2 simultaneousGesture that selects the row and copies its text via HistoryCopy. Single-click selection is unchanged. Refs altic-dev#566 [authored on non-Xcode host; pending build+test verification on studio]
Adds .onCopyCommand on the list; responder-chain based so it does not shadow ⌘C in the search field. Also enables Edit ▸ Copy. Refs altic-dev#566 [authored on non-Xcode host; pending build+test verification on studio]
Transient per-row pill shown after double-click/⌘C copy, since neither gesture gives other feedback. Optional polish; isolated commit so it can be dropped if maintainers prefer no toast. Refs altic-dev#566 [authored on non-Xcode host; pending build+test verification on studio]
The standalone HistoryCopyTests.swift was not a member of the FluidDictationIntegrationTests target (explicit membership, not folder-synced), so its cases never ran. Relocate the 6 tests next to the sibling clipboardText tests in DictationE2ETests.swift. Refs altic-dev#566
The copy button, right-click Copy (Text/Raw/Both), double-click, and ⌘C now all trigger the same "Copied" confirmation. Adds a matching indicator in the detail header next to the Copy button. Refs altic-dev#566 [authored on non-Xcode host; pending build+test verification on studio]
Replace the inline row/header "Copied" pills with a small floating panel that appears next to the mouse cursor and fades out — the expected copy feedback, shown where the user is looking. Non-activating panel so ⌘V still targets the frontmost app. All copy actions share it. Refs altic-dev#566 [authored on non-Xcode host; pending build verification on studio]
⌘C via .onCopyCommand never fires because the custom Button-based list never becomes first responder (same root cause as arrow keys driving the sidebar instead of the list). Remove the non-working path and its helper so this PR ships only what works: double-click + right-click + Copy button, all with the cursor toast. ⌘C is tracked with keyboard navigation in a follow-up issue. Refs altic-dev#566
Make the entry list a real keyboard focus target: focusable + .onMoveCommand (↑/↓ moves the selection and scrolls it into view) + .onCopyCommand (⌘C copies the selected entry, respecting the search field). Clicking a row focuses the list. Nav index math lives in HistoryCopy.nextIndex with unit tests. Fixes the root cause behind both the non-firing ⌘C and arrow keys driving the sidebar instead of the list. Refs altic-dev#566, altic-dev#567 [authored on non-Xcode host; pending build+test verification on studio]
|
The PR Policy check is blocking this PR because required template information is missing. Please update the PR description with:
Visual files detected:
Screenshots or video are required for UI, UX, settings, onboarding, overlay, menu bar, or visual behavior changes. If this PR has no visual changes, check the no-visual-change box in the template. If this remains incomplete for 48 hours after opening, the PR may be closed. |
Greptile SummaryAdds keyboard-navigable copy affordances to the Transcription History list: double-click, ⌘C, and ↑/↓ selection join the existing Copy button and right-click menu, all sharing a single cursor-following "Copied" toast. Previously-raised issues (dismiss-race, silent ⌘C with no visible selection,
|
- CursorCopyToast: guard the fade-out completion with a generation counter so a copy fired during the 0.2s dismiss no longer hides the fresh confirmation toast. - copyCommandProviders: ignore ⌘C when no row is explicitly selected (was silently copying the first entry after Clear All). - flashCopied: drop the unused UUID parameter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b1e16dbf9a
ℹ️ 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".
| if let text = HistoryCopy.text(for: entry) { | ||
| self.copyToClipboard(text) | ||
| self.flashCopied() |
There was a problem hiding this comment.
Keep shortcut copy text consistent with Copy controls
This new double-click path copies HistoryCopy.text(for:), which trims whitespace and falls back to raw text, while the existing Copy button and context-menu Copy in this view still call copyToClipboard(entry.processedText) directly. For entries with leading/trailing whitespace, or restored/legacy entries whose processed text is empty but raw text exists, double-click/⌘C now place different content on the pasteboard than the visible Copy controls. Please route the button/menu through the same helper, or otherwise make all History copy paths use the same source.
Useful? React with 👍 / 👎.
- Route the detail-pane Copy button and context-menu Copy Text through the same clipboardText selection (altic-dev#450) already used by double-click, Cmd-C, and the Copy Last Transcript menu action. Fixes the Copy button copying raw, untrimmed processedText (and an empty string for transcriptions with no AI text). - moveSelection: derive the current index from the explicit selection so the first arrow press with nothing selected lands on the first row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Re: the copy-text consistency feedback from the automated review — I've routed all the "copy this transcription" paths (double-click, ⌘C, the detail-pane Copy button, and the context-menu Copy Text) through the existing Also addressed the other review notes in this push: guarded ⌘C so it no longer copies the first row when nothing is explicitly selected, fixed the same nil-selection fallback in arrow-key navigation (the first ↑/↓ now lands on the first row instead of skipping it), hardened the toast's dismiss so a fresh copy firing mid-fade isn't hidden, and dropped the unused |
Description
Adds faster copy affordances to Activity → History and makes the entry list keyboard-navigable:
No change to what gets copied — every path reuses the existing
TranscriptionHistoryEntry.clipboardTextselection (processed-then-raw) centralized in #450, so gestures, keyboard, menu, and button all place identical text on the pasteboard.Why
The Copy button and right-click menu already work, but double-click and ⌘C are the muscle-memory gestures for "grab this text" everywhere else on macOS (Finder, Mail, Notes). For a dictation app whose whole point is getting text out quickly, wiring the standard gestures + arrow-key navigation into History removes friction.
Implementation notes
ScrollView+LazyVStackof plainButtonrows with a manual@Stateselection, so it never became the keyboard first responder — which is exactly why ⌘C and the arrow keys didn't reach it. The list container is now.focusable()and takes focus on row click, handling.onMoveCommand(↑/↓, with the selected row scrolled into view viaScrollViewReader) and.onCopyCommand(⌘C).HistoryCopyenum (text(for:),nextIndex(current:count:moveUp:)) so it's unit-testable without a running app.NSPanelat the cursor, so a subsequent ⌘V still targets the frontmost app.Type of Change
Related Issue or Discussion
Closes #566
Closes #567
(Lineage: extends the clipboard idea from #3 and the menu-bar "Copy Last Transcript" from #450 into the History list.)
Testing
swiftlint --strict --config .swiftlint.ymlon the changed files → 0 violationsswiftformat --config .swiftformaton the changed files → 0 require formattingHistoryCopyunit tests pass —** TEST SUCCEEDED **Screenshots / Video
"Copied" toast on a selected row (double-click / ⌘C):
Same unified toast from the Copy button:
Notes
DictationE2ETests.swiftrather than a standalone file: the test target uses explicit file membership (not folder-sync), so a new standalone test file wouldn't be compiled into the target.Personal note: I'm running a build with this now, and it's already made grabbing past transcriptions noticeably easier for me. I'm dealing with an injury that makes extra mouse-aiming and keystrokes costly, so double-click / ⌘C / arrow-key access to History is a real day-to-day accessibility win — which is a big part of why I wanted to contribute it back rather than just keep a local patch. Thank you for building FluidVoice and keeping it open source. 🙏