diff options
-rw-r--r-- | ui/message-view.go | 31 | ||||
-rw-r--r-- | ui/messages/htmlmessage.go | 47 | ||||
-rw-r--r-- | ui/messages/parser/htmlparser.go | 37 |
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, }, |