refactor text styling to line/segment APIs and fix list selection

This commit is contained in:
ayn2op 2026-02-08 02:22:40 -05:00
parent d86b2f6e60
commit 01fe923a34
7 changed files with 27 additions and 19 deletions

2
go.mod
View file

@ -7,7 +7,7 @@ go 1.25.3
require (
github.com/BurntSushi/toml v1.6.0
github.com/andybalholm/brotli v1.2.0
github.com/ayn2op/tview v0.0.0-20260208060151-4a4f3e6ac892
github.com/ayn2op/tview v0.0.0-20260208071935-3324c648db69
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
github.com/diamondburned/arikawa/v3 v3.6.1-0.20250928004212-a891a653eb26
github.com/diamondburned/ningen/v3 v3.0.1-0.20250920191746-98fbd92e134d

4
go.sum
View file

@ -8,8 +8,8 @@ github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
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-20260208060151-4a4f3e6ac892 h1:lQHJobFgud7g57eKr7ODWRqW0CWuuPwLtITSmVYbbhQ=
github.com/ayn2op/tview v0.0.0-20260208060151-4a4f3e6ac892/go.mod h1:g6IOdF9SlnVZMDnRABANP8I0LFseKyYxWqEkzBSL5ho=
github.com/ayn2op/tview v0.0.0-20260208071935-3324c648db69 h1:DU0vNRmldUajM4tY5feFG/WsxaLhiPUHuWaQotmCLH8=
github.com/ayn2op/tview v0.0.0-20260208071935-3324c648db69/go.mod h1:g6IOdF9SlnVZMDnRABANP8I0LFseKyYxWqEkzBSL5ho=
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

@ -68,7 +68,7 @@ func (gt *guildsTree) createFolderNode(folder gateway.GuildFolder) {
folderNode := tview.NewTreeNode(name).SetExpanded(gt.cfg.Theme.GuildsTree.AutoExpandFolders)
if folder.Color != 0 {
folderStyle := tcell.StyleDefault.Foreground(tcell.NewHexColor(int32(folder.Color)))
folderNode.SetTextStyle(folderStyle)
gt.setNodeLineStyle(folderNode, folderStyle)
}
gt.GetRoot().AddChild(folderNode)
@ -109,9 +109,8 @@ func (gt *guildsTree) getChannelNodeStyle(channelID discord.ChannelID) tcell.Sty
}
func (gt *guildsTree) createGuildNode(n *tview.TreeNode, guild discord.Guild) {
guildNode := tview.NewTreeNode(guild.Name).
SetReference(guild.ID).
SetTextStyle(gt.getGuildNodeStyle(guild.ID))
guildNode := tview.NewTreeNode(guild.Name).SetReference(guild.ID)
gt.setNodeLineStyle(guildNode, gt.getGuildNodeStyle(guild.ID))
n.AddChild(guildNode)
gt.guildNodeByID[guild.ID] = guildNode
}
@ -121,13 +120,20 @@ func (gt *guildsTree) createChannelNode(node *tview.TreeNode, channel discord.Ch
return
}
channelNode := tview.NewTreeNode(ui.ChannelToString(channel, gt.cfg.Icons)).
SetReference(channel.ID).
SetTextStyle(gt.getChannelNodeStyle(channel.ID))
channelNode := tview.NewTreeNode(ui.ChannelToString(channel, gt.cfg.Icons)).SetReference(channel.ID)
gt.setNodeLineStyle(channelNode, gt.getChannelNodeStyle(channel.ID))
node.AddChild(channelNode)
gt.channelNodeByID[channel.ID] = channelNode
}
func (gt *guildsTree) setNodeLineStyle(node *tview.TreeNode, style tcell.Style) {
line := node.GetLine()
for i := range line {
line[i].Style = style
}
node.SetLine(line)
}
func (gt *guildsTree) createChannelNodes(node *tview.TreeNode, channels []discord.Channel) {
// Preserve exact ordering semantics:
// 1) top-level non-categories (in input order),
@ -243,14 +249,16 @@ func (gt *guildsTree) onSelected(node *tview.TreeNode) {
hasNoPerm := channel.Type != discord.DirectMessage && channel.Type != discord.GroupDM && !gt.chatView.state.HasPermissions(channel.ID, discord.PermissionSendMessages)
gt.chatView.messageInput.SetDisabled(hasNoPerm)
var text string
if hasNoPerm {
gt.chatView.messageInput.SetPlaceholder("You do not have permission to send messages in this channel.")
text = "You do not have permission to send messages in this channel."
} else {
gt.chatView.messageInput.SetPlaceholder("Message...")
text = "Message..."
if gt.cfg.AutoFocus {
gt.chatView.app.SetFocus(gt.chatView.messageInput)
}
}
gt.chatView.messageInput.SetPlaceholder(tview.NewLine(tview.NewSegment(text, tcell.StyleDefault.Dim(true))))
case dmNode: // Direct messages folder
channels, err := gt.chatView.state.PrivateChannels()
if err != nil {

View file

@ -51,15 +51,16 @@ func (m *mentionsList) rebuild() {
item := m.items[index]
style := item.style
if index == cursor {
style = style.Foreground(tview.Styles.PrimitiveBackgroundColor).Background(tview.Styles.PrimaryTextColor)
style = style.Reverse(true)
}
line := tview.NewLine(tview.NewSegment(item.displayText, style))
return tview.NewTextView().
SetScrollable(false).
SetWrap(false).
SetWordWrap(false).
SetTextStyle(style).
SetLines([]tview.Line{{{Text: item.displayText, Style: style}}})
SetLines([]tview.Line{line})
})
if len(m.items) == 0 {

View file

@ -65,8 +65,7 @@ func newMessageInput(cfg *config.Config, chatView *View) *messageInput {
mi.Box = ui.ConfigureBox(mi.Box, &cfg.Theme)
mi.SetInputCapture(mi.onInputCapture)
mi.
SetPlaceholder("Select a channel to start chatting").
SetPlaceholderStyle(tcell.StyleDefault.Dim(true)).
SetPlaceholder(tview.NewLine(tview.NewSegment("Select a channel to start chatting", tcell.StyleDefault.Dim(true)))).
SetClipboard(
func(s string) { clipboard.Write(clipboard.FmtText, []byte(s)) },
func() string { return string(clipboard.Read(clipboard.FmtText)) },

View file

@ -268,7 +268,7 @@ func (v *View) onReadUpdate(event *read.UpdateEvent) {
var updated bool
if event.GuildID.IsValid() {
if guildNode := v.guildsTree.findNodeByReference(event.GuildID); guildNode != nil {
guildNode.SetTextStyle(v.guildsTree.getGuildNodeStyle(event.GuildID))
v.guildsTree.setNodeLineStyle(guildNode, v.guildsTree.getGuildNodeStyle(event.GuildID))
updated = true
}
}
@ -276,7 +276,7 @@ func (v *View) onReadUpdate(event *read.UpdateEvent) {
// Channel style is always updated for the target channel regardless of
// whether it's in a guild or DM.
if channelNode := v.guildsTree.findNodeByReference(event.ChannelID); channelNode != nil {
channelNode.SetTextStyle(v.guildsTree.getChannelNodeStyle(event.ChannelID))
v.guildsTree.setNodeLineStyle(channelNode, v.guildsTree.getChannelNodeStyle(event.ChannelID))
updated = true
}

View file

@ -66,7 +66,7 @@ func (p *Picker) setFilteredItems(filtered Items) {
}
style := tcell.StyleDefault
if index == cursor {
style = style.Foreground(tview.Styles.PrimitiveBackgroundColor).Background(tview.Styles.PrimaryTextColor)
style = style.Reverse(true)
}
return tview.NewTextView().
SetScrollable(false).