eleven / messenger Public

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>
Paul Campbell 4f87503c96d912dd929dad1d636cf1426f7c2d5c parent 0a15b1e
2 files changed, +21 −0
  • ios/LChatMac/LChatMacApp.swift +11 −0
  • ios/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