From 926dd8cedd1744f0234377400874e1ec9c2cbf15 Mon Sep 17 00:00:00 2001 From: ayn2op Date: Thu, 19 Mar 2026 20:51:36 -0400 Subject: [PATCH 1/3] refactor(ui/chat): migrate onReady to command-based arch --- internal/ui/chat/model.go | 2 +- internal/ui/chat/state.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/ui/chat/model.go b/internal/ui/chat/model.go index 9c3f47a..0fb8a79 100644 --- a/internal/ui/chat/model.go +++ b/internal/ui/chat/model.go @@ -254,7 +254,7 @@ func (m *Model) HandleEvent(event tview.Event) tview.Command { m.onRaw(event) case *gateway.ReadyEvent: - m.onReady(event) + return tview.Batch(m.onReady(event), m.listen()) case *gateway.MessageCreateEvent: m.onMessageCreate(event) diff --git a/internal/ui/chat/state.go b/internal/ui/chat/state.go index 29f6952..866bb31 100644 --- a/internal/ui/chat/state.go +++ b/internal/ui/chat/state.go @@ -29,7 +29,7 @@ func (m *Model) onRaw(event *ws.RawEvent) { ) } -func (m *Model) onReady(event *gateway.ReadyEvent) { +func (m *Model) onReady(event *gateway.ReadyEvent) tview.Command { // Rebuild indexes from scratch so reconnects and account switches do not // retain pointers to detached tree nodes. m.guildsTree.resetNodeIndex() @@ -92,7 +92,7 @@ func (m *Model) onReady(event *gateway.ReadyEvent) { } m.guildsTree.SetCurrentNode(root) - m.app.SetFocus(m.guildsTree) + return tview.SetFocus(m.guildsTree) } func (m *Model) onMessageCreate(message *gateway.MessageCreateEvent) { From 7dcdff9d275adbe2af23c421275ae849fdb0613b Mon Sep 17 00:00:00 2001 From: ayn2op Date: Thu, 19 Mar 2026 20:57:33 -0400 Subject: [PATCH 2/3] refactor(ui/chat): migrate onMessageCreate to command-based arch --- internal/notifications/notifications.go | 2 +- internal/ui/chat/model.go | 2 +- internal/ui/chat/state.go | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/internal/notifications/notifications.go b/internal/notifications/notifications.go index db55853..cb2e445 100644 --- a/internal/notifications/notifications.go +++ b/internal/notifications/notifications.go @@ -15,7 +15,7 @@ import ( "github.com/diamondburned/ningen/v3" ) -func Notify(state *ningen.State, message *gateway.MessageCreateEvent, cfg *config.Config) error { +func Notify(state *ningen.State, message gateway.MessageCreateEvent, cfg *config.Config) error { if !cfg.Notifications.Enabled || cfg.Status == discord.DoNotDisturbStatus { return nil } diff --git a/internal/ui/chat/model.go b/internal/ui/chat/model.go index 0fb8a79..1f99cb1 100644 --- a/internal/ui/chat/model.go +++ b/internal/ui/chat/model.go @@ -257,7 +257,7 @@ func (m *Model) HandleEvent(event tview.Event) tview.Command { return tview.Batch(m.onReady(event), m.listen()) case *gateway.MessageCreateEvent: - m.onMessageCreate(event) + return tview.Batch(m.onMessageCreate(event), m.listen()) case *gateway.MessageUpdateEvent: m.onMessageUpdate(event) case *gateway.MessageDeleteEvent: diff --git a/internal/ui/chat/state.go b/internal/ui/chat/state.go index 866bb31..3b55b7d 100644 --- a/internal/ui/chat/state.go +++ b/internal/ui/chat/state.go @@ -11,6 +11,7 @@ import ( "github.com/diamondburned/arikawa/v3/utils/httputil/httpdriver" "github.com/diamondburned/arikawa/v3/utils/ws" "github.com/diamondburned/ningen/v3/states/read" + "github.com/gdamore/tcell/v3" ) func (m *Model) onRequest(r httpdriver.Request) error { @@ -95,15 +96,24 @@ func (m *Model) onReady(event *gateway.ReadyEvent) tview.Command { return tview.SetFocus(m.guildsTree) } -func (m *Model) onMessageCreate(message *gateway.MessageCreateEvent) { +func (m *Model) onMessageCreate(message *gateway.MessageCreateEvent) tview.Command { selectedChannel := m.SelectedChannel() if selectedChannel != nil && selectedChannel.ID == message.ChannelID { m.removeTyper(message.Author.ID) m.messagesList.addMessage(message.Message) - } else { + return nil + } + + return m.notify(*message) +} + +func (m *Model) notify(message gateway.MessageCreateEvent) tview.Command { + return func() tview.Event { if err := notifications.Notify(m.state, message, m.cfg); err != nil { slog.Error("failed to notify", "err", err, "channel_id", message.ChannelID, "message_id", message.ID) + return tcell.NewEventError(err) } + return nil } } From 10d37651fcdb0840aa4b498d44297b2e6015d57f Mon Sep 17 00:00:00 2001 From: ayn2op Date: Thu, 19 Mar 2026 21:01:26 -0400 Subject: [PATCH 3/3] style(ui/chat): simplify selected channel guard in onMessageUpdate --- internal/ui/chat/state.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/ui/chat/state.go b/internal/ui/chat/state.go index 3b55b7d..1d1340f 100644 --- a/internal/ui/chat/state.go +++ b/internal/ui/chat/state.go @@ -118,7 +118,12 @@ func (m *Model) notify(message gateway.MessageCreateEvent) tview.Command { } func (m *Model) onMessageUpdate(message *gateway.MessageUpdateEvent) { - if selected := m.SelectedChannel(); selected != nil && selected.ID == message.ChannelID { + selectedChannel := m.SelectedChannel() + if selectedChannel == nil { + return + } + + if selectedChannel.ID == message.ChannelID { index := slices.IndexFunc(m.messagesList.messages, func(m discord.Message) bool { return m.ID == message.ID })