Add support for editing messages
This commit is contained in:
		
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@@ -19,7 +19,7 @@ require (
 | 
			
		||||
	golang.org/x/net v0.0.0-20200202094626-16171245cfb2
 | 
			
		||||
	gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
 | 
			
		||||
	gopkg.in/yaml.v2 v2.2.8
 | 
			
		||||
	maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218191514-cb8e637f1c62
 | 
			
		||||
	maunium.net/go/mauview v0.0.0-20200218183549-88ecb1321176
 | 
			
		||||
	maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218231230-3f49fda72ac9
 | 
			
		||||
	maunium.net/go/mauview v0.0.0-20200218231215-04d01c601d5b
 | 
			
		||||
	maunium.net/go/tcell v1.1.2-0.20200218183045-87c4a25c5b09
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							@@ -72,7 +72,11 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218183645-fea33ed88d03 h1:0fvOe9KeB/JAkMAzJTmj6mg1P9xGPAgFhJcCSxNe1Rk=
 | 
			
		||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218183645-fea33ed88d03/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4=
 | 
			
		||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218191514-cb8e637f1c62/go.mod h1:g10T1fh2Q2HkJWycVs93eBXdWpqD67f1YVQhNxdIDr4=
 | 
			
		||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218231230-3f49fda72ac9 h1:emsSg9ZDiSqI2RrxU3+JddoF4rxshpNn71NNHcy3HUI=
 | 
			
		||||
maunium.net/go/mautrix v0.1.0-alpha.3.0.20200218231230-3f49fda72ac9/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/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/go.mod h1:jwg3Ow7akzsCX3q38pZAfmEC5gGN8gXwMyyjy/yZVMg=
 | 
			
		||||
maunium.net/go/tcell v1.1.2-0.20200218183045-87c4a25c5b09 h1:hu+R+0nodoZPS19WGyYiw/d63+/NQS/R3Duw3d9HqAU=
 | 
			
		||||
maunium.net/go/tcell v1.1.2-0.20200218183045-87c4a25c5b09/go.mod h1:Ru7KmI5AU7xHUx6hGltgJvknrS+8jlGGMKK15pZuc9k=
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ type MatrixContainer interface {
 | 
			
		||||
	Logout()
 | 
			
		||||
 | 
			
		||||
	SendPreferencesToMatrix()
 | 
			
		||||
	PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, message string) *event.Event
 | 
			
		||||
	PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, message string, edit *event.Event) *event.Event
 | 
			
		||||
	SendEvent(evt *event.Event) (string, error)
 | 
			
		||||
	SendTyping(roomID string, typing bool)
 | 
			
		||||
	MarkRead(roomID, eventID string)
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,14 @@ type Event struct {
 | 
			
		||||
	Gomuks GomuksContent `json:"-"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (evt *Event) SomewhatDangerousCopy() *Event {
 | 
			
		||||
	base := *evt.Event
 | 
			
		||||
	return &Event{
 | 
			
		||||
		Event: &base,
 | 
			
		||||
		Gomuks: evt.Gomuks,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Wrap(event *mautrix.Event) *Event {
 | 
			
		||||
	return &Event{Event: event}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -690,7 +690,7 @@ func (c *Container) MarkRead(roomID, eventID string) {
 | 
			
		||||
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
 | 
			
		||||
var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\\)")
 | 
			
		||||
 | 
			
		||||
func (c *Container) PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string) *event.Event {
 | 
			
		||||
func (c *Container) PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string, edit *event.Event) *event.Event {
 | 
			
		||||
	content := format.RenderMarkdown(text)
 | 
			
		||||
	content.MsgType = msgtype
 | 
			
		||||
 | 
			
		||||
@@ -698,6 +698,19 @@ func (c *Container) PrepareMarkdownMessage(roomID string, msgtype mautrix.Messag
 | 
			
		||||
	content.Body = mentionRegex.ReplaceAllString(content.Body, "$1")
 | 
			
		||||
	content.Body = roomRegex.ReplaceAllString(content.Body, "$1")
 | 
			
		||||
 | 
			
		||||
	if edit != nil {
 | 
			
		||||
		contentCopy := content
 | 
			
		||||
		content.NewContent = &contentCopy
 | 
			
		||||
		content.Body = "* " + content.Body
 | 
			
		||||
		if len(content.FormattedBody) > 0 {
 | 
			
		||||
			content.FormattedBody = "* " + content.FormattedBody
 | 
			
		||||
		}
 | 
			
		||||
		content.RelatesTo = &mautrix.RelatesTo{
 | 
			
		||||
			Type:    mautrix.RelReplace,
 | 
			
		||||
			EventID: edit.ID,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txnID := c.client.TxnID()
 | 
			
		||||
	localEcho := event.Wrap(&mautrix.Event{
 | 
			
		||||
		ID:        txnID,
 | 
			
		||||
@@ -711,6 +724,10 @@ func (c *Container) PrepareMarkdownMessage(roomID string, msgtype mautrix.Messag
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	localEcho.Gomuks.OutgoingState = event.StateLocalEcho
 | 
			
		||||
	if edit != nil {
 | 
			
		||||
		localEcho.ID = edit.ID
 | 
			
		||||
		localEcho.Gomuks.Edits = []*event.Event{localEcho}
 | 
			
		||||
	}
 | 
			
		||||
	return localEcho
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
package messages
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +54,7 @@ type UIMessage struct {
 | 
			
		||||
	IsHighlight        bool
 | 
			
		||||
	IsService          bool
 | 
			
		||||
	Edited             bool
 | 
			
		||||
	Source             json.RawMessage
 | 
			
		||||
	Event              *event.Event
 | 
			
		||||
	ReplyTo            *UIMessage
 | 
			
		||||
	Renderer           MessageRenderer
 | 
			
		||||
}
 | 
			
		||||
@@ -82,7 +81,7 @@ func newUIMessage(evt *event.Event, displayname string, renderer MessageRenderer
 | 
			
		||||
		IsHighlight:        false,
 | 
			
		||||
		IsService:          false,
 | 
			
		||||
		Edited:             len(evt.Gomuks.Edits) > 0,
 | 
			
		||||
		Source:             evt.Content.VeryRaw,
 | 
			
		||||
		Event:              evt,
 | 
			
		||||
		Renderer:           renderer,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -128,6 +128,7 @@ func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *event.Event
 | 
			
		||||
		evt.Content.RemoveReplyFallback()
 | 
			
		||||
	}
 | 
			
		||||
	if len(evt.Gomuks.Edits) > 0 {
 | 
			
		||||
		evt = evt.SomewhatDangerousCopy()
 | 
			
		||||
		evt.Content = *evt.Gomuks.Edits[len(evt.Gomuks.Edits)-1].Content.NewContent
 | 
			
		||||
	}
 | 
			
		||||
	switch evt.Content.MsgType {
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,9 @@ type RoomView struct {
 | 
			
		||||
 | 
			
		||||
	typing []string
 | 
			
		||||
 | 
			
		||||
	editing      *event.Event
 | 
			
		||||
	editMoveText string
 | 
			
		||||
 | 
			
		||||
	completions struct {
 | 
			
		||||
		list      []string
 | 
			
		||||
		textCache string
 | 
			
		||||
@@ -107,7 +110,9 @@ func NewRoomView(parent *MainView, room *rooms.Room) *RoomView {
 | 
			
		||||
		SetBackgroundColor(tcell.ColorDefault).
 | 
			
		||||
		SetPlaceholder("Send a message...").
 | 
			
		||||
		SetPlaceholderTextColor(tcell.ColorGray).
 | 
			
		||||
		SetTabCompleteFunc(view.InputTabComplete)
 | 
			
		||||
		SetTabCompleteFunc(view.InputTabComplete).
 | 
			
		||||
		SetPressKeyUpAtStartFunc(view.EditPrevious).
 | 
			
		||||
		SetPressKeyDownAtEndFunc(view.EditNext)
 | 
			
		||||
 | 
			
		||||
	view.topic.
 | 
			
		||||
		SetTextColor(tcell.ColorWhite).
 | 
			
		||||
@@ -149,6 +154,10 @@ func (view *RoomView) Blur() {
 | 
			
		||||
func (view *RoomView) GetStatus() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
 | 
			
		||||
	if view.editing != nil {
 | 
			
		||||
		buf.WriteString("Editing message - ")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(view.completions.list) > 0 {
 | 
			
		||||
		if view.completions.textCache != view.input.GetText() || view.completions.time.Add(10*time.Second).Before(time.Now()) {
 | 
			
		||||
			view.completions.list = []string{}
 | 
			
		||||
@@ -354,6 +363,61 @@ func (view *RoomView) autocompleteEmoji(word string) (completions []string) {
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (view *RoomView) SetEditing(evt *event.Event) {
 | 
			
		||||
	if evt == nil {
 | 
			
		||||
		view.editing = nil
 | 
			
		||||
		view.SetInputText(view.editMoveText)
 | 
			
		||||
		view.editMoveText = ""
 | 
			
		||||
	} else {
 | 
			
		||||
		if view.editing == nil {
 | 
			
		||||
			view.editMoveText = view.GetInputText()
 | 
			
		||||
		}
 | 
			
		||||
		view.editing = evt
 | 
			
		||||
		view.SetInputText(view.editing.Content.Body)
 | 
			
		||||
	}
 | 
			
		||||
	view.status.SetText(view.GetStatus())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (view *RoomView) EditNext() {
 | 
			
		||||
	if view.editing == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var foundEvent *event.Event
 | 
			
		||||
	currentFound := view.editing == nil
 | 
			
		||||
	self := view.parent.matrix.Client().UserID
 | 
			
		||||
	for _, msg := range view.MessageView().messages {
 | 
			
		||||
		if currentFound {
 | 
			
		||||
			if msg.SenderID == self {
 | 
			
		||||
				foundEvent = msg.Event
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		} else if msg.EventID == view.editing.ID {
 | 
			
		||||
			currentFound = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	view.SetEditing(foundEvent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (view *RoomView) EditPrevious() {
 | 
			
		||||
	var foundEvent *event.Event
 | 
			
		||||
	currentFound := view.editing == nil
 | 
			
		||||
	self := view.parent.matrix.Client().UserID
 | 
			
		||||
	msgs := view.MessageView().messages
 | 
			
		||||
	for i := len(msgs) - 1; i >= 0; i-- {
 | 
			
		||||
		if currentFound {
 | 
			
		||||
			if msgs[i].SenderID == self {
 | 
			
		||||
				foundEvent = msgs[i].Event
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		} else if msgs[i].EventID == view.editing.ID {
 | 
			
		||||
			currentFound = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if foundEvent != nil {
 | 
			
		||||
		view.SetEditing(foundEvent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (view *RoomView) InputTabComplete(text string, cursorOffset int) {
 | 
			
		||||
	debug.Print("Tab completing", cursorOffset, text)
 | 
			
		||||
	str := runewidth.Truncate(text, cursorOffset, "")
 | 
			
		||||
@@ -396,11 +460,12 @@ func (view *RoomView) InputTabComplete(text string, cursorOffset int) {
 | 
			
		||||
func (view *RoomView) InputSubmit(text string) {
 | 
			
		||||
	if len(text) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	} else if cmd := view.parent.cmdProcessor.ParseCommand(view, text); cmd != nil {
 | 
			
		||||
	} else if cmd := view.parent.cmdProcessor.ParseCommand(view, text); view.editing == nil && cmd != nil {
 | 
			
		||||
		go view.parent.cmdProcessor.HandleCommand(cmd)
 | 
			
		||||
	} else {
 | 
			
		||||
		go view.SendMessage(mautrix.MsgText, text)
 | 
			
		||||
	}
 | 
			
		||||
	view.editMoveText = ""
 | 
			
		||||
	view.SetInputText("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -410,9 +475,11 @@ func (view *RoomView) SendMessage(msgtype mautrix.MessageType, text string) {
 | 
			
		||||
	if !view.config.Preferences.DisableEmojis {
 | 
			
		||||
		text = emoji.Sprint(text)
 | 
			
		||||
	}
 | 
			
		||||
	evt := view.parent.matrix.PrepareMarkdownMessage(view.Room.ID, msgtype, text)
 | 
			
		||||
	evt := view.parent.matrix.PrepareMarkdownMessage(view.Room.ID, msgtype, text, view.editing)
 | 
			
		||||
	msg := view.parseEvent(evt)
 | 
			
		||||
	view.content.AddMessage(msg, AppendMessage)
 | 
			
		||||
	view.editing = nil
 | 
			
		||||
	view.status.SetText(view.GetStatus())
 | 
			
		||||
	eventID, err := view.parent.matrix.SendEvent(evt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		msg.State = event.StateSendFail
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user