It compiles. Ship it!

This commit is contained in:
Tulir Asokan 2019-04-10 01:04:39 +03:00
parent dbee49476d
commit bbde121947
11 changed files with 113 additions and 152 deletions

View File

@ -34,8 +34,8 @@ type MatrixContainer interface {
Logout()
SendPreferencesToMatrix()
SendMessage(roomID string, msgtype mautrix.MessageType, message string) (string, error)
SendMarkdownMessage(roomID string, msgtype mautrix.MessageType, message string) (string, error)
PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, message string) *mautrix.Event
SendEvent(event *mautrix.Event) (string, error)
SendTyping(roomID string, typing bool)
MarkRead(roomID, eventID string)
JoinRoom(roomID, server string) (*rooms.Room, error)

View File

@ -53,14 +53,6 @@ type MainView interface {
InitialSyncDone()
}
type MessageDirection int
const (
AppendMessage MessageDirection = iota
PrependMessage
IgnoreMessage
)
type RoomView interface {
MxRoom() *rooms.Room
@ -69,8 +61,7 @@ type RoomView interface {
UpdateUserList()
ParseEvent(evt *mautrix.Event) Message
AppendMessage(message Message)
MarkMessageFailed(message Message)
AddMessage(message Message)
AddServiceMessage(message string)
}
@ -81,4 +72,8 @@ type Message interface {
Timestamp() time.Time
NotificationSenderName() string
NotificationContent() string
SetState(state mautrix.OutgoingEventState)
SetIsHighlight(highlight bool)
SetID(id string)
}

View File

@ -304,9 +304,9 @@ func (c *Container) HandleMessage(source EventSource, evt *mautrix.Event) {
}
// TODO switch to roomView.AddEvent
message := mainView.ParseEvent(roomView, evt)
message := roomView.ParseEvent(evt)
if message != nil {
roomView.AddMessage(message, ifc.AppendMessage)
roomView.AddMessage(message)
roomView.MxRoom().LastReceivedMessage = message.Timestamp()
if c.syncer.FirstSyncDone {
pushRules := c.PushRules().GetActions(roomView.MxRoom(), evt).Should()
@ -480,25 +480,10 @@ func (c *Container) MarkRead(roomID, eventID string) {
c.client.MakeRequest("POST", urlPath, struct{}{}, nil)
}
// SendMessage sends a message with the given text to the given room.
func (c *Container) SendMessage(roomID string, msgtype mautrix.MessageType, text string) (string, error) {
defer debug.Recover()
c.SendTyping(roomID, false)
resp, err := c.client.SendMessageEvent(roomID, mautrix.EventMessage,
mautrix.Content{MsgType: msgtype, Body: text})
if err != nil {
return "", err
}
return resp.EventID, nil
}
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
var roomRegex = regexp.MustCompile("\\[.+?]\\(https://matrix.to/#/(#.+?:[^/]+?)\\)")
// SendMarkdownMessage sends a message with the given markdown text to the given room.
func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string) (string, error) {
defer debug.Recover()
func (c *Container) PrepareMarkdownMessage(roomID string, msgtype mautrix.MessageType, text string) *mautrix.Event {
content := format.RenderMarkdown(text)
content.MsgType = msgtype
@ -506,10 +491,9 @@ func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageTy
content.Body = mentionRegex.ReplaceAllString(content.Body, "$1")
content.Body = roomRegex.ReplaceAllString(content.Body, "$1")
c.SendTyping(roomID, false)
roomView := c.ui.MainView().GetRoom(roomID)
txnID := c.client.TxnID()
localEcho := roomView.ParseEvent(&mautrix.Event{
localEcho := &mautrix.Event{
ID: txnID,
Sender: c.config.UserID,
Type: mautrix.EventMessage,
Timestamp: time.Now().UnixNano() / 1e6,
@ -519,11 +503,17 @@ func (c *Container) SendMarkdownMessage(roomID string, msgtype mautrix.MessageTy
TransactionID: txnID,
OutgoingState: mautrix.EventStateLocalEcho,
},
})
roomView.AppendMessage(localEcho)
resp, err := c.client.SendMessageEvent(roomID, mautrix.EventMessage, content, mautrix.ReqSendEvent{TransactionID: txnID})
}
return localEcho
}
// SendMarkdownMessage sends a message with the given markdown text to the given room.
func (c *Container) SendEvent(event *mautrix.Event) (string, error) {
defer debug.Recover()
c.SendTyping(event.RoomID, false)
resp, err := c.client.SendMessageEvent(event.RoomID, event.Type, event.Content, mautrix.ReqSendEvent{TransactionID: event.Unsigned.TransactionID})
if err != nil {
roomView.MarkMessageFailed(localEcho, err)
return "", err
}
return resp.EventID, nil
@ -592,6 +582,7 @@ func (c *Container) GetHistory(room *rooms.Room, limit int) ([]*mautrix.Event, e
}
}
room.PrevBatch = resp.End
c.config.PutRoom(room)
debug.Printf("Loaded %d events for %s from server from %s to %s", len(resp.Chunk), room.ID, resp.Start, resp.End)
return resp.Chunk, nil
}

View File

@ -27,16 +27,13 @@ import (
"github.com/lucasb-eyer/go-colorful"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/format"
"maunium.net/go/gomuks/debug"
"maunium.net/go/mautrix"
)
func cmdMe(cmd *Command) {
text := strings.Join(cmd.Args, " ")
tempMessage := cmd.Room.NewTempMessage("m.emote", text)
go cmd.MainView.sendTempMessage(cmd.Room, tempMessage, text)
go cmd.Room.SendMessage(mautrix.MsgEmote, text)
cmd.UI.Render()
}
@ -97,8 +94,7 @@ func cmdRainbow(cmd *Command) {
color := rainbow.GetInterpolatedColorFor(float64(i) / float64(len(text))).Hex()
fmt.Fprintf(&html, "<font color=\"%s\">%c</font>", color, char)
}
tempMessage := cmd.Room.NewTempMessage("m.text", format.HTMLToText(html.String()))
go cmd.MainView.sendTempMessage(cmd.Room, tempMessage, html.String())
go cmd.Room.SendMessage("m.text", html.String())
cmd.UI.Render()
}

View File

@ -89,7 +89,7 @@ func (view *MessageView) updateWidestSender(sender string) {
}
}
func (view *MessageView) UpdateMessageID(ifcMessage ifc.Message, newID string) {
/*func (view *MessageView) UpdateMessageID(ifcMessage ifc.Message, newID string) {
message, ok := ifcMessage.(messages.UIMessage)
if !ok {
debug.Print("[Warning] Passed non-UIMessage ifc.Message object to UpdateMessageID().")
@ -99,9 +99,17 @@ func (view *MessageView) UpdateMessageID(ifcMessage ifc.Message, newID string) {
delete(view.messageIDs, message.ID())
message.SetID(newID)
view.messageIDs[message.ID()] = message
}
}*/
func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction ifc.MessageDirection) {
type MessageDirection int
const (
AppendMessage MessageDirection = iota
PrependMessage
IgnoreMessage
)
func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction MessageDirection) {
if ifcMessage == nil {
return
}
@ -117,11 +125,11 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction ifc.Messag
var messageExists bool
if oldMsg, messageExists = view.messageIDs[message.ID()]; messageExists {
view.replaceMessage(oldMsg, message)
direction = ifc.IgnoreMessage
direction = IgnoreMessage
} else if oldMsg, messageExists = view.messageIDs[message.TxnID()]; messageExists {
view.replaceMessage(oldMsg, message)
delete(view.messageIDs, message.TxnID())
direction = ifc.IgnoreMessage
direction = IgnoreMessage
}
view.updateWidestSender(message.Sender())
@ -133,13 +141,13 @@ func (view *MessageView) AddMessage(ifcMessage ifc.Message, direction ifc.Messag
}
message.CalculateBuffer(view.config.Preferences, width)
if direction == ifc.AppendMessage {
if direction == AppendMessage {
if view.ScrollOffset > 0 {
view.ScrollOffset += message.Height()
}
view.messages = append(view.messages, message)
view.appendBuffer(message)
} else if direction == ifc.PrependMessage {
} else if direction == PrependMessage {
view.messages = append([]messages.UIMessage{message}, view.messages...)
} else if oldMsg != nil {
view.replaceBuffer(oldMsg, message)

View File

@ -192,6 +192,9 @@ func (msg *BaseMessage) FormatDate() string {
}
func (msg *BaseMessage) ID() string {
if len(msg.MsgID) == 0 {
return msg.MsgTxnID
}
return msg.MsgID
}
@ -199,6 +202,10 @@ func (msg *BaseMessage) SetID(id string) {
msg.MsgID = id
}
func (msg *BaseMessage) TxnID() string {
return msg.MsgTxnID
}
func (msg *BaseMessage) Type() mautrix.MessageType {
return msg.MsgType
}
@ -219,14 +226,6 @@ func (msg *BaseMessage) SetIsHighlight(isHighlight bool) {
msg.MsgIsHighlight = isHighlight
}
func (msg *BaseMessage) IsService() bool {
return msg.MsgIsService
}
func (msg *BaseMessage) SetIsService(isService bool) {
msg.MsgIsService = isService
}
func (msg *BaseMessage) Source() json.RawMessage {
return msg.MsgSource
}

View File

@ -19,6 +19,7 @@ package messages
import (
"maunium.net/go/gomuks/config"
"maunium.net/go/gomuks/interface"
"maunium.net/go/mautrix"
"maunium.net/go/mauview"
"maunium.net/go/tcell"
)
@ -27,6 +28,7 @@ import (
type UIMessage interface {
ifc.Message
Type() mautrix.MessageType
Sender() string
SenderColor() tcell.Color
TextColor() tcell.Color

View File

@ -29,7 +29,6 @@ import (
"maunium.net/go/gomuks/ui/messages/html"
"maunium.net/go/gomuks/ui/messages/tstring"
"maunium.net/go/gomuks/ui/widget"
htmlp "maunium.net/go/gomuks/ui/messages/html"
)
func ParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *mautrix.Event) UIMessage {

View File

@ -18,6 +18,7 @@ package messages
import (
"fmt"
"time"
"maunium.net/go/mautrix"
@ -39,6 +40,18 @@ func NewTextMessage(event *mautrix.Event, displayname string, text string) UIMes
}
}
func NewServiceMessage(text string) UIMessage {
return &TextMessage{
BaseMessage: BaseMessage{
MsgSenderID: "*",
MsgSender: "*",
MsgTimestamp: time.Now(),
MsgIsService: true,
},
MsgText: text,
}
}
func (msg *TextMessage) getCache() tstring.TString {
if msg.cache == nil {
switch msg.MsgType {
@ -57,11 +70,6 @@ func (msg *TextMessage) SetIsHighlight(isHighlight bool) {
msg.cache = nil
}
func (msg *TextMessage) SetIsService(isService bool) {
msg.BaseMessage.SetIsService(isService)
msg.cache = nil
}
func (msg *TextMessage) NotificationContent() string {
return msg.MsgText
}

View File

@ -20,7 +20,6 @@ import (
"fmt"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
@ -251,7 +250,7 @@ func (view *RoomView) OnKeyEvent(event mauview.KeyEvent) bool {
msgView.AddScrollOffset(-msgView.Height() / 2)
return true
case tcell.KeyEnter:
if event.Modifiers() & tcell.ModShift == 0 && event.Modifiers() & tcell.ModCtrl == 0 && view.inputSubmitFunc != nil {
if event.Modifiers()&tcell.ModShift == 0 && event.Modifiers()&tcell.ModCtrl == 0 && view.inputSubmitFunc != nil {
view.inputSubmitFunc(view, view.input.GetText())
return true
}
@ -379,6 +378,44 @@ func (view *RoomView) InputTabComplete(text string, cursorOffset int) {
view.SetCompletions(strCompletions)
}
func (view *RoomView) InputSubmit(text string) {
if len(text) == 0 {
return
} else if cmd := view.parent.cmdProcessor.ParseCommand(view, text); cmd != nil {
go view.parent.cmdProcessor.HandleCommand(cmd)
} else {
go view.SendMessage(mautrix.MsgText, text)
}
view.SetInputText("")
}
func (view *RoomView) SendMessage(msgtype mautrix.MessageType, text string) {
defer debug.Recover()
debug.Print("Sending message", msgtype, text, "to", view.Room.ID)
if !view.config.Preferences.DisableEmojis {
text = emoji.Sprint(text)
}
evt := view.parent.matrix.PrepareMarkdownMessage(view.Room.ID, msgtype, text)
msg := view.ParseEvent(evt)
view.AddMessage(msg)
eventID, err := view.parent.matrix.SendEvent(evt)
if err != nil {
msg.SetState(mautrix.EventStateSendFail)
// Show shorter version if available
if httpErr, ok := err.(mautrix.HTTPError); ok {
err = httpErr
if respErr := httpErr.RespError; respErr != nil {
err = respErr
}
}
view.AddServiceMessage(fmt.Sprintf("Failed to send message: %v", err))
view.parent.parent.Render()
} else {
debug.Print("Event ID received:", eventID)
//view.MessageView().UpdateMessageID(msg, eventID)
}
}
func (view *RoomView) MessageView() *MessageView {
return view.content
}
@ -406,37 +443,12 @@ func (view *RoomView) UpdateUserList() {
}
}
func (view *RoomView) newUIMessage(id, sender string, msgtype mautrix.MessageType, text string, timestamp time.Time) messages.UIMessage {
member := view.Room.GetMember(sender)
displayname := sender
if member != nil {
displayname = member.Displayname
}
msg := messages.NewTextMessage(id, sender, displayname, msgtype, text, timestamp)
return msg
}
func (view *RoomView) NewTempMessage(msgtype mautrix.MessageType, text string) ifc.Message {
now := time.Now()
id := strconv.FormatInt(now.UnixNano(), 10)
sender := ""
if ownerMember := view.Room.GetMember(view.Room.GetSessionOwner()); ownerMember != nil {
sender = ownerMember.Displayname
}
message := view.newUIMessage(id, sender, msgtype, text, now)
message.SetState(ifc.MessageStateSending)
view.AddMessage(message, ifc.AppendMessage)
return message
}
func (view *RoomView) AddServiceMessage(text string) {
message := view.newUIMessage(view.parent.matrix.Client().TxnID(), "*", "gomuks.service", text, time.Now())
message.SetIsService(true)
view.AddMessage(message, ifc.AppendMessage)
view.content.AddMessage(messages.NewServiceMessage(text), AppendMessage)
}
func (view *RoomView) AddMessage(message ifc.Message, direction ifc.MessageDirection) {
view.content.AddMessage(message, direction)
func (view *RoomView) AddMessage(message ifc.Message) {
view.content.AddMessage(message, AppendMessage)
}
func (view *RoomView) ParseEvent(evt *mautrix.Event) ifc.Message {

View File

@ -23,9 +23,6 @@ import (
"time"
"unicode"
"github.com/kyokomi/emoji"
"maunium.net/go/mautrix"
"maunium.net/go/mauview"
"maunium.net/go/tcell"
@ -152,45 +149,6 @@ func findWordToTabComplete(text string) string {
return output
}
func (view *MainView) InputSubmit(roomView *RoomView, text string) {
if len(text) == 0 {
return
} else if text[0] == '/' {
cmd := view.cmdProcessor.ParseCommand(roomView, text)
go view.cmdProcessor.HandleCommand(cmd)
} else {
view.SendMessage(roomView, text)
}
roomView.SetInputText("")
}
func (view *MainView) SendMessage(roomView *RoomView, text string) {
go view.goSendMessage(roomView, text)
}
func (view *MainView) goSendMessage(roomView *RoomView, text string) {
defer debug.Recover()
debug.Print("Sending message", tempMessage.Type(), text)
if !roomView.config.Preferences.DisableEmojis {
text = emoji.Sprint(text)
}
eventID, err := view.matrix.SendMarkdownMessage(roomView.Room.ID, tempMessage.Type(), text)
if err != nil {
tempMessage.SetState(ifc.MessageStateFailed)
if httpErr, ok := err.(mautrix.HTTPError); ok {
if respErr := httpErr.RespError; respErr != nil {
// Show shorter version if available
err = respErr
}
}
roomView.AddServiceMessage(fmt.Sprintf("Failed to send message: %v", err))
view.parent.Render()
} else {
debug.Print("Event ID received:", eventID)
roomView.MessageView().UpdateMessageID(tempMessage, eventID)
}
}
func (view *MainView) ShowBare(roomView *RoomView) {
if roomView == nil {
return
@ -204,7 +162,7 @@ func (view *MainView) ShowBare(roomView *RoomView) {
fmt.Println(roomView.MessageView().CapturePlaintext(height))
fmt.Println("Press enter to return to normal mode.")
reader := bufio.NewReader(os.Stdin)
reader.ReadRune()
_, _, _ = reader.ReadRune()
print("\033[2J\033[0;0H")
})
}
@ -310,7 +268,6 @@ func (view *MainView) SwitchRoom(tag string, room *rooms.Room) {
func (view *MainView) addRoomPage(room *rooms.Room) {
if _, ok := view.rooms[room.ID]; !ok {
roomView := NewRoomView(view, room).
SetInputSubmitFunc(view.InputSubmit).
SetInputChangedFunc(view.InputChanged)
view.rooms[room.ID] = roomView
roomView.UpdateUserList()
@ -428,8 +385,8 @@ func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, shoul
sendNotification(room, message.NotificationSenderName(), message.NotificationContent(), should.Highlight, shouldPlaySound)
}
// TODO Make sure this happens somewhere else
//message.SetIsHighlight(should.Highlight)
// TODO this should probably happen somewhere else
message.SetIsHighlight(should.Highlight)
}
func (view *MainView) InitialSyncDone() {
@ -443,15 +400,16 @@ func (view *MainView) InitialSyncDone() {
func (view *MainView) LoadHistory(room string) {
defer debug.Recover()
roomView := view.rooms[room]
msgView := roomView.MessageView()
batch := roomView.Room.PrevBatch
lockTime := time.Now().Unix() + 1
roomView.Room.LockHistory()
roomView.MessageView().LoadingMessages = true
msgView.LoadingMessages = true
defer func() {
roomView.Room.UnlockHistory()
roomView.MessageView().LoadingMessages = false
msgView.LoadingMessages = false
}()
// There's no clean way to try to lock a mutex, so we just check if we still
@ -468,16 +426,9 @@ func (view *MainView) LoadHistory(room string) {
return
}
for _, evt := range history {
message := roomView.ParseEvent(evt)
if message != nil {
roomView.AddMessage(message, ifc.PrependMessage)
if message := roomView.ParseEvent(evt); message != nil {
msgView.AddMessage(message, PrependMessage)
}
}
// TODO?
/*err = roomView.SaveHistory(view.config.HistoryDir)
if err != nil {
debug.Printf("Failed to save history of %s: %v", roomView.Room.GetTitle(), err)
}*/
view.config.PutRoom(roomView.Room)
view.parent.Render()
}