From a5bdba204e66d4a0ce141e2b75a1ebe1be0f2122 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 15 Apr 2022 15:14:18 +0300 Subject: [PATCH] Add support for rendering spoilers. Fixes #331 --- CHANGELOG.md | 2 + ui/messages/base.go | 4 +- ui/messages/expandedtextmessage.go | 2 +- ui/messages/filemessage.go | 2 +- ui/messages/html/base.go | 6 +- ui/messages/html/blockquote.go | 8 +- ui/messages/html/break.go | 6 +- ui/messages/html/codeblock.go | 10 ++- ui/messages/html/container.go | 16 ++-- ui/messages/html/entity.go | 18 ++++- ui/messages/html/horizontalline.go | 6 +- ui/messages/html/list.go | 9 ++- ui/messages/html/parser.go | 39 ++++++---- ui/messages/html/spoiler.go | 120 +++++++++++++++++++++++++++++ ui/messages/html/text.go | 12 +-- ui/messages/htmlmessage.go | 27 ++----- ui/messages/redactedmessage.go | 2 +- ui/messages/textmessage.go | 4 +- 18 files changed, 212 insertions(+), 81 deletions(-) create mode 100644 ui/messages/html/spoiler.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 34d15d2..99287db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ (thanks to [@tleb] in [#354]). * Added tab-completion support for `/toggle` options (thanks to [@n-peugnet] in [#362]). +* Added initial support for rendering spoilers in messages. +* Fixed mentions being lost when editing messages. * Fixed date change messages showing the wrong date. * Fixed some whitespace in HTML being rendered even when it shouldn't. diff --git a/ui/messages/base.go b/ui/messages/base.go index a5aa62d..bf87a89 100644 --- a/ui/messages/base.go +++ b/ui/messages/base.go @@ -34,7 +34,7 @@ import ( ) type MessageRenderer interface { - Draw(screen mauview.Screen) + Draw(screen mauview.Screen, msg *UIMessage) NotificationContent() string PlainText() string CalculateBuffer(prefs config.UserPreferences, width int, msg *UIMessage) @@ -324,7 +324,7 @@ func (msg *UIMessage) DrawReactions(screen mauview.Screen) { func (msg *UIMessage) Draw(screen mauview.Screen) { proxyScreen := msg.DrawReply(screen) - msg.Renderer.Draw(proxyScreen) + msg.Renderer.Draw(proxyScreen, msg) msg.DrawReactions(proxyScreen) if msg.IsSelected { w, h := screen.Size() diff --git a/ui/messages/expandedtextmessage.go b/ui/messages/expandedtextmessage.go index 17f8236..6a1df3e 100644 --- a/ui/messages/expandedtextmessage.go +++ b/ui/messages/expandedtextmessage.go @@ -83,7 +83,7 @@ func (msg *ExpandedTextMessage) Height() int { return len(msg.buffer) } -func (msg *ExpandedTextMessage) Draw(screen mauview.Screen) { +func (msg *ExpandedTextMessage) Draw(screen mauview.Screen, _ *UIMessage) { for y, line := range msg.buffer { line.Draw(screen, 0, y) } diff --git a/ui/messages/filemessage.go b/ui/messages/filemessage.go index 8788d12..318bd1f 100644 --- a/ui/messages/filemessage.go +++ b/ui/messages/filemessage.go @@ -170,7 +170,7 @@ func (msg *FileMessage) Height() int { return len(msg.buffer) } -func (msg *FileMessage) Draw(screen mauview.Screen) { +func (msg *FileMessage) Draw(screen mauview.Screen, _ *UIMessage) { for y, line := range msg.buffer { line.Draw(screen, 0, y) } diff --git a/ui/messages/html/base.go b/ui/messages/html/base.go index db41c03..ad5c72c 100644 --- a/ui/messages/html/base.go +++ b/ui/messages/html/base.go @@ -38,7 +38,7 @@ type BaseEntity struct { } // AdjustStyle changes the style of this text entity. -func (be *BaseEntity) AdjustStyle(fn AdjustStyleFunc) Entity { +func (be *BaseEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { be.Style = fn(be.Style) return be } @@ -87,7 +87,7 @@ func (be *BaseEntity) String() string { } // CalculateBuffer prepares this entity for rendering with the given parameters. -func (be *BaseEntity) CalculateBuffer(width, startX int, bare bool) int { +func (be *BaseEntity) CalculateBuffer(width, startX int, ctx DrawContext) int { be.height = be.DefaultHeight be.startX = startX if be.Block { @@ -96,6 +96,6 @@ func (be *BaseEntity) CalculateBuffer(width, startX int, bare bool) int { return be.startX } -func (be *BaseEntity) Draw(screen mauview.Screen) { +func (be *BaseEntity) Draw(screen mauview.Screen, ctx DrawContext) { panic("Called Draw() of BaseEntity") } diff --git a/ui/messages/html/blockquote.go b/ui/messages/html/blockquote.go index 88e7aaf..25123da 100644 --- a/ui/messages/html/blockquote.go +++ b/ui/messages/html/blockquote.go @@ -40,8 +40,8 @@ func NewBlockquoteEntity(children []Entity) *BlockquoteEntity { }} } -func (be *BlockquoteEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - be.BaseEntity = be.BaseEntity.AdjustStyle(fn).(*BaseEntity) +func (be *BlockquoteEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + be.BaseEntity = be.BaseEntity.AdjustStyle(fn, reason).(*BaseEntity) return be } @@ -49,8 +49,8 @@ func (be *BlockquoteEntity) Clone() Entity { return &BlockquoteEntity{ContainerEntity: be.ContainerEntity.Clone().(*ContainerEntity)} } -func (be *BlockquoteEntity) Draw(screen mauview.Screen) { - be.ContainerEntity.Draw(screen) +func (be *BlockquoteEntity) Draw(screen mauview.Screen, ctx DrawContext) { + be.ContainerEntity.Draw(screen, ctx) for y := 0; y < be.height; y++ { screen.SetContent(0, y, BlockQuoteChar, nil, be.Style) } diff --git a/ui/messages/html/break.go b/ui/messages/html/break.go index 8996e56..f702a76 100644 --- a/ui/messages/html/break.go +++ b/ui/messages/html/break.go @@ -32,8 +32,8 @@ func NewBreakEntity() *BreakEntity { } // AdjustStyle changes the style of this text entity. -func (be *BreakEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - be.BaseEntity = be.BaseEntity.AdjustStyle(fn).(*BaseEntity) +func (be *BreakEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + be.BaseEntity = be.BaseEntity.AdjustStyle(fn, reason).(*BaseEntity) return be } @@ -49,6 +49,6 @@ func (be *BreakEntity) String() string { return "&html.BreakEntity{},\n" } -func (be *BreakEntity) Draw(screen mauview.Screen) { +func (be *BreakEntity) Draw(screen mauview.Screen, ctx DrawContext) { // No-op, the logic happens in containers } diff --git a/ui/messages/html/codeblock.go b/ui/messages/html/codeblock.go index 3c578ee..42d4433 100644 --- a/ui/messages/html/codeblock.go +++ b/ui/messages/html/codeblock.go @@ -46,12 +46,14 @@ func (ce *CodeBlockEntity) Clone() Entity { } } -func (ce *CodeBlockEntity) Draw(screen mauview.Screen) { +func (ce *CodeBlockEntity) Draw(screen mauview.Screen, ctx DrawContext) { screen.Fill(' ', ce.Background) - ce.ContainerEntity.Draw(screen) + ce.ContainerEntity.Draw(screen, ctx) } -func (ce *CodeBlockEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - // Don't allow adjusting code block style. +func (ce *CodeBlockEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + if reason != AdjustStyleReasonNormal { + ce.ContainerEntity.AdjustStyle(fn, reason) + } return ce } diff --git a/ui/messages/html/container.go b/ui/messages/html/container.go index 6ce1961..17e7aa9 100644 --- a/ui/messages/html/container.go +++ b/ui/messages/html/container.go @@ -61,15 +61,15 @@ func (ce *ContainerEntity) PlainText() string { } // AdjustStyle recursively changes the style of this entity and all its children. -func (ce *ContainerEntity) AdjustStyle(fn AdjustStyleFunc) Entity { +func (ce *ContainerEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { for _, child := range ce.Children { - child.AdjustStyle(fn) + child.AdjustStyle(fn, reason) } ce.Style = fn(ce.Style) return ce } -// clone creates a deep copy of this base entity. +// Clone creates a deep copy of this base entity. func (ce *ContainerEntity) Clone() Entity { children := make([]Entity, len(ce.Children)) for i, child := range ce.Children { @@ -98,7 +98,7 @@ func (ce *ContainerEntity) String() string { } // Draw draws this entity onto the given mauview Screen. -func (ce *ContainerEntity) Draw(screen mauview.Screen) { +func (ce *ContainerEntity) Draw(screen mauview.Screen, ctx DrawContext) { if len(ce.Children) == 0 { return } @@ -110,7 +110,7 @@ func (ce *ContainerEntity) Draw(screen mauview.Screen) { proxyScreen.OffsetY++ } proxyScreen.Height = entity.Height() - entity.Draw(proxyScreen) + entity.Draw(proxyScreen, ctx) proxyScreen.SetStyle(ce.Style) proxyScreen.OffsetY += entity.Height() - 1 _, isBreak := entity.(*BreakEntity) @@ -122,8 +122,8 @@ func (ce *ContainerEntity) Draw(screen mauview.Screen) { } // CalculateBuffer prepares this entity and all its children for rendering with the given parameters -func (ce *ContainerEntity) CalculateBuffer(width, startX int, bare bool) int { - ce.BaseEntity.CalculateBuffer(width, startX, bare) +func (ce *ContainerEntity) CalculateBuffer(width, startX int, ctx DrawContext) int { + ce.BaseEntity.CalculateBuffer(width, startX, ctx) if len(ce.Children) > 0 { ce.height = 0 childStartX := ce.startX @@ -132,7 +132,7 @@ func (ce *ContainerEntity) CalculateBuffer(width, startX int, bare bool) int { if entity.IsBlock() || childStartX == 0 || ce.height == 0 { ce.height++ } - childStartX = entity.CalculateBuffer(width-ce.Indent, childStartX, bare) + childStartX = entity.CalculateBuffer(width-ce.Indent, childStartX, ctx) ce.height += entity.Height() - 1 _, isBreak := entity.(*BreakEntity) if prevBreak && isBreak { diff --git a/ui/messages/html/entity.go b/ui/messages/html/entity.go index 5561ea9..094fa10 100644 --- a/ui/messages/html/entity.go +++ b/ui/messages/html/entity.go @@ -24,11 +24,23 @@ import ( // AdjustStyleFunc is a lambda function type to edit an existing tcell Style. type AdjustStyleFunc func(tcell.Style) tcell.Style +type AdjustStyleReason int + +const ( + AdjustStyleReasonNormal AdjustStyleReason = iota + AdjustStyleReasonHideSpoiler +) + +type DrawContext struct { + IsSelected bool + BareMessages bool +} + type Entity interface { // AdjustStyle recursively changes the style of the entity and all its children. - AdjustStyle(AdjustStyleFunc) Entity + AdjustStyle(AdjustStyleFunc, AdjustStyleReason) Entity // Draw draws the entity onto the given mauview Screen. - Draw(screen mauview.Screen) + Draw(screen mauview.Screen, ctx DrawContext) // IsBlock returns whether or not it's a block-type entity. IsBlock() bool // GetTag returns the HTML tag of the entity. @@ -43,7 +55,7 @@ type Entity interface { // Height returns the render height of the entity. Height() int // CalculateBuffer prepares the entity and all its children for rendering with the given parameters - CalculateBuffer(width, startX int, bare bool) int + CalculateBuffer(width, startX int, ctx DrawContext) int getStartX() int diff --git a/ui/messages/html/horizontalline.go b/ui/messages/html/horizontalline.go index ce10003..ff12709 100644 --- a/ui/messages/html/horizontalline.go +++ b/ui/messages/html/horizontalline.go @@ -36,8 +36,8 @@ func NewHorizontalLineEntity() *HorizontalLineEntity { }} } -func (he *HorizontalLineEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - he.BaseEntity = he.BaseEntity.AdjustStyle(fn).(*BaseEntity) +func (he *HorizontalLineEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + he.BaseEntity = he.BaseEntity.AdjustStyle(fn, reason).(*BaseEntity) return he } @@ -45,7 +45,7 @@ func (he *HorizontalLineEntity) Clone() Entity { return NewHorizontalLineEntity() } -func (he *HorizontalLineEntity) Draw(screen mauview.Screen) { +func (he *HorizontalLineEntity) Draw(screen mauview.Screen, ctx DrawContext) { width, _ := screen.Size() for x := 0; x < width; x++ { screen.SetContent(x, 0, HorizontalLineChar, nil, he.Style) diff --git a/ui/messages/html/list.go b/ui/messages/html/list.go index c101bdb..f5ddc83 100644 --- a/ui/messages/html/list.go +++ b/ui/messages/html/list.go @@ -59,8 +59,9 @@ func NewListEntity(ordered bool, start int, children []Entity) *ListEntity { return entity } -func (le *ListEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - le.BaseEntity = le.BaseEntity.AdjustStyle(fn).(*BaseEntity) +func (le *ListEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + le.BaseEntity = le.BaseEntity.AdjustStyle(fn, reason).(*BaseEntity) + le.ContainerEntity.AdjustStyle(fn, reason) return le } @@ -72,7 +73,7 @@ func (le *ListEntity) Clone() Entity { } } -func (le *ListEntity) Draw(screen mauview.Screen) { +func (le *ListEntity) Draw(screen mauview.Screen, ctx DrawContext) { width, _ := screen.Size() proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent, Style: le.Style} @@ -85,7 +86,7 @@ func (le *ListEntity) Draw(screen mauview.Screen) { } else { screen.SetContent(0, proxyScreen.OffsetY, '●', nil, le.Style) } - entity.Draw(proxyScreen) + entity.Draw(proxyScreen, ctx) proxyScreen.SetStyle(le.Style) proxyScreen.OffsetY += entity.Height() } diff --git a/ui/messages/html/parser.go b/ui/messages/html/parser.go index c09dd74..57474db 100644 --- a/ui/messages/html/parser.go +++ b/ui/messages/html/parser.go @@ -75,22 +75,23 @@ func AdjustStyleBackgroundColor(color tcell.Color) func(tcell.Style) tcell.Style } } -func (parser *htmlParser) getAttribute(node *html.Node, attribute string) string { +func (parser *htmlParser) maybeGetAttribute(node *html.Node, attribute string) (string, bool) { for _, attr := range node.Attr { if attr.Key == attribute { - return attr.Val + return attr.Val, true } } - return "" + return "", false +} + +func (parser *htmlParser) getAttribute(node *html.Node, attribute string) string { + val, _ := parser.maybeGetAttribute(node, attribute) + return val } func (parser *htmlParser) hasAttribute(node *html.Node, attribute string) bool { - for _, attr := range node.Attr { - if attr.Key == attribute { - return true - } - } - return false + _, ok := parser.maybeGetAttribute(node, attribute) + return ok } func (parser *htmlParser) listToEntity(node *html.Node) Entity { @@ -124,21 +125,25 @@ func (parser *htmlParser) basicFormatToEntity(node *html.Node) Entity { } switch node.Data { case "b", "strong": - entity.AdjustStyle(AdjustStyleBold) + entity.AdjustStyle(AdjustStyleBold, AdjustStyleReasonNormal) case "i", "em": - entity.AdjustStyle(AdjustStyleItalic) + entity.AdjustStyle(AdjustStyleItalic, AdjustStyleReasonNormal) case "s", "del", "strike": - entity.AdjustStyle(AdjustStyleStrikethrough) + entity.AdjustStyle(AdjustStyleStrikethrough, AdjustStyleReasonNormal) case "u", "ins": - entity.AdjustStyle(AdjustStyleUnderline) + entity.AdjustStyle(AdjustStyleUnderline, AdjustStyleReasonNormal) case "font", "span": fgColor, ok := parser.parseColor(node, "data-mx-color", "color") if ok { - entity.AdjustStyle(AdjustStyleTextColor(fgColor)) + entity.AdjustStyle(AdjustStyleTextColor(fgColor), AdjustStyleReasonNormal) } bgColor, ok := parser.parseColor(node, "data-mx-bg-color", "background-color") if ok { - entity.AdjustStyle(AdjustStyleBackgroundColor(bgColor)) + entity.AdjustStyle(AdjustStyleBackgroundColor(bgColor), AdjustStyleReasonNormal) + } + spoilerReason, isSpoiler := parser.maybeGetAttribute(node, "data-mx-spoiler") + if isSpoiler { + return NewSpoilerEntity(entity, spoilerReason) } } return entity @@ -175,7 +180,7 @@ func (parser *htmlParser) headerToEntity(node *html.Node) Entity { []Entity{NewTextEntity(strings.Repeat("#", int(node.Data[1]-'0')) + " ")}, parser.nodeToEntities(node.FirstChild)..., ), - }).AdjustStyle(AdjustStyleBold) + }).AdjustStyle(AdjustStyleBold, AdjustStyleReasonNormal) } func (parser *htmlParser) blockquoteToEntity(node *html.Node) Entity { @@ -468,7 +473,7 @@ func Parse(prefs *config.UserPreferences, room *rooms.Room, content *event.Messa }, Children: []Entity{ NewTextEntity("* "), - NewTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(sender))), + NewTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(sender)), AdjustStyleReasonNormal), NewTextEntity(" "), root, }, diff --git a/ui/messages/html/spoiler.go b/ui/messages/html/spoiler.go new file mode 100644 index 0000000..f28e8b8 --- /dev/null +++ b/ui/messages/html/spoiler.go @@ -0,0 +1,120 @@ +// gomuks - A terminal Matrix client written in Go. +// Copyright (C) 2022 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package html + +import ( + "fmt" + "strings" + + "go.mau.fi/mauview" + "go.mau.fi/tcell" +) + +type SpoilerEntity struct { + reason string + hidden *ContainerEntity + visible *ContainerEntity +} + +const SpoilerColor = tcell.ColorYellow + +func NewSpoilerEntity(visible *ContainerEntity, reason string) *SpoilerEntity { + hidden := visible.Clone().(*ContainerEntity) + hidden.AdjustStyle(func(style tcell.Style) tcell.Style { + return style.Foreground(SpoilerColor).Background(SpoilerColor) + }, AdjustStyleReasonHideSpoiler) + if len(reason) > 0 { + reasonEnt := NewTextEntity(fmt.Sprintf("(%s)", reason)) + hidden.Children = append([]Entity{reasonEnt}, hidden.Children...) + visible.Children = append([]Entity{reasonEnt}, visible.Children...) + } + return &SpoilerEntity{ + reason: reason, + hidden: hidden, + visible: visible, + } +} + +func (se *SpoilerEntity) Clone() Entity { + return &SpoilerEntity{ + reason: se.reason, + hidden: se.hidden.Clone().(*ContainerEntity), + visible: se.visible.Clone().(*ContainerEntity), + } +} + +func (se *SpoilerEntity) IsBlock() bool { + return false +} + +func (se *SpoilerEntity) GetTag() string { + return "span" +} + +func (se *SpoilerEntity) Draw(screen mauview.Screen, ctx DrawContext) { + if ctx.IsSelected { + se.visible.Draw(screen, ctx) + } else { + se.hidden.Draw(screen, ctx) + } +} + +func (se *SpoilerEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + if reason != AdjustStyleReasonHideSpoiler { + se.hidden.AdjustStyle(func(style tcell.Style) tcell.Style { + return fn(style).Foreground(SpoilerColor).Background(SpoilerColor) + }, reason) + se.visible.AdjustStyle(fn, reason) + } + return se +} + +func (se *SpoilerEntity) PlainText() string { + if len(se.reason) > 0 { + return fmt.Sprintf("spoiler: %s", se.reason) + } else { + return "spoiler" + } +} + +func (se *SpoilerEntity) String() string { + var buf strings.Builder + _, _ = fmt.Fprintf(&buf, `&html.SpoilerEntity{reason=%s`, se.reason) + buf.WriteString("\n visible=") + buf.WriteString(strings.Join(strings.Split(strings.TrimRight(se.visible.String(), "\n"), "\n"), "\n ")) + buf.WriteString("\n hidden=") + buf.WriteString(strings.Join(strings.Split(strings.TrimRight(se.hidden.String(), "\n"), "\n"), "\n ")) + buf.WriteString("\n]},") + return buf.String() +} + +func (se *SpoilerEntity) Height() int { + return se.visible.Height() +} + +func (se *SpoilerEntity) CalculateBuffer(width, startX int, ctx DrawContext) int { + se.hidden.CalculateBuffer(width, startX, ctx) + return se.visible.CalculateBuffer(width, startX, ctx) +} + +func (se *SpoilerEntity) getStartX() int { + return se.visible.getStartX() +} + +func (se *SpoilerEntity) IsEmpty() bool { + return se.visible.IsEmpty() +} diff --git a/ui/messages/html/text.go b/ui/messages/html/text.go index 9e5ab2e..1b8860c 100644 --- a/ui/messages/html/text.go +++ b/ui/messages/html/text.go @@ -49,8 +49,8 @@ func (te *TextEntity) IsEmpty() bool { return len(te.Text) == 0 } -func (te *TextEntity) AdjustStyle(fn AdjustStyleFunc) Entity { - te.BaseEntity = te.BaseEntity.AdjustStyle(fn).(*BaseEntity) +func (te *TextEntity) AdjustStyle(fn AdjustStyleFunc, reason AdjustStyleReason) Entity { + te.BaseEntity = te.BaseEntity.AdjustStyle(fn, reason).(*BaseEntity) return te } @@ -69,7 +69,7 @@ func (te *TextEntity) String() string { return fmt.Sprintf("&html.TextEntity{Text=%s, Base=%s},\n", te.Text, te.BaseEntity) } -func (te *TextEntity) Draw(screen mauview.Screen) { +func (te *TextEntity) Draw(screen mauview.Screen, ctx DrawContext) { width, _ := screen.Size() x := te.startX for y, line := range te.buffer { @@ -78,8 +78,8 @@ func (te *TextEntity) Draw(screen mauview.Screen) { } } -func (te *TextEntity) CalculateBuffer(width, startX int, bare bool) int { - te.BaseEntity.CalculateBuffer(width, startX, bare) +func (te *TextEntity) CalculateBuffer(width, startX int, ctx DrawContext) int { + te.BaseEntity.CalculateBuffer(width, startX, ctx) if len(te.Text) == 0 { return te.startX } @@ -94,7 +94,7 @@ func (te *TextEntity) CalculateBuffer(width, startX int, bare bool) int { for { // TODO add option no wrap and character wrap options extract := runewidth.Truncate(text, width-textStartX, "") - extract, wordWrapped := trim(extract, text, bare) + extract, wordWrapped := trim(extract, text, ctx.BareMessages) if !wordWrapped && textStartX > 0 { if bufPtr < len(te.buffer) { te.buffer[bufPtr] = "" diff --git a/ui/messages/htmlmessage.go b/ui/messages/htmlmessage.go index ea84bd3..d3593a6 100644 --- a/ui/messages/htmlmessage.go +++ b/ui/messages/htmlmessage.go @@ -28,9 +28,7 @@ import ( type HTMLMessage struct { Root html.Entity - FocusedBg tcell.Color TextColor tcell.Color - focused bool } func NewHTMLMessage(evt *muksevt.Event, displayname string, root html.Entity) *UIMessage { @@ -41,15 +39,11 @@ func NewHTMLMessage(evt *muksevt.Event, displayname string, root html.Entity) *U func (hw *HTMLMessage) Clone() MessageRenderer { return &HTMLMessage{ - Root: hw.Root.Clone(), - FocusedBg: hw.FocusedBg, + Root: hw.Root.Clone(), } } -func (hw *HTMLMessage) Draw(screen mauview.Screen) { - if hw.focused { - screen.SetStyle(tcell.StyleDefault.Background(hw.FocusedBg).Foreground(hw.TextColor)) - } +func (hw *HTMLMessage) Draw(screen mauview.Screen, msg *UIMessage) { if hw.TextColor != tcell.ColorDefault { hw.Root.AdjustStyle(func(style tcell.Style) tcell.Style { fg, _, _ := style.Decompose() @@ -57,18 +51,10 @@ func (hw *HTMLMessage) Draw(screen mauview.Screen) { return style.Foreground(hw.TextColor) } return style - }) + }, html.AdjustStyleReasonNormal) } screen.Clear() - hw.Root.Draw(screen) -} - -func (hw *HTMLMessage) Focus() { - hw.focused = true -} - -func (hw *HTMLMessage) Blur() { - hw.focused = false + hw.Root.Draw(screen, html.DrawContext{IsSelected: msg.IsSelected}) } func (hw *HTMLMessage) OnKeyEvent(event mauview.KeyEvent) bool { @@ -90,7 +76,10 @@ func (hw *HTMLMessage) CalculateBuffer(preferences config.UserPreferences, width // TODO account for bare messages in initial startX startX := 0 hw.TextColor = msg.TextColor() - hw.Root.CalculateBuffer(width, startX, preferences.BareMessageView) + hw.Root.CalculateBuffer(width, startX, html.DrawContext{ + IsSelected: msg.IsSelected, + BareMessages: preferences.BareMessageView, + }) } func (hw *HTMLMessage) Height() int { diff --git a/ui/messages/redactedmessage.go b/ui/messages/redactedmessage.go index dc61c65..e3e1718 100644 --- a/ui/messages/redactedmessage.go +++ b/ui/messages/redactedmessage.go @@ -59,7 +59,7 @@ const RedactionMaxWidth = 40 var RedactionStyle = tcell.StyleDefault.Foreground(tcell.NewRGBColor(50, 0, 0)) -func (msg *RedactedMessage) Draw(screen mauview.Screen) { +func (msg *RedactedMessage) Draw(screen mauview.Screen, _ *UIMessage) { w, _ := screen.Size() for x := 0; x < w && x < RedactionMaxWidth; x++ { screen.SetContent(x, 0, RedactionChar, nil, RedactionStyle) diff --git a/ui/messages/textmessage.go b/ui/messages/textmessage.go index 2fe0cbd..6705f6f 100644 --- a/ui/messages/textmessage.go +++ b/ui/messages/textmessage.go @@ -21,9 +21,9 @@ import ( "time" "go.mau.fi/mauview" - "maunium.net/go/gomuks/matrix/muksevt" "maunium.net/go/gomuks/config" + "maunium.net/go/gomuks/matrix/muksevt" "maunium.net/go/gomuks/ui/messages/tstring" ) @@ -95,7 +95,7 @@ func (msg *TextMessage) Height() int { return len(msg.buffer) } -func (msg *TextMessage) Draw(screen mauview.Screen) { +func (msg *TextMessage) Draw(screen mauview.Screen, _ *UIMessage) { for y, line := range msg.buffer { line.Draw(screen, 0, y) }