refactor(ui/chat): adapt UI handlers to unified HandleEvent API

This commit is contained in:
ayn2op 2026-03-02 00:05:39 -05:00
parent bab0ee8856
commit aa2e1e2497
9 changed files with 293 additions and 257 deletions

7
go.mod
View file

@ -2,11 +2,16 @@ module github.com/ayn2op/discordo
go 1.26.0
// replace (
// github.com/ayn2op/tview => ../tview
// github.com/diamondburned/arikawa/v3 => ../arikawa
// )
require (
github.com/BurntSushi/toml v1.6.0
github.com/alecthomas/chroma/v2 v2.23.1
github.com/andybalholm/brotli v1.2.0
github.com/ayn2op/tview v0.0.0-20260301025618-69fc2518f451
github.com/ayn2op/tview v0.0.0-20260302045935-716714ee7442
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
github.com/diamondburned/arikawa/v3 v3.6.1-0.20260226015332-783a3e8e8e86
github.com/diamondburned/ningen/v3 v3.0.1-0.20260226220604-93f1e60c3cdb

4
go.sum
View file

@ -14,8 +14,8 @@ github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/ayn2op/tview v0.0.0-20260301025618-69fc2518f451 h1:DfZZiNSwERJNZ9f33hsxWIFFiAgGY2T+Fi7unZ6Ka7A=
github.com/ayn2op/tview v0.0.0-20260301025618-69fc2518f451/go.mod h1:lZ8RdOegQWBQafTOasGE7Ps1/Ymy4jmXoPt5vz2QsS0=
github.com/ayn2op/tview v0.0.0-20260302045935-716714ee7442 h1:5CN5nE/5s7zbIp51hiH1CY6hpDgvzfvh4CF38FXJCGk=
github.com/ayn2op/tview v0.0.0-20260302045935-716714ee7442/go.mod h1:lZ8RdOegQWBQafTOasGE7Ps1/Ymy4jmXoPt5vz2QsS0=
github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=

View file

@ -393,36 +393,39 @@ func (gt *guildsTree) collapseParentNode(node *tview.TreeNode) {
})
}
func (gt *guildsTree) InputHandler(event *tcell.EventKey) tview.Command {
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
handler := gt.TreeView.InputHandler
func (gt *guildsTree) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
handler := gt.TreeView.HandleEvent
switch {
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.CollapseParentNode.Keybind):
gt.collapseParentNode(gt.GetCurrentNode())
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.MoveToParentNode.Keybind):
return handler(tcell.NewEventKey(tcell.KeyRune, "K", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Up.Keybind):
return handler(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Down.Keybind):
return handler(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Top.Keybind):
gt.Move(gt.GetRowCount() * -1)
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Bottom.Keybind):
gt.Move(gt.GetRowCount())
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.SelectCurrent.Keybind):
return handler(tcell.NewEventKey(tcell.KeyEnter, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.YankID.Keybind):
gt.yankID()
switch {
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.CollapseParentNode.Keybind):
gt.collapseParentNode(gt.GetCurrentNode())
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.MoveToParentNode.Keybind):
return handler(tcell.NewEventKey(tcell.KeyRune, "K", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Up.Keybind):
return handler(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Down.Keybind):
return handler(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Top.Keybind):
gt.Move(gt.GetRowCount() * -1)
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.Bottom.Keybind):
gt.Move(gt.GetRowCount())
return consumeRedraw
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.SelectCurrent.Keybind):
return handler(tcell.NewEventKey(tcell.KeyEnter, "", tcell.ModNone))
case keybind.Matches(event, gt.cfg.Keybinds.GuildsTree.YankID.Keybind):
gt.yankID()
return consume
}
// Do not fall through to TreeView defaults for unmatched keys.
return consume
}
// Do not fall through to TreeView defaults for unmatched keys.
return consume
return gt.TreeView.HandleEvent(event)
}
func (gt *guildsTree) yankID() {

View file

@ -92,81 +92,99 @@ func (mi *messageInput) stopTypingTimer() {
}
}
func (mi *messageInput) InputHandler(event *tcell.EventKey) tview.Command {
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
handler := mi.TextArea.InputHandler
switch {
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Paste.Keybind):
mi.paste()
return handler(tcell.NewEventKey(tcell.KeyCtrlV, "", tcell.ModNone))
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Send.Keybind):
if mi.chatView.GetVisible(mentionsListLayerName) {
mi.tabComplete()
} else {
mi.send()
func (mi *messageInput) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
handler := mi.TextArea.HandleEvent
switch {
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Paste.Keybind):
mi.paste()
return handler(tcell.NewEventKey(tcell.KeyCtrlV, "", tcell.ModNone))
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Send.Keybind):
if mi.chatView.GetVisible(mentionsListLayerName) {
mi.tabComplete()
} else {
mi.send()
}
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.OpenEditor.Keybind):
var cmds tview.BatchCommand
mi.stopTabCompletion(func(next tview.Command) {
if next != nil {
cmds = append(cmds, next)
}
})
mi.editor()
cmds = append(cmds, consumeRedraw)
return cmds
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.OpenFilePicker.Keybind):
var cmds tview.BatchCommand
mi.stopTabCompletion(func(next tview.Command) {
if next != nil {
cmds = append(cmds, next)
}
})
mi.openFilePicker()
cmds = append(cmds, consumeRedraw)
return cmds
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Cancel.Keybind):
var cmds tview.BatchCommand
if mi.chatView.GetVisible(mentionsListLayerName) {
mi.stopTabCompletion(func(next tview.Command) {
if next != nil {
cmds = append(cmds, next)
}
})
} else {
mi.reset()
}
cmds = append(cmds, consumeRedraw)
return cmds
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.TabComplete.Keybind):
go mi.chatView.app.QueueUpdateDraw(func() { mi.tabComplete() })
return consume
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Undo.Keybind):
return handler(tcell.NewEventKey(tcell.KeyCtrlZ, "", tcell.ModNone))
}
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.OpenEditor.Keybind):
var cmd tview.Command
mi.stopTabCompletion(func(next tview.Command) { cmd = tview.AppendCommand(cmd, next) })
mi.editor()
return tview.AppendCommand(cmd, consumeRedraw)
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.OpenFilePicker.Keybind):
var cmd tview.Command
mi.stopTabCompletion(func(next tview.Command) { cmd = tview.AppendCommand(cmd, next) })
mi.openFilePicker()
return tview.AppendCommand(cmd, consumeRedraw)
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Cancel.Keybind):
var cmd tview.Command
if mi.chatView.GetVisible(mentionsListLayerName) {
mi.stopTabCompletion(func(next tview.Command) { cmd = tview.AppendCommand(cmd, next) })
} else {
mi.reset()
}
return tview.AppendCommand(cmd, consumeRedraw)
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.TabComplete.Keybind):
go mi.chatView.app.QueueUpdateDraw(func() { mi.tabComplete() })
return consume
case keybind.Matches(event, mi.cfg.Keybinds.MessageInput.Undo.Keybind):
return handler(tcell.NewEventKey(tcell.KeyCtrlZ, "", tcell.ModNone))
}
if mi.cfg.TypingIndicator.Send && mi.typingTimer == nil {
mi.typingTimer = time.AfterFunc(typingDuration, func() {
mi.typingTimerMu.Lock()
mi.typingTimer = nil
mi.typingTimerMu.Unlock()
})
if mi.cfg.TypingIndicator.Send && mi.typingTimer == nil {
mi.typingTimer = time.AfterFunc(typingDuration, func() {
mi.typingTimerMu.Lock()
mi.typingTimer = nil
mi.typingTimerMu.Unlock()
})
if selectedChannel := mi.chatView.SelectedChannel(); selectedChannel != nil {
go mi.chatView.state.Typing(selectedChannel.ID)
}
}
if mi.cfg.AutocompleteLimit > 0 {
if mi.chatView.GetVisible(mentionsListLayerName) {
switch {
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Up.Keybind):
mi.mentionsList.InputHandler(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Down.Keybind):
mi.mentionsList.InputHandler(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Top.Keybind):
mi.mentionsList.InputHandler(tcell.NewEventKey(tcell.KeyHome, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Bottom.Keybind):
mi.mentionsList.InputHandler(tcell.NewEventKey(tcell.KeyEnd, "", tcell.ModNone))
return consumeRedraw
if selectedChannel := mi.chatView.SelectedChannel(); selectedChannel != nil {
go mi.chatView.state.Typing(selectedChannel.ID)
}
}
go mi.chatView.app.QueueUpdateDraw(func() { mi.tabSuggestion() })
}
if mi.cfg.AutocompleteLimit > 0 {
if mi.chatView.GetVisible(mentionsListLayerName) {
switch {
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Up.Keybind):
mi.mentionsList.HandleEvent(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Down.Keybind):
mi.mentionsList.HandleEvent(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Top.Keybind):
mi.mentionsList.HandleEvent(tcell.NewEventKey(tcell.KeyHome, "", tcell.ModNone))
return consumeRedraw
case keybind.Matches(event, mi.cfg.Keybinds.MentionsList.Bottom.Keybind):
mi.mentionsList.HandleEvent(tcell.NewEventKey(tcell.KeyEnd, "", tcell.ModNone))
return consumeRedraw
}
}
return handler(event)
go mi.chatView.app.QueueUpdateDraw(func() { mi.tabSuggestion() })
}
return handler(event)
}
return mi.TextArea.HandleEvent(event)
}
func (mi *messageInput) paste() {

View file

@ -525,72 +525,76 @@ func (ml *messagesList) selectedMessage() (*discord.Message, error) {
return &ml.messages[cursor], nil
}
func (ml *messagesList) InputHandler(event *tcell.EventKey) tview.Command {
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
func (ml *messagesList) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
consume := tview.ConsumeEventCommand{}
consumeRedraw := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
switch {
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollUp.Keybind):
ml.ScrollUp()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollDown.Keybind):
ml.ScrollDown()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollTop.Keybind):
ml.ScrollToStart()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollBottom.Keybind):
ml.ScrollToEnd()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Cancel.Keybind):
ml.clearSelection()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectUp.Keybind):
ml.selectUp()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectDown.Keybind):
ml.selectDown()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectTop.Keybind):
ml.selectTop()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectBottom.Keybind):
ml.selectBottom()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectReply.Keybind):
ml.selectReply()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankID.Keybind):
ml.yankID()
switch {
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollUp.Keybind):
ml.ScrollUp()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollDown.Keybind):
ml.ScrollDown()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollTop.Keybind):
ml.ScrollToStart()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ScrollBottom.Keybind):
ml.ScrollToEnd()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Cancel.Keybind):
ml.clearSelection()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectUp.Keybind):
ml.selectUp()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectDown.Keybind):
ml.selectDown()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectTop.Keybind):
ml.selectTop()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectBottom.Keybind):
ml.selectBottom()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.SelectReply.Keybind):
ml.selectReply()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankID.Keybind):
ml.yankID()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankContent.Keybind):
ml.yankContent()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankURL.Keybind):
ml.yankURL()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Open.Keybind):
ml.open()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Reply.Keybind):
ml.reply(false)
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ReplyMention.Keybind):
ml.reply(true)
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Edit.Keybind):
ml.edit()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Delete.Keybind):
ml.delete()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.DeleteConfirm.Keybind):
ml.confirmDelete()
return consumeRedraw
}
// Do not fall through to List defaults for unmatched keys.
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankContent.Keybind):
ml.yankContent()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.YankURL.Keybind):
ml.yankURL()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Open.Keybind):
ml.open()
return consume
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Reply.Keybind):
ml.reply(false)
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.ReplyMention.Keybind):
ml.reply(true)
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Edit.Keybind):
ml.edit()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.Delete.Keybind):
ml.delete()
return consumeRedraw
case keybind.Matches(event, ml.cfg.Keybinds.MessagesList.DeleteConfirm.Keybind):
ml.confirmDelete()
return consumeRedraw
}
// Do not fall through to List defaults for unmatched keys.
return consume
return ml.List.HandleEvent(event)
}
func (ml *messagesList) selectUp() {

View file

@ -222,48 +222,53 @@ func (v *View) focusNext() {
}
}
func (v *View) InputHandler(event *tcell.EventKey) tview.Command {
consume := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
func (v *View) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
consume := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
switch {
case keybind.Matches(event, v.cfg.Keybinds.ToggleHelp.Keybind):
v.help.SetShowAll(!v.help.ShowAll())
v.updateHelpHeight()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusGuildsTree.Keybind):
v.messageInput.removeMentionsList()
v.focusGuildsTree()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusMessagesList.Keybind):
v.messageInput.removeMentionsList()
v.app.SetFocus(v.messagesList)
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusMessageInput.Keybind):
v.focusMessageInput()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusPrevious.Keybind):
v.focusPrevious()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusNext.Keybind):
v.focusNext()
return consume
case keybind.Matches(event, v.cfg.Keybinds.Logout.Keybind):
if v.onLogout != nil {
v.onLogout()
switch {
case keybind.Matches(event, v.cfg.Keybinds.ToggleHelp.Keybind):
v.help.SetShowAll(!v.help.ShowAll())
v.updateHelpHeight()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusGuildsTree.Keybind):
v.messageInput.removeMentionsList()
v.focusGuildsTree()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusMessagesList.Keybind):
v.messageInput.removeMentionsList()
v.app.SetFocus(v.messagesList)
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusMessageInput.Keybind):
v.focusMessageInput()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusPrevious.Keybind):
v.focusPrevious()
return consume
case keybind.Matches(event, v.cfg.Keybinds.FocusNext.Keybind):
v.focusNext()
return consume
case keybind.Matches(event, v.cfg.Keybinds.Logout.Keybind):
if v.onLogout != nil {
v.onLogout()
}
if err := keyring.DeleteToken(); err != nil {
slog.Error("failed to delete token from keyring", "err", err)
}
return consume
case keybind.Matches(event, v.cfg.Keybinds.ToggleGuildsTree.Keybind):
v.toggleGuildsTree()
return consume
case keybind.Matches(event, v.cfg.Keybinds.ToggleChannelsPicker.Keybind):
v.togglePicker()
return consume
}
if err := keyring.DeleteToken(); err != nil {
slog.Error("failed to delete token from keyring", "err", err)
}
return consume
case keybind.Matches(event, v.cfg.Keybinds.ToggleGuildsTree.Keybind):
v.toggleGuildsTree()
return consume
case keybind.Matches(event, v.cfg.Keybinds.ToggleChannelsPicker.Keybind):
v.togglePicker()
return consume
cmd := v.Layers.HandleEvent(event)
return v.consumeLayerCommands(cmd)
}
cmd := v.Layers.InputHandler(event)
cmd := v.Layers.HandleEvent(event)
return v.consumeLayerCommands(cmd)
}

View file

@ -63,15 +63,19 @@ func newQRLogin(app *tview.Application, cfg *config.Config, done func(token stri
return q
}
func (q *qrLogin) InputHandler(event *tcell.EventKey) tview.Command {
if event.Key() == tcell.KeyEsc {
q.stop()
if q.done != nil {
q.done("", nil)
func (q *qrLogin) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
if event.Key() == tcell.KeyEsc {
q.stop()
if q.done != nil {
q.done("", nil)
}
return tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
}
return tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
return q.TextView.HandleEvent(event)
}
return q.TextView.InputHandler(event)
return q.TextView.HandleEvent(event)
}
func (q *qrLogin) start() {

View file

@ -123,18 +123,25 @@ func (v *View) Draw(screen tcell.Screen) {
v.inner.Draw(screen)
}
func (v *View) InputHandler(event *tcell.EventKey) tview.Command {
switch {
case keybind.Matches(event, v.cfg.Keybinds.Suspend.Keybind):
v.suspend()
return tview.ConsumeEventCommand{}
case keybind.Matches(event, v.cfg.Keybinds.Quit.Keybind):
v.closeChatViewState()
return tview.QuitCommand{}
}
func (v *View) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
switch {
case keybind.Matches(event, v.cfg.Keybinds.Suspend.Keybind):
v.suspend()
return tview.ConsumeEventCommand{}
case keybind.Matches(event, v.cfg.Keybinds.Quit.Keybind):
v.closeChatViewState()
return tview.QuitCommand{}
}
if v.inner != nil {
return v.inner.InputHandler(event)
if v.inner != nil {
return v.inner.HandleEvent(event)
}
case *tview.MouseEvent, *tview.PasteEvent:
if v.inner != nil {
return v.inner.HandleEvent(event)
}
}
return nil
}
@ -160,17 +167,3 @@ func (v *View) Blur() {
}
v.Box.Blur()
}
func (v *View) MouseHandler(action tview.MouseAction, event *tcell.EventMouse) (tview.Primitive, tview.Command) {
if v.inner == nil {
return nil, nil
}
return v.inner.MouseHandler(action, event)
}
func (v *View) PasteHandler(text string) tview.Command {
if v.inner == nil {
return nil
}
return v.inner.PasteHandler(text)
}

View file

@ -148,33 +148,37 @@ func (p *Picker) onInputChanged(text string) {
p.setFilteredItems(fuzzied)
}
func (p *Picker) InputHandler(event *tcell.EventKey) tview.Command {
consume := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
func (p *Picker) HandleEvent(event tcell.Event) tview.Command {
switch event := event.(type) {
case *tview.KeyEvent:
consume := tview.BatchCommand{tview.RedrawCommand{}, tview.ConsumeEventCommand{}}
if p.keyMap != nil {
switch {
case keybind.Matches(event, p.keyMap.Up):
p.list.InputHandler(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Down):
p.list.InputHandler(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Top):
p.list.InputHandler(tcell.NewEventKey(tcell.KeyHome, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Bottom):
p.list.InputHandler(tcell.NewEventKey(tcell.KeyEnd, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Select):
p.onListSelected(p.list.Cursor())
return consume
case keybind.Matches(event, p.keyMap.Cancel):
if p.onCancel != nil {
p.onCancel()
if p.keyMap != nil {
switch {
case keybind.Matches(event, p.keyMap.Up):
p.list.HandleEvent(tcell.NewEventKey(tcell.KeyUp, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Down):
p.list.HandleEvent(tcell.NewEventKey(tcell.KeyDown, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Top):
p.list.HandleEvent(tcell.NewEventKey(tcell.KeyHome, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Bottom):
p.list.HandleEvent(tcell.NewEventKey(tcell.KeyEnd, "", tcell.ModNone))
return consume
case keybind.Matches(event, p.keyMap.Select):
p.onListSelected(p.list.Cursor())
return consume
case keybind.Matches(event, p.keyMap.Cancel):
if p.onCancel != nil {
p.onCancel()
}
return consume
}
return consume
}
}
return p.Flex.InputHandler(event)
return p.Flex.HandleEvent(event)
}
return p.Flex.HandleEvent(event)
}