aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui/types/message.go185
-rw-r--r--ui/types/meta.go17
-rw-r--r--ui/widget/message-view.go6
3 files changed, 155 insertions, 53 deletions
diff --git a/ui/types/message.go b/ui/types/message.go
index 5cbc61d..e212a80 100644
--- a/ui/types/message.go
+++ b/ui/types/message.go
@@ -25,55 +25,176 @@ import (
"github.com/mattn/go-runewidth"
)
+// 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
+)
+
+// Message is a wrapper for the content and metadata of a Matrix message intended to be displayed.
type Message struct {
- BasicMeta
- Type string
ID string
+ Type string
+ Sender string
+ SenderColor tcell.Color
+ Timestamp string
+ Date string
Text string
- sending bool
+ State MessageState
buffer []string
prevBufferWidth int
}
+// NewMessage creates a new Message object with the provided values and the default state.
func NewMessage(id, sender, msgtype, text, timestamp, date string, senderColor tcell.Color) *Message {
return &Message{
- BasicMeta: BasicMeta{
- Sender: sender,
- Timestamp: timestamp,
- Date: date,
- SenderColor: senderColor,
- TextColor: tcell.ColorDefault,
- TimestampColor: tcell.ColorDefault,
- },
+ Sender: sender,
+ Timestamp: timestamp,
+ Date: date,
+ SenderColor: senderColor,
Type: msgtype,
Text: text,
ID: id,
prevBufferWidth: 0,
- sending: false,
+ State: MessageStateDefault,
}
}
-var (
- boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
- spacePattern = regexp.MustCompile(`\s+`)
-)
-
+// CopyTo copies the content of this message to the given message.
func (message *Message) CopyTo(to *Message) {
- to.BasicMeta = message.BasicMeta
to.ID = message.ID
+ to.Type = message.Type
+ to.Sender = message.Sender
+ to.SenderColor = message.SenderColor
+ to.Timestamp = message.Timestamp
+ to.Date = message.Date
to.Text = message.Text
to.RecalculateBuffer()
}
+// GetSender gets the string that should be displayed as the sender of this message.
+//
+// If the message is being sent, the sender is "Sending...".
+// If sending has failed, the sender is "Error".
+// If the message is an emote, the sender is blank.
+// In any other case, the sender is the display name of the user who sent the message.
+func (message *Message) GetSender() string {
+ switch message.State {
+ case MessageStateSending:
+ return "Sending..."
+ case MessageStateFailed:
+ return "Error"
+ }
+ switch message.Type {
+ case "m.emote":
+ // Emotes don't show a separate sender, it's included in the buffer.
+ return ""
+ default:
+ return message.Sender
+ }
+}
+
+// GetSenderColor returns the color the name of the sender should be shown in.
+//
+// If the message is being sent, the color is gray.
+// If sending has failed, the color is red.
+//
+// In any other case, the color is whatever is specified in the Message struct.
+// Usually that means it is the hash-based color of the sender (see ui/widget/color.go)
+func (message *Message) GetSenderColor() tcell.Color {
+ switch message.State {
+ case MessageStateSending:
+ return tcell.ColorGray
+ case MessageStateFailed:
+ return tcell.ColorRed
+ case MessageStateDefault:
+ fallthrough
+ default:
+ return message.SenderColor
+ }
+}
+
+// GetTextColor returns the color the actual content of the message should be shown in.
+//
+// As with GetSenderColor(), messages being sent and messages that failed to be sent are
+// gray and red respectively.
+//
+// However, other messages are the default color instead of a color stored in the struct.
+func (message *Message) GetTextColor() tcell.Color {
+ switch message.State {
+ case MessageStateSending:
+ return tcell.ColorGray
+ case MessageStateFailed:
+ return tcell.ColorRed
+ default:
+ return tcell.ColorDefault
+ }
+}
+
+// GetTimestampColor returns the color the timestamp should be shown in.
+//
+// Currently, this simply calls GetTextColor().
+func (message *Message) GetTimestampColor() tcell.Color {
+ return message.GetTextColor()
+}
+
+// RecalculateBuffer calculates the buffer again with the previously provided width.
+func (message *Message) RecalculateBuffer() {
+ message.CalculateBuffer(message.prevBufferWidth)
+}
+
+// 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 (message *Message) Buffer() []string {
+ return message.buffer
+}
+
+// Height returns the number of rows in the computed buffer (see Buffer()).
+func (message *Message) Height() int {
+ return len(message.buffer)
+}
+
+// GetTimestamp returns the formatted time when the message was sent.
+func (message *Message) GetTimestamp() string {
+ return message.Timestamp
+}
+
+// GetDate returns the formatted date when the message was sent.
+func (message *Message) GetDate() string {
+ return message.Date
+}
+
+// Regular expressions used to split lines when calculating the buffer.
+//
+// From tview/textview.go
+var (
+ boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
+ spacePattern = regexp.MustCompile(`\s+`)
+)
+
+// CalculateBuffer generates the internal buffer for this message that consists
+// of the text of this message split into lines at most as wide as the width
+// parameter.
func (message *Message) CalculateBuffer(width int) {
if width < 2 {
return
}
+
message.buffer = []string{}
text := message.Text
if message.Type == "m.emote" {
text = fmt.Sprintf("* %s %s", message.Sender, message.Text)
}
+
forcedLinebreaks := strings.Split(text, "\n")
newlines := 0
for _, str := range forcedLinebreaks {
@@ -102,31 +223,3 @@ func (message *Message) CalculateBuffer(width int) {
}
message.prevBufferWidth = width
}
-
-func (message *Message) GetDisplaySender() string {
- if message.sending {
- return "Sending..."
- }
- switch message.Type {
- case "m.emote":
- return ""
- default:
- return message.Sender
- }
-}
-
-func (message *Message) SetIsSending(sending bool) {
- message.sending = sending
-}
-
-func (message *Message) RecalculateBuffer() {
- message.CalculateBuffer(message.prevBufferWidth)
-}
-
-func (message *Message) Buffer() []string {
- return message.buffer
-}
-
-func (message *Message) Height() int {
- return len(message.buffer)
-}
diff --git a/ui/types/meta.go b/ui/types/meta.go
index 03e18d6..fdc6dba 100644
--- a/ui/types/meta.go
+++ b/ui/types/meta.go
@@ -20,9 +20,11 @@ import (
"github.com/gdamore/tcell"
)
+// MessageMeta is an interface to get the metadata of a message.
+//
+// See BasicMeta for a simple implementation and documentation of methods.
type MessageMeta interface {
GetSender() string
- GetDisplaySender() string
GetSenderColor() tcell.Color
GetTextColor() tcell.Color
GetTimestampColor() tcell.Color
@@ -30,35 +32,40 @@ type MessageMeta interface {
GetDate() string
}
+// BasicMeta is a simple variable store implementation of MessageMeta.
type BasicMeta struct {
Sender, Timestamp, Date string
SenderColor, TextColor, TimestampColor tcell.Color
}
-func (meta *BasicMeta) GetDisplaySender() string {
- return meta.Sender
-}
-
+// GetSender gets the string that should be displayed as the sender of this message.
func (meta *BasicMeta) GetSender() string {
return meta.Sender
}
+// GetSenderColor returns the color the name of the sender should be shown in.
func (meta *BasicMeta) GetSenderColor() tcell.Color {
return meta.SenderColor
}
+// GetTimestamp returns the formatted time when the message was sent.
func (meta *BasicMeta) GetTimestamp() string {
return meta.Timestamp
}
+// GetDate returns the formatted date when the message was sent.
func (meta *BasicMeta) GetDate() string {
return meta.Date
}
+// GetTextColor returns the color the actual content of the message should be shown in.
func (meta *BasicMeta) GetTextColor() tcell.Color {
return meta.TextColor
}
+// GetTimestampColor 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) GetTimestampColor() tcell.Color {
return meta.TimestampColor
}
diff --git a/ui/widget/message-view.go b/ui/widget/message-view.go
index a4ba236..444aa03 100644
--- a/ui/widget/message-view.go
+++ b/ui/widget/message-view.go
@@ -315,7 +315,6 @@ func (view *MessageView) Draw(screen tcell.Screen) {
screen.SetContent(separatorX, separatorY, view.Separator, nil, tcell.StyleDefault)
}
- var prevMeta types.MessageMeta
indexOffset := len(view.textBuffer) - view.ScrollOffset - height
if indexOffset <= -PaddingAtTop {
message := "Scroll up to load more messages."
@@ -324,10 +323,13 @@ func (view *MessageView) Draw(screen tcell.Screen) {
}
view.writeLine(screen, message, x+messageOffsetX, y, tcell.ColorGreen)
}
+
if len(view.textBuffer) != len(view.metaBuffer) {
debug.ExtPrintf("Unexpected text/meta buffer length mismatch: %d != %d.", len(view.textBuffer), len(view.metaBuffer))
return
}
+
+ var prevMeta types.MessageMeta
for line := 0; line < height; line++ {
index := indexOffset + line
if index < 0 {
@@ -342,7 +344,7 @@ func (view *MessageView) Draw(screen tcell.Screen) {
}
if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() {
view.writeLineRight(
- screen, meta.GetDisplaySender(),
+ screen, meta.GetSender(),
x+usernameOffsetX, y+line,
view.widestSender, meta.GetSenderColor())
}