Start refactoring various things in message rendering and sending
This commit is contained in:
parent
2b6c435e50
commit
dbee49476d
@ -19,11 +19,9 @@ package ifc
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
|
||||||
"maunium.net/go/tcell"
|
|
||||||
|
|
||||||
"maunium.net/go/gomuks/matrix/pushrules"
|
"maunium.net/go/gomuks/matrix/pushrules"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
|
"maunium.net/go/mautrix"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UIProvider func(gmx Gomuks) GomuksUI
|
type UIProvider func(gmx Gomuks) GomuksUI
|
||||||
@ -50,7 +48,6 @@ type MainView interface {
|
|||||||
UpdateTags(room *rooms.Room)
|
UpdateTags(room *rooms.Room)
|
||||||
|
|
||||||
SetTyping(roomID string, users []string)
|
SetTyping(roomID string, users []string)
|
||||||
ParseEvent(roomView RoomView, evt *mautrix.Event) Message
|
|
||||||
|
|
||||||
NotifyMessage(room *rooms.Room, message Message, should pushrules.PushActionArrayShould)
|
NotifyMessage(room *rooms.Room, message Message, should pushrules.PushActionArrayShould)
|
||||||
InitialSyncDone()
|
InitialSyncDone()
|
||||||
@ -71,50 +68,17 @@ type RoomView interface {
|
|||||||
SetTyping(users []string)
|
SetTyping(users []string)
|
||||||
UpdateUserList()
|
UpdateUserList()
|
||||||
|
|
||||||
NewTempMessage(msgtype mautrix.MessageType, text string) Message
|
ParseEvent(evt *mautrix.Event) Message
|
||||||
AddMessage(message Message, direction MessageDirection)
|
AppendMessage(message Message)
|
||||||
|
MarkMessageFailed(message Message)
|
||||||
AddServiceMessage(message string)
|
AddServiceMessage(message string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageMeta interface {
|
|
||||||
Sender() string
|
|
||||||
SenderColor() tcell.Color
|
|
||||||
TextColor() tcell.Color
|
|
||||||
TimestampColor() tcell.Color
|
|
||||||
Timestamp() time.Time
|
|
||||||
FormatTime() string
|
|
||||||
FormatDate() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageState is an enum to specify if a Message is being sent, failed to send or was successfully sent.
|
|
||||||
type MessageState int
|
|
||||||
|
|
||||||
// Allowed MessageStates.
|
|
||||||
const (
|
|
||||||
MessageStateSending MessageState = iota
|
|
||||||
MessageStateDefault
|
|
||||||
MessageStateFailed
|
|
||||||
)
|
|
||||||
|
|
||||||
type Message interface {
|
type Message interface {
|
||||||
MessageMeta
|
|
||||||
|
|
||||||
SetIsHighlight(isHighlight bool)
|
|
||||||
IsHighlight() bool
|
|
||||||
|
|
||||||
SetIsService(isService bool)
|
|
||||||
IsService() bool
|
|
||||||
|
|
||||||
SetID(id string)
|
|
||||||
ID() string
|
ID() string
|
||||||
|
TxnID() string
|
||||||
SetType(msgtype mautrix.MessageType)
|
|
||||||
Type() mautrix.MessageType
|
|
||||||
|
|
||||||
NotificationContent() string
|
|
||||||
|
|
||||||
SetState(state MessageState)
|
|
||||||
State() MessageState
|
|
||||||
|
|
||||||
SenderID() string
|
SenderID() string
|
||||||
|
Timestamp() time.Time
|
||||||
|
NotificationSenderName() string
|
||||||
|
NotificationContent() string
|
||||||
}
|
}
|
||||||
|
@ -303,6 +303,7 @@ func (c *Container) HandleMessage(source EventSource, evt *mautrix.Event) {
|
|||||||
debug.Printf("Failed to add event %s to history: %v", evt.ID, err)
|
debug.Printf("Failed to add event %s to history: %v", evt.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO switch to roomView.AddEvent
|
||||||
message := mainView.ParseEvent(roomView, evt)
|
message := mainView.ParseEvent(roomView, evt)
|
||||||
if message != nil {
|
if message != nil {
|
||||||
roomView.AddMessage(message, ifc.AppendMessage)
|
roomView.AddMessage(message, ifc.AppendMessage)
|
||||||
@ -494,10 +495,7 @@ func (c *Container) SendMessage(roomID string, msgtype mautrix.MessageType, text
|
|||||||
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
|
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
|
||||||
var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\\)")
|
var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\\)")
|
||||||
|
|
||||||
// SendMarkdownMessage sends a message with the given text to the given room.
|
// SendMarkdownMessage sends a message with the given markdown text to the given room.
|
||||||
//
|
|
||||||
// If the given text contains markdown formatting symbols, it will be rendered into HTML before sending.
|
|
||||||
// Otherwise, it will be sent as plain text.
|
|
||||||
func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string) (string, error) {
|
func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string) (string, error) {
|
||||||
defer debug.Recover()
|
defer debug.Recover()
|
||||||
|
|
||||||
@ -509,8 +507,23 @@ func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageTy
|
|||||||
content.Body = roomRegex.ReplaceAllString(content.Body, "$1")
|
content.Body = roomRegex.ReplaceAllString(content.Body, "$1")
|
||||||
|
|
||||||
c.SendTyping(roomID, false)
|
c.SendTyping(roomID, false)
|
||||||
resp, err := c.client.SendMessageEvent(roomID, mautrix.EventMessage, content)
|
roomView := c.ui.MainView().GetRoom(roomID)
|
||||||
|
txnID := c.client.TxnID()
|
||||||
|
localEcho := roomView.ParseEvent(&mautrix.Event{
|
||||||
|
Sender: c.config.UserID,
|
||||||
|
Type: mautrix.EventMessage,
|
||||||
|
Timestamp: time.Now().UnixNano() / 1e6,
|
||||||
|
RoomID: roomID,
|
||||||
|
Content: content,
|
||||||
|
Unsigned: mautrix.Unsigned{
|
||||||
|
TransactionID: txnID,
|
||||||
|
OutgoingState: mautrix.EventStateLocalEcho,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
roomView.AppendMessage(localEcho)
|
||||||
|
resp, err := c.client.SendMessageEvent(roomID, mautrix.EventMessage, content, mautrix.ReqSendEvent{TransactionID: txnID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
roomView.MarkMessageFailed(localEcho, err)
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return resp.EventID, nil
|
return resp.EventID, nil
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/lib/open"
|
"maunium.net/go/gomuks/lib/open"
|
||||||
"maunium.net/go/gomuks/ui/messages"
|
"maunium.net/go/gomuks/ui/messages"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,8 +56,7 @@ type MessageView struct {
|
|||||||
messageIDs map[string]messages.UIMessage
|
messageIDs map[string]messages.UIMessage
|
||||||
messages []messages.UIMessage
|
messages []messages.UIMessage
|
||||||
|
|
||||||
textBuffer []tstring.TString
|
msgBuffer []messages.UIMessage
|
||||||
metaBuffer []ifc.MessageMeta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageView(parent *RoomView) *MessageView {
|
func NewMessageView(parent *RoomView) *MessageView {
|
||||||
@ -72,8 +70,7 @@ func NewMessageView(parent *RoomView) *MessageView {
|
|||||||
|
|
||||||
messages: make([]messages.UIMessage, 0),
|
messages: make([]messages.UIMessage, 0),
|
||||||
messageIDs: make(map[string]messages.UIMessage),
|
messageIDs: make(map[string]messages.UIMessage),
|
||||||
textBuffer: make([]tstring.TString, 0),
|
msgBuffer: make([]messages.UIMessage, 0),
|
||||||
metaBuffer: make([]ifc.MessageMeta, 0),
|
|
||||||
|
|
||||||
width: 80,
|
width: 80,
|
||||||
widestSender: 5,
|
widestSender: 5,
|
||||||
@ -115,10 +112,16 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction ifc.Messag
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oldMsg, messageExists := view.messageIDs[message.ID()]
|
|
||||||
if messageExists {
|
var oldMsg messages.UIMessage
|
||||||
|
var messageExists bool
|
||||||
|
if oldMsg, messageExists = view.messageIDs[message.ID()]; messageExists {
|
||||||
view.replaceMessage(oldMsg, message)
|
view.replaceMessage(oldMsg, message)
|
||||||
direction = ifc.IgnoreMessage
|
direction = ifc.IgnoreMessage
|
||||||
|
} else if oldMsg, messageExists = view.messageIDs[message.TxnID()]; messageExists {
|
||||||
|
view.replaceMessage(oldMsg, message)
|
||||||
|
delete(view.messageIDs, message.TxnID())
|
||||||
|
direction = ifc.IgnoreMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
view.updateWidestSender(message.Sender())
|
view.updateWidestSender(message.Sender())
|
||||||
@ -149,20 +152,19 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction ifc.Messag
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) appendBuffer(message messages.UIMessage) {
|
func (view *MessageView) appendBuffer(message messages.UIMessage) {
|
||||||
if len(view.metaBuffer) > 0 {
|
if len(view.msgBuffer) > 0 {
|
||||||
prevMeta := view.metaBuffer[len(view.metaBuffer)-1]
|
prevMeta := view.msgBuffer[len(view.msgBuffer)-1]
|
||||||
if prevMeta != nil && prevMeta.FormatDate() != message.FormatDate() {
|
if prevMeta != nil && prevMeta.FormatDate() != message.FormatDate() {
|
||||||
view.textBuffer = append(view.textBuffer, tstring.NewColorTString(
|
/* FIXME view.textBuffer = append(view.textBuffer, tstring.NewColorTString(
|
||||||
fmt.Sprintf("Date changed to %s", message.FormatDate()),
|
fmt.Sprintf("Date changed to %s", message.FormatDate()),
|
||||||
tcell.ColorGreen))
|
tcell.ColorGreen))
|
||||||
view.metaBuffer = append(view.metaBuffer, &messages.BasicMeta{
|
view.msgBuffer = append(view.msgBuffer, &messages.BasicMeta{
|
||||||
BTimestampColor: tcell.ColorDefault, BTextColor: tcell.ColorGreen})
|
BTimestampColor: tcell.ColorDefault, BTextColor: tcell.ColorGreen})*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < message.Height(); i++ {
|
for i := 0; i < message.Height(); i++ {
|
||||||
view.textBuffer = append(view.textBuffer, nil)
|
view.msgBuffer = append(view.msgBuffer, message)
|
||||||
view.metaBuffer = append(view.metaBuffer, message)
|
|
||||||
}
|
}
|
||||||
view.prevMsgCount++
|
view.prevMsgCount++
|
||||||
}
|
}
|
||||||
@ -179,7 +181,7 @@ func (view *MessageView) replaceMessage(original messages.UIMessage, new message
|
|||||||
func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages.UIMessage) {
|
func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages.UIMessage) {
|
||||||
start := -1
|
start := -1
|
||||||
end := -1
|
end := -1
|
||||||
for index, meta := range view.metaBuffer {
|
for index, meta := range view.msgBuffer {
|
||||||
if meta == original {
|
if meta == original {
|
||||||
if start == -1 {
|
if start == -1 {
|
||||||
start = index
|
start = index
|
||||||
@ -197,7 +199,7 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(view.textBuffer) > end {
|
if len(view.msgBuffer) > end {
|
||||||
end++
|
end++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,17 +207,15 @@ func (view *MessageView) replaceBuffer(original messages.UIMessage, new messages
|
|||||||
new.CalculateBuffer(view.prevPrefs, view.prevWidth)
|
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 {
|
if new.Height() != end-start {
|
||||||
metaBuffer := view.metaBuffer[0:start]
|
metaBuffer := view.msgBuffer[0:start]
|
||||||
for i := 0; i < new.Height(); i++ {
|
for i := 0; i < new.Height(); i++ {
|
||||||
metaBuffer = append(metaBuffer, new)
|
metaBuffer = append(metaBuffer, new)
|
||||||
}
|
}
|
||||||
view.metaBuffer = append(metaBuffer, view.metaBuffer[end:]...)
|
view.msgBuffer = append(metaBuffer, view.msgBuffer[end:]...)
|
||||||
} else {
|
} else {
|
||||||
for i := start; i < end; i++ {
|
for i := start; i < end; i++ {
|
||||||
view.metaBuffer[i] = new
|
view.msgBuffer[i] = new
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,8 +230,7 @@ func (view *MessageView) recalculateBuffers() {
|
|||||||
if !prefs.BareMessageView {
|
if !prefs.BareMessageView {
|
||||||
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
|
width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
|
||||||
}
|
}
|
||||||
view.textBuffer = []tstring.TString{}
|
view.msgBuffer = []messages.UIMessage{}
|
||||||
view.metaBuffer = []ifc.MessageMeta{}
|
|
||||||
view.prevMsgCount = 0
|
view.prevMsgCount = 0
|
||||||
for i, message := range view.messages {
|
for i, message := range view.messages {
|
||||||
if message == nil {
|
if message == nil {
|
||||||
@ -249,7 +248,7 @@ func (view *MessageView) recalculateBuffers() {
|
|||||||
view.prevPrefs = prefs
|
view.prevPrefs = prefs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) handleMessageClick(message ifc.MessageMeta) bool {
|
func (view *MessageView) handleMessageClick(message messages.UIMessage) bool {
|
||||||
switch message := message.(type) {
|
switch message := message.(type) {
|
||||||
case *messages.ImageMessage:
|
case *messages.ImageMessage:
|
||||||
open.Open(message.Path())
|
open.Open(message.Path())
|
||||||
@ -259,21 +258,15 @@ func (view *MessageView) handleMessageClick(message ifc.MessageMeta) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) handleUsernameClick(message ifc.MessageMeta, prevMessage ifc.MessageMeta) bool {
|
func (view *MessageView) handleUsernameClick(message messages.UIMessage, prevMessage messages.UIMessage) bool {
|
||||||
uiMessage, ok := message.(messages.UIMessage)
|
if prevMessage != nil && prevMessage.Sender() == message.Sender() {
|
||||||
if !ok {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
prevUIMessage, _ := prevMessage.(messages.UIMessage)
|
if len(message.Sender()) == 0 {
|
||||||
if prevUIMessage != nil && prevUIMessage.Sender() == uiMessage.Sender() {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
sender := fmt.Sprintf("[%s](https://matrix.to/#/%s)", message.Sender(), message.SenderID())
|
||||||
if len(uiMessage.Sender()) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
sender := fmt.Sprintf("[%s](https://matrix.to/#/%s)", uiMessage.Sender(), uiMessage.SenderID())
|
|
||||||
|
|
||||||
cursorPos := view.parent.input.GetCursorOffset()
|
cursorPos := view.parent.input.GetCursorOffset()
|
||||||
text := view.parent.input.GetText()
|
text := view.parent.input.GetText()
|
||||||
@ -317,10 +310,10 @@ func (view *MessageView) OnMouseEvent(event mauview.MouseEvent) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
message := view.metaBuffer[line]
|
message := view.msgBuffer[line]
|
||||||
var prevMessage ifc.MessageMeta
|
var prevMessage messages.UIMessage
|
||||||
if y != 0 && line > 0 {
|
if y != 0 && line > 0 {
|
||||||
prevMessage = view.metaBuffer[line-1]
|
prevMessage = view.msgBuffer[line-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
usernameX := view.TimestampWidth + TimestampSenderGap
|
usernameX := view.TimestampWidth + TimestampSenderGap
|
||||||
@ -358,12 +351,11 @@ func (view *MessageView) Height() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) TotalHeight() int {
|
func (view *MessageView) TotalHeight() int {
|
||||||
return len(view.textBuffer)
|
return len(view.msgBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) IsAtTop() bool {
|
func (view *MessageView) IsAtTop() bool {
|
||||||
totalHeight := len(view.textBuffer)
|
return view.ScrollOffset >= len(view.msgBuffer)-view.height+PaddingAtTop
|
||||||
return view.ScrollOffset >= totalHeight-view.height+PaddingAtTop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -429,7 +421,7 @@ func (view *MessageView) CapturePlaintext(height int) string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := view.metaBuffer[index]
|
meta := view.msgBuffer[index]
|
||||||
message, ok := meta.(messages.UIMessage)
|
message, ok := meta.(messages.UIMessage)
|
||||||
if ok && message != prevMessage {
|
if ok && message != prevMessage {
|
||||||
var sender string
|
var sender string
|
||||||
@ -456,7 +448,6 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
|
|
||||||
usernameX := view.TimestampWidth + TimestampSenderGap
|
usernameX := view.TimestampWidth + TimestampSenderGap
|
||||||
messageX := usernameX + view.widestSender + SenderMessageGap
|
messageX := usernameX + view.widestSender + SenderMessageGap
|
||||||
separatorX := usernameX + view.widestSender + SenderSeparatorGap
|
|
||||||
|
|
||||||
bareMode := view.config.Preferences.BareMessageView
|
bareMode := view.config.Preferences.BareMessageView
|
||||||
if bareMode {
|
if bareMode {
|
||||||
@ -465,20 +456,15 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
|
|
||||||
indexOffset := view.getIndexOffset(screen, view.height, messageX)
|
indexOffset := view.getIndexOffset(screen, view.height, messageX)
|
||||||
|
|
||||||
if len(view.textBuffer) != len(view.metaBuffer) {
|
|
||||||
debug.Printf("Unexpected text/meta buffer length mismatch: %d != %d.", len(view.textBuffer), len(view.metaBuffer))
|
|
||||||
view.prevMsgCount = 0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
|
|
||||||
|
|
||||||
var prevMeta ifc.MessageMeta
|
|
||||||
|
|
||||||
viewStart := 0
|
viewStart := 0
|
||||||
if indexOffset < 0 {
|
if indexOffset < 0 {
|
||||||
viewStart = -indexOffset
|
viewStart = -indexOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !bareMode {
|
||||||
|
separatorX := usernameX + view.widestSender + SenderSeparatorGap
|
||||||
|
scrollBarHeight, scrollBarPos := view.calculateScrollBar(view.height)
|
||||||
|
|
||||||
for line := viewStart; line < view.height; line++ {
|
for line := viewStart; line < view.height; line++ {
|
||||||
showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
|
showScrollbar := line-viewStart >= scrollBarPos-scrollBarHeight && line-viewStart < scrollBarPos
|
||||||
isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
|
isTop := line == viewStart && view.ScrollOffset+view.height >= view.TotalHeight()
|
||||||
@ -486,38 +472,33 @@ func (view *MessageView) Draw(screen mauview.Screen) {
|
|||||||
|
|
||||||
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
|
||||||
|
|
||||||
if !bareMode {
|
|
||||||
screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
|
screen.SetContent(separatorX, line, borderChar, nil, borderStyle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var prevMsg messages.UIMessage
|
||||||
for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
|
for line := viewStart; line < view.height && indexOffset+line < view.TotalHeight(); line++ {
|
||||||
index := indexOffset + line
|
index := indexOffset + line
|
||||||
|
|
||||||
text, meta := view.textBuffer[index], view.metaBuffer[index]
|
msg := view.msgBuffer[index]
|
||||||
if meta != prevMeta {
|
if msg != prevMsg {
|
||||||
if len(meta.FormatTime()) > 0 {
|
if len(msg.FormatTime()) > 0 {
|
||||||
widget.WriteLineSimpleColor(screen, meta.FormatTime(), 0, line, meta.TimestampColor())
|
widget.WriteLineSimpleColor(screen, msg.FormatTime(), 0, line, msg.TimestampColor())
|
||||||
}
|
}
|
||||||
// TODO hiding senders might not be that nice after all, maybe an option? (disabled for now)
|
// TODO hiding senders might not be that nice after all, maybe an option? (disabled for now)
|
||||||
//if !bareMode && (prevMeta == nil || meta.Sender() != prevMeta.Sender()) {
|
//if !bareMode && (prevMsg == nil || meta.Sender() != prevMsg.Sender()) {
|
||||||
widget.WriteLineColor(
|
widget.WriteLineColor(
|
||||||
screen, mauview.AlignRight, meta.Sender(),
|
screen, mauview.AlignRight, msg.Sender(),
|
||||||
usernameX, line, view.widestSender,
|
usernameX, line, view.widestSender,
|
||||||
meta.SenderColor())
|
msg.SenderColor())
|
||||||
//}
|
//}
|
||||||
prevMeta = meta
|
prevMsg = msg
|
||||||
}
|
}
|
||||||
|
|
||||||
message, ok := meta.(messages.UIMessage)
|
for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- {
|
||||||
if ok {
|
|
||||||
for i := index - 1; i >= 0 && view.metaBuffer[i] == meta; i-- {
|
|
||||||
line--
|
line--
|
||||||
}
|
}
|
||||||
message.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, message.Height()))
|
msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width-messageX, msg.Height()))
|
||||||
line += message.Height() - 1
|
line += msg.Height() - 1
|
||||||
} else {
|
|
||||||
text.Draw(screen, messageX, line)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
@ -29,38 +29,51 @@ import (
|
|||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register(&BaseMessage{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type BaseMessage struct {
|
type BaseMessage struct {
|
||||||
MsgID string
|
MsgID string
|
||||||
|
MsgTxnID string
|
||||||
MsgType mautrix.MessageType
|
MsgType mautrix.MessageType
|
||||||
MsgSenderID string
|
MsgSenderID string
|
||||||
MsgSender string
|
MsgSender string
|
||||||
MsgSenderColor tcell.Color
|
MsgSenderColor tcell.Color
|
||||||
MsgTimestamp time.Time
|
MsgTimestamp time.Time
|
||||||
MsgState ifc.MessageState
|
MsgState mautrix.OutgoingEventState
|
||||||
MsgIsHighlight bool
|
MsgIsHighlight bool
|
||||||
MsgIsService bool
|
MsgIsService bool
|
||||||
|
MsgSource json.RawMessage
|
||||||
buffer []tstring.TString
|
buffer []tstring.TString
|
||||||
plainBuffer []tstring.TString
|
plainBuffer []tstring.TString
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBaseMessage(id, sender, displayname string, msgtype mautrix.MessageType, timestamp time.Time) BaseMessage {
|
func newBaseMessage(event *mautrix.Event, displayname string) BaseMessage {
|
||||||
|
msgtype := event.Content.MsgType
|
||||||
|
if len(msgtype) == 0 {
|
||||||
|
msgtype = mautrix.MessageType(event.Type.String())
|
||||||
|
}
|
||||||
|
|
||||||
return BaseMessage{
|
return BaseMessage{
|
||||||
MsgSenderID: sender,
|
MsgSenderID: event.Sender,
|
||||||
MsgSender: displayname,
|
MsgSender: displayname,
|
||||||
MsgTimestamp: timestamp,
|
MsgTimestamp: unixToTime(event.Timestamp),
|
||||||
MsgSenderColor: widget.GetHashColor(sender),
|
MsgSenderColor: widget.GetHashColor(event.Sender),
|
||||||
MsgType: msgtype,
|
MsgType: msgtype,
|
||||||
MsgID: id,
|
MsgID: event.ID,
|
||||||
MsgState: ifc.MessageStateDefault,
|
MsgTxnID: event.Unsigned.TransactionID,
|
||||||
|
MsgState: event.Unsigned.OutgoingState,
|
||||||
MsgIsHighlight: false,
|
MsgIsHighlight: false,
|
||||||
MsgIsService: false,
|
MsgIsService: false,
|
||||||
|
MsgSource: event.Content.VeryRaw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unixToTime(unix int64) time.Time {
|
||||||
|
timestamp := time.Now()
|
||||||
|
if unix != 0 {
|
||||||
|
timestamp = time.Unix(unix/1000, unix%1000*1000)
|
||||||
|
}
|
||||||
|
return timestamp
|
||||||
|
}
|
||||||
|
|
||||||
func (msg *BaseMessage) RegisterMatrix(matrix ifc.MatrixContainer) {}
|
func (msg *BaseMessage) RegisterMatrix(matrix ifc.MatrixContainer) {}
|
||||||
|
|
||||||
// Sender gets the string that should be displayed as the sender of this message.
|
// Sender gets the string that should be displayed as the sender of this message.
|
||||||
@ -71,9 +84,9 @@ func (msg *BaseMessage) RegisterMatrix(matrix ifc.MatrixContainer) {}
|
|||||||
// In any other case, the sender is the display name of the user who sent the message.
|
// In any other case, the sender is the display name of the user who sent the message.
|
||||||
func (msg *BaseMessage) Sender() string {
|
func (msg *BaseMessage) Sender() string {
|
||||||
switch msg.MsgState {
|
switch msg.MsgState {
|
||||||
case ifc.MessageStateSending:
|
case mautrix.EventStateLocalEcho:
|
||||||
return "Sending..."
|
return "Sending..."
|
||||||
case ifc.MessageStateFailed:
|
case mautrix.EventStateSendFail:
|
||||||
return "Error"
|
return "Error"
|
||||||
}
|
}
|
||||||
switch msg.MsgType {
|
switch msg.MsgType {
|
||||||
@ -93,13 +106,17 @@ func (msg *BaseMessage) RealSender() string {
|
|||||||
return msg.MsgSender
|
return msg.MsgSender
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) NotificationSenderName() string {
|
||||||
|
return msg.MsgSender
|
||||||
|
}
|
||||||
|
|
||||||
func (msg *BaseMessage) getStateSpecificColor() tcell.Color {
|
func (msg *BaseMessage) getStateSpecificColor() tcell.Color {
|
||||||
switch msg.MsgState {
|
switch msg.MsgState {
|
||||||
case ifc.MessageStateSending:
|
case mautrix.EventStateLocalEcho:
|
||||||
return tcell.ColorGray
|
return tcell.ColorGray
|
||||||
case ifc.MessageStateFailed:
|
case mautrix.EventStateSendFail:
|
||||||
return tcell.ColorRed
|
return tcell.ColorRed
|
||||||
case ifc.MessageStateDefault:
|
case mautrix.EventStateDefault:
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
return tcell.ColorDefault
|
return tcell.ColorDefault
|
||||||
@ -154,17 +171,6 @@ func (msg *BaseMessage) TimestampColor() tcell.Color {
|
|||||||
return msg.getStateSpecificColor()
|
return msg.getStateSpecificColor()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer returns the computed text buffer.
|
|
||||||
//
|
|
||||||
// The buffer contains the text of the message split into lines with a maximum
|
|
||||||
// width of whatever was provided to CalculateBuffer().
|
|
||||||
//
|
|
||||||
// N.B. This will NOT automatically calculate the buffer if it hasn't been
|
|
||||||
// calculated already, as that requires the target width.
|
|
||||||
func (msg *BaseMessage) Buffer() []tstring.TString {
|
|
||||||
return msg.buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Height returns the number of rows in the computed buffer (see Buffer()).
|
// Height returns the number of rows in the computed buffer (see Buffer()).
|
||||||
func (msg *BaseMessage) Height() int {
|
func (msg *BaseMessage) Height() int {
|
||||||
return len(msg.buffer)
|
return len(msg.buffer)
|
||||||
@ -197,15 +203,11 @@ func (msg *BaseMessage) Type() mautrix.MessageType {
|
|||||||
return msg.MsgType
|
return msg.MsgType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *BaseMessage) SetType(msgtype mautrix.MessageType) {
|
func (msg *BaseMessage) State() mautrix.OutgoingEventState {
|
||||||
msg.MsgType = msgtype
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *BaseMessage) State() ifc.MessageState {
|
|
||||||
return msg.MsgState
|
return msg.MsgState
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *BaseMessage) SetState(state ifc.MessageState) {
|
func (msg *BaseMessage) SetState(state mautrix.OutgoingEventState) {
|
||||||
msg.MsgState = state
|
msg.MsgState = state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +227,10 @@ func (msg *BaseMessage) SetIsService(isService bool) {
|
|||||||
msg.MsgIsService = isService
|
msg.MsgIsService = isService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) Source() json.RawMessage {
|
||||||
|
return msg.MsgSource
|
||||||
|
}
|
||||||
|
|
||||||
func (msg *BaseMessage) Draw(screen mauview.Screen) {
|
func (msg *BaseMessage) Draw(screen mauview.Screen) {
|
||||||
for y, line := range msg.buffer {
|
for y, line := range msg.buffer {
|
||||||
line.Draw(screen, 0, y)
|
line.Draw(screen, 0, y)
|
||||||
|
@ -17,28 +17,21 @@
|
|||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register(&ExpandedTextMessage{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExpandedTextMessage struct {
|
type ExpandedTextMessage struct {
|
||||||
BaseMessage
|
BaseMessage
|
||||||
MsgText tstring.TString
|
MsgText tstring.TString
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExpandedTextMessage creates a new ExpandedTextMessage object with the provided values and the default state.
|
// NewExpandedTextMessage creates a new ExpandedTextMessage object with the provided values and the default state.
|
||||||
func NewExpandedTextMessage(id, sender, displayname string, msgtype mautrix.MessageType, text tstring.TString, timestamp time.Time) UIMessage {
|
func NewExpandedTextMessage(event *mautrix.Event, displayname string, text tstring.TString) UIMessage {
|
||||||
return &ExpandedTextMessage{
|
return &ExpandedTextMessage{
|
||||||
BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
BaseMessage: newBaseMessage(event, displayname),
|
||||||
MsgText: text,
|
MsgText: text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,12 @@
|
|||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"maunium.net/go/gomuks/ui/messages/html"
|
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
|
"maunium.net/go/gomuks/ui/messages/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HTMLMessage struct {
|
type HTMLMessage struct {
|
||||||
@ -36,7 +35,7 @@ type HTMLMessage struct {
|
|||||||
|
|
||||||
func NewHTMLMessage(event *mautrix.Event, displayname string, root html.Entity) UIMessage {
|
func NewHTMLMessage(event *mautrix.Event, displayname string, root html.Entity) UIMessage {
|
||||||
return &HTMLMessage{
|
return &HTMLMessage{
|
||||||
BaseMessage: newBaseMessage(event.ID, event.Sender, displayname, event.Content.MsgType, unixToTime(event.Timestamp)),
|
BaseMessage: newBaseMessage(event, displayname),
|
||||||
Root: root,
|
Root: root,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,8 @@ package messages
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/gob"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"time"
|
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
@ -33,10 +31,6 @@ import (
|
|||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register(&ImageMessage{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type ImageMessage struct {
|
type ImageMessage struct {
|
||||||
BaseMessage
|
BaseMessage
|
||||||
Body string
|
Body string
|
||||||
@ -48,9 +42,9 @@ type ImageMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewImageMessage creates a new ImageMessage object with the provided values and the default state.
|
// NewImageMessage creates a new ImageMessage object with the provided values and the default state.
|
||||||
func NewImageMessage(matrix ifc.MatrixContainer, id, sender, displayname string, msgtype mautrix.MessageType, body, homeserver, fileID string, data []byte, timestamp time.Time) UIMessage {
|
func NewImageMessage(matrix ifc.MatrixContainer, event *mautrix.Event, displayname string, body, homeserver, fileID string, data []byte) UIMessage {
|
||||||
return &ImageMessage{
|
return &ImageMessage{
|
||||||
newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
newBaseMessage(event, displayname),
|
||||||
body,
|
body,
|
||||||
homeserver,
|
homeserver,
|
||||||
fileID,
|
fileID,
|
||||||
|
@ -20,12 +20,20 @@ import (
|
|||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
|
"maunium.net/go/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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.
|
||||||
type UIMessage interface {
|
type UIMessage interface {
|
||||||
ifc.Message
|
ifc.Message
|
||||||
|
|
||||||
|
Sender() string
|
||||||
|
SenderColor() tcell.Color
|
||||||
|
TextColor() tcell.Color
|
||||||
|
TimestampColor() tcell.Color
|
||||||
|
FormatTime() string
|
||||||
|
FormatDate() string
|
||||||
|
|
||||||
CalculateBuffer(preferences config.UserPreferences, width int)
|
CalculateBuffer(preferences config.UserPreferences, width int)
|
||||||
Draw(screen mauview.Screen)
|
Draw(screen mauview.Screen)
|
||||||
Height() int
|
Height() int
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
// gomuks - A terminal Matrix client written in Go.
|
|
||||||
// Copyright (C) 2019 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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package messages
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"maunium.net/go/tcell"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BasicMeta is a simple variable store implementation of MessageMeta.
|
|
||||||
type BasicMeta struct {
|
|
||||||
BSender string
|
|
||||||
BTimestamp time.Time
|
|
||||||
BSenderColor, BTextColor, BTimestampColor tcell.Color
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sender gets the string that should be displayed as the sender of this message.
|
|
||||||
func (meta *BasicMeta) Sender() string {
|
|
||||||
return meta.BSender
|
|
||||||
}
|
|
||||||
|
|
||||||
func (meta *BasicMeta) SenderID() string {
|
|
||||||
return meta.BSender
|
|
||||||
}
|
|
||||||
|
|
||||||
// SenderColor returns the color the name of the sender should be shown in.
|
|
||||||
func (meta *BasicMeta) SenderColor() tcell.Color {
|
|
||||||
return meta.BSenderColor
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timestamp returns the full time when the message was sent.
|
|
||||||
func (meta *BasicMeta) Timestamp() time.Time {
|
|
||||||
return meta.BTimestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatTime returns the formatted time when the message was sent.
|
|
||||||
func (meta *BasicMeta) FormatTime() string {
|
|
||||||
return meta.BTimestamp.Format(TimeFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatDate returns the formatted date when the message was sent.
|
|
||||||
func (meta *BasicMeta) FormatDate() string {
|
|
||||||
return meta.BTimestamp.Format(DateFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextColor returns the color the actual content of the message should be shown in.
|
|
||||||
func (meta *BasicMeta) TextColor() tcell.Color {
|
|
||||||
return meta.BTextColor
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimestampColor returns the color the timestamp should be shown in.
|
|
||||||
//
|
|
||||||
// This usually does not apply to the date, as it is rendered separately from the message.
|
|
||||||
func (meta *BasicMeta) TimestampColor() tcell.Color {
|
|
||||||
return meta.BTimestampColor
|
|
||||||
}
|
|
@ -18,9 +18,7 @@ package messages
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
@ -28,12 +26,33 @@ import (
|
|||||||
"maunium.net/go/gomuks/debug"
|
"maunium.net/go/gomuks/debug"
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
|
"maunium.net/go/gomuks/ui/messages/html"
|
||||||
"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"
|
||||||
htmlp "maunium.net/go/gomuks/ui/messages/html"
|
htmlp "maunium.net/go/gomuks/ui/messages/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
||||||
|
msg := directParseEvent(matrix, room, evt)
|
||||||
|
if msg == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(evt.Content.GetReplyTo()) > 0 {
|
||||||
|
roomID := evt.Content.RelatesTo.InReplyTo.RoomID
|
||||||
|
if len(roomID) == 0 {
|
||||||
|
roomID = room.ID
|
||||||
|
}
|
||||||
|
replyToEvt, _ := matrix.GetEvent(room, evt.Content.GetReplyTo())
|
||||||
|
if replyToEvt != nil {
|
||||||
|
// TODO add reply header
|
||||||
|
} else {
|
||||||
|
// TODO add unknown reply header
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func directParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
||||||
switch evt.Type {
|
switch evt.Type {
|
||||||
case mautrix.EventSticker:
|
case mautrix.EventSticker:
|
||||||
evt.Content.MsgType = mautrix.MsgImage
|
evt.Content.MsgType = mautrix.MsgImage
|
||||||
@ -48,14 +67,6 @@ func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unixToTime(unix int64) time.Time {
|
|
||||||
timestamp := time.Now()
|
|
||||||
if unix != 0 {
|
|
||||||
timestamp = time.Unix(unix/1000, unix%1000*1000)
|
|
||||||
}
|
|
||||||
return timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseStateEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
func ParseStateEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
||||||
displayname := evt.Sender
|
displayname := evt.Sender
|
||||||
member := room.GetMember(evt.Sender)
|
member := room.GetMember(evt.Sender)
|
||||||
@ -91,8 +102,7 @@ func ParseStateEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.
|
|||||||
case mautrix.StateAliases:
|
case mautrix.StateAliases:
|
||||||
text = ParseAliasEvent(evt, displayname)
|
text = ParseAliasEvent(evt, displayname)
|
||||||
}
|
}
|
||||||
ts := unixToTime(evt.Timestamp)
|
return NewExpandedTextMessage(evt, displayname, text)
|
||||||
return NewExpandedTextMessage(evt.ID, evt.Sender, displayname, mautrix.MessageType(evt.Type.Type), text, ts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {
|
||||||
@ -103,39 +113,20 @@ func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Eve
|
|||||||
}
|
}
|
||||||
if len(evt.Content.GetReplyTo()) > 0 {
|
if len(evt.Content.GetReplyTo()) > 0 {
|
||||||
evt.Content.RemoveReplyFallback()
|
evt.Content.RemoveReplyFallback()
|
||||||
roomID := evt.Content.RelatesTo.InReplyTo.RoomID
|
|
||||||
if len(roomID) == 0 {
|
|
||||||
roomID = room.ID
|
|
||||||
}
|
}
|
||||||
replyToEvt, _ := matrix.GetEvent(room, evt.Content.GetReplyTo())
|
|
||||||
if replyToEvt != nil {
|
|
||||||
replyToEvt.Content.RemoveReplyFallback()
|
|
||||||
if len(replyToEvt.Content.FormattedBody) == 0 {
|
|
||||||
replyToEvt.Content.FormattedBody = html.EscapeString(replyToEvt.Content.Body)
|
|
||||||
}
|
|
||||||
evt.Content.FormattedBody = fmt.Sprintf(
|
|
||||||
"In reply to <a href='https://matrix.to/#/%[1]s'>%[1]s</a><blockquote>%[2]s</blockquote><br/><br/>%[3]s",
|
|
||||||
replyToEvt.Sender, replyToEvt.Content.FormattedBody, evt.Content.FormattedBody)
|
|
||||||
} else {
|
|
||||||
evt.Content.FormattedBody = fmt.Sprintf(
|
|
||||||
"In reply to unknown event https://matrix.to/#/%[1]s/%[2]s<br/>%[3]s",
|
|
||||||
roomID, evt.Content.GetReplyTo(), evt.Content.FormattedBody)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ts := unixToTime(evt.Timestamp)
|
|
||||||
switch evt.Content.MsgType {
|
switch evt.Content.MsgType {
|
||||||
case "m.text", "m.notice", "m.emote":
|
case "m.text", "m.notice", "m.emote":
|
||||||
if evt.Content.Format == mautrix.FormatHTML {
|
if evt.Content.Format == mautrix.FormatHTML {
|
||||||
return NewHTMLMessage(evt, displayname, htmlp.Parse(room, evt, displayname))
|
return NewHTMLMessage(evt, displayname, html.Parse(room, evt, displayname))
|
||||||
}
|
}
|
||||||
evt.Content.Body = strings.Replace(evt.Content.Body, "\t", " ", -1)
|
evt.Content.Body = strings.Replace(evt.Content.Body, "\t", " ", -1)
|
||||||
return NewTextMessage(evt.ID, evt.Sender, displayname, evt.Content.MsgType, evt.Content.Body, ts)
|
return NewTextMessage(evt, displayname, evt.Content.Body)
|
||||||
case "m.image":
|
case "m.image":
|
||||||
data, hs, id, err := matrix.Download(evt.Content.URL)
|
data, hs, id, err := matrix.Download(evt.Content.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Printf("Failed to download %s: %v", evt.Content.URL, err)
|
debug.Printf("Failed to download %s: %v", evt.Content.URL, err)
|
||||||
}
|
}
|
||||||
return NewImageMessage(matrix, evt.ID, evt.Sender, displayname, evt.Content.MsgType, evt.Content.Body, hs, id, data, ts)
|
return NewImageMessage(matrix, evt, displayname, evt.Content.Body, hs, id, data)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -220,8 +211,7 @@ func ParseMembershipEvent(room *rooms.Room, evt *mautrix.Event) UIMessage {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ts := unixToTime(evt.Timestamp)
|
return NewExpandedTextMessage(evt, displayname, text)
|
||||||
return NewExpandedTextMessage(evt.ID, evt.Sender, displayname, "m.room.member", text, ts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseAliasEvent(evt *mautrix.Event, displayname string) tstring.TString {
|
func ParseAliasEvent(evt *mautrix.Event, displayname string) tstring.TString {
|
||||||
|
@ -17,21 +17,14 @@
|
|||||||
package messages
|
package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
"maunium.net/go/gomuks/interface"
|
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register(&TextMessage{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TextMessage struct {
|
type TextMessage struct {
|
||||||
BaseMessage
|
BaseMessage
|
||||||
cache tstring.TString
|
cache tstring.TString
|
||||||
@ -39,9 +32,9 @@ type TextMessage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTextMessage creates a new UITextMessage object with the provided values and the default state.
|
// NewTextMessage creates a new UITextMessage object with the provided values and the default state.
|
||||||
func NewTextMessage(id, sender, displayname string, msgtype mautrix.MessageType, text string, timestamp time.Time) UIMessage {
|
func NewTextMessage(event *mautrix.Event, displayname string, text string) UIMessage {
|
||||||
return &TextMessage{
|
return &TextMessage{
|
||||||
BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp),
|
BaseMessage: newBaseMessage(event, displayname),
|
||||||
MsgText: text,
|
MsgText: text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,16 +52,6 @@ func (msg *TextMessage) getCache() tstring.TString {
|
|||||||
return msg.cache
|
return msg.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *TextMessage) SetType(msgtype mautrix.MessageType) {
|
|
||||||
msg.BaseMessage.SetType(msgtype)
|
|
||||||
msg.cache = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *TextMessage) SetState(state ifc.MessageState) {
|
|
||||||
msg.BaseMessage.SetState(state)
|
|
||||||
msg.cache = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *TextMessage) SetIsHighlight(isHighlight bool) {
|
func (msg *TextMessage) SetIsHighlight(isHighlight bool) {
|
||||||
msg.BaseMessage.SetIsHighlight(isHighlight)
|
msg.BaseMessage.SetIsHighlight(isHighlight)
|
||||||
msg.cache = nil
|
msg.cache = nil
|
||||||
|
@ -438,3 +438,7 @@ func (view *RoomView) AddServiceMessage(text string) {
|
|||||||
func (view *RoomView) AddMessage(message ifc.Message, direction ifc.MessageDirection) {
|
func (view *RoomView) AddMessage(message ifc.Message, direction ifc.MessageDirection) {
|
||||||
view.content.AddMessage(message, direction)
|
view.content.AddMessage(message, direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *RoomView) ParseEvent(evt *mautrix.Event) ifc.Message {
|
||||||
|
return messages.ParseEvent(view.parent.matrix, view.Room, evt)
|
||||||
|
}
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"maunium.net/go/gomuks/lib/notification"
|
"maunium.net/go/gomuks/lib/notification"
|
||||||
"maunium.net/go/gomuks/matrix/pushrules"
|
"maunium.net/go/gomuks/matrix/pushrules"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"maunium.net/go/gomuks/ui/messages"
|
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -166,11 +165,10 @@ func (view *MainView) InputSubmit(roomView *RoomView, text string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SendMessage(roomView *RoomView, text string) {
|
func (view *MainView) SendMessage(roomView *RoomView, text string) {
|
||||||
tempMessage := roomView.NewTempMessage("m.text", text)
|
go view.goSendMessage(roomView, text)
|
||||||
go view.sendTempMessage(roomView, tempMessage, text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) sendTempMessage(roomView *RoomView, tempMessage ifc.Message, text string) {
|
func (view *MainView) goSendMessage(roomView *RoomView, text string) {
|
||||||
defer debug.Recover()
|
defer debug.Recover()
|
||||||
debug.Print("Sending message", tempMessage.Type(), text)
|
debug.Print("Sending message", tempMessage.Type(), text)
|
||||||
if !roomView.config.Preferences.DisableEmojis {
|
if !roomView.config.Preferences.DisableEmojis {
|
||||||
@ -317,11 +315,10 @@ func (view *MainView) addRoomPage(room *rooms.Room) {
|
|||||||
view.rooms[room.ID] = roomView
|
view.rooms[room.ID] = roomView
|
||||||
roomView.UpdateUserList()
|
roomView.UpdateUserList()
|
||||||
|
|
||||||
// FIXME
|
// TODO make sure this works
|
||||||
/*_, err := roomView.LoadHistory(view.matrix, view.config.HistoryDir)
|
if len(roomView.MessageView().messages) == 0 {
|
||||||
if err != nil {
|
go view.LoadHistory(room.ID)
|
||||||
debug.Printf("Failed to load history of %s: %v", roomView.Room.GetTitle(), err)
|
}
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,10 +425,11 @@ func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, shoul
|
|||||||
if shouldNotify && !recentlyFocused {
|
if shouldNotify && !recentlyFocused {
|
||||||
// Push rules say notify and the terminal is not focused, send desktop notification.
|
// Push rules say notify and the terminal is not focused, send desktop notification.
|
||||||
shouldPlaySound := should.PlaySound && should.SoundName == "default"
|
shouldPlaySound := should.PlaySound && should.SoundName == "default"
|
||||||
sendNotification(room, message.Sender(), message.NotificationContent(), should.Highlight, shouldPlaySound)
|
sendNotification(room, message.NotificationSenderName(), message.NotificationContent(), should.Highlight, shouldPlaySound)
|
||||||
}
|
}
|
||||||
|
|
||||||
message.SetIsHighlight(should.Highlight)
|
// TODO Make sure this happens somewhere else
|
||||||
|
//message.SetIsHighlight(should.Highlight)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) InitialSyncDone() {
|
func (view *MainView) InitialSyncDone() {
|
||||||
@ -470,7 +468,7 @@ func (view *MainView) LoadHistory(room string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, evt := range history {
|
for _, evt := range history {
|
||||||
message := view.ParseEvent(roomView, evt)
|
message := roomView.ParseEvent(evt)
|
||||||
if message != nil {
|
if message != nil {
|
||||||
roomView.AddMessage(message, ifc.PrependMessage)
|
roomView.AddMessage(message, ifc.PrependMessage)
|
||||||
}
|
}
|
||||||
@ -483,7 +481,3 @@ func (view *MainView) LoadHistory(room string) {
|
|||||||
view.config.PutRoom(roomView.Room)
|
view.config.PutRoom(roomView.Room)
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) ParseEvent(roomView ifc.RoomView, evt *mautrix.Event) ifc.Message {
|
|
||||||
return messages.ParseEvent(view.matrix, roomView.MxRoom(), evt)
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user