diff --git a/internal/ui/chat/composer/model.go b/internal/ui/chat/composer/model.go index 5f8b217..b821347 100644 --- a/internal/ui/chat/composer/model.go +++ b/internal/ui/chat/composer/model.go @@ -221,86 +221,81 @@ func (c *Model) reset() { c.editState.SetValue("") } +// Update returns c changed in response to msg and a command to run, or nil. func (c Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := c.update(msg) - return c, cmd -} - -// update changes c in response to msg and returns a command to run, or nil. -func (c *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case TabSuggestMsg: - return c.tabSuggest() + return c, c.tabSuggest() case imagePastedMsg: if len(msg) == 0 { - return nil + return c, nil } c.attach(imageAttachmentName, bytes.NewReader(msg)) - return nil + return c, nil case filesPickedMsg: selectedChannel := c.channel if selectedChannel == nil || selectedChannel.ID != msg.channelID { - return closeFiles(msg.files) + return c, closeFiles(msg.files) } for _, file := range msg.files { c.attach(file.Name, file.Reader) } - return nil + return c, nil case editorMsg: c.editState.SetValue(string(msg)) - return nil + return c, nil case editMsg: c.editState.Apply(textarea.Change(msg)) typingCmd := c.sendTyping() if c.cfg.AutocompleteLimit > 0 { - return tview.Batch(typingCmd, c.tabSuggest()) + return c, tview.Batch(typingCmd, c.tabSuggest()) } - return typingCmd + return c, typingCmd case tview.KeyMsg: switch { case keybind.Matches(msg, c.cfg.Keybinds.Composer.EditLast.Keybind) && c.canEditLastMessage(): - return c.editLastMessage() + return c, c.editLastMessage() case keybind.Matches(msg, c.cfg.Keybinds.Composer.Paste.Keybind): c.pasteText() - return pasteImage() + return c, pasteImage() case keybind.Matches(msg, c.cfg.Keybinds.Composer.Send.Keybind): if c.mentionsVisible { - return c.tabComplete() + return c, c.tabComplete() } - return c.send() + return c, c.send() case keybind.Matches(msg, c.cfg.Keybinds.Composer.OpenEditor.Keybind): c.stopTabCompletion() - return c.openEditor() + return c, c.openEditor() case keybind.Matches(msg, c.cfg.Keybinds.Composer.OpenFilePicker.Keybind): c.stopTabCompletion() - return c.pickFiles() + return c, c.pickFiles() case keybind.Matches(msg, c.cfg.Keybinds.Composer.Cancel.Keybind): if c.mentionsVisible { c.stopTabCompletion() - return nil + return c, nil } c.reset() - return nil + return c, nil case keybind.Matches(msg, c.cfg.Keybinds.Composer.TabComplete.Keybind): if c.mentionsVisible { - return c.tabComplete() + return c, c.tabComplete() } c.insert("\t") - return nil + return c, nil case keybind.Matches(msg, c.cfg.Keybinds.Composer.ToggleReplyMention.Keybind): c.toggleReplyMention() - return nil + return c, nil case keybind.Matches(msg, c.cfg.Keybinds.Composer.Undo.Keybind): c.editState.Undo() - return nil + return c, nil } case mentionslist.Msg: var cmd tview.Cmd c.mentionsList, cmd = c.mentionsList.Update(msg) - return cmd + return c, cmd } - return nil + return c, nil } func (c *Model) canEditLastMessage() bool { diff --git a/internal/ui/chat/guildstree/model.go b/internal/ui/chat/guildstree/model.go index 0026f78..9b07450 100644 --- a/internal/ui/chat/guildstree/model.go +++ b/internal/ui/chat/guildstree/model.go @@ -300,47 +300,42 @@ func (m *Model) collapseParentNode(node *tree.Node) { m.selectionState.SetCurrentNode(parent) } +// Update returns m changed in response to msg and a command to run, or nil. func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := m.update(msg) - return m, cmd -} - -// update changes m in response to msg and returns a command to run, or nil. -func (m *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case *gateway.ReadyEvent: m.rebuild(msg) - return nil + return m, nil case *gateway.MessageCreateEvent: if !msg.GuildID.IsValid() { m.moveDMToFront(msg.ChannelID) } - return nil + return m, nil case *gateway.PresenceUpdateEvent: m.updateDMNodeStyle(msg.User.ID) - return nil + return m, nil case *read.UpdateEvent: m.refreshReadStyles(msg) - return nil + return m, nil case NavigateMsg: - return m.navigate(msg.ChannelID) + return m, m.navigate(msg.ChannelID) case Msg: m.selectionState.Apply(tree.Change(msg)) - return nil + return m, nil case SelectedMsg: m.selectionState.SetCurrentNode(msg.Node) - return m.selectNode(msg.Node) + return m, m.selectNode(msg.Node) case tview.KeyMsg: switch { case keybind.Matches(msg, m.cfg.Keybinds.GuildsTree.CollapseAll.Keybind): for _, node := range m.root.Children() { node.CollapseAll() } - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.GuildsTree.CollapseParentNode.Keybind): m.collapseParentNode(m.selectionState.CurrentNode()) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.GuildsTree.SelectPreviousUnread.Keybind, m.cfg.Keybinds.GuildsTree.SelectNextUnread.Keybind): previous := keybind.Matches(msg, m.cfg.Keybinds.GuildsTree.SelectPreviousUnread.Keybind) if node := adjacentNode(m.root, m.selectionState.CurrentNode(), m.isUnread, previous); node != nil { @@ -354,12 +349,12 @@ func (m *Model) update(msg tview.Msg) tview.Cmd { m.expandPathToNode(node) m.selectionState.SetCurrentNode(node) } - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.GuildsTree.YankID.Keybind): - return uitree.YankID(m.selectionState.CurrentNode()) + return m, uitree.YankID(m.selectionState.CurrentNode()) } } - return nil + return m, nil } // isUnread reports whether node is an unread channel, or a guild or the direct messages whose channels are not shown yet and has one. diff --git a/internal/ui/chat/memberstree/model.go b/internal/ui/chat/memberstree/model.go index 51d54c8..e528db4 100644 --- a/internal/ui/chat/memberstree/model.go +++ b/internal/ui/chat/memberstree/model.go @@ -88,36 +88,31 @@ func (m Model) View(focused bool) tview.Widget { return uitree.New(m.root, m.selectionState, m.cfg, m.cfg.Theme.MembersTree, m.cfg.Keybinds.MembersTree, focused, onChange, onSelect).Title("Members") } +// Update returns m changed in response to msg and a command to run, or nil. func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := m.update(msg) - return m, cmd -} - -// update changes m in response to msg and returns a command to run, or nil. -func (m *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case *gateway.ReadyEvent: // ningen drops its member lists on READY, so request the list again. m.rebuild() - return m.requestMembers(0) + return m, m.requestMembers(0) case *gateway.GuildMemberListUpdateEvent: if channel := m.channel; channel != nil && channel.GuildID == msg.GuildID && m.state.MemberState.ListID(channel) == msg.ID { m.rebuild() } - return nil + return m, nil case *gateway.PresenceUpdateEvent: m.refreshStatus(msg.User.ID) - return nil + return m, nil case Msg: m.selectionState.Apply(tree.Change(msg)) - return m.requestSelectedMembers() + return m, m.requestSelectedMembers() case SelectedMsg: m.selectionState.SetCurrentNode(msg.Node) if _, ok := msg.Node.Reference().(groupRef); ok { msg.Node.SetExpanded(!msg.Node.Expanded()) } - return m.requestSelectedMembers() + return m, m.requestSelectedMembers() case tview.KeyMsg: kbs := m.cfg.Keybinds.MembersTree switch { @@ -125,18 +120,18 @@ func (m *Model) update(msg tview.Msg) tview.Cmd { for _, node := range m.root.Children() { node.Collapse() } - return nil + return m, nil case keybind.Matches(msg, kbs.CollapseParentNode.Keybind): if parent := m.parent(m.selectionState.CurrentNode()); parent != nil { parent.Collapse() m.selectionState.SetCurrentNode(parent) } - return nil + return m, nil case keybind.Matches(msg, kbs.YankID.Keybind): - return uitree.YankID(m.selectionState.CurrentNode()) + return m, uitree.YankID(m.selectionState.CurrentNode()) } } - return nil + return m, nil } // rebuild recreates the tree from the member list of the selected channel. diff --git a/internal/ui/chat/messageslist/model.go b/internal/ui/chat/messageslist/model.go index 21ae188..1c1e4e0 100644 --- a/internal/ui/chat/messageslist/model.go +++ b/internal/ui/chat/messageslist/model.go @@ -837,64 +837,50 @@ func (ml *Model) selectedMessage() (*discord.Message, bool) { return &ml.items[cursor].message, true } +// Update returns ml changed in response to msg and a command to run, or nil. func (ml Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := ml.update(msg) - return ml, cmd -} - -// atTop reports whether the oldest message shown is selected. -func (ml *Model) atTop() bool { - return ml.cursor() >= 0 && ml.cursor() == ml.messageIndex(-1, 1) -} - -// update changes ml in response to msg and returns a command to run, or nil. -func (ml *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case tview.KeyMsg: switch { case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Cancel.Keybind): ml.clearSelection() - return nil case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.SelectUp.Keybind): - return ml.selectUp() + return ml, ml.selectUp() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.SelectDown.Keybind): ml.selectDown() - return nil case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.SelectTop.Keybind): - return ml.selectTop() + return ml, ml.selectTop() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.SelectBottom.Keybind): ml.selectBottom() - return nil case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.SelectReply.Keybind): ml.selectReply() - return nil case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.YankID.Keybind): - return ml.yankMessageID() + return ml, ml.yankMessageID() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.YankContent.Keybind): - return ml.yankContent() + return ml, ml.yankContent() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.YankURL.Keybind): - return ml.yankURL() + return ml, ml.yankURL() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Open.Keybind): - return ml.open() + return ml, ml.open() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.OpenInBrowser.Keybind): - return ml.openInBrowser() + return ml, ml.openInBrowser() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Download.Keybind): - return ml.download() + return ml, ml.download() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Reply.Keybind): - return ml.reply(false) + return ml, ml.reply(false) case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.ReplyMention.Keybind): - return ml.reply(true) + return ml, ml.reply(true) case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Edit.Keybind): - return ml.editSelectedMessage() + return ml, ml.editSelectedMessage() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Delete.Keybind): - return ml.deleteSelectedMessage() + return ml, ml.deleteSelectedMessage() case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.DeleteConfirm.Keybind): - return ml.confirmDelete() + return ml, ml.confirmDelete() } case olderMessagesLoadedMsg: selectedChannel := ml.channel if selectedChannel == nil || selectedChannel.ID != msg.ChannelID { - return nil + return ml, nil } prevCursor := ml.cursor() @@ -908,13 +894,13 @@ func (ml *Model) update(msg tview.Msg) tview.Cmd { } ml.rebuildItems() if selectedChannel.GuildID.IsValid() { - return tview.Batch(ml.requestGuildMembers(selectedChannel.GuildID, msg.Older), ml.loadPreviews()) + return ml, tview.Batch(ml.requestGuildMembers(selectedChannel.GuildID, msg.Older), ml.loadPreviews()) } - return ml.loadPreviews() + return ml, ml.loadPreviews() case previewLoadedMsg: index := slices.IndexFunc(ml.items, func(item messageItem) bool { return !item.separator && item.message.ID == msg.messageID }) if index < 0 || ml.items[index].previews == nil { - return nil + return ml, nil } preview, cmd := msg.preview, tview.Cmd(nil) if ml.kitty { @@ -925,7 +911,7 @@ func (ml *Model) update(msg tview.Msg) tview.Cmd { ml.items[index].previews[msg.proxy] = preview // Invalidate the view so it is laid out with the preview. ml.items[index].view = nil - return cmd + return ml, cmd case tview.ResizeMsg: cols, rows := msg.Size() width, height := msg.PixelSize() @@ -947,10 +933,15 @@ func (ml *Model) update(msg tview.Msg) tview.Cmd { ml.selectionState.Apply(list.Change(msg)) ml.onRowCursorChanged(ml.cursor()) if !top && ml.atTop() { - return ml.fetchOlderMessages() + return ml, ml.fetchOlderMessages() } } - return nil + return ml, nil +} + +// atTop reports whether the oldest message shown is selected. +func (ml *Model) atTop() bool { + return ml.cursor() >= 0 && ml.cursor() == ml.messageIndex(-1, 1) } func (ml *Model) selectDown() { diff --git a/internal/ui/chat/model.go b/internal/ui/chat/model.go index da3111a..4237671 100644 --- a/internal/ui/chat/model.go +++ b/internal/ui/chat/model.go @@ -193,27 +193,22 @@ func (m Model) Init() tview.Cmd { return tview.Batch(openState(m.state), listen(m.events), tview.RequestTerminalInfo()) } +// Update returns m changed in response to msg and a command to run, or nil. func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := m.update(msg) - return m, cmd -} - -// update changes m in response to msg and returns a command to run, or nil. -func (m *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case gateway.Event: - return tview.Batch(m.applyEvent(msg), listen(m.events)) + return m, tview.Batch(m.applyEvent(msg), listen(m.events)) case tview.FocusMsg: m.windowUnfocused = !msg.Focused - return nil + return m, nil case guildstree.ChannelLoadedMsg: node := m.guildsTree.CurrentNode() if node == nil { - return nil + return m, nil } channelID, ok := node.Reference().(discord.ChannelID) if !ok || channelID != msg.Channel.ID { - return nil + return m, nil } membersCmd := m.setSelectedChannel(&msg.Channel) @@ -223,97 +218,97 @@ func (m *Model) update(msg tview.Msg) tview.Cmd { m.setFocus(paneComposer) } title := ui.ChannelToString(msg.Channel, m.cfg.Icons, m.state) + " - " + consts.Name - return tview.Batch(tview.SetTitle(title), m.messagesList.SetChannel(&msg.Channel, msg.Messages), membersCmd) + return m, tview.Batch(tview.SetTitle(title), m.messagesList.SetChannel(&msg.Channel, msg.Messages), membersCmd) case messageslist.Msg, tview.TerminalInfoMsg, tview.ResizeMsg: - return m.updatePane(paneMessagesList, msg) + return m, m.updatePane(paneMessagesList, msg) case typingExpiredMsg: if until, ok := m.typers[msg.userID]; ok && !time.Now().Before(until) { delete(m.typers, msg.userID) } - return nil + return m, nil case channelspicker.SelectedMsg: - return m.navigateToChannel(msg.ChannelID) + return m, m.navigateToChannel(msg.ChannelID) case channelspicker.CancelMsg: m.closePicker() - return nil + return m, nil case attachmentspicker.SelectedMsg: m.overlay = overlayNone - return msg.Action + return m, msg.Action case attachmentspicker.CancelMsg: m.overlay = overlayNone - return nil + return m, nil case messageslist.ShowAttachmentsMsg: m.attachmentsPicker.SetItems(picker.Items(msg)) m.overlay = overlayAttachmentsPicker - return nil + return m, nil case messageslist.ReplyMsg: m.composer.StartReply(msg.Message, msg.Name, msg.Mention) m.setFocus(paneComposer) - return nil + return m, nil case messageslist.EditMsg: m.composer.StartEdit(discord.Message(msg)) m.setFocus(paneComposer) - return nil + return m, nil case composer.EditLastMsg: if message, ok := m.messagesList.SelectLastOwn(); ok { m.composer.StartEdit(message) } - return nil + return m, nil case composer.SentMsg: m.messagesList.ShowNewest() - return nil + return m, nil case QuitMsg: - return closeState(m.state) + return m, closeState(m.state) case tview.KeyMsg: switch { case keybind.Matches(msg, m.cfg.Keybinds.FocusGuildsTree.Keybind): m.composer.CloseMentions() m.setFocus(paneGuildsTree) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.FocusMembersTree.Keybind): m.composer.CloseMentions() m.setFocus(paneMembersTree) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.FocusMessagesList.Keybind): m.composer.CloseMentions() m.setFocus(paneMessagesList) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.FocusComposer.Keybind): m.setFocus(paneComposer) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.FocusPrevious.Keybind): m.cycleFocus(-1) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.FocusNext.Keybind): m.cycleFocus(1) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.ToggleGuildsTree.Keybind): m.toggle(&m.guildsTreeVisible, paneGuildsTree) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.ToggleMembersTree.Keybind): m.toggle(&m.membersTreeVisible, paneMembersTree) - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.ToggleChannelsPicker.Keybind): m.togglePicker() - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.Logout.Keybind): - return tview.Sequence(closeState(m.state), logout()) + return m, tview.Sequence(closeState(m.state), logout()) } case composer.TabSuggestMsg, mentionslist.Msg: - return m.updatePane(paneComposer, msg) + return m, m.updatePane(paneComposer, msg) case paneMsg: if msg.focus { m.setFocus(msg.pane) } if msg.msg == nil { - return nil + return m, nil } - return m.updatePane(msg.pane, msg.msg) + return m, m.updatePane(msg.pane, msg.msg) } - return m.route(msg) + return m, m.route(msg) } // route sends msg to the open picker, which takes all input, and otherwise to the focused pane. diff --git a/internal/ui/login/qr/model.go b/internal/ui/login/qr/model.go index 999f32b..a422843 100644 --- a/internal/ui/login/qr/model.go +++ b/internal/ui/login/qr/model.go @@ -42,80 +42,75 @@ func (Model) Init() tview.Cmd { return func() tview.Msg { return startMsg{} } } +// Update returns m changed in response to msg and a command to run, or nil. func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := m.update(msg) - return m, cmd -} - -// update changes m in response to msg and returns a command to run, or nil. -func (m *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case startMsg: m.status = "Connecting to Remote Auth Gateway..." - return connect() + return m, connect() case tview.KeyMsg: if msg.Key() == tcell.KeyEsc { m.status = "Canceled" - return closeConn(m.conn) + return m, closeConn(m.conn) } - return nil + return m, nil case scrollMsg: m.scrollState.Apply(textview.Change(msg)) - return nil + return m, nil case connCreateMsg: m.conn = msg.conn m.status = "Connected. Handshaking..." - return listen(m.conn) + return m, listen(m.conn) case connCloseMsg: m.conn = nil - return nil + return m, nil case helloMsg: m.heartbeatInterval = time.Duration(msg.heartbeatInterval) * time.Millisecond - return tview.Batch(listen(m.conn), scheduleHeartbeat(m.heartbeatInterval), generatePrivateKey()) + return m, tview.Batch(listen(m.conn), scheduleHeartbeat(m.heartbeatInterval), generatePrivateKey()) case privateKeyMsg: m.privateKey = msg.privateKey - return sendInit(m.conn, m.privateKey) + return m, sendInit(m.conn, m.privateKey) case nonceProofMsg: - return tview.Batch(listen(m.conn), sendNonceProof(m.conn, m.privateKey, msg.encryptedNonce)) + return m, tview.Batch(listen(m.conn), sendNonceProof(m.conn, m.privateKey, msg.encryptedNonce)) case pendingRemoteInitMsg: m.fingerprint = msg.fingerprint - return tview.Batch(listen(m.conn), generateQRCode(msg.fingerprint)) + return m, tview.Batch(listen(m.conn), generateQRCode(msg.fingerprint)) case qrCodeMsg: m.qrCode = msg.qrCode m.status = "Scan this with the Discord mobile app to log in instantly." - return nil + return m, nil case pendingTicketMsg: - return tview.Batch(listen(m.conn), decryptUserPayload(m.privateKey, msg.encryptedUserPayload)) + return m, tview.Batch(listen(m.conn), decryptUserPayload(m.privateKey, msg.encryptedUserPayload)) case userMsg: name := msg.username if msg.discriminator != "0" { name += "#" + msg.discriminator } m.status = "Check your phone! Logging in as " + name - return nil + return m, nil case pendingLoginMsg: m.status = "Authenticating..." - return tview.Batch(closeConn(m.conn), exchangeTicket(m.fingerprint, m.privateKey, msg.ticket)) + return m, tview.Batch(closeConn(m.conn), exchangeTicket(m.fingerprint, m.privateKey, msg.ticket)) case ignoredMsg: - return listen(m.conn) + return m, listen(m.conn) case cancelMsg: m.status = "Login canceled on mobile" - return closeConn(m.conn) + return m, closeConn(m.conn) case heartbeatTickMsg: if m.conn == nil { - return nil + return m, nil } - return tview.Batch(scheduleHeartbeat(m.heartbeatInterval), sendHeartbeat(m.conn)) + return m, tview.Batch(scheduleHeartbeat(m.heartbeatInterval), sendHeartbeat(m.conn)) case error: m.status = msg.Error() - return closeConn(m.conn) + return m, closeConn(m.conn) } - return nil + return m, nil } // halfBlock packs a vertical pair of QR pixels into one glyph, fitting two bitmap rows into a single terminal row. diff --git a/internal/ui/root/model.go b/internal/ui/root/model.go index e6cd61d..4752ee5 100644 --- a/internal/ui/root/model.go +++ b/internal/ui/root/model.go @@ -71,28 +71,23 @@ func (m Model) Init() tview.Cmd { ) } +// Update returns m changed in response to msg and a command to run, or nil. func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) { - cmd := m.update(msg) - return m, cmd -} - -// update changes m in response to msg and returns a command to run, or nil. -func (m *Model) update(msg tview.Msg) tview.Cmd { switch msg := msg.(type) { case loginMsg: - return m.showLogin() + return m, m.showLogin() case tokenMsg: - return m.showChat(string(msg)) + return m, m.showChat(string(msg)) case password.TokenMsg: - return tview.Batch(m.showChat(string(msg)), setToken(string(msg))) + return m, tview.Batch(m.showChat(string(msg)), setToken(string(msg))) case qr.TokenMsg: - return tview.Batch(m.showChat(string(msg)), setToken(string(msg))) + return m, tview.Batch(m.showChat(string(msg)), setToken(string(msg))) case token.TokenMsg: - return tview.Batch(m.showChat(string(msg)), setToken(string(msg))) + return m, tview.Batch(m.showChat(string(msg)), setToken(string(msg))) case chat.LogoutMsg: - return tview.Batch( + return m, tview.Batch( m.showLogin(), deleteToken(), ) @@ -100,41 +95,41 @@ func (m *Model) update(msg tview.Msg) tview.Cmd { if m.modal == nil { m.modal, m.dialogFocus = &msg, 0 } - return nil + return m, nil case dialogFocusMsg: m.dialogFocus = int(msg) - return nil + return m, nil case dialogDoneMsg: - return m.finishModal(int(msg)) + return m, m.finishModal(int(msg)) case tview.KeyMsg: // The dialog takes all input while it is open, so nothing behind it reacts. if m.modal != nil { - return nil + return m, nil } switch { case keybind.Matches(msg, m.cfg.Keybinds.ToggleHelp.Keybind): m.toggleHelp() - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.ToggleFullHelp.Keybind): if m.cfg.Help.Enabled { m.helpShowAll = !m.helpShowAll } - return nil + return m, nil case keybind.Matches(msg, m.cfg.Keybinds.Suspend.Keybind): - return suspend() + return m, suspend() case keybind.Matches(msg, m.cfg.Keybinds.Quit.Keybind): - return tview.Batch(m.updateScreen(chat.QuitMsg{}), tview.Quit()) + return m, tview.Batch(m.updateScreen(chat.QuitMsg{}), tview.Quit()) } case tview.MouseMsg, tview.PasteMsg: if m.modal != nil { - return nil + return m, nil } case tview.ResizeMsg: m.resize = msg } - return m.updateScreen(msg) + return m, m.updateScreen(msg) } // updateScreen updates the model shown above help with msg.