Unknown changes that possibly fix and/or break things
This commit is contained in:
parent
7e5e802e90
commit
69c163cfe9
@ -119,8 +119,7 @@ type Message interface {
|
|||||||
SetType(msgtype string)
|
SetType(msgtype string)
|
||||||
Type() string
|
Type() string
|
||||||
|
|
||||||
SetText(text string)
|
NotificationContent() string
|
||||||
Text() string
|
|
||||||
|
|
||||||
SetState(state MessageState)
|
SetState(state MessageState)
|
||||||
State() MessageState
|
State() MessageState
|
||||||
|
@ -124,8 +124,8 @@ func (ai *ANSImage) Render() []tstring.TString {
|
|||||||
rows := make([]tstring.TString, ai.h/2)
|
rows := make([]tstring.TString, ai.h/2)
|
||||||
for y := 0; y < ai.h; y += ai.maxprocs {
|
for y := 0; y < ai.h; y += ai.maxprocs {
|
||||||
ch := make(chan renderData, ai.maxprocs)
|
ch := make(chan renderData, ai.maxprocs)
|
||||||
for n, r := 0, y+1; (n <= ai.maxprocs) && (2*r+1 < ai.h); n, r = n+1, y+n+1 {
|
for n, row := 0, y; (n <= ai.maxprocs) && (2*row+1 < ai.h); n, row = n+1, y+n {
|
||||||
go func(r, y int) {
|
go func(row, y int) {
|
||||||
str := make(tstring.TString, ai.w)
|
str := make(tstring.TString, ai.w)
|
||||||
for x := 0; x < ai.w; x++ {
|
for x := 0; x < ai.w; x++ {
|
||||||
topPixel := ai.pixmap[y][x]
|
topPixel := ai.pixmap[y][x]
|
||||||
@ -139,10 +139,10 @@ func (ai *ANSImage) Render() []tstring.TString {
|
|||||||
Style: tcell.StyleDefault.Background(topColor).Foreground(bottomColor),
|
Style: tcell.StyleDefault.Background(topColor).Foreground(bottomColor),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ch <- renderData{row: r, render: str}
|
ch <- renderData{row: row, render: str}
|
||||||
}(r, 2*r)
|
}(row, 2*row)
|
||||||
}
|
}
|
||||||
for n, r := 0, y+1; (n <= ai.maxprocs) && (2*r+1 < ai.h); n, r = n+1, y+n+1 {
|
for n, row := 0, y; (n <= ai.maxprocs) && (2*row+1 < ai.h); n, row = n+1, y+n {
|
||||||
data := <-ch
|
data := <-ch
|
||||||
rows[data.row] = data.render
|
rows[data.row] = data.render
|
||||||
}
|
}
|
||||||
|
@ -265,11 +265,11 @@ func (view *MessageView) HandleClick(x, y int, button tcell.ButtonMask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message := view.metaBuffer[line]
|
message := view.metaBuffer[line]
|
||||||
imageMessage, ok := message.(*messages.UIImageMessage)
|
imageMessage, ok := message.(*messages.ImageMessage)
|
||||||
if !ok {
|
if !ok {
|
||||||
uiMessage, ok := message.(messages.UIMessage)
|
uiMessage, ok := message.(messages.UIMessage)
|
||||||
if ok {
|
if ok {
|
||||||
debug.Print("Message clicked:", uiMessage.Text())
|
debug.Print("Message clicked:", uiMessage.NotificationContent())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
236
ui/messages/base.go
Normal file
236
ui/messages/base.go
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
// gomuks - A terminal Matrix client written in Go.
|
||||||
|
// Copyright (C) 2018 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package messages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/interface"
|
||||||
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
|
"maunium.net/go/tcell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gob.Register(&BaseMessage{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseMessage struct {
|
||||||
|
MsgID string
|
||||||
|
MsgType string
|
||||||
|
MsgSender string
|
||||||
|
MsgSenderColor tcell.Color
|
||||||
|
MsgTimestamp time.Time
|
||||||
|
MsgState ifc.MessageState
|
||||||
|
MsgIsHighlight bool
|
||||||
|
MsgIsService bool
|
||||||
|
buffer []tstring.TString
|
||||||
|
prevBufferWidth int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBaseMessage(id, sender, msgtype string, timestamp time.Time) BaseMessage {
|
||||||
|
return BaseMessage{
|
||||||
|
MsgSender: sender,
|
||||||
|
MsgTimestamp: timestamp,
|
||||||
|
MsgSenderColor: widget.GetHashColor(sender),
|
||||||
|
MsgType: msgtype,
|
||||||
|
MsgID: id,
|
||||||
|
prevBufferWidth: 0,
|
||||||
|
MsgState: ifc.MessageStateDefault,
|
||||||
|
MsgIsHighlight: false,
|
||||||
|
MsgIsService: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) RegisterGomuks(gmx ifc.Gomuks) {}
|
||||||
|
|
||||||
|
// CopyFrom replaces the content of this message object with the content of the given object.
|
||||||
|
func (msg *BaseMessage) CopyFrom(from ifc.MessageMeta) {
|
||||||
|
msg.MsgSender = from.Sender()
|
||||||
|
msg.MsgSenderColor = from.SenderColor()
|
||||||
|
|
||||||
|
fromMsg, ok := from.(UIMessage)
|
||||||
|
if ok {
|
||||||
|
msg.MsgSender = fromMsg.RealSender()
|
||||||
|
msg.MsgID = fromMsg.ID()
|
||||||
|
msg.MsgType = fromMsg.Type()
|
||||||
|
msg.MsgTimestamp = fromMsg.Timestamp()
|
||||||
|
msg.MsgState = fromMsg.State()
|
||||||
|
msg.MsgIsService = fromMsg.IsService()
|
||||||
|
msg.MsgIsHighlight = fromMsg.IsHighlight()
|
||||||
|
msg.buffer = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sender gets the string that should be displayed as the sender of this message.
|
||||||
|
//
|
||||||
|
// If the message is being sent, the sender is "Sending...".
|
||||||
|
// If sending has failed, the sender is "Error".
|
||||||
|
// If the message is an emote, the sender is blank.
|
||||||
|
// In any other case, the sender is the display name of the user who sent the message.
|
||||||
|
func (msg *BaseMessage) Sender() string {
|
||||||
|
switch msg.MsgState {
|
||||||
|
case ifc.MessageStateSending:
|
||||||
|
return "Sending..."
|
||||||
|
case ifc.MessageStateFailed:
|
||||||
|
return "Error"
|
||||||
|
}
|
||||||
|
switch msg.MsgType {
|
||||||
|
case "m.emote":
|
||||||
|
// Emotes don't show a separate sender, it's included in the buffer.
|
||||||
|
return ""
|
||||||
|
default:
|
||||||
|
return msg.MsgSender
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) RealSender() string {
|
||||||
|
return msg.MsgSender
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) getStateSpecificColor() tcell.Color {
|
||||||
|
switch msg.MsgState {
|
||||||
|
case ifc.MessageStateSending:
|
||||||
|
return tcell.ColorGray
|
||||||
|
case ifc.MessageStateFailed:
|
||||||
|
return tcell.ColorRed
|
||||||
|
case ifc.MessageStateDefault:
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
return tcell.ColorDefault
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SenderColor returns the color the name of the sender should be shown in.
|
||||||
|
//
|
||||||
|
// If the message is being sent, the color is gray.
|
||||||
|
// If sending has failed, the color is red.
|
||||||
|
//
|
||||||
|
// In any other case, the color is whatever is specified in the Message struct.
|
||||||
|
// Usually that means it is the hash-based color of the sender (see ui/widget/color.go)
|
||||||
|
func (msg *BaseMessage) SenderColor() tcell.Color {
|
||||||
|
stateColor := msg.getStateSpecificColor()
|
||||||
|
switch {
|
||||||
|
case stateColor != tcell.ColorDefault:
|
||||||
|
return stateColor
|
||||||
|
case msg.MsgIsService:
|
||||||
|
return tcell.ColorGray
|
||||||
|
default:
|
||||||
|
return msg.MsgSenderColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextColor returns the color the actual content of the message should be shown in.
|
||||||
|
func (msg *BaseMessage) TextColor() tcell.Color {
|
||||||
|
stateColor := msg.getStateSpecificColor()
|
||||||
|
switch {
|
||||||
|
case stateColor != tcell.ColorDefault:
|
||||||
|
return stateColor
|
||||||
|
case msg.MsgIsService:
|
||||||
|
fallthrough
|
||||||
|
case msg.MsgType == "m.notice":
|
||||||
|
return tcell.ColorGray
|
||||||
|
case msg.MsgIsHighlight:
|
||||||
|
return tcell.ColorYellow
|
||||||
|
case msg.MsgType == "m.room.member":
|
||||||
|
return tcell.ColorGreen
|
||||||
|
default:
|
||||||
|
return tcell.ColorDefault
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampColor returns the color the timestamp should be shown in.
|
||||||
|
//
|
||||||
|
// As with SenderColor(), messages being sent and messages that failed to be sent are
|
||||||
|
// gray and red respectively.
|
||||||
|
//
|
||||||
|
// However, other messages are the default color instead of a color stored in the struct.
|
||||||
|
func (msg *BaseMessage) TimestampColor() tcell.Color {
|
||||||
|
return msg.getStateSpecificColor()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buffer returns the computed text buffer.
|
||||||
|
//
|
||||||
|
// The buffer contains the text of the message split into lines with a maximum
|
||||||
|
// width of whatever was provided to CalculateBuffer().
|
||||||
|
//
|
||||||
|
// N.B. This will NOT automatically calculate the buffer if it hasn't been
|
||||||
|
// calculated already, as that requires the target width.
|
||||||
|
func (msg *BaseMessage) Buffer() []tstring.TString {
|
||||||
|
return msg.buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height returns the number of rows in the computed buffer (see Buffer()).
|
||||||
|
func (msg *BaseMessage) Height() int {
|
||||||
|
return len(msg.buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timestamp returns the full timestamp when the message was sent.
|
||||||
|
func (msg *BaseMessage) Timestamp() time.Time {
|
||||||
|
return msg.MsgTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatTime returns the formatted time when the message was sent.
|
||||||
|
func (msg *BaseMessage) FormatTime() string {
|
||||||
|
return msg.MsgTimestamp.Format(TimeFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormatDate returns the formatted date when the message was sent.
|
||||||
|
func (msg *BaseMessage) FormatDate() string {
|
||||||
|
return msg.MsgTimestamp.Format(DateFormat)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) ID() string {
|
||||||
|
return msg.MsgID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) SetID(id string) {
|
||||||
|
msg.MsgID = id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) Type() string {
|
||||||
|
return msg.MsgType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) SetType(msgtype string) {
|
||||||
|
msg.MsgType = msgtype
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) State() ifc.MessageState {
|
||||||
|
return msg.MsgState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) SetState(state ifc.MessageState) {
|
||||||
|
msg.MsgState = state
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *BaseMessage) IsHighlight() bool {
|
||||||
|
return msg.MsgIsHighlight
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
@ -22,65 +22,50 @@ import (
|
|||||||
|
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gob.Register(&UITextMessage{})
|
gob.Register(&ExpandedTextMessage{})
|
||||||
gob.Register(&UIExpandedTextMessage{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UIExpandedTextMessage struct {
|
type ExpandedTextMessage struct {
|
||||||
UITextMessage
|
BaseTextMessage
|
||||||
MsgTStringText tstring.TString
|
MsgText tstring.TString
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExpandedTextMessage creates a new UIExpandedTextMessage object with the provided values and the default state.
|
// NewExpandedTextMessage creates a new ExpandedTextMessage object with the provided values and the default state.
|
||||||
func NewExpandedTextMessage(id, sender, msgtype string, text tstring.TString, timestamp time.Time) UIMessage {
|
func NewExpandedTextMessage(id, sender, msgtype string, text tstring.TString, timestamp time.Time) UIMessage {
|
||||||
return &UIExpandedTextMessage{
|
return &ExpandedTextMessage{
|
||||||
UITextMessage{
|
BaseTextMessage: newBaseTextMessage(id, sender, msgtype, timestamp),
|
||||||
MsgSender: sender,
|
MsgText: text,
|
||||||
MsgTimestamp: timestamp,
|
|
||||||
MsgSenderColor: widget.GetHashColor(sender),
|
|
||||||
MsgType: msgtype,
|
|
||||||
MsgText: text.String(),
|
|
||||||
MsgID: id,
|
|
||||||
prevBufferWidth: 0,
|
|
||||||
MsgState: ifc.MessageStateDefault,
|
|
||||||
MsgIsHighlight: false,
|
|
||||||
MsgIsService: false,
|
|
||||||
},
|
|
||||||
text,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UIExpandedTextMessage) GetTStringText() tstring.TString {
|
func (msg *ExpandedTextMessage) GenerateText() tstring.TString {
|
||||||
return msg.MsgTStringText
|
return msg.MsgText
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyFrom replaces the content of this message object with the content of the given object.
|
// CopyFrom replaces the content of this message object with the content of the given object.
|
||||||
func (msg *UIExpandedTextMessage) CopyFrom(from ifc.MessageMeta) {
|
func (msg *ExpandedTextMessage) CopyFrom(from ifc.MessageMeta) {
|
||||||
msg.MsgSender = from.Sender()
|
msg.BaseTextMessage.CopyFrom(from)
|
||||||
msg.MsgSenderColor = from.SenderColor()
|
|
||||||
|
|
||||||
fromMsg, ok := from.(UIMessage)
|
fromExpandedMsg, ok := from.(*ExpandedTextMessage)
|
||||||
if ok {
|
if ok {
|
||||||
msg.MsgSender = fromMsg.RealSender()
|
msg.MsgText = fromExpandedMsg.MsgText
|
||||||
msg.MsgID = fromMsg.ID()
|
|
||||||
msg.MsgType = fromMsg.Type()
|
|
||||||
msg.MsgTimestamp = fromMsg.Timestamp()
|
|
||||||
msg.MsgState = fromMsg.State()
|
|
||||||
msg.MsgIsService = fromMsg.IsService()
|
|
||||||
msg.MsgIsHighlight = fromMsg.IsHighlight()
|
|
||||||
msg.buffer = nil
|
|
||||||
|
|
||||||
fromExpandedMsg, ok := from.(*UIExpandedTextMessage)
|
|
||||||
if ok {
|
|
||||||
msg.MsgTStringText = fromExpandedMsg.MsgTStringText
|
|
||||||
} else {
|
|
||||||
msg.MsgTStringText = tstring.NewColorTString(fromMsg.Text(), from.TextColor())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.RecalculateBuffer()
|
msg.RecalculateBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (msg *ExpandedTextMessage) NotificationContent() string {
|
||||||
|
return msg.MsgText.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ExpandedTextMessage) CalculateBuffer(width int) {
|
||||||
|
msg.BaseTextMessage.calculateBufferWithText(msg.MsgText, width)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
||||||
|
func (msg *ExpandedTextMessage) RecalculateBuffer() {
|
||||||
|
msg.CalculateBuffer(msg.prevBufferWidth)
|
||||||
}
|
}
|
||||||
|
@ -28,16 +28,15 @@ import (
|
|||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/lib/ansimage"
|
"maunium.net/go/gomuks/lib/ansimage"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gob.Register(&UIImageMessage{})
|
gob.Register(&ImageMessage{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type UIImageMessage struct {
|
type ImageMessage struct {
|
||||||
UITextMessage
|
BaseMessage
|
||||||
Homeserver string
|
Homeserver string
|
||||||
FileID string
|
FileID string
|
||||||
data []byte
|
data []byte
|
||||||
@ -45,20 +44,10 @@ type UIImageMessage struct {
|
|||||||
gmx ifc.Gomuks
|
gmx ifc.Gomuks
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImageMessage creates a new UIImageMessage object with the provided values and the default state.
|
// NewImageMessage creates a new ImageMessage object with the provided values and the default state.
|
||||||
func NewImageMessage(gmx ifc.Gomuks, id, sender, msgtype, homeserver, fileID string, data []byte, timestamp time.Time) UIMessage {
|
func NewImageMessage(gmx ifc.Gomuks, id, sender, msgtype, homeserver, fileID string, data []byte, timestamp time.Time) UIMessage {
|
||||||
return &UIImageMessage{
|
return &ImageMessage{
|
||||||
UITextMessage{
|
newBaseMessage(id, sender, msgtype, timestamp),
|
||||||
MsgSender: sender,
|
|
||||||
MsgTimestamp: timestamp,
|
|
||||||
MsgSenderColor: widget.GetHashColor(sender),
|
|
||||||
MsgType: msgtype,
|
|
||||||
MsgID: id,
|
|
||||||
prevBufferWidth: 0,
|
|
||||||
MsgState: ifc.MessageStateDefault,
|
|
||||||
MsgIsHighlight: false,
|
|
||||||
MsgIsService: false,
|
|
||||||
},
|
|
||||||
homeserver,
|
homeserver,
|
||||||
fileID,
|
fileID,
|
||||||
data,
|
data,
|
||||||
@ -66,7 +55,7 @@ func NewImageMessage(gmx ifc.Gomuks, id, sender, msgtype, homeserver, fileID str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UIImageMessage) RegisterGomuks(gmx ifc.Gomuks) {
|
func (msg *ImageMessage) RegisterGomuks(gmx ifc.Gomuks) {
|
||||||
msg.gmx = gmx
|
msg.gmx = gmx
|
||||||
|
|
||||||
debug.Print(len(msg.data), msg.data)
|
debug.Print(len(msg.data), msg.data)
|
||||||
@ -78,7 +67,11 @@ func (msg *UIImageMessage) RegisterGomuks(gmx ifc.Gomuks) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UIImageMessage) updateData() {
|
func (msg *ImageMessage) NotificationContent() string {
|
||||||
|
return "Sent an image"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *ImageMessage) updateData() {
|
||||||
debug.Print("Loading image:", msg.Homeserver, msg.FileID)
|
debug.Print("Loading image:", msg.Homeserver, msg.FileID)
|
||||||
data, _, _, err := msg.gmx.Matrix().Download(fmt.Sprintf("mxc://%s/%s", msg.Homeserver, msg.FileID))
|
data, _, _, err := msg.gmx.Matrix().Download(fmt.Sprintf("mxc://%s/%s", msg.Homeserver, msg.FileID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -88,39 +81,26 @@ func (msg *UIImageMessage) updateData() {
|
|||||||
msg.data = data
|
msg.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UIImageMessage) Path() string {
|
func (msg *ImageMessage) Path() string {
|
||||||
return msg.gmx.Matrix().GetCachePath(msg.Homeserver, msg.FileID)
|
return msg.gmx.Matrix().GetCachePath(msg.Homeserver, msg.FileID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyFrom replaces the content of this message object with the content of the given object.
|
// CopyFrom replaces the content of this message object with the content of the given object.
|
||||||
func (msg *UIImageMessage) CopyFrom(from ifc.MessageMeta) {
|
func (msg *ImageMessage) CopyFrom(from ifc.MessageMeta) {
|
||||||
msg.MsgSender = from.Sender()
|
msg.BaseMessage.CopyFrom(from)
|
||||||
msg.MsgSenderColor = from.SenderColor()
|
|
||||||
|
|
||||||
fromMsg, ok := from.(UIMessage)
|
fromImgMsg, ok := from.(*ImageMessage)
|
||||||
if ok {
|
|
||||||
msg.MsgSender = fromMsg.RealSender()
|
|
||||||
msg.MsgID = fromMsg.ID()
|
|
||||||
msg.MsgType = fromMsg.Type()
|
|
||||||
msg.MsgTimestamp = fromMsg.Timestamp()
|
|
||||||
msg.MsgState = fromMsg.State()
|
|
||||||
msg.MsgIsService = fromMsg.IsService()
|
|
||||||
msg.MsgIsHighlight = fromMsg.IsHighlight()
|
|
||||||
msg.buffer = nil
|
|
||||||
|
|
||||||
fromImgMsg, ok := from.(*UIImageMessage)
|
|
||||||
if ok {
|
if ok {
|
||||||
msg.data = fromImgMsg.data
|
msg.data = fromImgMsg.data
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.RecalculateBuffer()
|
msg.RecalculateBuffer()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalculateBuffer generates the internal buffer for this message that consists
|
// CalculateBuffer generates the internal buffer for this message that consists
|
||||||
// of the text of this message split into lines at most as wide as the width
|
// of the text of this message split into lines at most as wide as the width
|
||||||
// parameter.
|
// parameter.
|
||||||
func (msg *UIImageMessage) CalculateBuffer(width int) {
|
func (msg *ImageMessage) CalculateBuffer(width int) {
|
||||||
if width < 2 {
|
if width < 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -135,3 +115,9 @@ func (msg *UIImageMessage) CalculateBuffer(width int) {
|
|||||||
msg.buffer = image.Render()
|
msg.buffer = image.Render()
|
||||||
msg.prevBufferWidth = width
|
msg.prevBufferWidth = width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
||||||
|
func (msg *ImageMessage) RecalculateBuffer() {
|
||||||
|
msg.CalculateBuffer(msg.prevBufferWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ func ParseMessage(gmx ifc.Gomuks, evt *gomatrix.Event) UIMessage {
|
|||||||
msgtype, _ := evt.Content["msgtype"].(string)
|
msgtype, _ := evt.Content["msgtype"].(string)
|
||||||
ts := unixToTime(evt.Timestamp)
|
ts := unixToTime(evt.Timestamp)
|
||||||
switch msgtype {
|
switch msgtype {
|
||||||
case "m.text", "m.notice":
|
case "m.text", "m.notice", "m.emote":
|
||||||
text, _ := evt.Content["body"].(string)
|
text, _ := evt.Content["body"].(string)
|
||||||
return NewTextMessage(evt.ID, evt.Sender, msgtype, text, ts)
|
return NewTextMessage(evt.ID, evt.Sender, msgtype, text, ts)
|
||||||
case "m.image":
|
case "m.image":
|
||||||
@ -86,7 +86,7 @@ func getMembershipEventContent(evt *gomatrix.Event) (sender string, text tstring
|
|||||||
switch membership {
|
switch membership {
|
||||||
case "invite":
|
case "invite":
|
||||||
sender = "---"
|
sender = "---"
|
||||||
text = tstring.NewColorTString(fmt.Sprintf("%s invited %s.", evt.Sender, displayname), tcell.ColorYellow)
|
text = tstring.NewColorTString(fmt.Sprintf("%s invited %s.", evt.Sender, displayname), tcell.ColorGreen)
|
||||||
text.Colorize(0, len(evt.Sender), widget.GetHashColor(evt.Sender))
|
text.Colorize(0, len(evt.Sender), widget.GetHashColor(evt.Sender))
|
||||||
text.Colorize(len(evt.Sender)+len(" invited "), len(displayname), widget.GetHashColor(displayname))
|
text.Colorize(len(evt.Sender)+len(" invited "), len(displayname), widget.GetHashColor(displayname))
|
||||||
case "join":
|
case "join":
|
||||||
|
84
ui/messages/textbase.go
Normal file
84
ui/messages/textbase.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// gomuks - A terminal Matrix client written in Go.
|
||||||
|
// Copyright (C) 2018 Tulir Asokan
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package messages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/gob"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
gob.Register(BaseTextMessage{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseTextMessage struct {
|
||||||
|
BaseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBaseTextMessage(id, sender, msgtype string, timestamp time.Time) BaseTextMessage {
|
||||||
|
return BaseTextMessage{newBaseMessage(id, sender, msgtype, timestamp)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regular expressions used to split lines when calculating the buffer.
|
||||||
|
//
|
||||||
|
// From tview/textview.go
|
||||||
|
var (
|
||||||
|
boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
|
||||||
|
spacePattern = regexp.MustCompile(`\s+`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// CalculateBuffer generates the internal buffer for this message that consists
|
||||||
|
// of the text of this message split into lines at most as wide as the width
|
||||||
|
// parameter.
|
||||||
|
func (msg *BaseTextMessage) calculateBufferWithText(text tstring.TString, width int) {
|
||||||
|
if width < 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.buffer = []tstring.TString{}
|
||||||
|
|
||||||
|
forcedLinebreaks := text.Split('\n')
|
||||||
|
newlines := 0
|
||||||
|
for _, str := range forcedLinebreaks {
|
||||||
|
if len(str) == 0 && newlines < 1 {
|
||||||
|
msg.buffer = append(msg.buffer, tstring.TString{})
|
||||||
|
newlines++
|
||||||
|
} else {
|
||||||
|
newlines = 0
|
||||||
|
}
|
||||||
|
// Mostly from tview/textview.go#reindexBuffer()
|
||||||
|
for len(str) > 0 {
|
||||||
|
extract := str.Truncate(width)
|
||||||
|
if len(extract) < len(str) {
|
||||||
|
if spaces := spacePattern.FindStringIndex(str[len(extract):].String()); spaces != nil && spaces[0] == 0 {
|
||||||
|
extract = str[:len(extract)+spaces[1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := boundaryPattern.FindAllStringIndex(extract.String(), -1)
|
||||||
|
if len(matches) > 0 {
|
||||||
|
extract = extract[:matches[len(matches)-1][1]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.buffer = append(msg.buffer, extract)
|
||||||
|
str = str[len(extract):]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.prevBufferWidth = width
|
||||||
|
}
|
@ -19,302 +19,84 @@ package messages
|
|||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/interface"
|
"maunium.net/go/gomuks/interface"
|
||||||
"maunium.net/go/gomuks/ui/messages/tstring"
|
"maunium.net/go/gomuks/ui/messages/tstring"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
|
||||||
"maunium.net/go/tcell"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gob.Register(&UITextMessage{})
|
gob.Register(&TextMessage{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type UITextMessage struct {
|
type TextMessage struct {
|
||||||
MsgID string
|
BaseTextMessage
|
||||||
MsgType string
|
cache tstring.TString
|
||||||
MsgSender string
|
|
||||||
MsgSenderColor tcell.Color
|
|
||||||
MsgTimestamp time.Time
|
|
||||||
MsgText string
|
MsgText string
|
||||||
MsgState ifc.MessageState
|
|
||||||
MsgIsHighlight bool
|
|
||||||
MsgIsService bool
|
|
||||||
text tstring.TString
|
|
||||||
buffer []tstring.TString
|
|
||||||
prevBufferWidth int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTextMessage creates a new UITextMessage object with the provided values and the default state.
|
// NewTextMessage creates a new UITextMessage object with the provided values and the default state.
|
||||||
func NewTextMessage(id, sender, msgtype, text string, timestamp time.Time) UIMessage {
|
func NewTextMessage(id, sender, msgtype, text string, timestamp time.Time) UIMessage {
|
||||||
return &UITextMessage{
|
return &TextMessage{
|
||||||
MsgSender: sender,
|
BaseTextMessage: newBaseTextMessage(id, sender, msgtype, timestamp),
|
||||||
MsgTimestamp: timestamp,
|
|
||||||
MsgSenderColor: widget.GetHashColor(sender),
|
|
||||||
MsgType: msgtype,
|
|
||||||
MsgText: text,
|
MsgText: text,
|
||||||
MsgID: id,
|
|
||||||
prevBufferWidth: 0,
|
|
||||||
MsgState: ifc.MessageStateDefault,
|
|
||||||
MsgIsHighlight: false,
|
|
||||||
MsgIsService: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UITextMessage) RegisterGomuks(gmx ifc.Gomuks) {}
|
func (msg *TextMessage) getCache() tstring.TString {
|
||||||
|
if msg.cache == nil {
|
||||||
// CopyFrom replaces the content of this message object with the content of the given object.
|
|
||||||
func (msg *UITextMessage) CopyFrom(from ifc.MessageMeta) {
|
|
||||||
msg.MsgSender = from.Sender()
|
|
||||||
msg.MsgSenderColor = from.SenderColor()
|
|
||||||
|
|
||||||
fromMsg, ok := from.(UIMessage)
|
|
||||||
if ok {
|
|
||||||
msg.MsgSender = fromMsg.RealSender()
|
|
||||||
msg.MsgID = fromMsg.ID()
|
|
||||||
msg.MsgType = fromMsg.Type()
|
|
||||||
msg.MsgTimestamp = fromMsg.Timestamp()
|
|
||||||
msg.MsgText = fromMsg.Text()
|
|
||||||
msg.MsgState = fromMsg.State()
|
|
||||||
msg.MsgIsService = fromMsg.IsService()
|
|
||||||
msg.MsgIsHighlight = fromMsg.IsHighlight()
|
|
||||||
msg.buffer = nil
|
|
||||||
|
|
||||||
msg.RecalculateBuffer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sender gets the string that should be displayed as the sender of this message.
|
|
||||||
//
|
|
||||||
// If the message is being sent, the sender is "Sending...".
|
|
||||||
// If sending has failed, the sender is "Error".
|
|
||||||
// If the message is an emote, the sender is blank.
|
|
||||||
// In any other case, the sender is the display name of the user who sent the message.
|
|
||||||
func (msg *UITextMessage) Sender() string {
|
|
||||||
switch msg.MsgState {
|
|
||||||
case ifc.MessageStateSending:
|
|
||||||
return "Sending..."
|
|
||||||
case ifc.MessageStateFailed:
|
|
||||||
return "Error"
|
|
||||||
}
|
|
||||||
switch msg.MsgType {
|
switch msg.MsgType {
|
||||||
case "m.emote":
|
case "m.emote":
|
||||||
// Emotes don't show a separate sender, it's included in the buffer.
|
msg.cache = tstring.NewColorTString(fmt.Sprintf("* %s %s", msg.MsgSender, msg.MsgText), msg.TextColor())
|
||||||
return ""
|
msg.cache.Colorize(0, len(msg.MsgSender)+2, msg.SenderColor())
|
||||||
default:
|
default:
|
||||||
return msg.MsgSender
|
msg.cache = tstring.NewColorTString(msg.MsgText, msg.TextColor())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) RealSender() string {
|
|
||||||
return msg.MsgSender
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) getStateSpecificColor() tcell.Color {
|
|
||||||
switch msg.MsgState {
|
|
||||||
case ifc.MessageStateSending:
|
|
||||||
return tcell.ColorGray
|
|
||||||
case ifc.MessageStateFailed:
|
|
||||||
return tcell.ColorRed
|
|
||||||
case ifc.MessageStateDefault:
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
return tcell.ColorDefault
|
|
||||||
}
|
}
|
||||||
|
return msg.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderColor returns the color the name of the sender should be shown in.
|
// CopyFrom replaces the content of this message object with the content of the given object.
|
||||||
//
|
func (msg *TextMessage) CopyFrom(from ifc.MessageMeta) {
|
||||||
// If the message is being sent, the color is gray.
|
msg.BaseTextMessage.CopyFrom(from)
|
||||||
// If sending has failed, the color is red.
|
|
||||||
//
|
fromTextMsg, ok := from.(*TextMessage)
|
||||||
// In any other case, the color is whatever is specified in the Message struct.
|
if ok {
|
||||||
// Usually that means it is the hash-based color of the sender (see ui/widget/color.go)
|
msg.MsgText = fromTextMsg.MsgText
|
||||||
func (msg *UITextMessage) SenderColor() tcell.Color {
|
|
||||||
stateColor := msg.getStateSpecificColor()
|
|
||||||
switch {
|
|
||||||
case stateColor != tcell.ColorDefault:
|
|
||||||
return stateColor
|
|
||||||
case msg.MsgIsService:
|
|
||||||
return tcell.ColorGray
|
|
||||||
default:
|
|
||||||
return msg.MsgSenderColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg.cache = nil
|
||||||
|
msg.RecalculateBuffer()
|
||||||
|
}
|
||||||
|
func (msg *TextMessage) SetType(msgtype string) {
|
||||||
|
msg.BaseTextMessage.SetType(msgtype)
|
||||||
|
msg.cache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextColor returns the color the actual content of the message should be shown in.
|
func (msg *TextMessage) SetState(state ifc.MessageState) {
|
||||||
func (msg *UITextMessage) TextColor() tcell.Color {
|
msg.BaseTextMessage.SetState(state)
|
||||||
stateColor := msg.getStateSpecificColor()
|
msg.cache = nil
|
||||||
switch {
|
|
||||||
case stateColor != tcell.ColorDefault:
|
|
||||||
return stateColor
|
|
||||||
case msg.MsgIsService:
|
|
||||||
return tcell.ColorGray
|
|
||||||
case msg.MsgIsHighlight:
|
|
||||||
return tcell.ColorYellow
|
|
||||||
case msg.MsgType == "m.room.member":
|
|
||||||
return tcell.ColorGreen
|
|
||||||
default:
|
|
||||||
return tcell.ColorDefault
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TimestampColor returns the color the timestamp should be shown in.
|
func (msg *TextMessage) SetIsHighlight(isHighlight bool) {
|
||||||
//
|
msg.BaseTextMessage.SetIsHighlight(isHighlight)
|
||||||
// As with SenderColor(), messages being sent and messages that failed to be sent are
|
msg.cache = nil
|
||||||
// gray and red respectively.
|
|
||||||
//
|
|
||||||
// However, other messages are the default color instead of a color stored in the struct.
|
|
||||||
func (msg *UITextMessage) TimestampColor() tcell.Color {
|
|
||||||
return msg.getStateSpecificColor()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
func (msg *TextMessage) SetIsService(isService bool) {
|
||||||
func (msg *UITextMessage) RecalculateBuffer() {
|
msg.BaseTextMessage.SetIsService(isService)
|
||||||
msg.CalculateBuffer(msg.prevBufferWidth)
|
msg.cache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer returns the computed text buffer.
|
func (msg *TextMessage) NotificationContent() string {
|
||||||
//
|
|
||||||
// The buffer contains the text of the message split into lines with a maximum
|
|
||||||
// width of whatever was provided to CalculateBuffer().
|
|
||||||
//
|
|
||||||
// N.B. This will NOT automatically calculate the buffer if it hasn't been
|
|
||||||
// calculated already, as that requires the target width.
|
|
||||||
func (msg *UITextMessage) Buffer() []tstring.TString {
|
|
||||||
return msg.buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Height returns the number of rows in the computed buffer (see Buffer()).
|
|
||||||
func (msg *UITextMessage) Height() int {
|
|
||||||
return len(msg.buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timestamp returns the full timestamp when the message was sent.
|
|
||||||
func (msg *UITextMessage) Timestamp() time.Time {
|
|
||||||
return msg.MsgTimestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatTime returns the formatted time when the message was sent.
|
|
||||||
func (msg *UITextMessage) FormatTime() string {
|
|
||||||
return msg.MsgTimestamp.Format(TimeFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormatDate returns the formatted date when the message was sent.
|
|
||||||
func (msg *UITextMessage) FormatDate() string {
|
|
||||||
return msg.MsgTimestamp.Format(DateFormat)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) ID() string {
|
|
||||||
return msg.MsgID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) SetID(id string) {
|
|
||||||
msg.MsgID = id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) Type() string {
|
|
||||||
return msg.MsgType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) SetType(msgtype string) {
|
|
||||||
msg.MsgType = msgtype
|
|
||||||
msg.text = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) Text() string {
|
|
||||||
return msg.MsgText
|
return msg.MsgText
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UITextMessage) SetText(text string) {
|
func (msg *TextMessage) CalculateBuffer(width int) {
|
||||||
msg.MsgText = text
|
msg.BaseTextMessage.calculateBufferWithText(msg.getCache(), width)
|
||||||
msg.text = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *UITextMessage) State() ifc.MessageState {
|
// RecalculateBuffer calculates the buffer again with the previously provided width.
|
||||||
return msg.MsgState
|
func (msg *TextMessage) RecalculateBuffer() {
|
||||||
}
|
msg.CalculateBuffer(msg.prevBufferWidth)
|
||||||
|
|
||||||
func (msg *UITextMessage) SetState(state ifc.MessageState) {
|
|
||||||
msg.MsgState = state
|
|
||||||
msg.text = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) IsHighlight() bool {
|
|
||||||
return msg.MsgIsHighlight
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) SetIsHighlight(isHighlight bool) {
|
|
||||||
msg.MsgIsHighlight = isHighlight
|
|
||||||
msg.text = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) IsService() bool {
|
|
||||||
return msg.MsgIsService
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) SetIsService(isService bool) {
|
|
||||||
msg.MsgIsService = isService
|
|
||||||
msg.text = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (msg *UITextMessage) GetTStringText() tstring.TString {
|
|
||||||
if msg.text == nil || len(msg.text) == 0 {
|
|
||||||
msg.text = tstring.NewColorTString(msg.Text(), msg.TextColor())
|
|
||||||
}
|
|
||||||
return msg.text
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular expressions used to split lines when calculating the buffer.
|
|
||||||
//
|
|
||||||
// From tview/textview.go
|
|
||||||
var (
|
|
||||||
boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
|
|
||||||
spacePattern = regexp.MustCompile(`\s+`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// CalculateBuffer generates the internal buffer for this message that consists
|
|
||||||
// of the text of this message split into lines at most as wide as the width
|
|
||||||
// parameter.
|
|
||||||
func (msg *UITextMessage) CalculateBuffer(width int) {
|
|
||||||
if width < 2 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.buffer = []tstring.TString{}
|
|
||||||
text := msg.GetTStringText()
|
|
||||||
if msg.MsgType == "m.emote" {
|
|
||||||
text = tstring.NewColorTString(fmt.Sprintf("* %s %s", msg.MsgSender, text.String()), msg.TextColor())
|
|
||||||
text.Colorize(0, len(msg.MsgSender), msg.SenderColor())
|
|
||||||
}
|
|
||||||
|
|
||||||
forcedLinebreaks := text.Split('\n')
|
|
||||||
newlines := 0
|
|
||||||
for _, str := range forcedLinebreaks {
|
|
||||||
if len(str) == 0 && newlines < 1 {
|
|
||||||
msg.buffer = append(msg.buffer, tstring.TString{})
|
|
||||||
newlines++
|
|
||||||
} else {
|
|
||||||
newlines = 0
|
|
||||||
}
|
|
||||||
// Mostly from tview/textview.go#reindexBuffer()
|
|
||||||
for len(str) > 0 {
|
|
||||||
extract := str.Truncate(width)
|
|
||||||
if len(extract) < len(str) {
|
|
||||||
if spaces := spacePattern.FindStringIndex(str[len(extract):].String()); spaces != nil && spaces[0] == 0 {
|
|
||||||
extract = str[:len(extract)+spaces[1]]
|
|
||||||
}
|
|
||||||
|
|
||||||
matches := boundaryPattern.FindAllStringIndex(extract.String(), -1)
|
|
||||||
if len(matches) > 0 {
|
|
||||||
extract = extract[:matches[len(matches)-1][1]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg.buffer = append(msg.buffer, extract)
|
|
||||||
str = str[len(extract):]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg.prevBufferWidth = width
|
|
||||||
}
|
}
|
||||||
|
@ -134,12 +134,12 @@ func (view *MainView) InputSubmit(roomView *RoomView, text string) {
|
|||||||
|
|
||||||
func (view *MainView) SendMessage(roomView *RoomView, text string) {
|
func (view *MainView) SendMessage(roomView *RoomView, text string) {
|
||||||
tempMessage := roomView.NewTempMessage("m.text", text)
|
tempMessage := roomView.NewTempMessage("m.text", text)
|
||||||
go view.sendTempMessage(roomView, tempMessage)
|
go view.sendTempMessage(roomView, tempMessage, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) sendTempMessage(roomView *RoomView, tempMessage ifc.Message) {
|
func (view *MainView) sendTempMessage(roomView *RoomView, tempMessage ifc.Message, text string) {
|
||||||
defer view.gmx.Recover()
|
defer view.gmx.Recover()
|
||||||
eventID, err := view.matrix.SendMessage(roomView.Room.ID, tempMessage.Type(), tempMessage.Text())
|
eventID, err := view.matrix.SendMessage(roomView.Room.ID, tempMessage.Type(), text)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tempMessage.SetState(ifc.MessageStateFailed)
|
tempMessage.SetState(ifc.MessageStateFailed)
|
||||||
roomView.SetStatus(fmt.Sprintf("Failed to send message: %s", err))
|
roomView.SetStatus(fmt.Sprintf("Failed to send message: %s", err))
|
||||||
@ -153,8 +153,9 @@ func (view *MainView) HandleCommand(roomView *RoomView, command string, args []s
|
|||||||
debug.Print("Handling command", command, args)
|
debug.Print("Handling command", command, args)
|
||||||
switch command {
|
switch command {
|
||||||
case "/me":
|
case "/me":
|
||||||
tempMessage := roomView.NewTempMessage("m.emote", strings.Join(args, " "))
|
text := strings.Join(args, " ")
|
||||||
go view.sendTempMessage(roomView, tempMessage)
|
tempMessage := roomView.NewTempMessage("m.emote", text)
|
||||||
|
go view.sendTempMessage(roomView, tempMessage, text)
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
case "/quit":
|
case "/quit":
|
||||||
view.gmx.Stop()
|
view.gmx.Stop()
|
||||||
@ -411,7 +412,7 @@ func (view *MainView) NotifyMessage(room *rooms.Room, message ifc.Message, shoul
|
|||||||
if shouldNotify && !isFocused {
|
if shouldNotify && !isFocused {
|
||||||
// Push rules say notify and the terminal is not focused, send desktop notification.
|
// Push rules say notify and the terminal is not focused, send desktop notification.
|
||||||
shouldPlaySound := should.PlaySound && should.SoundName == "default"
|
shouldPlaySound := should.PlaySound && should.SoundName == "default"
|
||||||
sendNotification(room, message.Sender(), message.Text(), should.Highlight, shouldPlaySound)
|
sendNotification(room, message.Sender(), message.NotificationContent(), should.Highlight, shouldPlaySound)
|
||||||
}
|
}
|
||||||
|
|
||||||
message.SetIsHighlight(should.Highlight)
|
message.SetIsHighlight(should.Highlight)
|
||||||
|
Loading…
Reference in New Issue
Block a user