refactor(ui): update to tview's Widget and help style builders

This commit is contained in:
ayn2op 2026-10-03 23:28:31 -04:00
parent f7180f8767
commit f9bb10d846
21 changed files with 79 additions and 81 deletions

2
go.mod
View file

@ -15,7 +15,7 @@ require (
github.com/andybalholm/brotli v1.2.6
github.com/ayn2op/arikawa/v3 v3.0.0-20260929021956-7d0802bf4d7c
github.com/ayn2op/ningen/v3 v3.0.1-0.20260929010920-29794d5fa70e
github.com/ayn2op/tview v0.0.0-20261003181757-a9ac55442caa
github.com/ayn2op/tview v0.0.0-20261004032233-8a715f5225e6
github.com/bogdanfinn/fhttp v0.6.9
github.com/bogdanfinn/tls-client v1.16.0
github.com/gdamore/tcell/v3 v3.5.0

4
go.sum
View file

@ -14,8 +14,8 @@ github.com/ayn2op/arikawa/v3 v3.0.0-20260929021956-7d0802bf4d7c h1:Qkl3W5RXzUQUR
github.com/ayn2op/arikawa/v3 v3.0.0-20260929021956-7d0802bf4d7c/go.mod h1:SHqcr+EmZKeNtVKZybHJn4HNz+ufA1XbeKNSTigBCEE=
github.com/ayn2op/ningen/v3 v3.0.1-0.20260929010920-29794d5fa70e h1:QAei/IVEyZV7GcpkpcFUh37+QRqwrt57z7OT3ciHrhI=
github.com/ayn2op/ningen/v3 v3.0.1-0.20260929010920-29794d5fa70e/go.mod h1:RsvYiMzi4Si1F7vmml5NCL2DaKIZXkNUQC7QlGTMtCw=
github.com/ayn2op/tview v0.0.0-20261003181757-a9ac55442caa h1:oTjG/n566Utl7gNRvrYMI7722fc/FgqnWD9C35avl6Q=
github.com/ayn2op/tview v0.0.0-20261003181757-a9ac55442caa/go.mod h1:oRPTSZgaEJPhv3dmmNvo6grBq/BemrLG3wFQLMTZJkY=
github.com/ayn2op/tview v0.0.0-20261004032233-8a715f5225e6 h1:Ja2H6nUN2NnXcpQ9TAf1HPNkAsurCIhSsVGHIEMrcIw=
github.com/ayn2op/tview v0.0.0-20261004032233-8a715f5225e6/go.mod h1:oRPTSZgaEJPhv3dmmNvo6grBq/BemrLG3wFQLMTZJkY=
github.com/bdandy/go-errors v1.2.2 h1:WdFv/oukjTJCLa79UfkGmwX7ZxONAihKu4V0mLIs11Q=
github.com/bdandy/go-errors v1.2.2/go.mod h1:NkYHl4Fey9oRRdbB1CoC6e84tuqQHiqrOcZpqFEkBxM=
github.com/bdandy/go-socks4 v1.2.3 h1:Q6Y2heY1GRjCtHbmlKfnwrKVU/k81LS8mRGLRlmDlic=

View file

@ -33,7 +33,7 @@ func (aw *AlignmentWrapper) UnmarshalTOML(v any) error {
return nil
}
type StyleWrapper struct{ tcell.Style }
type StyleWrapper struct{ tview.Style }
func (sw *StyleWrapper) UnmarshalTOML(v any) error {
m, ok := v.(map[string]any)
@ -288,7 +288,7 @@ type CommonTreeTheme struct {
}
// StatusStyle returns the style for a user with status.
func (ctt CommonTreeTheme) StatusStyle(status discord.Status) tcell.Style {
func (ctt CommonTreeTheme) StatusStyle(status discord.Status) tview.Style {
switch status {
case discord.OnlineStatus:
return ctt.OnlineStyle.Style

View file

@ -28,18 +28,18 @@ func NewRenderer(cfg *config.Config) *Renderer {
return &Renderer{cfg: cfg}
}
func (r *Renderer) RenderText(source []byte, node ast.Node, base tcell.Style) richtext.Text {
func (r *Renderer) RenderText(source []byte, node ast.Node, base tview.Style) richtext.Text {
r.listIx = nil
r.listNested = 0
builder := new(richtext.Builder)
styleStack := []tcell.Style{base}
styleStack := []tview.Style{base}
linkDepth := 0
currentStyle := func() tcell.Style {
currentStyle := func() tview.Style {
return styleStack[len(styleStack)-1]
}
pushStyle := func(style tcell.Style) {
pushStyle := func(style tview.Style) {
styleStack = append(styleStack, style)
}
popStyle := func() {
@ -145,7 +145,7 @@ func (r *Renderer) RenderText(source []byte, node ast.Node, base tcell.Style) ri
return builder.Finish()
}
func (r *Renderer) renderFencedCodeBlock(builder *richtext.Builder, source []byte, node *ast.FencedCodeBlock, base tcell.Style) {
func (r *Renderer) renderFencedCodeBlock(builder *richtext.Builder, source []byte, node *ast.FencedCodeBlock, base tview.Style) {
var code strings.Builder
lines := node.Lines()
for i := range lines.Len() {
@ -215,7 +215,7 @@ func (r *Renderer) renderFencedCodeBlock(builder *richtext.Builder, source []byt
}
}
func applyChromaStyle(base tcell.Style, entry chroma.StyleEntry) tcell.Style {
func applyChromaStyle(base tview.Style, entry chroma.StyleEntry) tview.Style {
style := base
if entry.Colour.IsSet() {
style = style.Foreground(tcell.NewRGBColor(
@ -263,7 +263,7 @@ func mentionText(node *md.Mention) string {
}
}
func applyInlineAttr(style tcell.Style, attr md.Attribute, inLink bool) tcell.Style {
func applyInlineAttr(style tview.Style, attr md.Attribute, inLink bool) tview.Style {
if attr&md.AttrBold != 0 {
style = style.Bold(true)
}

View file

@ -18,7 +18,7 @@ func NewModel(cfg *config.Config) Model {
var _ tview.Model[Model] = Model{}
// View shows the picker in a box titled Attachments.
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
return m.Model.View(func(item picker.Item) tview.Msg {
action, ok := item.Reference.(tview.Cmd)
if !ok {

View file

@ -24,7 +24,7 @@ func NewModel(cfg *config.Config) Model {
var _ tview.Model[Model] = Model{}
// View shows the picker in a box titled Channels.
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
return m.Model.View(func(item picker.Item) tview.Msg {
channelID, ok := item.Reference.(discord.ChannelID)
if !ok || !channelID.IsValid() {

View file

@ -110,7 +110,7 @@ func (c *Model) Disabled() bool {
}
// View shows the text area in a box, taking keys if focused.
func (c Model) View(focused bool) tview.Element { return view{&c, focused} }
func (c Model) View(focused bool) tview.Widget { return view{&c, focused} }
// view is the composer as shown, with or without the focus.
type view struct {
@ -489,7 +489,7 @@ func (c *Model) OnGuildMemberRemove(event *gateway.GuildMemberRemoveEvent) {
}
// MentionsView places the mentions list just above the composer, near the cursor, or returns nil if it is hidden.
func (c *Model) MentionsView() tview.Element {
func (c *Model) MentionsView() tview.Widget {
if !c.mentionsVisible {
return nil
}

View file

@ -47,7 +47,7 @@ func (m *Model) CurrentNode() *tree.Node {
}
// View shows the tree in a box titled Guilds.
func (m Model) View(focused bool) tview.Element {
func (m Model) View(focused bool) tview.Widget {
onChange := func(c tree.Change) tview.Msg { return Msg(c) }
onSelect := func(n *tree.Node) tview.Msg { return SelectedMsg{Node: n} }
return uitree.New(
@ -177,12 +177,12 @@ func (m *Model) createFolderNode(folder gateway.GuildFolder, guildsByID map[disc
}
}
func (m *Model) guildNodeStyle(guildID discord.GuildID) tcell.Style {
func (m *Model) guildNodeStyle(guildID discord.GuildID) tview.Style {
indication := m.state.GuildIsUnread(guildID, ningen.GuildUnreadOpts{IncludeMutedCategories: true})
return unreadStyle(indication)
}
func (m *Model) channelNodeStyle(channel discord.Channel) tcell.Style {
func (m *Model) channelNodeStyle(channel discord.Channel) tview.Style {
unread := unreadStyle(m.state.ChannelIsUnread(channel.ID, ningen.UnreadOpts{IncludeMutedCategories: true}))
if channel.Type != discord.DirectMessage || len(channel.DMRecipients) != 1 {
return unread
@ -234,7 +234,7 @@ func (m *Model) createChannelNode(parent *tree.Node, channel discord.Channel) {
m.nodes[discord.Snowflake(channel.ID)] = channelNode
}
func (m *Model) setNodeLineStyle(node *tree.Node, style tcell.Style) {
func (m *Model) setNodeLineStyle(node *tree.Node, style tview.Style) {
line := node.Line()
for i := range line {
line[i].Style = style
@ -455,8 +455,8 @@ func (m *Model) expandPathToNode(node *tree.Node) {
}
}
func unreadStyle(indication ningen.UnreadIndication) tcell.Style {
var style tcell.Style
func unreadStyle(indication ningen.UnreadIndication) tview.Style {
var style tview.Style
switch indication {
case ningen.ChannelRead:
style = style.Dim(true)

View file

@ -82,7 +82,7 @@ func (m *Model) SetChannel(channel *discord.Channel) tview.Cmd {
}
// View shows the tree in a box titled Members.
func (m Model) View(focused bool) tview.Element {
func (m Model) View(focused bool) tview.Widget {
onChange := func(c tree.Change) tview.Msg { return Msg(c) }
onSelect := func(n *tree.Node) tview.Msg { return SelectedMsg{Node: n} }
return uitree.New(m.root, m.selectionState, m.cfg, m.cfg.Theme.MembersTree, m.cfg.Keybinds.MembersTree, focused, onChange, onSelect).Title("Members")
@ -207,7 +207,7 @@ func (m *Model) addRecipients(recipients []discord.User) {
func (m *Model) addGroup(guildID discord.GuildID, group gateway.GuildMemberListGroup) *tree.Node {
name := "Members"
var style tcell.Style
var style tview.Style
switch group.ID {
case "online":
name = "Online"
@ -239,7 +239,7 @@ func (m *Model) addGroup(guildID discord.GuildID, group gateway.GuildMemberListG
// addMember adds a member as Discord shows it: a status dot, then the name in the color of their highest colored role, dimmed when offline.
func (m *Model) addMember(group *tree.Node, guildID discord.GuildID, member discord.Member, index int) {
name := cmp.Or(member.Nick, member.User.DisplayName, member.User.Username)
var nameStyle tcell.Style
var nameStyle tview.Style
color, ok := state.MemberColor(&member, func(id discord.RoleID) *discord.Role {
r, _ := m.state.Cabinet.Role(guildID, id)
return r

View file

@ -1,9 +1,9 @@
package mentionslist
import "github.com/gdamore/tcell/v3"
import "github.com/ayn2op/tview"
type Item struct {
InsertText string
DisplayText string
Style tcell.Style
Style tview.Style
}

View file

@ -6,7 +6,6 @@ import (
"github.com/ayn2op/tview"
"github.com/ayn2op/tview/layout"
"github.com/ayn2op/tview/list"
"github.com/gdamore/tcell/v3"
"github.com/rivo/uniseg"
)
@ -22,7 +21,7 @@ func NewModel(cfg *config.Config) Model {
}
// View shows the list in a box whose bottom corners join the composer's border below it.
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
set := m.cfg.Theme.Border.NormalSet.BorderSet
set.BottomLeft, set.BottomRight = set.BottomT, set.BottomT
return ui.Box(m.listView(), &m.cfg.Theme, false).Title("Mentions").BorderSet(set)
@ -31,7 +30,7 @@ func (m Model) View() tview.Element {
func (Model) Init() tview.Cmd { return nil }
func (m Model) listView() list.Widget {
return list.New(m.selectionState, len(m.items), func(i int) tview.Element {
return list.New(m.selectionState, len(m.items), func(i int) tview.Widget {
item := m.items[i]
return row{text: item.DisplayText, style: item.Style}
}).
@ -87,7 +86,7 @@ var _ tview.Model[Model] = Model{}
// row is a mention on one line in its style.
type row struct {
text string
style tcell.Style
style tview.Style
}
// Size returns Fill and a height of one row.

View file

@ -2,7 +2,6 @@ package messageslist
import (
"fmt"
"github.com/ayn2op/tview/layout"
"io"
"log/slog"
"net/http"
@ -14,6 +13,8 @@ import (
"time"
"unicode/utf8"
"github.com/ayn2op/tview/layout"
"github.com/ayn2op/arikawa/v3/discord"
md "github.com/ayn2op/arikawa/v3/markdown"
"github.com/ayn2op/arikawa/v3/state"
@ -37,7 +38,7 @@ import (
type messageItem struct {
message discord.Message
view tview.Element
view tview.Widget
separator bool
timestamp discord.Timestamp
@ -89,7 +90,7 @@ func NewModel(cfg *config.Config, state *ningen.State) Model {
}
// View shows the messages in a box titled with the channel and footed with footer, such as who is typing.
func (ml Model) View(focused bool, footer string) tview.Element {
func (ml Model) View(focused bool, footer string) tview.Widget {
return ui.Box(ml.listView(focused), &ml.cfg.Theme, focused).Title(ml.title()).Footer(footer)
}
@ -239,7 +240,7 @@ func (ml *Model) clearSelection() {
ml.setCursor(-1)
}
func (ml *Model) buildItem(index int) tview.Element {
func (ml *Model) buildItem(index int) tview.Widget {
if index < 0 || index >= len(ml.items) {
return nil
}
@ -315,7 +316,7 @@ func (v *messageView) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg { re
// dateSeparator is a line with the date in the middle, filled to the width it is drawn at.
type dateSeparator struct {
date, fill string
style tcell.Style
style tview.Style
}
// Size returns Fill and a height of one row.
@ -338,7 +339,7 @@ func (d dateSeparator) Draw(screen tview.Screen, area tview.Rectangle) {
func (dateSeparator) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg { return msg }
func (ml *Model) renderMessage(message discord.Message, baseStyle tcell.Style) richtext.Text {
func (ml *Model) renderMessage(message discord.Message, baseStyle tview.Style) richtext.Text {
builder := new(richtext.Builder)
ml.writeMessage(builder, message, baseStyle)
return builder.Finish()
@ -393,7 +394,7 @@ func (ml *Model) onRowCursorChanged(index int) {
ml.setCursor(target)
}
func (ml *Model) writeMessage(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) writeMessage(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
if ml.cfg.HideBlockedUsers {
isBlocked := ml.state.UserIsBlocked(message.Author.ID)
if isBlocked {
@ -424,7 +425,7 @@ func (ml *Model) writeMessage(builder *richtext.Builder, message discord.Message
ml.drawReactions(builder, message.Reactions, baseStyle)
}
func (ml *Model) drawReactions(builder *richtext.Builder, reactions []discord.Reaction, baseStyle tcell.Style) {
func (ml *Model) drawReactions(builder *richtext.Builder, reactions []discord.Reaction, baseStyle tview.Style) {
if len(reactions) == 0 {
return
}
@ -451,12 +452,12 @@ func (ml *Model) formatTimestamp(ts discord.Timestamp) string {
return ts.Time().In(time.Local).Format(ml.cfg.Timestamps.Format)
}
func (ml *Model) drawTimestamps(builder *richtext.Builder, ts discord.Timestamp, baseStyle tcell.Style) {
func (ml *Model) drawTimestamps(builder *richtext.Builder, ts discord.Timestamp, baseStyle tview.Style) {
dimStyle := baseStyle.Dim(true)
builder.Write(ml.formatTimestamp(ts)+" ", dimStyle)
}
func (ml *Model) drawAuthor(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) drawAuthor(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
name := message.Author.DisplayOrUsername()
foreground := tcell.ColorDefault
@ -495,7 +496,7 @@ func (ml *Model) memberForMessage(message discord.Message) *discord.Member {
// drawContent renders the message body and returns the parsed markdown AST together with the source bytes it indexes into, so callers can reuse them instead of re-parsing the same content (see drawEmbeds).
// root is nil when markdown rendering is disabled.
func (ml *Model) drawContent(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) (ast.Node, []byte) {
func (ml *Model) drawContent(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) (ast.Node, []byte) {
content, root, source := ml.renderContent(message, baseStyle, false)
if ml.cfg.Markdown.Enabled && !builder.LineEmpty() {
startsWithCodeBlock := false
@ -521,7 +522,7 @@ func (ml *Model) drawContent(builder *richtext.Builder, message discord.Message,
return root, source
}
func (ml *Model) renderContent(message discord.Message, baseStyle tcell.Style, forceMarkdown bool) (richtext.Text, ast.Node, []byte) {
func (ml *Model) renderContent(message discord.Message, baseStyle tview.Style, forceMarkdown bool) (richtext.Text, ast.Node, []byte) {
// Keep one rendering path for both normal messages and embed fragments so we preserve mention/link parsing behavior consistently across both.
if forceMarkdown || ml.cfg.Markdown.Enabled {
c := []byte(message.Content)
@ -534,7 +535,7 @@ func (ml *Model) renderContent(message discord.Message, baseStyle tcell.Style, f
return b.Finish(), nil, nil
}
func (ml *Model) drawSnapshotContent(builder *richtext.Builder, parent discord.Message, snapshot discord.MessageSnapshotMessage, baseStyle tcell.Style) {
func (ml *Model) drawSnapshotContent(builder *richtext.Builder, parent discord.Message, snapshot discord.MessageSnapshotMessage, baseStyle tview.Style) {
// Convert discord.MessageSnapshotMessage to discord.Message with common fields.
message := discord.Message{
Type: snapshot.Type,
@ -554,7 +555,7 @@ func (ml *Model) drawSnapshotContent(builder *richtext.Builder, parent discord.M
ml.drawContent(builder, message, baseStyle)
}
func (ml *Model) drawDefaultMessage(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) drawDefaultMessage(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
if ml.cfg.Timestamps.Enabled {
ml.drawTimestamps(builder, message.Timestamp, baseStyle)
}
@ -582,7 +583,7 @@ func (ml *Model) drawDefaultMessage(builder *richtext.Builder, message discord.M
}
}
func (ml *Model) drawEmbeds(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style, contentRoot ast.Node, contentSource []byte) {
func (ml *Model) drawEmbeds(builder *richtext.Builder, message discord.Message, baseStyle tview.Style, contentRoot ast.Node, contentSource []byte) {
if len(message.Embeds) == 0 {
return
}
@ -675,8 +676,8 @@ const (
embedLineURL
)
func embedLineStyles(baseStyle tcell.Style, theme config.MessagesListEmbedsTheme) [8]tcell.Style {
styles := [8]tcell.Style{}
func embedLineStyles(baseStyle tview.Style, theme config.MessagesListEmbedsTheme) [8]tview.Style {
styles := [8]tview.Style{}
styles[embedLineProvider] = tview.MergeStyle(baseStyle, theme.ProviderStyle.Style)
styles[embedLineAuthor] = tview.MergeStyle(baseStyle, theme.AuthorStyle.Style)
styles[embedLineTitle] = tview.MergeStyle(baseStyle, theme.TitleStyle.Style)
@ -804,7 +805,7 @@ func isMarkdownEscapable(c byte) bool {
}
}
func (ml *Model) drawForwardedMessage(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) drawForwardedMessage(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
dimStyle := baseStyle.Dim(true)
ml.drawTimestamps(builder, message.Timestamp, baseStyle)
ml.drawAuthor(builder, message, baseStyle)
@ -813,7 +814,7 @@ func (ml *Model) drawForwardedMessage(builder *richtext.Builder, message discord
builder.Write(" ("+ml.formatTimestamp(message.MessageSnapshots[0].Message.Timestamp)+") ", dimStyle)
}
func (ml *Model) drawReplyMessage(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) drawReplyMessage(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
dimStyle := baseStyle.Dim(true)
builder.Write(ml.cfg.Theme.MessagesList.ReplyIndicator+" ", dimStyle)
@ -829,7 +830,7 @@ func (ml *Model) drawReplyMessage(builder *richtext.Builder, message discord.Mes
ml.drawDefaultMessage(builder, message, baseStyle)
}
func (ml *Model) drawPinnedMessage(builder *richtext.Builder, message discord.Message, baseStyle tcell.Style) {
func (ml *Model) drawPinnedMessage(builder *richtext.Builder, message discord.Message, baseStyle tview.Style) {
builder.Write(message.Author.DisplayOrUsername()+" pinned a message.", baseStyle)
}

View file

@ -132,7 +132,7 @@ const (
)
// pickerView returns the view of the picker shown on top, or nil if none is open.
func (m Model) pickerView() tview.Element {
func (m Model) pickerView() tview.Widget {
switch m.overlay {
case overlayChannelsPicker:
return m.channelsPicker.View()
@ -346,25 +346,25 @@ func (m *Model) updatePane(p pane, msg tview.Msg) tview.Cmd {
return cmd
}
// paneElement passes input to the element of a pane and marks mouse input within the pane as meant for it.
type paneElement struct {
// paneWidget passes input to the widget of a pane and marks mouse input within the pane as meant for it.
type paneWidget struct {
pane pane
child tview.Element
child tview.Widget
}
func (p paneElement) Size() (width, height layout.Length) {
func (p paneWidget) Size() (width, height layout.Length) {
return p.child.Size()
}
func (p paneElement) Layout(limits layout.Limits) layout.Size {
func (p paneWidget) Layout(limits layout.Limits) layout.Size {
return p.child.Layout(limits)
}
func (p paneElement) Draw(screen tview.Screen, area tview.Rectangle) {
func (p paneWidget) Draw(screen tview.Screen, area tview.Rectangle) {
p.child.Draw(screen, area)
}
func (p paneElement) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg {
func (p paneWidget) Handle(msg tview.Msg, area tview.Rectangle) tview.Msg {
out := p.child.Handle(msg, area)
if mouse, ok := msg.(tview.MouseMsg); ok && area.Contains(mouse.Position()) {
return paneMsg{pane: p.pane, msg: out, focus: mouse.Action == tview.MouseLeftDown}
@ -385,9 +385,9 @@ const (
)
// paneView returns the view of p, focused if it has the focus and no picker is open, marked so that clicking it focuses it.
func (m Model) paneView(p pane) tview.Element {
func (m Model) paneView(p pane) tview.Widget {
focused := m.focused == p && m.overlay == overlayNone
var child tview.Element
var child tview.Widget
switch p {
case paneGuildsTree:
child = m.guildsTree.View(focused)
@ -398,7 +398,7 @@ func (m Model) paneView(p pane) tview.Element {
case paneMembersTree:
child = m.membersTree.View(focused)
}
return paneElement{pane: p, child: child}
return paneWidget{pane: p, child: child}
}
// setFocus focuses p if it can take the focus.
@ -423,10 +423,10 @@ func (m Model) canFocus(p pane) bool {
}
// View shows the guilds tree left of the messages above the composer, with the mentions list over the messages and an open picker on top.
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
picker := m.pickerView()
var right tview.Element = column.New(
var right tview.Widget = column.New(
m.paneView(paneMessagesList),
column.New(m.paneView(paneComposer)).Height(layout.Fixed(m.composer.Height())),
)

View file

@ -67,7 +67,7 @@ func (m *Model) navigateToChannel(channelID discord.ChannelID) tview.Cmd {
return cmd
}
// paneMsg is what a pane's element made of a mouse message within it. A left mouse button press also focuses the pane.
// paneMsg is what a pane's widget made of a mouse message within it. A left mouse button press also focuses the pane.
type paneMsg struct {
pane pane
msg tview.Msg

View file

@ -50,8 +50,8 @@ func (m Model) Init() tview.Cmd {
}
// View shows the tabs in a box.
func (m Model) View() tview.Element {
var content tview.Element
func (m Model) View() tview.Widget {
var content tview.Widget
switch m.active {
case tabPassword:
content = m.password.View()

View file

@ -60,7 +60,7 @@ func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
return m, nil
}
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
labelWidth := layout.Fixed(len("Password") + 1)
login := textinput.New(&m.login).
Focused(m.focus == focusLogin).

View file

@ -135,7 +135,7 @@ func halfBlock(top, bottom bool) rune {
}
// View centers the code, which scrolls when it is taller than the tab.
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
return center.New(
textview.New(m.code).
ScrollState(&m.scrollState).

View file

@ -46,7 +46,7 @@ func (m Model) Update(msg tview.Msg) (Model, tview.Cmd) {
return m, nil
}
func (m Model) View() tview.Element {
func (m Model) View() tview.Widget {
input := textinput.New(&m.token).
Mask("*").
Focused(!m.buttonFocused).

View file

@ -25,7 +25,7 @@ func NewModel(cfg *config.Config, title string) Model {
func (Model) Init() tview.Cmd { return nil }
// View shows the picker, turning the selected item into the message onSelect returns and canceling with onCancel.
func (m Model) View(onSelect func(picker.Item) tview.Msg, onCancel tview.Msg) tview.Element {
func (m Model) View(onSelect func(picker.Item) tview.Msg, onCancel tview.Msg) tview.Widget {
cfg := m.cfg
bar := scrollbar.New().
SymbolSet(cfg.Theme.ScrollBar.SymbolSet.SymbolSet).

View file

@ -151,8 +151,8 @@ func (m Model) helpHeight() int {
}
// View shows the inner model above help, with the modal dialog on top of both when one is open.
func (m Model) View() tview.Element {
var innerView, helpView tview.Element
func (m Model) View() tview.Widget {
var innerView, helpView tview.Widget
switch m.screen {
case screenLogin:
innerView = m.login.View()
@ -173,13 +173,11 @@ func (m Model) View() tview.Element {
// helpView returns the help for the keybinds that currently apply.
func (m Model) helpView() help.Widget {
cfg := m.cfg
styles := help.DefaultStyles()
styles.ShortKey = cfg.Theme.Help.ShortKeyStyle.Style
styles.ShortDesc = cfg.Theme.Help.ShortDescStyle.Style
styles.FullKey = cfg.Theme.Help.FullKeyStyle.Style
styles.FullDesc = cfg.Theme.Help.FullDescStyle.Style
return help.New(m).
Styles(styles).
ShortKeyStyle(cfg.Theme.Help.ShortKeyStyle.Style).
ShortDescStyle(cfg.Theme.Help.ShortDescStyle.Style).
FullKeyStyle(cfg.Theme.Help.FullKeyStyle.Style).
FullDescStyle(cfg.Theme.Help.FullDescStyle.Style).
CompactModifiers(cfg.Help.CompactModifiers).
ShortSeparator(cfg.Help.Separator).
ShowAll(m.helpShowAll)
@ -191,7 +189,7 @@ type (
)
// dialogView returns the dialog for the open modal request.
func (m Model) dialogView() tview.Element {
func (m Model) dialogView() tview.Widget {
labels := make([]string, len(m.modal.Buttons))
for i, button := range m.modal.Buttons {
labels[i] = button.Label

View file

@ -13,7 +13,7 @@ import (
)
// Box returns child in a box styled by the theme, highlighted while focused.
func Box(child tview.Element, theme *config.Theme, focused bool) box.Widget {
func Box(child tview.Widget, theme *config.Theme, focused bool) box.Widget {
padding := theme.Border.Padding
b := box.New(child).
Padding(padding[0], padding[1], padding[2], padding[3]).