refactor(ui): update to tview's Widget and help style builders
This commit is contained in:
parent
f7180f8767
commit
f9bb10d846
21 changed files with 79 additions and 81 deletions
2
go.mod
2
go.mod
|
|
@ -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
4
go.sum
|
|
@ -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=
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue