From 68ee346501c52fc071fc84b4a007862fcc1d452f Mon Sep 17 00:00:00 2001 From: ayn2op Date: Sun, 18 Oct 2026 16:25:03 -0400 Subject: [PATCH] refactor(ui): drop custom widgets where tview's do the job, for the mentions, the login field labels and the composer --- internal/ui/chat/composer/model.go | 37 +++++--------------------- internal/ui/chat/mentionslist/model.go | 26 ++---------------- internal/ui/login/password/model.go | 4 +-- internal/ui/login/token/model.go | 2 +- 4 files changed, 12 insertions(+), 57 deletions(-) diff --git a/internal/ui/chat/composer/model.go b/internal/ui/chat/composer/model.go index f722185..c809432 100644 --- a/internal/ui/chat/composer/model.go +++ b/internal/ui/chat/composer/model.go @@ -119,39 +119,13 @@ func (m Model) placeholder() string { } // View shows the text area in a box, taking keys if focused. -func (m Model) View(focused bool) tview.Widget { return view{&m, focused} } - -// view is the composer as shown, with or without the focus. -type view struct { - *Model - focused bool -} - -func (v view) Size() (width, height layout.Length) { - return v.box(v.focused).Size() -} - -func (v view) Layout(limits layout.Limits) layout.Size { - return v.box(v.focused).Layout(limits) -} - -func (v view) Draw(screen tview.Screen, area tview.Rectangle) { - v.box(v.focused).Draw(screen, area) -} - -// Handle leaves bound keys to Update and passes other messages to the text area. -func (v view) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg { - if key, ok := msg.(tview.KeyMsg); ok && v.isBound(key) { - return msg - } - return v.box(v.focused).Handle(msg, area) -} +func (m Model) View(focused bool) tview.Widget { return m.box(focused) } // box returns the text area in a box with the title and footer. func (m *Model) box(focused bool) box.Widget { text := textarea.New(m.text, m.cursor). Placeholder(m.placeholder()). - Keybind(m.editAction). + Keybind(m.keybind). Focused(focused && !m.disabled). OnInput(func(text string, cursor int) tview.Msg { return editMsg{text, cursor} }). Height(layout.Shrink.Max(m.cfg.Composer.MaxHeight)) @@ -638,8 +612,11 @@ func (m Model) canAttachFiles() bool { return m.channel != nil && m.state.HasPermissions(m.channel.ID, discord.PermissionAttachFiles) } -// editAction binds the configured newline key and textarea's other default keys. -func (m Model) editAction(key tview.KeyMsg) textarea.Action { +// keybind binds the configured newline key and textarea's other default keys, leaving the composer's own keys to Update. +func (m Model) keybind(key tview.KeyMsg) textarea.Action { + if m.isBound(key) { + return textarea.ActionNone + } if keybind.Matches(key, m.cfg.Keybinds.Composer.Newline.Keybind) { return textarea.ActionNewline } diff --git a/internal/ui/chat/mentionslist/model.go b/internal/ui/chat/mentionslist/model.go index c791cb4..65bd06b 100644 --- a/internal/ui/chat/mentionslist/model.go +++ b/internal/ui/chat/mentionslist/model.go @@ -7,6 +7,7 @@ import ( "github.com/ayn2op/tview/layout" "github.com/ayn2op/tview/list" "github.com/ayn2op/tview/scrollbar" + "github.com/ayn2op/tview/text" "github.com/ayn2op/tview/viewport" "github.com/rockorager/go-uucode" ) @@ -43,7 +44,7 @@ func (Model) Init() tview.Cmd { return nil } func (m Model) listView() viewport.Widget { l := list.New(m.cursor, len(m.items), func(i int) tview.Widget { item := m.items[i] - return row{text: item.DisplayText, style: item.Style} + return text.New(item.DisplayText).Style(item.Style).Wrapping(text.WrappingNone) }). SelectedStyle(m.cfg.Theme.MentionsList.SelectedStyle.Style). Keybind(ui.SelectionKeybind(m.cfg.Keybinds.MentionsList.SelectionKeybinds)). @@ -102,26 +103,3 @@ func (m *Model) Rebuild() { } var _ tview.Model[Model] = Model{} - -// row is a mention on one line in its style. -type row struct { - text string - style tview.Style -} - -// Size returns Fill and a height of one row. -func (row) Size() (width, height layout.Length) { return layout.Fill, layout.Fixed(1) } - -// Layout returns a height of one row. -func (row) Layout(limits layout.Limits) layout.Size { - return layout.Atomic(limits, layout.Fill, layout.Fixed(1)) -} - -func (r row) Draw(screen tview.Screen, area tview.Rectangle) { - for x := area.X; x < area.X+area.Width; x++ { - screen.Put(x, area.Y, " ", r.style) - } - tview.Print(screen, r.text, area.X, area.Y, area.Width, tview.HorizontalAlignmentLeft, r.style) -} - -func (row) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg { return msg } diff --git a/internal/ui/login/password/model.go b/internal/ui/login/password/model.go index 8a3ca74..58f0512 100644 --- a/internal/ui/login/password/model.go +++ b/internal/ui/login/password/model.go @@ -78,8 +78,8 @@ func (m Model) View() tview.Widget { Focused(m.focus == focusButton). OnClick(submitMsg{}) return column.New( - row.New(column.New(text.New("Login")).Width(labelWidth), login).Height(layout.Shrink), - row.New(column.New(text.New("Password")).Width(labelWidth), password).Height(layout.Shrink), + row.New(text.New("Login").Width(labelWidth), login).Height(layout.Shrink), + row.New(text.New("Password").Width(labelWidth), password).Height(layout.Shrink), submit, ).Spacing(1).AlignX(tview.HorizontalAlignmentCenter) } diff --git a/internal/ui/login/token/model.go b/internal/ui/login/token/model.go index 3024bdf..6d4bde4 100644 --- a/internal/ui/login/token/model.go +++ b/internal/ui/login/token/model.go @@ -59,7 +59,7 @@ func (m Model) View() tview.Widget { Focused(m.buttonFocused). OnClick(submitMsg{}) return column.New( - row.New(column.New(text.New("Token")).Width(layout.Fixed(len("Token")+1)), input).Height(layout.Shrink), + row.New(text.New("Token").Width(layout.Fixed(len("Token")+1)), input).Height(layout.Shrink), submit, ).Spacing(1).AlignX(tview.HorizontalAlignmentCenter) }