Add support for m.emote. Fixes #6
This commit is contained in:
parent
702a75a8c0
commit
152b89ed5e
@ -28,7 +28,7 @@ type MatrixContainer interface {
|
|||||||
Login(user, password string) error
|
Login(user, password string) error
|
||||||
Start()
|
Start()
|
||||||
Stop()
|
Stop()
|
||||||
SendMessage(roomID, message string) (string, error)
|
SendMessage(roomID, msgtype, message string) (string, error)
|
||||||
SendTyping(roomID string, typing bool)
|
SendTyping(roomID string, typing bool)
|
||||||
JoinRoom(roomID string) error
|
JoinRoom(roomID string) error
|
||||||
LeaveRoom(roomID string) error
|
LeaveRoom(roomID string) error
|
||||||
|
@ -47,7 +47,7 @@ type MainView interface {
|
|||||||
SaveAllHistory()
|
SaveAllHistory()
|
||||||
|
|
||||||
SetTyping(roomID string, users []string)
|
SetTyping(roomID string, users []string)
|
||||||
AddServiceMessage(roomID string, message string)
|
AddServiceMessage(roomID *widget.RoomView, message string)
|
||||||
ProcessMessageEvent(evt *gomatrix.Event) (*widget.RoomView, *types.Message)
|
ProcessMessageEvent(evt *gomatrix.Event) (*widget.RoomView, *types.Message)
|
||||||
ProcessMembershipEvent(evt *gomatrix.Event, new bool) (*widget.RoomView, *types.Message)
|
ProcessMembershipEvent(evt *gomatrix.Event, new bool) (*widget.RoomView, *types.Message)
|
||||||
}
|
}
|
||||||
|
@ -280,10 +280,11 @@ func (c *Container) HandleTyping(evt *gomatrix.Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SendMessage sends a message with the given text to the given room.
|
// SendMessage sends a message with the given text to the given room.
|
||||||
func (c *Container) SendMessage(roomID, text string) (string, error) {
|
func (c *Container) SendMessage(roomID, msgtype, text string) (string, error) {
|
||||||
defer c.gmx.Recover()
|
defer c.gmx.Recover()
|
||||||
c.SendTyping(roomID, false)
|
c.SendTyping(roomID, false)
|
||||||
resp, err := c.client.SendText(roomID, text)
|
resp, err := c.client.SendMessageEvent(roomID, "m.room.message",
|
||||||
|
gomatrix.TextMessage{MsgType: msgtype, Body: text})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -225,6 +225,11 @@ func (room *Room) GetMember(userID string) *Member {
|
|||||||
return member
|
return member
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSessionOwner returns the Member instance of the user whose session this room was created for.
|
||||||
|
func (room *Room) GetSessionOwner() *Member {
|
||||||
|
return room.GetMember(room.SessionUserID)
|
||||||
|
}
|
||||||
|
|
||||||
// NewRoom creates a new Room with the given ID
|
// NewRoom creates a new Room with the given ID
|
||||||
func NewRoom(roomID, owner string) *Room {
|
func NewRoom(roomID, owner string) *Room {
|
||||||
return &Room{
|
return &Room{
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -26,13 +27,15 @@ import (
|
|||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
BasicMeta
|
BasicMeta
|
||||||
|
Type string
|
||||||
ID string
|
ID string
|
||||||
Text string
|
Text string
|
||||||
|
sending bool
|
||||||
buffer []string
|
buffer []string
|
||||||
prevBufferWidth int
|
prevBufferWidth int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessage(id, sender, text, timestamp, date string, senderColor tcell.Color) *Message {
|
func NewMessage(id, sender, msgtype, text, timestamp, date string, senderColor tcell.Color) *Message {
|
||||||
return &Message{
|
return &Message{
|
||||||
BasicMeta: BasicMeta{
|
BasicMeta: BasicMeta{
|
||||||
Sender: sender,
|
Sender: sender,
|
||||||
@ -42,9 +45,11 @@ func NewMessage(id, sender, text, timestamp, date string, senderColor tcell.Colo
|
|||||||
TextColor: tcell.ColorDefault,
|
TextColor: tcell.ColorDefault,
|
||||||
TimestampColor: tcell.ColorDefault,
|
TimestampColor: tcell.ColorDefault,
|
||||||
},
|
},
|
||||||
|
Type: msgtype,
|
||||||
Text: text,
|
Text: text,
|
||||||
ID: id,
|
ID: id,
|
||||||
prevBufferWidth: 0,
|
prevBufferWidth: 0,
|
||||||
|
sending: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +70,11 @@ func (message *Message) CalculateBuffer(width int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
message.buffer = []string{}
|
message.buffer = []string{}
|
||||||
forcedLinebreaks := strings.Split(message.Text, "\n")
|
text := message.Text
|
||||||
|
if message.Type == "m.emote" {
|
||||||
|
text = fmt.Sprintf("* %s %s", message.Sender, message.Text)
|
||||||
|
}
|
||||||
|
forcedLinebreaks := strings.Split(text, "\n")
|
||||||
newlines := 0
|
newlines := 0
|
||||||
for _, str := range forcedLinebreaks {
|
for _, str := range forcedLinebreaks {
|
||||||
if len(str) == 0 && newlines < 1 {
|
if len(str) == 0 && newlines < 1 {
|
||||||
@ -94,6 +103,22 @@ func (message *Message) CalculateBuffer(width int) {
|
|||||||
message.prevBufferWidth = width
|
message.prevBufferWidth = width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (message *Message) GetDisplaySender() string {
|
||||||
|
if message.sending {
|
||||||
|
return "Sending..."
|
||||||
|
}
|
||||||
|
switch message.Type {
|
||||||
|
case "m.emote":
|
||||||
|
return ""
|
||||||
|
default:
|
||||||
|
return message.Sender
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (message *Message) SetIsSending(sending bool) {
|
||||||
|
message.sending = sending
|
||||||
|
}
|
||||||
|
|
||||||
func (message *Message) RecalculateBuffer() {
|
func (message *Message) RecalculateBuffer() {
|
||||||
message.CalculateBuffer(message.prevBufferWidth)
|
message.CalculateBuffer(message.prevBufferWidth)
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
type MessageMeta interface {
|
type MessageMeta interface {
|
||||||
GetSender() string
|
GetSender() string
|
||||||
|
GetDisplaySender() string
|
||||||
GetSenderColor() tcell.Color
|
GetSenderColor() tcell.Color
|
||||||
GetTextColor() tcell.Color
|
GetTextColor() tcell.Color
|
||||||
GetTimestampColor() tcell.Color
|
GetTimestampColor() tcell.Color
|
||||||
@ -34,6 +35,10 @@ type BasicMeta struct {
|
|||||||
SenderColor, TextColor, TimestampColor tcell.Color
|
SenderColor, TextColor, TimestampColor tcell.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (meta *BasicMeta) GetDisplaySender() string {
|
||||||
|
return meta.Sender
|
||||||
|
}
|
||||||
|
|
||||||
func (meta *BasicMeta) GetSender() string {
|
func (meta *BasicMeta) GetSender() string {
|
||||||
return meta.Sender
|
return meta.Sender
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
@ -123,42 +122,40 @@ func (view *MainView) InputSubmit(roomView *widget.RoomView, text string) {
|
|||||||
args := strings.SplitN(text, " ", 2)
|
args := strings.SplitN(text, " ", 2)
|
||||||
command := strings.ToLower(args[0])
|
command := strings.ToLower(args[0])
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
go view.HandleCommand(roomView.Room.ID, command, args)
|
go view.HandleCommand(roomView, command, args)
|
||||||
} else {
|
} else {
|
||||||
view.SendMessage(roomView.Room.ID, text)
|
view.SendMessage(roomView, text)
|
||||||
}
|
}
|
||||||
roomView.SetInputText("")
|
roomView.SetInputText("")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) SendMessage(room, text string) {
|
func (view *MainView) SendMessage(roomView *widget.RoomView, text string) {
|
||||||
now := time.Now()
|
tempMessage := roomView.NewTempMessage("m.text", text)
|
||||||
roomView := view.GetRoom(room)
|
go view.sendTempMessage(roomView, tempMessage)
|
||||||
tempMessage := roomView.NewMessage(
|
|
||||||
strconv.FormatInt(now.UnixNano(), 10),
|
|
||||||
"Sending...", text, now)
|
|
||||||
tempMessage.TimestampColor = tcell.ColorGray
|
|
||||||
tempMessage.TextColor = tcell.ColorGray
|
|
||||||
tempMessage.SenderColor = tcell.ColorGray
|
|
||||||
roomView.AddMessage(tempMessage, widget.AppendMessage)
|
|
||||||
go func() {
|
|
||||||
defer view.gmx.Recover()
|
|
||||||
eventID, err := view.matrix.SendMessage(room, text)
|
|
||||||
if err != nil {
|
|
||||||
tempMessage.TextColor = tcell.ColorRed
|
|
||||||
tempMessage.TimestampColor = tcell.ColorRed
|
|
||||||
tempMessage.SenderColor = tcell.ColorRed
|
|
||||||
tempMessage.Sender = "Error"
|
|
||||||
roomView.SetStatus(fmt.Sprintf("Failed to send message: %s", err))
|
|
||||||
} else {
|
|
||||||
roomView.MessageView().UpdateMessageID(tempMessage, eventID)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) HandleCommand(room, command string, args []string) {
|
func (view *MainView) sendTempMessage(roomView *widget.RoomView, tempMessage *types.Message) {
|
||||||
|
defer view.gmx.Recover()
|
||||||
|
eventID, err := view.matrix.SendMessage(roomView.Room.ID, tempMessage.Type, tempMessage.Text)
|
||||||
|
if err != nil {
|
||||||
|
tempMessage.TextColor = tcell.ColorRed
|
||||||
|
tempMessage.TimestampColor = tcell.ColorRed
|
||||||
|
tempMessage.SenderColor = tcell.ColorRed
|
||||||
|
tempMessage.Sender = "Error"
|
||||||
|
roomView.SetStatus(fmt.Sprintf("Failed to send message: %s", err))
|
||||||
|
} else {
|
||||||
|
roomView.MessageView().UpdateMessageID(tempMessage, eventID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *MainView) HandleCommand(roomView *widget.RoomView, command string, args []string) {
|
||||||
defer view.gmx.Recover()
|
defer view.gmx.Recover()
|
||||||
debug.Print("Handling command", command, args)
|
debug.Print("Handling command", command, args)
|
||||||
switch command {
|
switch command {
|
||||||
|
case "/me":
|
||||||
|
tempMessage := roomView.NewTempMessage("m.emote", strings.Join(args, " "))
|
||||||
|
go view.sendTempMessage(roomView, tempMessage)
|
||||||
|
view.parent.Render()
|
||||||
case "/quit":
|
case "/quit":
|
||||||
view.gmx.Stop()
|
view.gmx.Stop()
|
||||||
case "/clearcache":
|
case "/clearcache":
|
||||||
@ -169,15 +166,15 @@ func (view *MainView) HandleCommand(room, command string, args []string) {
|
|||||||
case "/part":
|
case "/part":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "/leave":
|
case "/leave":
|
||||||
debug.Print(view.matrix.LeaveRoom(room))
|
debug.Print("Leave room result:", view.matrix.LeaveRoom(roomView.Room.ID))
|
||||||
case "/join":
|
case "/join":
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
view.AddServiceMessage(room, "Usage: /join <room>")
|
view.AddServiceMessage(roomView, "Usage: /join <room>")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
debug.Print(view.matrix.JoinRoom(args[0]))
|
debug.Print("Join room result:", view.matrix.JoinRoom(args[0]))
|
||||||
default:
|
default:
|
||||||
view.AddServiceMessage(room, "Unknown command.")
|
view.AddServiceMessage(roomView, "Unknown command.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,13 +328,12 @@ func (view *MainView) SetTyping(room string, users []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) AddServiceMessage(room, message string) {
|
func (view *MainView) AddServiceMessage(roomView *widget.RoomView, text string) {
|
||||||
roomView, ok := view.rooms[room]
|
message := roomView.NewMessage("", "*", "gomuks.service", text, time.Now())
|
||||||
if ok {
|
message.TextColor = tcell.ColorGray
|
||||||
message := roomView.NewMessage("", "*", message, time.Now())
|
message.SenderColor = tcell.ColorGray
|
||||||
roomView.AddMessage(message, widget.AppendMessage)
|
roomView.AddMessage(message, widget.AppendMessage)
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) LoadMoreHistory(room string) {
|
func (view *MainView) LoadMoreHistory(room string) {
|
||||||
@ -375,7 +371,7 @@ func (view *MainView) LoadHistory(room string, initial bool) {
|
|||||||
debug.Print("Loading history for", room, "starting from", batch, "(initial:", initial, ")")
|
debug.Print("Loading history for", room, "starting from", batch, "(initial:", initial, ")")
|
||||||
history, prevBatch, err := view.matrix.GetHistory(roomView.Room.ID, batch, 50)
|
history, prevBatch, err := view.matrix.GetHistory(roomView.Room.ID, batch, 50)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
view.AddServiceMessage(room, "Failed to fetch history")
|
view.AddServiceMessage(roomView, "Failed to fetch history")
|
||||||
debug.Print("Failed to fetch history for", roomView.Room.ID, err)
|
debug.Print("Failed to fetch history for", roomView.Room.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -404,7 +400,8 @@ func (view *MainView) ProcessMessageEvent(evt *gomatrix.Event) (room *widget.Roo
|
|||||||
room = view.GetRoom(evt.RoomID)
|
room = view.GetRoom(evt.RoomID)
|
||||||
if room != nil {
|
if room != nil {
|
||||||
text, _ := evt.Content["body"].(string)
|
text, _ := evt.Content["body"].(string)
|
||||||
message = room.NewMessage(evt.ID, evt.Sender, text, unixToTime(evt.Timestamp))
|
msgtype, _ := evt.Content["msgtype"].(string)
|
||||||
|
message = room.NewMessage(evt.ID, evt.Sender, msgtype, text, unixToTime(evt.Timestamp))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -452,7 +449,7 @@ func (view *MainView) ProcessMembershipEvent(evt *gomatrix.Event, new bool) (roo
|
|||||||
room = nil
|
room = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
message = room.NewMessage(evt.ID, sender, text, unixToTime(evt.Timestamp))
|
message = room.NewMessage(evt.ID, sender, "m.room.member", text, unixToTime(evt.Timestamp))
|
||||||
message.TextColor = tcell.ColorGreen
|
message.TextColor = tcell.ColorGreen
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -74,8 +74,8 @@ func NewMessageView() *MessageView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MessageView) NewMessage(id, sender, text string, timestamp time.Time) *types.Message {
|
func (view *MessageView) NewMessage(id, sender, msgtype, text string, timestamp time.Time) *types.Message {
|
||||||
return types.NewMessage(id, sender, text,
|
return types.NewMessage(id, sender, msgtype, text,
|
||||||
timestamp.Format(view.TimestampFormat),
|
timestamp.Format(view.TimestampFormat),
|
||||||
timestamp.Format(view.DateFormat),
|
timestamp.Format(view.DateFormat),
|
||||||
GetHashColor(sender))
|
GetHashColor(sender))
|
||||||
@ -151,6 +151,8 @@ func (view *MessageView) AddMessage(message *types.Message, direction MessageDir
|
|||||||
msg, messageExists := view.messageIDs[message.ID]
|
msg, messageExists := view.messageIDs[message.ID]
|
||||||
if msg != nil && messageExists {
|
if msg != nil && messageExists {
|
||||||
message.CopyTo(msg)
|
message.CopyTo(msg)
|
||||||
|
message = msg
|
||||||
|
message.SetIsSending(false)
|
||||||
direction = IgnoreMessage
|
direction = IgnoreMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,9 +340,9 @@ func (view *MessageView) Draw(screen tcell.Screen) {
|
|||||||
if len(meta.GetTimestamp()) > 0 {
|
if len(meta.GetTimestamp()) > 0 {
|
||||||
view.writeLine(screen, meta.GetTimestamp(), x, y+line, meta.GetTimestampColor())
|
view.writeLine(screen, meta.GetTimestamp(), x, y+line, meta.GetTimestampColor())
|
||||||
}
|
}
|
||||||
if len(meta.GetSender()) > 0 && (prevMeta == nil || meta.GetSender() != prevMeta.GetSender()) {
|
if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() {
|
||||||
view.writeLineRight(
|
view.writeLineRight(
|
||||||
screen, meta.GetSender(),
|
screen, meta.GetDisplaySender(),
|
||||||
x+usernameOffsetX, y+line,
|
x+usernameOffsetX, y+line,
|
||||||
view.widestSender, meta.GetSenderColor())
|
view.widestSender, meta.GetSenderColor())
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ package widget
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -239,12 +240,25 @@ func (view *RoomView) UpdateUserList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *RoomView) NewMessage(id, sender, text string, timestamp time.Time) *types.Message {
|
func (view *RoomView) NewMessage(id, sender, msgtype, text string, timestamp time.Time) *types.Message {
|
||||||
member := view.Room.GetMember(sender)
|
member := view.Room.GetMember(sender)
|
||||||
if member != nil {
|
if member != nil {
|
||||||
sender = member.DisplayName
|
sender = member.DisplayName
|
||||||
}
|
}
|
||||||
return view.content.NewMessage(id, sender, text, timestamp)
|
return view.content.NewMessage(id, sender, msgtype, text, timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (view *RoomView) NewTempMessage(msgtype, text string) *types.Message {
|
||||||
|
now := time.Now()
|
||||||
|
id := strconv.FormatInt(now.UnixNano(), 10)
|
||||||
|
sender := view.Room.GetSessionOwner().DisplayName
|
||||||
|
message := view.NewMessage(id, sender, msgtype, text, now)
|
||||||
|
message.SetIsSending(true)
|
||||||
|
message.TimestampColor = tcell.ColorGray
|
||||||
|
message.TextColor = tcell.ColorGray
|
||||||
|
message.SenderColor = tcell.ColorGray
|
||||||
|
view.AddMessage(message, AppendMessage)
|
||||||
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *RoomView) AddMessage(message *types.Message, direction MessageDirection) {
|
func (view *RoomView) AddMessage(message *types.Message, direction MessageDirection) {
|
||||||
|
Loading…
Reference in New Issue
Block a user