refactor(ui): merge each model's update into Update
This commit is contained in:
parent
c8b024eb0e
commit
c3cb114e22
7 changed files with 142 additions and 181 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue