aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/message-view.go54
-rw-r--r--ui/messages/base.go90
-rw-r--r--ui/messages/parser.go1
-rw-r--r--ui/room-view.go17
4 files changed, 137 insertions, 25 deletions
diff --git a/ui/message-view.go b/ui/message-view.go
index 9d67c7b..20ee149 100644
--- a/ui/message-view.go
+++ b/ui/message-view.go
@@ -284,11 +284,16 @@ func (view *MessageView) replaceBuffer(original *messages.UIMessage, new *messag
view.msgBufferLock.Lock()
if new.Height() != end-start {
- metaBuffer := view.msgBuffer[0:start]
- for i := 0; i < new.Height(); i++ {
- metaBuffer = append(metaBuffer, new)
+ height := new.Height()
+
+ newBuffer := make([]*messages.UIMessage, height + len(view.msgBuffer) - end)
+ for i := 0; i < height; i++ {
+ newBuffer[i] = new
+ }
+ for i := height; i < len(newBuffer); i++ {
+ newBuffer[i] = view.msgBuffer[end + (i - height)]
}
- view.msgBuffer = append(metaBuffer, view.msgBuffer[end:]...)
+ view.msgBuffer = append(view.msgBuffer[0:start], newBuffer...)
} else {
for i := start; i < end; i++ {
view.msgBuffer[i] = new
@@ -594,33 +599,38 @@ func (view *MessageView) Draw(screen mauview.Screen) {
var prevMsg *messages.UIMessage
view.msgBufferLock.RLock()
- for line := viewStart; line < height && indexOffset+line < len(view.msgBuffer); line++ {
+ for line := viewStart; line < height && indexOffset+line < len(view.msgBuffer); {
index := indexOffset + line
msg := view.msgBuffer[index]
- if msg != prevMsg {
- if len(msg.FormatTime()) > 0 {
- 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)
- //if !bareMode && (prevMsg == nil || meta.Sender() != prevMsg.Sender()) {
- widget.WriteLineColor(
- screen, mauview.AlignRight, msg.Sender(),
- usernameX, line, view.widestSender(),
- msg.SenderColor())
- //}
- if msg.Edited {
- // TODO add better indicator for edits
- screen.SetCell(usernameX + view.widestSender(), line, tcell.StyleDefault.Foreground(tcell.ColorDarkRed), '*')
- }
- prevMsg = msg
+ if msg == prevMsg {
+ debug.Print("Unexpected re-encounter of", msg, msg.Height(), "at", line, index)
+ line++
+ continue
+ }
+
+ if len(msg.FormatTime()) > 0 {
+ 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)
+ //if !bareMode && (prevMsg == nil || meta.Sender() != prevMsg.Sender()) {
+ widget.WriteLineColor(
+ screen, mauview.AlignRight, msg.Sender(),
+ usernameX, line, view.widestSender(),
+ msg.SenderColor())
+ //}
+ if msg.Edited {
+ // TODO add better indicator for edits
+ screen.SetCell(usernameX+view.widestSender(), line, tcell.StyleDefault.Foreground(tcell.ColorDarkRed), '*')
}
for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- {
line--
}
msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width()-messageX, msg.Height()))
- line += msg.Height() - 1
+ line += msg.Height()
+
+ prevMsg = msg
}
view.msgBufferLock.RUnlock()
}
diff --git a/ui/messages/base.go b/ui/messages/base.go
index b54691e..4dba9de 100644
--- a/ui/messages/base.go
+++ b/ui/messages/base.go
@@ -18,6 +18,8 @@ package messages
import (
"fmt"
+ "sort"
+ "strings"
"time"
"maunium.net/go/gomuks/config"
@@ -41,6 +43,29 @@ type MessageRenderer interface {
String() string
}
+type ReactionItem struct {
+ Key string
+ Count int
+}
+
+func (ri ReactionItem) String() string {
+ return fmt.Sprintf("%d %s", ri.Count, ri.Key)
+}
+
+type ReactionSlice []ReactionItem
+
+func (rs ReactionSlice) Len() int {
+ return len(rs)
+}
+
+func (rs ReactionSlice) Less(i, j int) bool {
+ return rs[i].Key < rs[j].Key
+}
+
+func (rs ReactionSlice) Swap(i, j int) {
+ rs[i], rs[j] = rs[j], rs[i]
+}
+
type UIMessage struct {
EventID string
TxnID string
@@ -56,7 +81,10 @@ type UIMessage struct {
Edited bool
Event *event.Event
ReplyTo *UIMessage
+ Reactions ReactionSlice
Renderer MessageRenderer
+
+ reactionBuffer string
}
const DateFormat = "January _2, 2006"
@@ -68,6 +96,15 @@ func newUIMessage(evt *event.Event, displayname string, renderer MessageRenderer
msgtype = mautrix.MessageType(evt.Type.String())
}
+ reactions := make(ReactionSlice, 0, len(evt.Unsigned.Relations.Annotations.Map))
+ for key, count := range evt.Unsigned.Relations.Annotations.Map {
+ reactions = append(reactions, ReactionItem{
+ Key: key,
+ Count: count,
+ })
+ }
+ sort.Sort(reactions)
+
return &UIMessage{
SenderID: evt.Sender,
SenderName: displayname,
@@ -81,11 +118,31 @@ func newUIMessage(evt *event.Event, displayname string, renderer MessageRenderer
IsHighlight: false,
IsService: false,
Edited: len(evt.Gomuks.Edits) > 0,
+ Reactions: reactions,
Event: evt,
Renderer: renderer,
}
}
+func (msg *UIMessage) AddReaction(key string) {
+ found := false
+ for _, rs := range msg.Reactions {
+ if rs.Key == key {
+ rs.Count++
+ found = true
+ break
+ }
+ }
+ if !found {
+ msg.Reactions = append(msg.Reactions, ReactionItem{
+ Key: key,
+ Count: 1,
+ })
+ }
+ sort.Sort(msg.Reactions)
+ msg.CalculateReactionBuffer()
+}
+
func unixToTime(unix int64) time.Time {
timestamp := time.Now()
if unix != 0 {
@@ -195,9 +252,16 @@ func (msg *UIMessage) ReplyHeight() int {
return 0
}
+func (msg *UIMessage) ReactionHeight() int {
+ if len(msg.Reactions) > 0 {
+ return 1
+ }
+ return 0
+}
+
// Height returns the number of rows in the computed buffer (see Buffer()).
func (msg *UIMessage) Height() int {
- return msg.ReplyHeight() + msg.Renderer.Height()
+ return msg.ReplyHeight() + msg.Renderer.Height() + msg.ReactionHeight()
}
func (msg *UIMessage) Time() time.Time {
@@ -235,14 +299,25 @@ func (msg *UIMessage) SetIsHighlight(isHighlight bool) {
msg.IsHighlight = isHighlight
}
+func (msg *UIMessage) DrawReactions(screen mauview.Screen) {
+ if len(msg.Reactions) == 0 {
+ return
+ }
+ width, height := screen.Size()
+ screen = mauview.NewProxyScreen(screen, 0, height-1, width, 1)
+ mauview.Print(screen, msg.reactionBuffer, 0, 0, width, mauview.AlignLeft, mauview.Styles.PrimaryTextColor)
+}
+
func (msg *UIMessage) Draw(screen mauview.Screen) {
screen = msg.DrawReply(screen)
msg.Renderer.Draw(screen)
+ msg.DrawReactions(screen)
}
func (msg *UIMessage) Clone() *UIMessage {
clone := *msg
clone.ReplyTo = nil
+ clone.Reactions = nil
clone.Renderer = clone.Renderer.Clone()
return &clone
}
@@ -254,9 +329,19 @@ func (msg *UIMessage) CalculateReplyBuffer(preferences config.UserPreferences, w
msg.ReplyTo.CalculateBuffer(preferences, width-1)
}
+func (msg *UIMessage) CalculateReactionBuffer() {
+ var text strings.Builder
+ for _, reaction := range msg.Reactions {
+ text.WriteString(reaction.String())
+ text.WriteRune(' ')
+ }
+ msg.reactionBuffer = text.String()
+}
+
func (msg *UIMessage) CalculateBuffer(preferences config.UserPreferences, width int) {
msg.Renderer.CalculateBuffer(preferences, width, msg)
msg.CalculateReplyBuffer(preferences, width)
+ msg.CalculateReactionBuffer()
}
func (msg *UIMessage) DrawReply(screen mauview.Screen) mauview.Screen {
@@ -286,8 +371,7 @@ func (msg *UIMessage) String() string {
msg.EventID, msg.TxnID,
msg.Type, msg.Timestamp.String(),
msg.SenderID, msg.SenderName, msg.DefaultSenderColor.Hex(),
- msg.IsService, msg.IsHighlight, msg.Renderer.String(),
- )
+ msg.IsService, msg.IsHighlight, msg.Renderer.String())
}
func (msg *UIMessage) PlainText() string {
diff --git a/ui/messages/parser.go b/ui/messages/parser.go
index 53d30e3..c242f47 100644
--- a/ui/messages/parser.go
+++ b/ui/messages/parser.go
@@ -54,6 +54,7 @@ func ParseEvent(matrix ifc.MatrixContainer, mainView ifc.MainView, room *rooms.R
} else if replyToEvt, _ := matrix.GetEvent(room, evt.Content.GetReplyTo()); replyToEvt != nil {
if replyToMsg := directParseEvent(matrix, room, replyToEvt); replyToMsg != nil {
msg.ReplyTo = replyToMsg
+ msg.ReplyTo.Reactions = nil
} else {
// TODO add unrenderable reply header
}
diff --git a/ui/room-view.go b/ui/room-view.go
index 126f1ff..ab31ca7 100644
--- a/ui/room-view.go
+++ b/ui/room-view.go
@@ -558,6 +558,23 @@ func (view *RoomView) AddEdit(evt *event.Event) {
}
}
+func (view *RoomView) AddReaction(evt *event.Event, key string) {
+ msgView := view.MessageView()
+ msg := msgView.getMessageByID(evt.ID)
+ if msg == nil {
+ // Message not in view, nothing to do
+ return
+ }
+ recalculate := len(msg.Reactions) == 0
+ msg.AddReaction(key)
+ if recalculate {
+ debug.Print(msg.ReactionHeight(), msg.Height())
+ // Recalculate height for message
+ msg.CalculateBuffer(msgView.prevPrefs, msgView.prevWidth())
+ msgView.replaceBuffer(msg, msg)
+ }
+}
+
func (view *RoomView) GetEvent(eventID string) ifc.Message {
message, ok := view.content.messageIDs[eventID]
if !ok {