fix(chat): keep input focus when closing mentions

Make stopTabCompletion return a Cmd and remove closeLayer message indirection so Esc/close paths keep focus on message input consistently.
This commit is contained in:
ayn2op 2026-04-05 21:52:20 -04:00
parent 7202d95907
commit bd045c1ac2
5 changed files with 19 additions and 59 deletions

4
go.mod
View file

@ -2,7 +2,7 @@ module github.com/ayn2op/discordo
go 1.26.0
replace github.com/ayn2op/tview => ../tview
// replace github.com/ayn2op/tview => ../tview
// replace github.com/diamondburned/arikawa/v3 => ../arikawa
@ -11,7 +11,7 @@ require (
github.com/alecthomas/chroma/v2 v2.23.1
github.com/andybalholm/brotli v1.2.1
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97
github.com/ayn2op/tview v0.0.0-20260405220423-423e22d12e25
github.com/ayn2op/tview v0.0.0-20260406015348-02d490edcf9c
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
github.com/diamondburned/arikawa/v3 v3.6.1-0.20260311205148-176ad9b9440f
github.com/diamondburned/ningen/v3 v3.0.1-0.20260306213430-5a08d3a709b4

4
go.sum
View file

@ -14,8 +14,8 @@ github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eT
github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97 h1:WujETUV+v0DEJyZgjeLzQvihWyL80c0Tg4qf0dDo+Io=
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97/go.mod h1:3kFnpNCa3dF6WryzOMCDao7PfZ7DTCh+pievlfuwV80=
github.com/ayn2op/tview v0.0.0-20260405220423-423e22d12e25 h1:YVgQkUOqIPDHQyTE4BSYvW5azl/2MwbkcswXjjWwpmo=
github.com/ayn2op/tview v0.0.0-20260405220423-423e22d12e25/go.mod h1:xgkca32kuEswK7Kzkfk3Pk24WHcKPjqK4xGmDi9QqOY=
github.com/ayn2op/tview v0.0.0-20260406015348-02d490edcf9c h1:LAUkiouSdOjU5aFHnzODCKY6czWiYqetkeN+79D5I4g=
github.com/ayn2op/tview v0.0.0-20260406015348-02d490edcf9c/go.mod h1:xgkca32kuEswK7Kzkfk3Pk24WHcKPjqK4xGmDi9QqOY=
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

@ -123,35 +123,20 @@ func (mi *messageInput) Update(msg tview.Msg) tview.Cmd {
}
return nil
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.OpenEditor.Keybind):
var cmds []tview.Cmd
mi.stopTabCompletion(func(next tview.Cmd) {
if next != nil {
cmds = append(cmds, next)
}
})
cmd := mi.stopTabCompletion()
mi.editor()
return tview.Batch(cmds...)
return cmd
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.OpenFilePicker.Keybind):
var cmds []tview.Cmd
mi.stopTabCompletion(func(next tview.Cmd) {
if next != nil {
cmds = append(cmds, next)
}
})
cmd := mi.stopTabCompletion()
mi.openFilePicker()
return tview.Batch(cmds...)
return cmd
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.Cancel.Keybind):
var cmds []tview.Cmd
if mi.chat.GetVisible(mentionsListLayerName) {
mi.stopTabCompletion(func(next tview.Cmd) {
if next != nil {
cmds = append(cmds, next)
}
})
return mi.stopTabCompletion()
} else {
mi.reset()
}
return tview.Batch(cmds...)
return nil
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.TabComplete.Keybind):
return mi.tabComplete()
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.Undo.Keybind):
@ -328,8 +313,7 @@ func (mi *messageInput) tabComplete() tview.Cmd {
return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '.'
})
if r != '@' {
mi.stopTabCompletion(nil)
return nil
return mi.stopTabCompletion()
}
pos := posEnd - (len(name) + 1)
@ -373,8 +357,7 @@ func (mi *messageInput) tabComplete() tview.Cmd {
return nil
}
mi.Replace(pos, posEnd, "@"+name+" ")
mi.stopTabCompletion(nil)
return nil
return mi.stopTabCompletion()
}
func (mi *messageInput) tabSuggest() tview.Cmd {
@ -382,8 +365,7 @@ func (mi *messageInput) tabSuggest() tview.Cmd {
return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '.'
})
if r != '@' {
mi.stopTabCompletion(nil)
return nil
return mi.stopTabCompletion()
}
selected := mi.chat.SelectedChannel()
if selected == nil {
@ -460,14 +442,12 @@ func (mi *messageInput) tabSuggest() tview.Cmd {
}
}
if mi.mentionsList.itemCount() == 0 {
mi.stopTabCompletion(nil)
return searchCmd
return tview.Batch(mi.stopTabCompletion(), searchCmd)
}
}
if mi.mentionsList.itemCount() == 0 {
mi.stopTabCompletion(nil)
return nil
return mi.stopTabCompletion()
}
mi.mentionsList.rebuild()
@ -632,17 +612,13 @@ func (mi *messageInput) removeMentionsList() {
}
}
func (mi *messageInput) stopTabCompletion(emit func(tview.Cmd)) {
func (mi *messageInput) stopTabCompletion() tview.Cmd {
if mi.cfg.AutocompleteLimit > 0 {
mi.mentionsList.clear()
if emit != nil {
emit(closeLayer(mentionsListLayerName))
emit(tview.SetFocus(mi))
} else {
mi.removeMentionsList()
mi.chat.app.SetFocus(mi)
}
mi.removeMentionsList()
return tview.SetFocus(mi)
}
return nil
}
func (mi *messageInput) editor() {

View file

@ -354,11 +354,6 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
case keybind.Matches(msg, m.cfg.Keybinds.Logout.Keybind):
return tview.Batch(m.closeState(), m.logout())
}
case *closeLayerMsg:
if m.HasLayer(msg.name) {
m.HideLayer(msg.name)
}
return nil
case *tabSuggestMsg:
// Member search completes in a command goroutine; resume suggestion
// generation on the update loop to keep UI mutations serialized.

View file

@ -68,14 +68,3 @@ func (m *Model) logout() tview.Cmd {
}
type QuitMsg struct{ tcell.EventTime }
type closeLayerMsg struct {
tcell.EventTime
name string
}
func closeLayer(name string) tview.Cmd {
return func() tview.Msg {
return &closeLayerMsg{name: name}
}
}