mac: ⌘[ / ⌘] step through the chat list (#462)
Menu items (Previous/Next Chat) drive a signed tick on MacAppState; the active NativeChatView steps its selection through visibleThreads with wrap-around — so the shortcuts respect the current search/filter view.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2 files changed,
+21
−0
ios/LChatMac/LChatMacApp.swift+11 −0ios/LChatMac/NativeChatView.swift+10 −0
diff --git a/ios/LChatMac/LChatMacApp.swift b/ios/LChatMac/LChatMacApp.swift| index aa8cac9..c4916e8 100644 |
| --- a/ios/LChatMac/LChatMacApp.swift |
| +++ b/ios/LChatMac/LChatMacApp.swift |
| @@ -83,6 +83,13 @@ struct LChatMacApp: App { |
| // items win the same way ⌘C does. |
| Button("Find Chat…") { app.focusSearchTick += 1 } |
| .keyboardShortcut("f", modifiers: .command) |
| + // ⌘[ / ⌘] step through the chat list (Slack's ⌥↑/↓, in the |
| + // bracket idiom Paul asked for). Ticks, not toggles — each |
| + // press must fire even when the direction repeats. |
| + Button("Previous Chat") { app.cycleChatTick -= 1 } |
| + .keyboardShortcut("[", modifiers: .command) |
| + Button("Next Chat") { app.cycleChatTick += 1 } |
| + .keyboardShortcut("]", modifiers: .command) |
| } |
| // View → Make Text Bigger/Smaller (Messages' menu), stepping the |
| // same ladder as the Settings slider and the web's. The menu key |
| @@ -218,6 +225,10 @@ final class MacAppState: ObservableObject { |
| @Published var nativeChats: [NativePaletteChat] = [] |
| // Bumped by File ▸ Find Chat (⌘F) — the active surface focuses its search. |
| @Published var focusSearchTick = 0 |
| + // ⌘[ / ⌘] chat cycling: the SIGN of each change is the direction (the |
| + // counter moves ±1), and any change is one step — the active NativeChatView |
| + // observes it. |
| + @Published var cycleChatTick = 0 |
| // A "open this thread AND land on this message" request (search hits): |
| // the matching feed consumes it once its history contains the target. |
| @Published var nativeJump: NativeJumpTarget? |
diff --git a/ios/LChatMac/NativeChatView.swift b/ios/LChatMac/NativeChatView.swift| index fd06cbb..d05c97d 100644 |
| --- a/ios/LChatMac/NativeChatView.swift |
| +++ b/ios/LChatMac/NativeChatView.swift |
| @@ -169,6 +169,16 @@ struct NativeChatView: View { |
| .sheet(isPresented: $showInvite) { |
| InviteSomeoneSheet(store: store) |
| } |
| + // ⌘[ / ⌘] step through the chat list, wrapping — the change's SIGN is |
| + // the direction (LChatMacApp's menu items move the tick ±1). |
| + .onChange(of: app.cycleChatTick) { old, new in |
| + guard isActive else { return } |
| + let list = visibleThreads |
| + guard !list.isEmpty else { return } |
| + let dir = new > old ? 1 : -1 |
| + let at = list.firstIndex { $0.id == selectedID } ?? (dir == 1 ? -1 : 0) |
| + selectedID = list[(at + dir + list.count) % list.count].id |
| + } |
| .onChange(of: app.nativeOpenThread) { _, id in |
| guard isActive, let id else { return } |
| // "user:"/"app:" rows have no thread yet — create (the server |