From dbee49476d47bb391dc6af0b774f9fd101b0c917 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 9 Apr 2019 18:45:41 +0300 Subject: Start refactoring various things in message rendering and sending --- ui/messages/base.go | 74 ++++++++++++++++++++------------------ ui/messages/expandedtextmessage.go | 11 ++---- ui/messages/htmlmessage.go | 5 ++- ui/messages/imagemessage.go | 10 ++---- ui/messages/message.go | 8 +++++ ui/messages/meta.go | 71 ------------------------------------ ui/messages/parser.go | 62 ++++++++++++++------------------ ui/messages/textmessage.go | 21 ++--------- 8 files changed, 82 insertions(+), 180 deletions(-) delete mode 100644 ui/messages/meta.go (limited to 'ui/messages') diff --git a/ui/messages/base.go b/ui/messages/base.go index d045e42..b8b1694 100644 --- a/ui/messages/base.go +++ b/ui/messages/base.go @@ -17,7 +17,7 @@ package messages import ( - "encoding/gob" + "encoding/json" "time" "maunium.net/go/mautrix" @@ -29,38 +29,51 @@ import ( "maunium.net/go/gomuks/ui/widget" ) -func init() { - gob.Register(&BaseMessage{}) -} - type BaseMessage struct { MsgID string + MsgTxnID string MsgType mautrix.MessageType MsgSenderID string MsgSender string MsgSenderColor tcell.Color MsgTimestamp time.Time - MsgState ifc.MessageState + MsgState mautrix.OutgoingEventState MsgIsHighlight bool MsgIsService bool + MsgSource json.RawMessage buffer []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{ - MsgSenderID: sender, + MsgSenderID: event.Sender, MsgSender: displayname, - MsgTimestamp: timestamp, - MsgSenderColor: widget.GetHashColor(sender), + MsgTimestamp: unixToTime(event.Timestamp), + MsgSenderColor: widget.GetHashColor(event.Sender), MsgType: msgtype, - MsgID: id, - MsgState: ifc.MessageStateDefault, + MsgID: event.ID, + MsgTxnID: event.Unsigned.TransactionID, + MsgState: event.Unsigned.OutgoingState, MsgIsHighlight: 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) {} // 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. func (msg *BaseMessage) Sender() string { switch msg.MsgState { - case ifc.MessageStateSending: + case mautrix.EventStateLocalEcho: return "Sending..." - case ifc.MessageStateFailed: + case mautrix.EventStateSendFail: return "Error" } switch msg.MsgType { @@ -93,13 +106,17 @@ func (msg *BaseMessage) RealSender() string { return msg.MsgSender } +func (msg *BaseMessage) NotificationSenderName() string { + return msg.MsgSender +} + func (msg *BaseMessage) getStateSpecificColor() tcell.Color { switch msg.MsgState { - case ifc.MessageStateSending: + case mautrix.EventStateLocalEcho: return tcell.ColorGray - case ifc.MessageStateFailed: + case mautrix.EventStateSendFail: return tcell.ColorRed - case ifc.MessageStateDefault: + case mautrix.EventStateDefault: fallthrough default: return tcell.ColorDefault @@ -154,17 +171,6 @@ func (msg *BaseMessage) TimestampColor() tcell.Color { 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()). func (msg *BaseMessage) Height() int { return len(msg.buffer) @@ -197,15 +203,11 @@ func (msg *BaseMessage) Type() mautrix.MessageType { return msg.MsgType } -func (msg *BaseMessage) SetType(msgtype mautrix.MessageType) { - msg.MsgType = msgtype -} - -func (msg *BaseMessage) State() ifc.MessageState { +func (msg *BaseMessage) State() mautrix.OutgoingEventState { return msg.MsgState } -func (msg *BaseMessage) SetState(state ifc.MessageState) { +func (msg *BaseMessage) SetState(state mautrix.OutgoingEventState) { msg.MsgState = state } @@ -225,6 +227,10 @@ func (msg *BaseMessage) SetIsService(isService bool) { msg.MsgIsService = isService } +func (msg *BaseMessage) Source() json.RawMessage { + return msg.MsgSource +} + func (msg *BaseMessage) Draw(screen mauview.Screen) { for y, line := range msg.buffer { line.Draw(screen, 0, y) diff --git a/ui/messages/expandedtextmessage.go b/ui/messages/expandedtextmessage.go index 044613f..4a4ed24 100644 --- a/ui/messages/expandedtextmessage.go +++ b/ui/messages/expandedtextmessage.go @@ -17,28 +17,21 @@ package messages import ( - "encoding/gob" - "time" - "maunium.net/go/mautrix" "maunium.net/go/gomuks/config" "maunium.net/go/gomuks/ui/messages/tstring" ) -func init() { - gob.Register(&ExpandedTextMessage{}) -} - type ExpandedTextMessage struct { BaseMessage MsgText tstring.TString } // 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{ - BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp), + BaseMessage: newBaseMessage(event, displayname), MsgText: text, } } diff --git a/ui/messages/htmlmessage.go b/ui/messages/htmlmessage.go index ed8b7c1..ceee305 100644 --- a/ui/messages/htmlmessage.go +++ b/ui/messages/htmlmessage.go @@ -17,13 +17,12 @@ package messages import ( - "maunium.net/go/gomuks/ui/messages/html" - "maunium.net/go/mautrix" "maunium.net/go/mauview" "maunium.net/go/tcell" "maunium.net/go/gomuks/config" + "maunium.net/go/gomuks/ui/messages/html" ) type HTMLMessage struct { @@ -36,7 +35,7 @@ type HTMLMessage struct { func NewHTMLMessage(event *mautrix.Event, displayname string, root html.Entity) UIMessage { return &HTMLMessage{ - BaseMessage: newBaseMessage(event.ID, event.Sender, displayname, event.Content.MsgType, unixToTime(event.Timestamp)), + BaseMessage: newBaseMessage(event, displayname), Root: root, } } diff --git a/ui/messages/imagemessage.go b/ui/messages/imagemessage.go index 968f29e..9ce1a8e 100644 --- a/ui/messages/imagemessage.go +++ b/ui/messages/imagemessage.go @@ -18,10 +18,8 @@ package messages import ( "bytes" - "encoding/gob" "fmt" "image/color" - "time" "maunium.net/go/mautrix" "maunium.net/go/tcell" @@ -33,10 +31,6 @@ import ( "maunium.net/go/gomuks/ui/messages/tstring" ) -func init() { - gob.Register(&ImageMessage{}) -} - type ImageMessage struct { BaseMessage Body string @@ -48,9 +42,9 @@ type ImageMessage struct { } // 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{ - newBaseMessage(id, sender, displayname, msgtype, timestamp), + newBaseMessage(event, displayname), body, homeserver, fileID, diff --git a/ui/messages/message.go b/ui/messages/message.go index db93879..634bd11 100644 --- a/ui/messages/message.go +++ b/ui/messages/message.go @@ -20,12 +20,20 @@ import ( "maunium.net/go/gomuks/config" "maunium.net/go/gomuks/interface" "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. type UIMessage interface { ifc.Message + Sender() string + SenderColor() tcell.Color + TextColor() tcell.Color + TimestampColor() tcell.Color + FormatTime() string + FormatDate() string + CalculateBuffer(preferences config.UserPreferences, width int) Draw(screen mauview.Screen) Height() int diff --git a/ui/messages/meta.go b/ui/messages/meta.go deleted file mode 100644 index 0712be1..0000000 --- a/ui/messages/meta.go +++ /dev/null @@ -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 . - -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 -} diff --git a/ui/messages/parser.go b/ui/messages/parser.go index ae0606d..f45eea2 100644 --- a/ui/messages/parser.go +++ b/ui/messages/parser.go @@ -18,9 +18,7 @@ package messages import ( "fmt" - "html" "strings" - "time" "maunium.net/go/mautrix" "maunium.net/go/tcell" @@ -28,12 +26,33 @@ import ( "maunium.net/go/gomuks/debug" "maunium.net/go/gomuks/interface" "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/widget" htmlp "maunium.net/go/gomuks/ui/messages/html" ) 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 { case mautrix.EventSticker: evt.Content.MsgType = mautrix.MsgImage @@ -48,14 +67,6 @@ func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event 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 { displayname := evt.Sender member := room.GetMember(evt.Sender) @@ -91,8 +102,7 @@ func ParseStateEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix. case mautrix.StateAliases: text = ParseAliasEvent(evt, displayname) } - ts := unixToTime(evt.Timestamp) - return NewExpandedTextMessage(evt.ID, evt.Sender, displayname, mautrix.MessageType(evt.Type.Type), text, ts) + return NewExpandedTextMessage(evt, displayname, text) } 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 { 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 %[1]s
%[2]s


%[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
%[3]s", - roomID, evt.Content.GetReplyTo(), evt.Content.FormattedBody) - } } - ts := unixToTime(evt.Timestamp) switch evt.Content.MsgType { case "m.text", "m.notice", "m.emote": 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) - return NewTextMessage(evt.ID, evt.Sender, displayname, evt.Content.MsgType, evt.Content.Body, ts) + return NewTextMessage(evt, displayname, evt.Content.Body) case "m.image": data, hs, id, err := matrix.Download(evt.Content.URL) if err != nil { 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 } @@ -220,8 +211,7 @@ func ParseMembershipEvent(room *rooms.Room, evt *mautrix.Event) UIMessage { return nil } - ts := unixToTime(evt.Timestamp) - return NewExpandedTextMessage(evt.ID, evt.Sender, displayname, "m.room.member", text, ts) + return NewExpandedTextMessage(evt, displayname, text) } func ParseAliasEvent(evt *mautrix.Event, displayname string) tstring.TString { diff --git a/ui/messages/textmessage.go b/ui/messages/textmessage.go index 6364659..f7c54ca 100644 --- a/ui/messages/textmessage.go +++ b/ui/messages/textmessage.go @@ -17,21 +17,14 @@ package messages import ( - "encoding/gob" "fmt" - "time" "maunium.net/go/mautrix" "maunium.net/go/gomuks/config" - "maunium.net/go/gomuks/interface" "maunium.net/go/gomuks/ui/messages/tstring" ) -func init() { - gob.Register(&TextMessage{}) -} - type TextMessage struct { BaseMessage cache tstring.TString @@ -39,9 +32,9 @@ type TextMessage struct { } // 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{ - BaseMessage: newBaseMessage(id, sender, displayname, msgtype, timestamp), + BaseMessage: newBaseMessage(event, displayname), MsgText: text, } } @@ -59,16 +52,6 @@ func (msg *TextMessage) getCache() tstring.TString { 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) { msg.BaseMessage.SetIsHighlight(isHighlight) msg.cache = nil -- cgit v1.2.3