aboutsummaryrefslogtreecommitdiff
path: root/ui/types/message.go
blob: e6ded4a0e2bb762e145c3f7e6a210002db47a3e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// 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 types

import (
	"regexp"
	"strings"

	"github.com/gdamore/tcell"
	"github.com/mattn/go-runewidth"
)

type Message struct {
	BasicMeta
	ID              string
	Text            string
	buffer          []string
	prevBufferWidth int
}

func NewMessage(id, sender, text, timestamp, date string, senderColor tcell.Color) *Message {
	return &Message{
		BasicMeta: BasicMeta{
			Sender:         sender,
			Timestamp:      timestamp,
			Date:           date,
			SenderColor:    senderColor,
			TextColor:      tcell.ColorDefault,
			TimestampColor: tcell.ColorDefault,
		},
		Text:            text,
		ID:              id,
		prevBufferWidth: 0,
	}
}

var (
	boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
	spacePattern    = regexp.MustCompile(`\s+`)
)

func (message *Message) CopyTo(to *Message) {
	to.BasicMeta = message.BasicMeta
	to.ID = message.ID
	to.Text = message.Text
	to.RecalculateBuffer()
}

func (message *Message) CalculateBuffer(width int) {
	if width < 2 {
		return
	}
	message.buffer = []string{}
	forcedLinebreaks := strings.Split(message.Text, "\n")
	newlines := 0
	for _, str := range forcedLinebreaks {
		if len(str) == 0 && newlines < 1 {
			message.buffer = append(message.buffer, "")
			newlines++
		} else {
			newlines = 0
		}
		// From tview/textview.go#reindexBuffer()
		for len(str) > 0 {
			extract := runewidth.Truncate(str, width, "")
			if len(extract) < len(str) {
				if spaces := spacePattern.FindStringIndex(str[len(extract):]); spaces != nil && spaces[0] == 0 {
					extract = str[:len(extract)+spaces[1]]
				}

				matches := boundaryPattern.FindAllStringIndex(extract, -1)
				if len(matches) > 0 {
					extract = extract[:matches[len(matches)-1][1]]
				}
			}
			message.buffer = append(message.buffer, extract)
			str = str[len(extract):]
		}
	}
	message.prevBufferWidth = width
}

func (message *Message) RecalculateBuffer() {
	message.CalculateBuffer(message.prevBufferWidth)
}

func (message *Message) Buffer() []string {
	return message.buffer
}

func (message *Message) Height() int {
	return len(message.buffer)
}