Repository navigation
Redesign the main window, Keys, Sounds and transcript views - #304
Merged
Merged
Conversation
Settings - Keys: one row per action with a key pop-up (TriggerKeyStyleStore.assign), one activation mode for every key (per-key modes removed). - Sounds: new tab with a start/stop cue per key (TriggerKeySoundStore; a key with no voice of its own plays its action's setting). - Read Aloud and Sounds: section headings and the Read Aloud footer removed; General: Meetings gets a header, short subtitle and footer. Main window - Journal-style: one window-level scroll on a pale brand-green backdrop, no rule under the toolbar; keys as a keycap legend on a translucent panel; Library entries as compact white cards with a ⋯ menu. - Toolbar: Record, Browse, Filter menu, Settings, native search. - Full key names everywhere; nothing in the window reacts to a key press. - Files come in by drop (overlay only while dragging), Dock icon / Open With (Alternate document types), File › Open… (⌘O), or Browse. Transcripts - Opening an item slides the window over to it: back button, toolbar View menu (✨), Play/Stop (recording or speech, with a spinner until speech starts — TextReader.read(onStart:)), Copy, Show in Finder, Delete in its own group. No title for dictations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lide The window's path is bound to the transcripts model — a page while it has something open, none when idle — so items, recordings and file uploads push themselves, and popping (back or Esc) dismisses, abandoning an upload. The system back button replaces the custom one and is hidden during a recording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The Library is a stock List drawn as the same white cards (row backgrounds and insets), led by the keys legend: click selects, double-click or Return opens, ⌘C, Delete and arrows work again. The table's own highlight is turned off so a selected card takes a Journal-style accent ring; day headings are ordinary rows so they scroll instead of pinning. - The open item scrolls as one page, title included. - Dropping a file replaces the window's content with a single drop well instead of overlaying a label. - Split LibraryCard.swift and AudioFileDropTarget.swift out for swiftlint's file-length limit; removed the unused card() helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment on lines
+34
to
+37
| private static func table(in view: NSView) -> NSTableView? { | ||
| if let table = view as? NSTableView { return table } | ||
| for subview in view.subviews { | ||
| if let table = table(in: subview) { return table } |
There was a problem hiding this comment.
table(in:) recursively traverses subviews without a depth bound, so a deeply nested view hierarchy can exhaust the stack.
Show fix
Suggested change
| private static func table(in view: NSView) -> NSTableView? { | |
| if let table = view as? NSTableView { return table } | |
| for subview in view.subviews { | |
| if let table = table(in: subview) { return table } | |
| private static func table(in view: NSView, depth: Int = 0) -> NSTableView? { | |
| if depth >= 1000 { return nil } | |
| if let table = view as? NSTableView { return table } | |
| for subview in view.subviews { | |
| if let table = table(in: subview, depth: depth + 1) { return table } |
Details
✨ AI Reasoning
The helper searches descendant views recursively and has no bound on recursion depth. A sufficiently deep view hierarchy can cause excessive stack growth during highlight removal.
Reply on this comment to give feedback or ignore the issue.
More info
…update menu hint test onExitCommand needed the page focused and lost Esc to the View menu; a hidden cancelAction button works wherever focus is. The menu bar hint now spells the key as "Right Option", so the UI test matches that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tton in one wait testControlsFollowTheKeys failed on CI with "Settings tab 'Read Aloud' not found". Two things in the helpers made it fragile: - openSettingsWindow() only sent ⌘, when Settings wasn't open, so after a test clicked the harness, Settings stayed behind it and its toolbar was driven from the background. - selectSettingsTab waited 5s for a radio button that macOS 26 never exposes (its tabs are buttons), leaving the real button only 3s. Now ⌘, is always sent (it raises an open Settings), and the tab is found in the toolbar as either element type with one 10s wait. A miss dumps the window's element tree, so a CI failure explains itself without the .xcresult. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Settings
TriggerKeyStyleStore.assign(_:to:), tested). One Activation mode applies to every key; per-key modes are removed (TriggerKeyActivationStoredeleted).TriggerKeySoundStore, a newDefaultsKey). A key with no voice of its own plays its action's existing setting, so untouched installs sound the same.CueSoundPlayerkeeps a pair per key and plays the one whose press started the recording or read.Main window (Journal-style)
.searchablesearch (it doesn't take focus at launch; clicking the content unfocuses it).CFBundleDocumentTypes→application(_:open:));Transcripts
TranscriptPage: a back button, a toolbar ✨ View menu, Play/Stop, Copy, Show in Finder, and Delete in its own group.TextReader.read(onStart:), tested).Test plan
scripts/check.shgreen locally: engine tests and coverage, swift-format, swiftlint, periphery, iPhone checks, docs linters, and invariants.BlurtUITests): updated for the new Keys rows, Sounds tab, Filter menu, cards and transcript page, but not run locally. CI is the first run.🤖 Generated with Claude Code