aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui/message-view.go31
-rw-r--r--ui/messages/htmlmessage.go47
-rw-r--r--ui/messages/parser/htmlparser.go37
3 files changed, 69 insertions, 46 deletions
diff --git a/ui/message-view.go b/ui/message-view.go
index 144bfca..748eec3 100644
--- a/ui/message-view.go
+++ b/ui/message-view.go
@@ -474,29 +474,25 @@ func (view *MessageView) Draw(screen mauview.Screen) {
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
var prevMeta ifc.MessageMeta
- firstLine := true
- skippedLines := 0
- for line := 0; line < view.height; line++ {
- index := indexOffset + line
- if index < 0 {
- skippedLines++
- continue
- } else if index >= view.TotalHeight() {
- break
- }
-
- showScrollbar := line-skippedLines >= scrollBarPos-scrollBarHeight && line-skippedLines < scrollBarPos
- isTop := firstLine && view.ScrollOffset+view.height >= view.TotalHeight()
+ viewStart := 0
+ if indexOffset < 0 {
+ viewStart = -indexOffset
+ }
+ for line := viewStart; line < view.height; line++ {
+ showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
+ isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
isBottom := line == view.height-1 && view.ScrollOffset == 0
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
- firstLine = false
-
if !bareMode {
screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
}
+ }
+
+ for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
+ index := indexOffset + line
text, meta := view.textBuffer[index], view.metaBuffer[index]
if meta != prevMeta {
@@ -519,11 +515,6 @@ func (view *MessageView) Draw(screen mauview.Screen) {
line--
}
message.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, message.Height()))
- if !bareMode {
- for i := line; i < line+message.Height(); i++ {
- screen.SetContent(separatorX, i, borderChar, nil, borderStyle)
- }
- }
line += message.Height() - 1
} else {
text.Draw(screen, messageX, line)
diff --git a/ui/messages/htmlmessage.go b/ui/messages/htmlmessage.go
index 8685442..eac0841 100644
--- a/ui/messages/htmlmessage.go
+++ b/ui/messages/htmlmessage.go
@@ -36,6 +36,10 @@ type HTMLMessage struct {
BaseMessage
Root HTMLEntity
+
+ FocusedBackground tcell.Color
+
+ focused bool
}
func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType, root HTMLEntity, timestamp time.Time) UIMessage {
@@ -45,9 +49,21 @@ func NewHTMLMessage(id, sender, displayname string, msgtype mautrix.MessageType,
}
}
func (hw *HTMLMessage) Draw(screen mauview.Screen) {
+ if hw.focused {
+ screen.SetStyle(tcell.StyleDefault.Background(hw.FocusedBackground))
+ }
+ screen.Clear()
hw.Root.Draw(screen)
}
+func (hw *HTMLMessage) Focus() {
+ hw.focused = true
+}
+
+func (hw *HTMLMessage) Blur() {
+ hw.focused = false
+}
+
func (hw *HTMLMessage) OnKeyEvent(event mauview.KeyEvent) bool {
return false
}
@@ -154,7 +170,7 @@ func NewListEntity(ordered bool, start int, children []HTMLEntity) *ListEntity {
func (le *ListEntity) Draw(screen mauview.Screen) {
width, _ := screen.Size()
- proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent}
+ proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: le.Indent, Width: width - le.Indent, Style: le.Style}
for i, entity := range le.Children {
proxyScreen.Height = entity.Height()
if le.Ordered {
@@ -165,6 +181,7 @@ func (le *ListEntity) Draw(screen mauview.Screen) {
screen.SetContent(0, proxyScreen.OffsetY, '●', nil, le.Style)
}
entity.Draw(proxyScreen)
+ proxyScreen.SetStyle(le.Style)
proxyScreen.OffsetY += entity.Height()
}
}
@@ -173,6 +190,31 @@ func (le *ListEntity) String() string {
return fmt.Sprintf("&ListEntity{Ordered=%t, Start=%d, Base=%s},\n", le.Ordered, le.Start, le.BaseHTMLEntity)
}
+type CodeBlockEntity struct {
+ *BaseHTMLEntity
+ Background tcell.Style
+}
+
+func NewCodeBlockEntity(children []HTMLEntity, background tcell.Style) *CodeBlockEntity {
+ return &CodeBlockEntity{
+ BaseHTMLEntity: &BaseHTMLEntity{
+ Tag: "pre",
+ Block: true,
+ Children: children,
+ },
+ Background: background,
+ }
+}
+
+func (ce *CodeBlockEntity) Draw(screen mauview.Screen) {
+ screen.Fill(' ', ce.Background)
+ ce.BaseHTMLEntity.Draw(screen)
+}
+
+func (ce *CodeBlockEntity) AdjustStyle(fn AdjustStyleFunc) HTMLEntity {
+ return ce
+}
+
type BreakEntity struct {
*BaseHTMLEntity
}
@@ -297,13 +339,14 @@ func (he *BaseHTMLEntity) Draw(screen mauview.Screen) {
}
if len(he.Children) > 0 {
prevBreak := false
- proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent}
+ proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent, Style: he.Style}
for i, entity := range he.Children {
if i != 0 && entity.getStartX() == 0 {
proxyScreen.OffsetY++
}
proxyScreen.Height = entity.Height()
entity.Draw(proxyScreen)
+ proxyScreen.SetStyle(he.Style)
proxyScreen.OffsetY += entity.Height() - 1
_, isBreak := entity.(*BreakEntity)
if prevBreak && isBreak {
diff --git a/ui/messages/parser/htmlparser.go b/ui/messages/parser/htmlparser.go
index e658c61..6e218df 100644
--- a/ui/messages/parser/htmlparser.go
+++ b/ui/messages/parser/htmlparser.go
@@ -221,7 +221,7 @@ func styleEntryToStyle(se chroma.StyleEntry) tcell.Style {
}
func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEntity {
- lexer := lexers.Get(language)
+ lexer := lexers.Get(strings.ToLower(language))
if lexer == nil {
return nil
}
@@ -229,7 +229,9 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
if err != nil {
return nil
}
+ // TODO allow changing theme
style := styles.SolarizedDark
+
tokens := iter.Tokens()
children := make([]messages.HTMLEntity, len(tokens))
for i, token := range tokens {
@@ -245,39 +247,26 @@ func (parser *htmlParser) syntaxHighlight(text, language string) messages.HTMLEn
}
}
}
- return &messages.BaseHTMLEntity{
- Tag: "pre",
- Block: true,
- Children: children,
- }
+ return messages.NewCodeBlockEntity(children, styleEntryToStyle(style.Get(chroma.Background)))
}
func (parser *htmlParser) codeblockToEntity(node *html.Node) messages.HTMLEntity {
- entity := &messages.BaseHTMLEntity{
- Tag: "pre",
- Block: true,
- }
+ lang := "plaintext"
// TODO allow disabling syntax highlighting
if node.FirstChild.Type == html.ElementNode && node.FirstChild.Data == "code" {
- text := (&messages.BaseHTMLEntity{
- Children: parser.nodeToEntities(node.FirstChild.FirstChild, false),
- }).PlainText()
- attr := parser.getAttribute(node.FirstChild, "class")
- var lang string
+ node = node.FirstChild
+ attr := parser.getAttribute(node, "class")
for _, class := range strings.Split(attr, " ") {
if strings.HasPrefix(class, "language-") {
lang = class[len("language-"):]
break
}
}
- if len(lang) != 0 {
- if parsed := parser.syntaxHighlight(text, lang); parsed != nil {
- return parsed
- }
- }
}
- entity.Children = parser.nodeToEntities(node.FirstChild, false)
- return entity
+ text := (&messages.BaseHTMLEntity{
+ Children: parser.nodeToEntities(node.FirstChild, false),
+ }).PlainText()
+ return parser.syntaxHighlight(text, lang)
}
func (parser *htmlParser) tagNodeToEntity(node *html.Node, stripLinebreak bool) messages.HTMLEntity {
@@ -311,7 +300,7 @@ func (parser *htmlParser) singleNodeToEntity(node *html.Node, stripLinebreak boo
switch node.Type {
case html.TextNode:
if stripLinebreak {
- node.Data = strings.Replace(node.Data, "\n", "", -1)
+ node.Data = strings.ReplaceAll(node.Data, "\n", "")
}
return &messages.BaseHTMLEntity{
Tag: "text",
@@ -372,7 +361,7 @@ func ParseHTMLMessage(room *rooms.Room, evt *mautrix.Event, senderDisplayname st
Tag: "emote",
Children: []messages.HTMLEntity{
messages.NewHTMLTextEntity("* "),
- messages.NewHTMLTextEntity("* ").AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
+ messages.NewHTMLTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender))),
messages.NewHTMLTextEntity(" "),
root,
},