Conversation
Spacebar now toggles the current row into a checked set instead of paging down. Clicking the leading icon column (or hovering to preview the unchecked square) also toggles the row. When the checked set is non-empty, `d`, `x`, and `o` fan out across every checked item in display order; single-row behavior is unchanged when nothing is checked. Refresh clears the set and rows dropping out of the filtered list are pruned automatically. Hover detection for the icon column uses an NSTrackingArea-backed NSViewRepresentable — SwiftUI's `.onHover` on nested views wasn't firing under the row's outer tap gesture. Stuck-hover states on scroll are cleared by re-checking the cursor position against the view's visible rect, deferred to the next runloop to avoid mutating SwiftUI state inside AppKit's display cycle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Undo never held up in practice — between the 2.5s dispatch delay, the stale-entry warnings, and the subscription-restore / security-alert restore branches it was more complexity than it was worth. Ripping it out frees `u` for unsubscribe, which lets `x` take over the bulk-toggle role and returns `Space` to its original page-down behavior. Removes: `UndoEntry`, `UndoEffect`, `undoStack`, `applyUndo`, `pushUndo`, `pushSecurityAlertDismissUndo`, `removeUndoEntry`, `pushesUndo` parameter, the `restoreSubscription` ActionKind, `AppState.undo`, `startRestoreSubscriptionUndo`, the "last action can no longer be undone" warning, the `.undo` KeyboardCommand, the `.commandZ` KeyInput, and `InboxStore`'s now-dead `restoreDismissedSecurityAlert`. Committed-actions persistence is orthogonal and stays. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After undo was removed, a few artifacts survived: GitHubAPIClient's restoreSubscription method (plus its test) had no production caller, CLAUDE.md still listed Cmd+Z and "undo stack", and the icon hover detector was firing redundant SwiftUI @State writes on every scroll tick. Performance work on the rebuild path, since this runs on every keystroke in search and after every action: - Drop a duplicate threadActions.projectedNotifications(from: serverNotifications) call that was computing the menubar-icon count over already-projected data. - Skip serverNotificationsForCurrentMode + sortedByRecency when groupByRepo is off (orderedNotifications ignores repoOrderSource in that branch). - Memoize filteredNotifications as a stored property so its trim+lowercase+filter no longer runs on every read (~30 call sites). - Swap the filter from lowercased().contains() to localizedCaseInsensitiveContains() — no per-row string allocations. - Clear checkedThreadIDs before the bulk loop so each per-item rebuildDerivedState doesn't waste cycles pruning a shrinking set. Hover detector tightened: - Dedupe deliverHoverChange with a lastDeliveredHover field so no-op updates don't invalidate SwiftUI state. - Route the synchronous mouseEntered/mouseExited path without DispatchQueue.main.async; keep async only on the tracking-area/ window-change callbacks where it's needed to stay off AppKit's display cycle. Also removed stale "// Content" / "// Right side" narration comments in NotificationRowView. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When one or more rows are checked, append "· N selected" to the "X unread · Y in inbox" header. The selected suffix uses the accent color so it stands out against the secondary-colored base. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add "x sel" to the footer shortcut hints; tighten between-hint spacing to 8pt and drop the key/label gap to 0. - Bump the hint label color from tertiary to secondary for slightly higher contrast. - Rename the settings shortcut row from "Toggle selection for bulk actions" to "Select for bulk actions" to match the footer wording. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the user marks an item done, unsubscribes, or opens it, a small toast slides up from the footer showing what just happened — specific for single items (e.g. "Marked shadcn-ui/ui#10408 done") and counted for bulk ("Marked 4 items done"). Each toast lives 2 seconds; new ones stack over any still visible. Toasts clear when the panel closes so a stale one doesn't linger until the next open. The toast is a rounded card with inverted contrast — black background with white text in light mode, white with black in dark. Co-Authored-By: Claude Opus 4.7 (1M context) <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
x(or click the row's icon column) to toggle a notification into a checked set;d,u,othen apply to every checked row in display order. Header gains a blue· N selectedsuffix when the set is non-empty.UndoEntry/UndoEffectplumbing,AppState.undo(),startRestoreSubscriptionUndo, the 2.5s-window restore flow, and theCmd+Zbinding. Also trimmed the now-deadThreadActionStore.pushesUndoparameter,InboxStore.restoreDismissedSecurityAlert, andGitHubAPIClient.restoreSubscription.space→ page down (was toggle-check)x→ toggle check (was unsubscribe)u→ unsubscribe (was undo)Cmd+Z→ unboundprojectedUnreadfor the menubar-icon count instead of re-projecting.serverNotificationsForCurrentMode+sortedByRecencywhengroupByRepois off.filteredNotificationsas a stored property (was re-trimming + re-lowercasing + re-filtering on every read).localizedCaseInsensitiveContains(no per-row string allocations).checkedThreadIDsbefore the bulk loop so per-iteration rebuilds don't prune a shrinking set..onHoverwouldn't fire for the icon region under the row's outer tap gesture, so an NSTrackingArea-backedNSViewRepresentablehandles it. Deduped againstlastDeliveredHoverand split sync (mouseEntered/Exited) from async (tracking-area/window-change) paths to avoid redundant@Statewrites and the AppKit display-cycle crash.x seladded to the footer, inter-hint spacing tightened, label contrast bumped from tertiary to secondary; settings row renamed to "Select for bulk actions".Closes #5