More changes to do #91
This commit is contained in:
parent
21b81ccb27
commit
b0c4ef81e9
@ -80,7 +80,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
"send": {"sendevent"},
|
"send": {"sendevent"},
|
||||||
"msend": {"msendevent"},
|
"msend": {"msendevent"},
|
||||||
"state": {"setstate"},
|
"state": {"setstate"},
|
||||||
"mstate":{"msetstate"},
|
"mstate": {"msetstate"},
|
||||||
"rb": {"rainbow"},
|
"rb": {"rainbow"},
|
||||||
},
|
},
|
||||||
commands: map[string]CommandHandler{
|
commands: map[string]CommandHandler{
|
||||||
@ -102,6 +102,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
"msetstate": cmdMSetState,
|
"msetstate": cmdMSetState,
|
||||||
"rainbow": cmdRainbow,
|
"rainbow": cmdRainbow,
|
||||||
"invite": cmdInvite,
|
"invite": cmdInvite,
|
||||||
|
"hprof": cmdHeapProfile,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"runtime/pprof"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
@ -69,6 +72,18 @@ var rainbow = GradientTable{
|
|||||||
{colorful.LinearRgb(1, 0, 0.5), 1},
|
{colorful.LinearRgb(1, 0, 0.5), 1},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cmdHeapProfile(cmd *Command) {
|
||||||
|
runtime.GC()
|
||||||
|
memProfile, err := os.Create("gomuks.prof")
|
||||||
|
if err != nil {
|
||||||
|
debug.Print(err)
|
||||||
|
}
|
||||||
|
defer memProfile.Close()
|
||||||
|
if err := pprof.WriteHeapProfile(memProfile); err != nil {
|
||||||
|
debug.Print(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO this command definitely belongs in a plugin once we have a plugin system.
|
// TODO this command definitely belongs in a plugin once we have a plugin system.
|
||||||
func cmdRainbow(cmd *Command) {
|
func cmdRainbow(cmd *Command) {
|
||||||
text := strings.Join(cmd.Args, " ")
|
text := strings.Join(cmd.Args, " ")
|
||||||
|
@ -75,6 +75,7 @@ func NewMessageView(parent *RoomView) *MessageView {
|
|||||||
textBuffer: make([]tstring.TString, 0),
|
textBuffer: make([]tstring.TString, 0),
|
||||||
metaBuffer: make([]ifc.MessageMeta, 0),
|
metaBuffer: make([]ifc.MessageMeta, 0),
|
||||||
|
|
||||||
|
width: 80,
|
||||||
widestSender: 5,
|
widestSender: 5,
|
||||||
prevWidth: -1,
|
prevWidth: -1,
|
||||||
prevHeight: -1,
|
prevHeight: -1,
|
||||||
@ -159,8 +160,8 @@ func (view *MessageView) appendBuffer(message messages.UIMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view.textBuffer = append(view.textBuffer, message.Buffer()...)
|
for i := 0; i < message.Height(); i++ {
|
||||||
for range message.Buffer() {
|
view.textBuffer = append(view.textBuffer, nil)
|
||||||
view.metaBuffer = append(view.metaBuffer, message)
|
view.metaBuffer = append(view.metaBuffer, message)
|
||||||
}
|
}
|
||||||
view.prevMsgCount++
|
view.prevMsgCount++
|
||||||
@ -200,10 +201,15 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
|
|
||||||
view.textBuffer = append(append(view.textBuffer[0:start], new.Buffer()...), view.textBuffer[end:]...)
|
if new.Height() == 0 {
|
||||||
if len(new.Buffer()) != end-start {
|
new.CalculateBuffer(view.prevPrefs, view.prevWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
textBuf := make([]tstring.TString, new.Height())
|
||||||
|
view.textBuffer = append(append(view.textBuffer[0:start], textBuf...), view.textBuffer[end:]...)
|
||||||
|
if new.Height() != end-start {
|
||||||
metaBuffer := view.metaBuffer[0:start]
|
metaBuffer := view.metaBuffer[0:start]
|
||||||
for range new.Buffer() {
|
for i := 0; i < new.Height(); i++ {
|
||||||
metaBuffer = append(metaBuffer, new)
|
metaBuffer = append(metaBuffer, new)
|
||||||
}
|
}
|
||||||
view.metaBuffer = append(metaBuffer, view.metaBuffer[end:]...)
|
view.metaBuffer = append(metaBuffer, view.metaBuffer[end:]...)
|
||||||
@ -504,16 +510,22 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
meta.SenderColor())
|
meta.SenderColor())
|
||||||
}
|
}
|
||||||
prevMeta = meta
|
prevMeta = meta
|
||||||
htmlMessage, ok := meta.(*messages.HTMLMessage)
|
|
||||||
if ok {
|
|
||||||
htmlMessage.Draw(mauview.NewProxyScreen(screen, 0, line, view.width, htmlMessage.Height()))
|
|
||||||
if ok {
|
|
||||||
line += htmlMessage.Height()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message, ok := meta.(messages.UIMessage)
|
||||||
|
if ok {
|
||||||
|
for i := index - 1; i >= 0 && view.metaBuffer[i] == meta; i-- {
|
||||||
|
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)
|
text.Draw(screen, messageX, line)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/config"
|
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
@ -45,8 +45,6 @@ type BaseMessage struct {
|
|||||||
MsgIsService bool
|
MsgIsService bool
|
||||||
buffer []tstring.TString
|
buffer []tstring.TString
|
||||||
plainBuffer []tstring.TString
|
plainBuffer []tstring.TString
|
||||||
prevBufferWidth int
|
|
||||||
prevPrefs config.UserPreferences
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBaseMessage(id, sender, displayname string, msgtype mautrix.MessageType, timestamp time.Time) BaseMessage {
|
func newBaseMessage(id, sender, displayname string, msgtype mautrix.MessageType, timestamp time.Time) BaseMessage {
|
||||||
@ -57,7 +55,6 @@ func newBaseMessage(id, sender, displayname string, msgtype mautrix.MessageType,
|
|||||||
MsgSenderColor: widget.GetHashColor(sender),
|
MsgSenderColor: widget.GetHashColor(sender),
|
||||||
MsgType: msgtype,
|
MsgType: msgtype,
|
||||||
MsgID: id,
|
MsgID: id,
|
||||||
prevBufferWidth: 0,
|
|
||||||
MsgState: ifc.MessageStateDefault,
|
MsgState: ifc.MessageStateDefault,
|
||||||
MsgIsHighlight: false,
|
MsgIsHighlight: false,
|
||||||
MsgIsService: false,
|
MsgIsService: false,
|
||||||
@ -227,3 +224,9 @@ func (msg *BaseMessage) IsService() bool {
|
|||||||
func (msg *BaseMessage) SetIsService(isService bool) {
|
func (msg *BaseMessage) SetIsService(isService bool) {
|
||||||
msg.MsgIsService = isService
|
msg.MsgIsService = isService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) Draw(screen mauview.Screen) {
|
||||||
|
for y, line := range msg.buffer {
|
||||||
|
line.Draw(screen, 0, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -58,8 +58,3 @@ func (msg *ExpandedTextMessage) PlainText() string {
|
|||||||
func (msg *ExpandedTextMessage) CalculateBuffer(prefs config.UserPreferences, width int) {
|
func (msg *ExpandedTextMessage) CalculateBuffer(prefs config.UserPreferences, width int) {
|
||||||
msg.calculateBufferWithText(prefs, msg.MsgText, width)
|
msg.calculateBufferWithText(prefs, msg.MsgText, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
|
||||||
func (msg *ExpandedTextMessage) RecalculateBuffer() {
|
|
||||||
msg.CalculateBuffer(msg.prevPrefs, msg.prevBufferWidth)
|
|
||||||
}
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattn/go-runewidth"
|
"github.com/mattn/go-runewidth"
|
||||||
@ -57,9 +59,13 @@ func (hw *HTMLMessage) OnPasteEvent(event mauview.PasteEvent) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (hw *HTMLMessage) CalculateBuffer(preferences config.UserPreferences, width int) {
|
func (hw *HTMLMessage) CalculateBuffer(preferences config.UserPreferences, width int) {
|
||||||
|
if width <= 0 {
|
||||||
|
panic("Negative width in CalculateBuffer")
|
||||||
|
}
|
||||||
// TODO account for bare messages in initial startX
|
// TODO account for bare messages in initial startX
|
||||||
startX := 0
|
startX := 0
|
||||||
hw.Root.calculateBuffer(width, startX, preferences.BareMessageView)
|
hw.Root.calculateBuffer(width, startX, preferences.BareMessageView)
|
||||||
|
//debug.Print(hw.Root.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hw *HTMLMessage) Height() int {
|
func (hw *HTMLMessage) Height() int {
|
||||||
@ -109,8 +115,8 @@ func (he *HTMLEntity) Draw(screen mauview.Screen) {
|
|||||||
}
|
}
|
||||||
if len(he.Children) > 0 {
|
if len(he.Children) > 0 {
|
||||||
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent}
|
proxyScreen := &mauview.ProxyScreen{Parent: screen, OffsetX: he.Indent, Width: width - he.Indent}
|
||||||
for _, entity := range he.Children {
|
for i, entity := range he.Children {
|
||||||
if entity.Block {
|
if i != 0 && entity.startX == 0 {
|
||||||
proxyScreen.OffsetY++
|
proxyScreen.OffsetY++
|
||||||
}
|
}
|
||||||
proxyScreen.Height = entity.height
|
proxyScreen.Height = entity.height
|
||||||
@ -120,38 +126,87 @@ func (he *HTMLEntity) Draw(screen mauview.Screen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (he *HTMLEntity) calculateBuffer(width, startX int, bare bool) int {
|
func (he *HTMLEntity) String() string {
|
||||||
|
var buf strings.Builder
|
||||||
|
buf.WriteString("&HTMLEntity{\n")
|
||||||
|
_, _ = fmt.Fprintf(&buf, ` Tag="%s", Style=%d, Block=%t, Indent=%d, startX=%d, height=%d,\n`,
|
||||||
|
he.Tag, he.Style, he.Block, he.Indent, he.startX, he.height)
|
||||||
|
_, _ = fmt.Fprintf(&buf, ` Buffer=["%s"]`, strings.Join(he.buffer, "\", \""))
|
||||||
|
if len(he.Text) > 0 {
|
||||||
|
buf.WriteString(",\n")
|
||||||
|
_, _ = fmt.Fprintf(&buf, ` Text="%s"`, he.Text)
|
||||||
|
}
|
||||||
if len(he.Children) > 0 {
|
if len(he.Children) > 0 {
|
||||||
childStartX := 0
|
buf.WriteString(",\n")
|
||||||
|
buf.WriteString(" Children={")
|
||||||
|
for _, child := range he.Children {
|
||||||
|
buf.WriteString("\n ")
|
||||||
|
buf.WriteString(strings.Join(strings.Split(strings.TrimRight(child.String(), "\n"), "\n"), "\n "))
|
||||||
|
}
|
||||||
|
buf.WriteString("\n },")
|
||||||
|
}
|
||||||
|
buf.WriteString("\n},\n")
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (he *HTMLEntity) calculateBuffer(width, startX int, bare bool) int {
|
||||||
|
he.startX = startX
|
||||||
|
if he.Block {
|
||||||
|
he.startX = 0
|
||||||
|
}
|
||||||
|
he.height = 0
|
||||||
|
if len(he.Children) > 0 {
|
||||||
|
childStartX := he.startX
|
||||||
for _, entity := range he.Children {
|
for _, entity := range he.Children {
|
||||||
|
if entity.Block || childStartX == 0 || he.height == 0 {
|
||||||
|
he.height++
|
||||||
|
}
|
||||||
childStartX = entity.calculateBuffer(width-he.Indent, childStartX, bare)
|
childStartX = entity.calculateBuffer(width-he.Indent, childStartX, bare)
|
||||||
he.height += entity.height - 1
|
he.height += entity.height - 1
|
||||||
}
|
}
|
||||||
|
if len(he.Text) == 0 && !he.Block {
|
||||||
|
return childStartX
|
||||||
}
|
}
|
||||||
if len(he.Text) > 0 && width != he.prevWidth {
|
}
|
||||||
|
if len(he.Text) > 0 {
|
||||||
he.prevWidth = width
|
he.prevWidth = width
|
||||||
he.buffer = make([]string, 0, 1)
|
if he.buffer == nil {
|
||||||
text := he.Text
|
he.buffer = []string{}
|
||||||
if !he.Block {
|
|
||||||
he.startX = startX
|
|
||||||
} else {
|
|
||||||
startX = 0
|
|
||||||
}
|
}
|
||||||
|
bufPtr := 0
|
||||||
|
text := he.Text
|
||||||
|
textStartX := he.startX
|
||||||
for {
|
for {
|
||||||
extract := runewidth.Truncate(text, width-startX, "")
|
extract := runewidth.Truncate(text, width-textStartX, "")
|
||||||
extract = trim(extract, text, bare)
|
extract, wordWrapped := trim(extract, text, bare)
|
||||||
|
if !wordWrapped && textStartX > 0 {
|
||||||
|
if bufPtr < len(he.buffer) {
|
||||||
|
he.buffer[bufPtr] = ""
|
||||||
|
} else {
|
||||||
|
he.buffer = append(he.buffer, "")
|
||||||
|
}
|
||||||
|
bufPtr++
|
||||||
|
textStartX = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if bufPtr < len(he.buffer) {
|
||||||
|
he.buffer[bufPtr] = extract
|
||||||
|
} else {
|
||||||
he.buffer = append(he.buffer, extract)
|
he.buffer = append(he.buffer, extract)
|
||||||
|
}
|
||||||
|
bufPtr++
|
||||||
text = text[len(extract):]
|
text = text[len(extract):]
|
||||||
startX = 0
|
|
||||||
if len(text) == 0 {
|
if len(text) == 0 {
|
||||||
|
he.buffer = he.buffer[:bufPtr]
|
||||||
he.height += len(he.buffer)
|
he.height += len(he.buffer)
|
||||||
// This entity is over, return the startX for the next entity
|
// This entity is over, return the startX for the next entity
|
||||||
if he.Block {
|
if he.Block {
|
||||||
// ...except if it's a block entity
|
// ...except if it's a block entity
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return runewidth.StringWidth(extract)
|
return textStartX + runewidth.StringWidth(extract)
|
||||||
}
|
}
|
||||||
|
textStartX = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@ -164,12 +219,13 @@ func (he *HTMLEntity) calculateBuffer(width, startX int, bare bool) int {
|
|||||||
spacePattern = regexp.MustCompile(`\s+`)
|
spacePattern = regexp.MustCompile(`\s+`)
|
||||||
)*/
|
)*/
|
||||||
|
|
||||||
func trim(extract, full string, bare bool) string {
|
func trim(extract, full string, bare bool) (string, bool) {
|
||||||
if len(extract) == len(full) {
|
if len(extract) == len(full) {
|
||||||
return extract
|
return extract, true
|
||||||
}
|
}
|
||||||
if spaces := spacePattern.FindStringIndex(full[len(extract):]); spaces != nil && spaces[0] == 0 {
|
if spaces := spacePattern.FindStringIndex(full[len(extract):]); spaces != nil && spaces[0] == 0 {
|
||||||
extract = full[:len(extract)+spaces[1]]
|
extract = full[:len(extract)+spaces[1]]
|
||||||
|
//return extract, true
|
||||||
}
|
}
|
||||||
regex := boundaryPattern
|
regex := boundaryPattern
|
||||||
if bare {
|
if bare {
|
||||||
@ -180,8 +236,9 @@ func trim(extract, full string, bare bool) string {
|
|||||||
if match := matches[len(matches)-1]; len(match) >= 2 {
|
if match := matches[len(matches)-1]; len(match) >= 2 {
|
||||||
if until := match[1]; until < len(extract) {
|
if until := match[1]; until < len(extract) {
|
||||||
extract = extract[:until]
|
extract = extract[:until]
|
||||||
|
return extract, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return extract
|
return extract, len(extract) > 0 && extract[len(extract)-1] == ' '
|
||||||
}
|
}
|
||||||
|
@ -112,11 +112,4 @@ func (msg *ImageMessage) CalculateBuffer(prefs config.UserPreferences, width int
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg.buffer = image.Render()
|
msg.buffer = image.Render()
|
||||||
msg.prevBufferWidth = width
|
|
||||||
msg.prevPrefs = prefs
|
|
||||||
}
|
|
||||||
|
|
||||||
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
|
||||||
func (msg *ImageMessage) RecalculateBuffer() {
|
|
||||||
msg.CalculateBuffer(msg.prevPrefs, msg.prevBufferWidth)
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ package messages
|
|||||||
import (
|
import (
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/mauview"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UIMessage is a wrapper for the content and metadata of a Matrix message intended to be displayed.
|
// UIMessage is a wrapper for the content and metadata of a Matrix message intended to be displayed.
|
||||||
@ -27,7 +27,7 @@ type UIMessage interface {
|
|||||||
ifc.Message
|
ifc.Message
|
||||||
|
|
||||||
CalculateBuffer(preferences config.UserPreferences, width int)
|
CalculateBuffer(preferences config.UserPreferences, width int)
|
||||||
Buffer() []tstring.TString
|
Draw(screen mauview.Screen)
|
||||||
Height() int
|
Height() int
|
||||||
PlainText() string
|
PlainText() string
|
||||||
|
|
||||||
|
@ -266,6 +266,9 @@ func (parser *htmlParser) singleNodeToEntity(node *html.Node, stripLinebreak boo
|
|||||||
case html.ElementNode:
|
case html.ElementNode:
|
||||||
return parser.tagNodeToEntity(node, stripLinebreak)
|
return parser.tagNodeToEntity(node, stripLinebreak)
|
||||||
case html.DocumentNode:
|
case html.DocumentNode:
|
||||||
|
if node.FirstChild.Data == "html" && node.FirstChild.NextSibling == nil {
|
||||||
|
return parser.singleNodeToEntity(node.FirstChild, stripLinebreak)
|
||||||
|
}
|
||||||
return &messages.HTMLEntity{
|
return &messages.HTMLEntity{
|
||||||
Tag: "html",
|
Tag: "html",
|
||||||
Children: parser.nodeToEntities(node.FirstChild, stripLinebreak),
|
Children: parser.nodeToEntities(node.FirstChild, stripLinebreak),
|
||||||
|
@ -92,6 +92,4 @@ func (msg *BaseMessage) calculateBufferWithText(prefs config.UserPreferences, te
|
|||||||
str = str[len(extract):]
|
str = str[len(extract):]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg.prevBufferWidth = width
|
|
||||||
msg.prevPrefs = prefs
|
|
||||||
}
|
}
|
||||||
|
@ -90,8 +90,3 @@ func (msg *TextMessage) PlainText() string {
|
|||||||
func (msg *TextMessage) CalculateBuffer(prefs config.UserPreferences, width int) {
|
func (msg *TextMessage) CalculateBuffer(prefs config.UserPreferences, width int) {
|
||||||
msg.calculateBufferWithText(prefs, msg.getCache(), width)
|
msg.calculateBufferWithText(prefs, msg.getCache(), width)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
|
||||||
func (msg *TextMessage) RecalculateBuffer() {
|
|
||||||
msg.CalculateBuffer(msg.prevPrefs, msg.prevBufferWidth)
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user