Add support for displaying reactions
This commit is contained in:
		
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @@ -19,7 +19,7 @@ require ( | |||||||
| 	golang.org/x/net v0.0.0-20200202094626-16171245cfb2 | 	golang.org/x/net v0.0.0-20200202094626-16171245cfb2 | ||||||
| 	gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 | 	gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 | ||||||
| 	gopkg.in/yaml.v2 v2.2.8 | 	gopkg.in/yaml.v2 v2.2.8 | ||||||
| 	maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219230859-de66c34ea5bc | 	maunium.net/go/mautrix v0.1.0-alpha.3.0.20200220001222-8dc3dd5d538d | ||||||
| 	maunium.net/go/mauview v0.0.0-20200219222453-b984e20438e6 | 	maunium.net/go/mauview v0.0.0-20200219222453-b984e20438e6 | ||||||
| 	maunium.net/go/tcell v1.1.2-0.20200218183045-87c4a25c5b09 | 	maunium.net/go/tcell v1.1.2-0.20200218183045-87c4a25c5b09 | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @@ -80,6 +80,8 @@ maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219223957-21a588b7e623 h1:StXwGEEdQ | |||||||
| maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219223957-21a588b7e623/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4= | maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219223957-21a588b7e623/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4= | ||||||
| maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219230859-de66c34ea5bc h1:1iMzqdMF4z9Rp3CDfDa+gjuRHGfb9cZjZZR9Y68nPuo= | maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219230859-de66c34ea5bc h1:1iMzqdMF4z9Rp3CDfDa+gjuRHGfb9cZjZZR9Y68nPuo= | ||||||
| maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219230859-de66c34ea5bc/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4= | maunium.net/go/mautrix v0.1.0-alpha.3.0.20200219230859-de66c34ea5bc/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4= | ||||||
|  | maunium.net/go/mautrix v0.1.0-alpha.3.0.20200220001222-8dc3dd5d538d h1:doAHXnYCIgNy4qAgReZRRb3EaWR4D0w+Zs2y959Z8Uk= | ||||||
|  | maunium.net/go/mautrix v0.1.0-alpha.3.0.20200220001222-8dc3dd5d538d/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4= | ||||||
| maunium.net/go/mauview v0.0.0-20200218183549-88ecb1321176 h1:KoTm7ASEzFIZ1SvPWuWYzpkeA+wiR1fuUu4l7TCHcE0= | maunium.net/go/mauview v0.0.0-20200218183549-88ecb1321176 h1:KoTm7ASEzFIZ1SvPWuWYzpkeA+wiR1fuUu4l7TCHcE0= | ||||||
| maunium.net/go/mauview v0.0.0-20200218183549-88ecb1321176/go.mod h1:jwg3Ow7akzsCX3q38pZAfmEC5gGN8gXwMyyjy/yZVMg= | maunium.net/go/mauview v0.0.0-20200218183549-88ecb1321176/go.mod h1:jwg3Ow7akzsCX3q38pZAfmEC5gGN8gXwMyyjy/yZVMg= | ||||||
| maunium.net/go/mauview v0.0.0-20200218231215-04d01c601d5b h1:Bfov5IkJQpkqDexiFioHIZpx4XL7AILDA1GwLVdqtBw= | maunium.net/go/mauview v0.0.0-20200218231215-04d01c601d5b h1:Bfov5IkJQpkqDexiFioHIZpx4XL7AILDA1GwLVdqtBw= | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ type RoomView interface { | |||||||
| 	AddEvent(evt *event.Event) Message | 	AddEvent(evt *event.Event) Message | ||||||
| 	AddRedaction(evt *event.Event) | 	AddRedaction(evt *event.Event) | ||||||
| 	AddEdit(evt *event.Event) | 	AddEdit(evt *event.Event) | ||||||
|  | 	AddReaction(evt *event.Event, key string) | ||||||
| 	GetEvent(eventID string) Message | 	GetEvent(eventID string) Message | ||||||
| 	AddServiceMessage(message string) | 	AddServiceMessage(message string) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -297,9 +297,9 @@ func (c *Container) OnLogin() { | |||||||
| 	debug.Print("Initializing syncer") | 	debug.Print("Initializing syncer") | ||||||
| 	c.syncer = NewGomuksSyncer(c.config) | 	c.syncer = NewGomuksSyncer(c.config) | ||||||
| 	c.syncer.OnEventType(mautrix.EventMessage, c.HandleMessage) | 	c.syncer.OnEventType(mautrix.EventMessage, c.HandleMessage) | ||||||
| 	// Just pass encrypted events as messages, they'll show up with an encryption unsupported message. |  | ||||||
| 	c.syncer.OnEventType(mautrix.EventEncrypted, c.HandleMessage) | 	c.syncer.OnEventType(mautrix.EventEncrypted, c.HandleMessage) | ||||||
| 	c.syncer.OnEventType(mautrix.EventSticker, c.HandleMessage) | 	c.syncer.OnEventType(mautrix.EventSticker, c.HandleMessage) | ||||||
|  | 	c.syncer.OnEventType(mautrix.EventReaction, c.HandleMessage) | ||||||
| 	c.syncer.OnEventType(mautrix.EventRedaction, c.HandleRedaction) | 	c.syncer.OnEventType(mautrix.EventRedaction, c.HandleRedaction) | ||||||
| 	c.syncer.OnEventType(mautrix.StateAliases, c.HandleMessage) | 	c.syncer.OnEventType(mautrix.StateAliases, c.HandleMessage) | ||||||
| 	c.syncer.OnEventType(mautrix.StateCanonicalAlias, c.HandleMessage) | 	c.syncer.OnEventType(mautrix.StateCanonicalAlias, c.HandleMessage) | ||||||
| @@ -453,6 +453,37 @@ func (c *Container) HandleEdit(room *rooms.Room, editsID string, editEvent *even | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Container) HandleReaction(room *rooms.Room, reactsTo string, reactEvent *event.Event) { | ||||||
|  | 	rel := reactEvent.Content.GetRelatesTo() | ||||||
|  | 	var origEvt *event.Event | ||||||
|  | 	err := c.history.Update(room, reactsTo, func(evt *event.Event) error { | ||||||
|  | 		if evt.Unsigned.Relations.Annotations.Map == nil { | ||||||
|  | 			evt.Unsigned.Relations.Annotations.Map = make(map[string]int) | ||||||
|  | 		} | ||||||
|  | 		val, _ := evt.Unsigned.Relations.Annotations.Map[rel.Key] | ||||||
|  | 		evt.Unsigned.Relations.Annotations.Map[rel.Key] = val + 1 | ||||||
|  | 		origEvt = evt | ||||||
|  | 		return nil | ||||||
|  | 	}) | ||||||
|  | 	if err != nil { | ||||||
|  | 		debug.Print("Failed to store reaction in history db:", err) | ||||||
|  | 		return | ||||||
|  | 	} else if !c.config.AuthCache.InitialSyncDone || !room.Loaded() { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	roomView := c.ui.MainView().GetRoom(reactEvent.RoomID) | ||||||
|  | 	if roomView == nil { | ||||||
|  | 		debug.Printf("Failed to handle edit event %v: No room view found.", reactEvent) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	roomView.AddReaction(origEvt, rel.Key) | ||||||
|  | 	if c.syncer.FirstSyncDone { | ||||||
|  | 		c.ui.Render() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // HandleMessage is the event handler for the m.room.message timeline event. | // HandleMessage is the event handler for the m.room.message timeline event. | ||||||
| func (c *Container) HandleMessage(source EventSource, mxEvent *mautrix.Event) { | func (c *Container) HandleMessage(source EventSource, mxEvent *mautrix.Event) { | ||||||
| 	room := c.GetOrCreateRoom(mxEvent.RoomID) | 	room := c.GetOrCreateRoom(mxEvent.RoomID) | ||||||
| @@ -466,6 +497,9 @@ func (c *Container) HandleMessage(source EventSource, mxEvent *mautrix.Event) { | |||||||
| 	if editID := mxEvent.Content.GetRelatesTo().GetReplaceID(); len(editID) > 0 { | 	if editID := mxEvent.Content.GetRelatesTo().GetReplaceID(); len(editID) > 0 { | ||||||
| 		c.HandleEdit(room, editID, event.Wrap(mxEvent)) | 		c.HandleEdit(room, editID, event.Wrap(mxEvent)) | ||||||
| 		return | 		return | ||||||
|  | 	} else if reactionID := mxEvent.Content.GetRelatesTo().GetAnnotationID(); mxEvent.Type == mautrix.EventReaction && len(reactionID) > 0 { | ||||||
|  | 		c.HandleReaction(room, reactionID, event.Wrap(mxEvent)) | ||||||
|  | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	events, err := c.history.Append(room, []*mautrix.Event{mxEvent}) | 	events, err := c.history.Append(room, []*mautrix.Event{mxEvent}) | ||||||
|   | |||||||
| @@ -284,11 +284,16 @@ func (view *MessageView) replaceBuffer(original *messages.UIMessage, new *messag | |||||||
|  |  | ||||||
| 	view.msgBufferLock.Lock() | 	view.msgBufferLock.Lock() | ||||||
| 	if new.Height() != end-start { | 	if new.Height() != end-start { | ||||||
| 		metaBuffer := view.msgBuffer[0:start] | 		height := new.Height() | ||||||
| 		for i := 0; i < new.Height(); i++ { |  | ||||||
| 			metaBuffer = append(metaBuffer, new) | 		newBuffer := make([]*messages.UIMessage, height + len(view.msgBuffer) - end) | ||||||
|  | 		for i := 0; i < height; i++ { | ||||||
|  | 			newBuffer[i] = new | ||||||
| 		} | 		} | ||||||
| 		view.msgBuffer = append(metaBuffer, view.msgBuffer[end:]...) | 		for i := height; i < len(newBuffer); i++ { | ||||||
|  | 			newBuffer[i] = view.msgBuffer[end + (i - height)] | ||||||
|  | 		} | ||||||
|  | 		view.msgBuffer = append(view.msgBuffer[0:start], newBuffer...) | ||||||
| 	} else { | 	} else { | ||||||
| 		for i := start; i < end; i++ { | 		for i := start; i < end; i++ { | ||||||
| 			view.msgBuffer[i] = new | 			view.msgBuffer[i] = new | ||||||
| @@ -594,11 +599,16 @@ func (view *MessageView) Draw(screen mauview.Screen) { | |||||||
|  |  | ||||||
| 	var prevMsg *messages.UIMessage | 	var prevMsg *messages.UIMessage | ||||||
| 	view.msgBufferLock.RLock() | 	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 | 		index := indexOffset + line | ||||||
|  |  | ||||||
| 		msg := view.msgBuffer[index] | 		msg := view.msgBuffer[index] | ||||||
| 		if msg != prevMsg { | 		if msg == prevMsg { | ||||||
|  | 			debug.Print("Unexpected re-encounter of", msg, msg.Height(), "at", line, index) | ||||||
|  | 			line++ | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		if len(msg.FormatTime()) > 0 { | 		if len(msg.FormatTime()) > 0 { | ||||||
| 			widget.WriteLineSimpleColor(screen, msg.FormatTime(), 0, line, msg.TimestampColor()) | 			widget.WriteLineSimpleColor(screen, msg.FormatTime(), 0, line, msg.TimestampColor()) | ||||||
| 		} | 		} | ||||||
| @@ -611,16 +621,16 @@ func (view *MessageView) Draw(screen mauview.Screen) { | |||||||
| 		//} | 		//} | ||||||
| 		if msg.Edited { | 		if msg.Edited { | ||||||
| 			// TODO add better indicator for edits | 			// TODO add better indicator for edits | ||||||
| 				screen.SetCell(usernameX + view.widestSender(), line, tcell.StyleDefault.Foreground(tcell.ColorDarkRed), '*') | 			screen.SetCell(usernameX+view.widestSender(), line, tcell.StyleDefault.Foreground(tcell.ColorDarkRed), '*') | ||||||
| 			} |  | ||||||
| 			prevMsg = msg |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- { | 		for i := index - 1; i >= 0 && view.msgBuffer[i] == msg; i-- { | ||||||
| 			line-- | 			line-- | ||||||
| 		} | 		} | ||||||
| 		msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width()-messageX, msg.Height())) | 		msg.Draw(mauview.NewProxyScreen(screen, messageX, line, view.width()-messageX, msg.Height())) | ||||||
| 		line += msg.Height() - 1 | 		line += msg.Height() | ||||||
|  |  | ||||||
|  | 		prevMsg = msg | ||||||
| 	} | 	} | ||||||
| 	view.msgBufferLock.RUnlock() | 	view.msgBufferLock.RUnlock() | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ package messages | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"sort" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"maunium.net/go/gomuks/config" | 	"maunium.net/go/gomuks/config" | ||||||
| @@ -41,6 +43,29 @@ type MessageRenderer interface { | |||||||
| 	String() string | 	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 { | type UIMessage struct { | ||||||
| 	EventID            string | 	EventID            string | ||||||
| 	TxnID              string | 	TxnID              string | ||||||
| @@ -56,7 +81,10 @@ type UIMessage struct { | |||||||
| 	Edited             bool | 	Edited             bool | ||||||
| 	Event              *event.Event | 	Event              *event.Event | ||||||
| 	ReplyTo            *UIMessage | 	ReplyTo            *UIMessage | ||||||
|  | 	Reactions          ReactionSlice | ||||||
| 	Renderer           MessageRenderer | 	Renderer           MessageRenderer | ||||||
|  |  | ||||||
|  | 	reactionBuffer string | ||||||
| } | } | ||||||
|  |  | ||||||
| const DateFormat = "January _2, 2006" | const DateFormat = "January _2, 2006" | ||||||
| @@ -68,6 +96,15 @@ func newUIMessage(evt *event.Event, displayname string, renderer MessageRenderer | |||||||
| 		msgtype = mautrix.MessageType(evt.Type.String()) | 		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{ | 	return &UIMessage{ | ||||||
| 		SenderID:           evt.Sender, | 		SenderID:           evt.Sender, | ||||||
| 		SenderName:         displayname, | 		SenderName:         displayname, | ||||||
| @@ -81,11 +118,31 @@ func newUIMessage(evt *event.Event, displayname string, renderer MessageRenderer | |||||||
| 		IsHighlight:        false, | 		IsHighlight:        false, | ||||||
| 		IsService:          false, | 		IsService:          false, | ||||||
| 		Edited:             len(evt.Gomuks.Edits) > 0, | 		Edited:             len(evt.Gomuks.Edits) > 0, | ||||||
|  | 		Reactions:          reactions, | ||||||
| 		Event:              evt, | 		Event:              evt, | ||||||
| 		Renderer:           renderer, | 		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 { | func unixToTime(unix int64) time.Time { | ||||||
| 	timestamp := time.Now() | 	timestamp := time.Now() | ||||||
| 	if unix != 0 { | 	if unix != 0 { | ||||||
| @@ -195,9 +252,16 @@ func (msg *UIMessage) ReplyHeight() int { | |||||||
| 	return 0 | 	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()). | // Height returns the number of rows in the computed buffer (see Buffer()). | ||||||
| func (msg *UIMessage) Height() int { | 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 { | func (msg *UIMessage) Time() time.Time { | ||||||
| @@ -235,14 +299,25 @@ func (msg *UIMessage) SetIsHighlight(isHighlight bool) { | |||||||
| 	msg.IsHighlight = isHighlight | 	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) { | func (msg *UIMessage) Draw(screen mauview.Screen) { | ||||||
| 	screen = msg.DrawReply(screen) | 	screen = msg.DrawReply(screen) | ||||||
| 	msg.Renderer.Draw(screen) | 	msg.Renderer.Draw(screen) | ||||||
|  | 	msg.DrawReactions(screen) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (msg *UIMessage) Clone() *UIMessage { | func (msg *UIMessage) Clone() *UIMessage { | ||||||
| 	clone := *msg | 	clone := *msg | ||||||
| 	clone.ReplyTo = nil | 	clone.ReplyTo = nil | ||||||
|  | 	clone.Reactions = nil | ||||||
| 	clone.Renderer = clone.Renderer.Clone() | 	clone.Renderer = clone.Renderer.Clone() | ||||||
| 	return &clone | 	return &clone | ||||||
| } | } | ||||||
| @@ -254,9 +329,19 @@ func (msg *UIMessage) CalculateReplyBuffer(preferences config.UserPreferences, w | |||||||
| 	msg.ReplyTo.CalculateBuffer(preferences, width-1) | 	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) { | func (msg *UIMessage) CalculateBuffer(preferences config.UserPreferences, width int) { | ||||||
| 	msg.Renderer.CalculateBuffer(preferences, width, msg) | 	msg.Renderer.CalculateBuffer(preferences, width, msg) | ||||||
| 	msg.CalculateReplyBuffer(preferences, width) | 	msg.CalculateReplyBuffer(preferences, width) | ||||||
|  | 	msg.CalculateReactionBuffer() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (msg *UIMessage) DrawReply(screen mauview.Screen) mauview.Screen { | func (msg *UIMessage) DrawReply(screen mauview.Screen) mauview.Screen { | ||||||
| @@ -286,8 +371,7 @@ func (msg *UIMessage) String() string { | |||||||
| 		msg.EventID, msg.TxnID, | 		msg.EventID, msg.TxnID, | ||||||
| 		msg.Type, msg.Timestamp.String(), | 		msg.Type, msg.Timestamp.String(), | ||||||
| 		msg.SenderID, msg.SenderName, msg.DefaultSenderColor.Hex(), | 		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 { | func (msg *UIMessage) PlainText() string { | ||||||
|   | |||||||
| @@ -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 { | 		} else if replyToEvt, _ := matrix.GetEvent(room, evt.Content.GetReplyTo()); replyToEvt != nil { | ||||||
| 			if replyToMsg := directParseEvent(matrix, room, replyToEvt); replyToMsg != nil { | 			if replyToMsg := directParseEvent(matrix, room, replyToEvt); replyToMsg != nil { | ||||||
| 				msg.ReplyTo = replyToMsg | 				msg.ReplyTo = replyToMsg | ||||||
|  | 				msg.ReplyTo.Reactions = nil | ||||||
| 			} else { | 			} else { | ||||||
| 				// TODO add unrenderable reply header | 				// TODO add unrenderable reply header | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -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 { | func (view *RoomView) GetEvent(eventID string) ifc.Message { | ||||||
| 	message, ok := view.content.messageIDs[eventID] | 	message, ok := view.content.messageIDs[eventID] | ||||||
| 	if !ok { | 	if !ok { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user