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