From c96474bc9c1fe85f0c783ea43c437ebf7ba3b3c8 Mon Sep 17 00:00:00 2001 From: ayn2op Date: Thu, 4 Jun 2026 19:27:16 -0400 Subject: [PATCH] refactor(ui,chat,markdown): use tview.MergeStyle and uniseg.StringWidth --- go.mod | 2 +- go.sum | 4 ++-- internal/markdown/renderer.go | 9 ++++----- internal/ui/chat/guilds_tree.go | 4 ++-- internal/ui/chat/mentions_list.go | 3 ++- internal/ui/chat/messages_list.go | 20 ++++++++++---------- internal/ui/util.go | 23 ----------------------- 7 files changed, 21 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index fd166cb..fe68d7b 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/alecthomas/chroma/v2 v2.26.1 github.com/andybalholm/brotli v1.2.1 github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97 - github.com/ayn2op/tview v0.0.0-20260604212409-7075d4e3251a + github.com/ayn2op/tview v0.0.0-20260604231822-b8038457d689 github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb github.com/diamondburned/arikawa/v3 v3.6.1-0.20260518050745-b430932b3ee1 github.com/diamondburned/ningen/v3 v3.0.1-0.20260306213430-5a08d3a709b4 diff --git a/go.sum b/go.sum index 781872f..61b3d68 100644 --- a/go.sum +++ b/go.sum @@ -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-20260604212409-7075d4e3251a h1:mJ6+hfFcQrzFy/rUZLJgkHQzIXuVIeXxiUtU/OQiJF4= -github.com/ayn2op/tview v0.0.0-20260604212409-7075d4e3251a/go.mod h1:W0lZFznN+hDXma+CT27czLM8/zbNOda6vsfVgHI1Sew= +github.com/ayn2op/tview v0.0.0-20260604231822-b8038457d689 h1:DyyBD32TNUy4qy3WEG+PBN7BsOT4/R/bmVe71PoztUo= +github.com/ayn2op/tview v0.0.0-20260604231822-b8038457d689/go.mod h1:W0lZFznN+hDXma+CT27czLM8/zbNOda6vsfVgHI1Sew= github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= diff --git a/internal/markdown/renderer.go b/internal/markdown/renderer.go index 3738d8e..283c6b0 100644 --- a/internal/markdown/renderer.go +++ b/internal/markdown/renderer.go @@ -8,7 +8,6 @@ import ( "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" "github.com/ayn2op/discordo/internal/config" - "github.com/ayn2op/discordo/internal/ui" "github.com/ayn2op/tview" "github.com/diamondburned/ningen/v3/discordmd" "github.com/gdamore/tcell/v3" @@ -78,14 +77,14 @@ func (r *Renderer) RenderLines(source []byte, node ast.Node, base tcell.Style) [ case *ast.AutoLink: if entering { url := string(node.URL(source)) - style := ui.MergeStyle(currentStyle(), theme.URLStyle.Style).Url(url) + style := tview.MergeStyle(currentStyle(), theme.URLStyle.Style).Url(url) builder.Write(url, style) } case *ast.Link: if entering { url := string(node.Destination) linkDepth++ - pushStyle(ui.MergeStyle(currentStyle(), theme.URLStyle.Style).Url(url)) + pushStyle(tview.MergeStyle(currentStyle(), theme.URLStyle.Style).Url(url)) } else { if linkDepth > 0 { linkDepth-- @@ -126,11 +125,11 @@ func (r *Renderer) RenderLines(source []byte, node ast.Node, base tcell.Style) [ } case *discordmd.Mention: if entering { - builder.Write(mentionText(node), ui.MergeStyle(currentStyle(), theme.MentionStyle.Style)) + builder.Write(mentionText(node), tview.MergeStyle(currentStyle(), theme.MentionStyle.Style)) } case *discordmd.Emoji: if entering { - builder.Write(":"+node.Name+":", ui.MergeStyle(currentStyle(), theme.EmojiStyle.Style)) + builder.Write(":"+node.Name+":", tview.MergeStyle(currentStyle(), theme.EmojiStyle.Style)) } } return ast.WalkContinue, nil diff --git a/internal/ui/chat/guilds_tree.go b/internal/ui/chat/guilds_tree.go index c4a8646..f9034ec 100644 --- a/internal/ui/chat/guilds_tree.go +++ b/internal/ui/chat/guilds_tree.go @@ -123,10 +123,10 @@ func (gt *guildsTree) channelNodeStyle(channel discord.Channel) tcell.Style { recipient := channel.DMRecipients[0] presence, err := gt.chat.state.Cabinet.Presence(discord.NullGuildID, recipient.ID) if err != nil { - return ui.MergeStyle(gt.dmStatusStyle(discord.OfflineStatus), unread) + return tview.MergeStyle(gt.dmStatusStyle(discord.OfflineStatus), unread) } - return ui.MergeStyle(gt.dmStatusStyle(presence.Status), unread) + return tview.MergeStyle(gt.dmStatusStyle(presence.Status), unread) } func (gt *guildsTree) dmStatusStyle(status discord.Status) tcell.Style { diff --git a/internal/ui/chat/mentions_list.go b/internal/ui/chat/mentions_list.go index ac31749..8d3f3b3 100644 --- a/internal/ui/chat/mentions_list.go +++ b/internal/ui/chat/mentions_list.go @@ -6,6 +6,7 @@ import ( "github.com/ayn2op/tview" "github.com/ayn2op/tview/list" "github.com/gdamore/tcell/v3" + "github.com/rivo/uniseg" ) type mentionsListItem struct { @@ -90,7 +91,7 @@ func (m *mentionsList) selectedInsertText() (string, bool) { func (m *mentionsList) maxDisplayWidth() int { width := 0 for _, item := range m.items { - width = max(width, tview.TaggedStringWidth(item.displayText)) + width = max(width, uniseg.StringWidth(item.displayText)) } return width } diff --git a/internal/ui/chat/messages_list.go b/internal/ui/chat/messages_list.go index e95b766..8958734 100644 --- a/internal/ui/chat/messages_list.go +++ b/internal/ui/chat/messages_list.go @@ -494,7 +494,7 @@ func (ml *messagesList) drawDefaultMessage(builder *tview.LineBuilder, message d ml.drawEmbeds(builder, message, baseStyle, contentRoot, contentSource) - attachmentStyle := ui.MergeStyle(baseStyle, ml.cfg.Theme.MessagesList.AttachmentStyle.Style) + attachmentStyle := tview.MergeStyle(baseStyle, ml.cfg.Theme.MessagesList.AttachmentStyle.Style) for _, a := range message.Attachments { builder.NewLine() if ml.cfg.ShowAttachmentLinks { @@ -527,7 +527,7 @@ func (ml *messagesList) drawEmbeds(builder *tview.LineBuilder, message discord.M lineStyles := embedLineStyles(baseStyle, ml.cfg.Theme.MessagesList.Embeds) defaultBarStyle := baseStyle.Dim(true) prefixText := " ▎ " - prefixWidth := tview.TaggedStringWidth(prefixText) + prefixWidth := uniseg.StringWidth(prefixText) _, _, innerWidth, _ := ml.InnerRect() // Wrap against the current list viewport. This keeps embed wrapping stable even when sidebars/panes are resized. wrapWidth := max(innerWidth-prefixWidth, 1) @@ -674,14 +674,14 @@ const ( func embedLineStyles(baseStyle tcell.Style, theme config.MessagesListEmbedsTheme) [8]tcell.Style { styles := [8]tcell.Style{} - styles[embedLineProvider] = ui.MergeStyle(baseStyle, theme.ProviderStyle.Style) - styles[embedLineAuthor] = ui.MergeStyle(baseStyle, theme.AuthorStyle.Style) - styles[embedLineTitle] = ui.MergeStyle(baseStyle, theme.TitleStyle.Style) - styles[embedLineDescription] = ui.MergeStyle(baseStyle, theme.DescriptionStyle.Style) - styles[embedLineFieldName] = ui.MergeStyle(baseStyle, theme.FieldNameStyle.Style) - styles[embedLineFieldValue] = ui.MergeStyle(baseStyle, theme.FieldValueStyle.Style) - styles[embedLineFooter] = ui.MergeStyle(baseStyle, theme.FooterStyle.Style) - styles[embedLineURL] = ui.MergeStyle(baseStyle, theme.URLStyle.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) + styles[embedLineDescription] = tview.MergeStyle(baseStyle, theme.DescriptionStyle.Style) + styles[embedLineFieldName] = tview.MergeStyle(baseStyle, theme.FieldNameStyle.Style) + styles[embedLineFieldValue] = tview.MergeStyle(baseStyle, theme.FieldValueStyle.Style) + styles[embedLineFooter] = tview.MergeStyle(baseStyle, theme.FooterStyle.Style) + styles[embedLineURL] = tview.MergeStyle(baseStyle, theme.URLStyle.Style) return styles } diff --git a/internal/ui/util.go b/internal/ui/util.go index f9481af..a6633af 100644 --- a/internal/ui/util.go +++ b/internal/ui/util.go @@ -9,7 +9,6 @@ import ( "github.com/ayn2op/tview" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/ningen/v3" - "github.com/gdamore/tcell/v3" ) // ConfigureBox configures the provided box according to the provided theme. @@ -131,25 +130,3 @@ func getMessageIDFromChannel(channel discord.Channel) discord.MessageID { } return discord.MessageID(channel.ID) } - -func MergeStyle(base, overlay tcell.Style) tcell.Style { - fg := overlay.GetForeground() - if fg == tcell.ColorDefault { - fg = base.GetForeground() - } - bg := overlay.GetBackground() - if bg == tcell.ColorDefault { - bg = base.GetBackground() - } - style := base.Foreground(fg).Background(bg) - style = style.Bold(base.HasBold() || overlay.HasBold()) - style = style.Dim(base.HasDim() || overlay.HasDim()) - style = style.Italic(base.HasItalic() || overlay.HasItalic()) - style = style.Blink(base.HasBlink() || overlay.HasBlink()) - style = style.Reverse(base.HasReverse() || overlay.HasReverse()) - style = style.StrikeThrough(base.HasStrikeThrough() || overlay.HasStrikeThrough()) - if base.HasUnderline() || overlay.HasUnderline() { - style = style.Underline(true) - } - return style -}