aboutsummaryrefslogtreecommitdiff
path: root/ui/widget
diff options
context:
space:
mode:
authorTulir Asokan <tulir@maunium.net>2018-04-09 23:45:54 +0300
committerTulir Asokan <tulir@maunium.net>2018-04-09 23:45:54 +0300
commiteda2b575f06e72040ebf82d24a7ec1ac84b7948c (patch)
treefe02378ebd00443cb675675ddade335ceab25cd1 /ui/widget
parent2ba2fde3966211845b1117c85b27e3c947b6307f (diff)
Refactor UI to use interfaces everywhere
Diffstat (limited to 'ui/widget')
-rw-r--r--ui/widget/message-view.go354
-rw-r--r--ui/widget/room-list.go140
-rw-r--r--ui/widget/room-view.go275
-rw-r--r--ui/widget/util.go14
4 files changed, 7 insertions, 776 deletions
diff --git a/ui/widget/message-view.go b/ui/widget/message-view.go
deleted file mode 100644
index f0bdbad..0000000
--- a/ui/widget/message-view.go
+++ /dev/null
@@ -1,354 +0,0 @@
-// 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 widget
-
-import (
- "encoding/gob"
- "fmt"
- "math"
- "os"
- "time"
-
- "github.com/gdamore/tcell"
- "maunium.net/go/gomuks/ui/debug"
- "maunium.net/go/gomuks/ui/types"
- "maunium.net/go/tview"
-)
-
-type MessageView struct {
- *tview.Box
-
- ScrollOffset int
- MaxSenderWidth int
- DateFormat string
- TimestampFormat string
- TimestampWidth int
- LoadingMessages bool
-
- widestSender int
- prevWidth int
- prevHeight int
- prevMsgCount int
-
- messageIDs map[string]*types.Message
- messages []*types.Message
-
- textBuffer []string
- metaBuffer []types.MessageMeta
-}
-
-func NewMessageView() *MessageView {
- return &MessageView{
- Box: tview.NewBox(),
- MaxSenderWidth: 15,
- DateFormat: "January _2, 2006",
- TimestampFormat: "15:04:05",
- TimestampWidth: 8,
- ScrollOffset: 0,
-
- messages: make([]*types.Message, 0),
- messageIDs: make(map[string]*types.Message),
- textBuffer: make([]string, 0),
- metaBuffer: make([]types.MessageMeta, 0),
-
- widestSender: 5,
- prevWidth: -1,
- prevHeight: -1,
- prevMsgCount: -1,
- }
-}
-
-func (view *MessageView) NewMessage(id, sender, msgtype, text string, timestamp time.Time) *types.Message {
- return types.NewMessage(id, sender, msgtype, text,
- timestamp.Format(view.TimestampFormat),
- timestamp.Format(view.DateFormat),
- GetHashColor(sender))
-}
-
-func (view *MessageView) SaveHistory(path string) error {
- file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600)
- if err != nil {
- return err
- }
- defer file.Close()
-
- enc := gob.NewEncoder(file)
- err = enc.Encode(view.messages)
- if err != nil {
- return err
- }
-
- return nil
-}
-
-func (view *MessageView) LoadHistory(path string) (int, error) {
- file, err := os.OpenFile(path, os.O_RDONLY, 0600)
- if err != nil {
- if os.IsNotExist(err) {
- return 0, nil
- }
- return -1, err
- }
- defer file.Close()
-
- dec := gob.NewDecoder(file)
- err = dec.Decode(&view.messages)
- if err != nil {
- return -1, err
- }
-
- for _, message := range view.messages {
- view.updateWidestSender(message.Sender)
- }
-
- return len(view.messages), nil
-}
-
-func (view *MessageView) updateWidestSender(sender string) {
- if len(sender) > view.widestSender {
- view.widestSender = len(sender)
- if view.widestSender > view.MaxSenderWidth {
- view.widestSender = view.MaxSenderWidth
- }
- }
-}
-
-type MessageDirection int
-
-const (
- AppendMessage MessageDirection = iota
- PrependMessage
- IgnoreMessage
-)
-
-func (view *MessageView) UpdateMessageID(message *types.Message, newID string) {
- delete(view.messageIDs, message.ID)
- message.ID = newID
- view.messageIDs[message.ID] = message
-}
-
-func (view *MessageView) AddMessage(message *types.Message, direction MessageDirection) {
- if message == nil {
- return
- }
-
- msg, messageExists := view.messageIDs[message.ID]
- if msg != nil && messageExists {
- message.CopyTo(msg)
- message = msg
- direction = IgnoreMessage
- }
-
- view.updateWidestSender(message.Sender)
-
- _, _, width, _ := view.GetInnerRect()
- width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
- message.CalculateBuffer(width)
-
- if direction == AppendMessage {
- if view.ScrollOffset > 0 {
- view.ScrollOffset += message.Height()
- }
- view.messages = append(view.messages, message)
- view.appendBuffer(message)
- } else if direction == PrependMessage {
- view.messages = append([]*types.Message{message}, view.messages...)
- }
-
- view.messageIDs[message.ID] = message
-}
-
-func (view *MessageView) appendBuffer(message *types.Message) {
- if len(view.metaBuffer) > 0 {
- prevMeta := view.metaBuffer[len(view.metaBuffer)-1]
- if prevMeta != nil && prevMeta.GetDate() != message.Date {
- view.textBuffer = append(view.textBuffer, fmt.Sprintf("Date changed to %s", message.Date))
- view.metaBuffer = append(view.metaBuffer, &types.BasicMeta{TextColor: tcell.ColorGreen})
- }
- }
-
- view.textBuffer = append(view.textBuffer, message.Buffer()...)
- for range message.Buffer() {
- view.metaBuffer = append(view.metaBuffer, message)
- }
- view.prevMsgCount++
-}
-
-func (view *MessageView) recalculateBuffers() {
- _, _, width, height := view.GetInnerRect()
-
- width -= view.TimestampWidth + TimestampSenderGap + view.widestSender + SenderMessageGap
- recalculateMessageBuffers := width != view.prevWidth
- if height != view.prevHeight || recalculateMessageBuffers || len(view.messages) != view.prevMsgCount {
- view.textBuffer = []string{}
- view.metaBuffer = []types.MessageMeta{}
- view.prevMsgCount = 0
- for _, message := range view.messages {
- if recalculateMessageBuffers {
- message.CalculateBuffer(width)
- }
- view.appendBuffer(message)
- }
- view.prevHeight = height
- view.prevWidth = width
- }
-}
-
-const PaddingAtTop = 5
-
-func (view *MessageView) AddScrollOffset(diff int) {
- _, _, _, height := view.GetInnerRect()
-
- totalHeight := len(view.textBuffer)
- if diff >= 0 && view.ScrollOffset+diff >= totalHeight-height+PaddingAtTop {
- view.ScrollOffset = totalHeight - height + PaddingAtTop
- } else {
- view.ScrollOffset += diff
- }
-
- if view.ScrollOffset > totalHeight-height+PaddingAtTop {
- view.ScrollOffset = totalHeight - height + PaddingAtTop
- }
- if view.ScrollOffset < 0 {
- view.ScrollOffset = 0
- }
-}
-
-func (view *MessageView) Height() int {
- _, _, _, height := view.GetInnerRect()
- return height
-}
-
-func (view *MessageView) TotalHeight() int {
- return len(view.textBuffer)
-}
-
-func (view *MessageView) IsAtTop() bool {
- _, _, _, height := view.GetInnerRect()
- totalHeight := len(view.textBuffer)
- return view.ScrollOffset >= totalHeight-height+PaddingAtTop
-}
-
-const (
- TimestampSenderGap = 1
- SenderSeparatorGap = 1
- SenderMessageGap = 3
-)
-
-func getScrollbarStyle(scrollbarHere, isTop, isBottom bool) (char rune, style tcell.Style) {
- char = '│'
- style = tcell.StyleDefault
- if scrollbarHere {
- style = style.Foreground(tcell.ColorGreen)
- }
- if isTop {
- if scrollbarHere {
- char = '╥'
- } else {
- char = '┬'
- }
- } else if isBottom {
- if scrollbarHere {
- char = '╨'
- } else {
- char = '┴'
- }
- } else if scrollbarHere {
- char = '║'
- }
- return
-}
-
-func (view *MessageView) Draw(screen tcell.Screen) {
- view.Box.Draw(screen)
-
- x, y, _, height := view.GetInnerRect()
- view.recalculateBuffers()
-
- if len(view.textBuffer) == 0 {
- writeLineSimple(screen, "It's quite empty in here.", x, y+height)
- return
- }
-
- usernameX := x + view.TimestampWidth + TimestampSenderGap
- messageX := usernameX + view.widestSender + SenderMessageGap
- separatorX := usernameX + view.widestSender + SenderSeparatorGap
-
- indexOffset := len(view.textBuffer) - view.ScrollOffset - height
- if indexOffset <= -PaddingAtTop {
- message := "Scroll up to load more messages."
- if view.LoadingMessages {
- message = "Loading more messages..."
- }
- writeLineSimpleColor(screen, message, messageX, y, tcell.ColorGreen)
- }
-
- if len(view.textBuffer) != len(view.metaBuffer) {
- debug.ExtPrintf("Unexpected text/meta buffer length mismatch: %d != %d.", len(view.textBuffer), len(view.metaBuffer))
- return
- }
-
- var scrollBarHeight, scrollBarPos int
- // Black magic (aka math) used to figure out where the scroll bar should be put.
- {
- viewportHeight := float64(height)
- contentHeight := float64(len(view.textBuffer))
-
- scrollBarHeight = int(math.Ceil(viewportHeight / (contentHeight / viewportHeight)))
-
- scrollBarPos = height - int(math.Round(float64(view.ScrollOffset)/contentHeight*viewportHeight))
- }
-
- var prevMeta types.MessageMeta
- firstLine := true
- skippedLines := 0
-
- for line := 0; line < height; line++ {
- index := indexOffset + line
- if index < 0 {
- skippedLines++
- continue
- } else if index >= len(view.textBuffer) {
- break
- }
-
- showScrollbar := line-skippedLines >= scrollBarPos-scrollBarHeight && line-skippedLines < scrollBarPos
- isTop := firstLine && view.ScrollOffset+height >= len(view.textBuffer)
- isBottom := line == height-1 && view.ScrollOffset == 0
-
- borderChar, borderStyle := getScrollbarStyle(showScrollbar, isTop, isBottom)
-
- firstLine = false
-
- screen.SetContent(separatorX, y+line, borderChar, nil, borderStyle)
-
- text, meta := view.textBuffer[index], view.metaBuffer[index]
- if meta != prevMeta {
- if len(meta.GetTimestamp()) > 0 {
- writeLineSimpleColor(screen, meta.GetTimestamp(), x, y+line, meta.GetTimestampColor())
- }
- if prevMeta == nil || meta.GetSender() != prevMeta.GetSender() {
- writeLineColor(
- screen, tview.AlignRight, meta.GetSender(),
- usernameX, y+line, view.widestSender,
- meta.GetSenderColor())
- }
- prevMeta = meta
- }
- writeLineSimpleColor(screen, text, messageX, y+line, meta.GetTextColor())
- }
-}
diff --git a/ui/widget/room-list.go b/ui/widget/room-list.go
deleted file mode 100644
index d2fb543..0000000
--- a/ui/widget/room-list.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// 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 widget
-
-import (
- "fmt"
- "strconv"
-
- "github.com/gdamore/tcell"
- "maunium.net/go/gomuks/matrix/rooms"
- "maunium.net/go/tview"
-)
-
-type RoomList struct {
- *tview.Box
-
- indices map[*rooms.Room]int
- items []*rooms.Room
- selected *rooms.Room
-
- // The item main text color.
- mainTextColor tcell.Color
- // The text color for selected items.
- selectedTextColor tcell.Color
- // The background color for selected items.
- selectedBackgroundColor tcell.Color
-}
-
-func NewRoomList() *RoomList {
- return &RoomList{
- Box: tview.NewBox(),
- indices: make(map[*rooms.Room]int),
- items: []*rooms.Room{},
-
- mainTextColor: tcell.ColorWhite,
- selectedTextColor: tcell.ColorWhite,
- selectedBackgroundColor: tcell.ColorDarkGreen,
- }
-}
-
-func (list *RoomList) Add(room *rooms.Room) {
- list.indices[room] = len(list.items)
- list.items = append(list.items, room)
- if list.selected == nil {
- list.selected = room
- }
-}
-
-func (list *RoomList) Remove(room *rooms.Room) {
- index, ok := list.indices[room]
- if !ok {
- return
- }
- delete(list.indices, room)
- list.items = append(list.items[0:index], list.items[index+1:]...)
- if len(list.items) == 0 {
- list.selected = nil
- }
-}
-
-func (list *RoomList) Clear() {
- list.indices = make(map[*rooms.Room]int)
- list.items = []*rooms.Room{}
- list.selected = nil
-}
-
-func (list *RoomList) SetSelected(room *rooms.Room) {
- list.selected = room
-}
-
-// Draw draws this primitive onto the screen.
-func (list *RoomList) Draw(screen tcell.Screen) {
- list.Box.Draw(screen)
-
- x, y, width, height := list.GetInnerRect()
- bottomLimit := y + height
-
- var offset int
- currentItemIndex, hasSelected := list.indices[list.selected]
- if hasSelected && currentItemIndex >= height {
- offset = currentItemIndex + 1 - height
- }
-
- // Draw the list items.
- for index, item := range list.items {
- if index < offset {
- continue
- }
-
- if y >= bottomLimit {
- break
- }
-
- text := item.GetTitle()
-
- lineWidth := width
-
- style := tcell.StyleDefault.Foreground(list.mainTextColor)
- if item == list.selected {
- style = style.Foreground(list.selectedTextColor).Background(list.selectedBackgroundColor)
- }
- if item.HasNewMessages {
- style = style.Bold(true)
- }
-
- if item.UnreadMessages > 0 {
- unreadMessageCount := "99+"
- if item.UnreadMessages < 100 {
- unreadMessageCount = strconv.Itoa(item.UnreadMessages)
- }
- if item.Highlighted {
- unreadMessageCount += "!"
- }
- unreadMessageCount = fmt.Sprintf("(%s)", unreadMessageCount)
- writeLine(screen, tview.AlignRight, unreadMessageCount, x+lineWidth-6, y, 6, style)
- lineWidth -= len(unreadMessageCount) + 1
- }
-
- writeLine(screen, tview.AlignLeft, text, x, y, lineWidth, style)
-
- y++
- if y >= bottomLimit {
- break
- }
- }
-}
diff --git a/ui/widget/room-view.go b/ui/widget/room-view.go
deleted file mode 100644
index 4bab779..0000000
--- a/ui/widget/room-view.go
+++ /dev/null
@@ -1,275 +0,0 @@
-// 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 widget
-
-import (
- "fmt"
- "path/filepath"
- "strconv"
- "strings"
- "time"
-
- "github.com/gdamore/tcell"
- "maunium.net/go/gomuks/matrix/rooms"
- "maunium.net/go/gomuks/ui/types"
- "maunium.net/go/tview"
-)
-
-type RoomView struct {
- *tview.Box
-
- topic *tview.TextView
- content *MessageView
- status *tview.TextView
- userList *tview.TextView
- ulBorder *Border
- input *AdvancedInputField
- Room *rooms.Room
-}
-
-func NewRoomView(room *rooms.Room) *RoomView {
- view := &RoomView{
- Box: tview.NewBox(),
- topic: tview.NewTextView(),
- content: NewMessageView(),
- status: tview.NewTextView(),
- userList: tview.NewTextView(),
- ulBorder: NewBorder(),
- input: NewAdvancedInputField(),
- Room: room,
- }
-
- view.input.
- SetFieldBackgroundColor(tcell.ColorDefault).
- SetPlaceholder("Send a message...").
- SetPlaceholderExtColor(tcell.ColorGray)
-
- view.topic.
- SetText(strings.Replace(room.GetTopic(), "\n", " ", -1)).
- SetBackgroundColor(tcell.ColorDarkGreen)
-
- view.status.SetBackgroundColor(tcell.ColorDimGray)
-
- view.userList.
- SetDynamicColors(true).
- SetWrap(false)
-
- return view
-}
-
-func (view *RoomView) logPath(dir string) string {
- return filepath.Join(dir, fmt.Sprintf("%s.gmxlog", view.Room.ID))
-}
-
-func (view *RoomView) SaveHistory(dir string) error {
- return view.MessageView().SaveHistory(view.logPath(dir))
-}
-
-func (view *RoomView) LoadHistory(dir string) (int, error) {
- return view.MessageView().LoadHistory(view.logPath(dir))
-}
-
-func (view *RoomView) SetTabCompleteFunc(fn func(room *RoomView, text string, cursorOffset int) string) *RoomView {
- view.input.SetTabCompleteFunc(func(text string, cursorOffset int) string {
- return fn(view, text, cursorOffset)
- })
- return view
-}
-
-func (view *RoomView) SetInputCapture(fn func(room *RoomView, event *tcell.EventKey) *tcell.EventKey) *RoomView {
- view.input.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
- return fn(view, event)
- })
- return view
-}
-
-func (view *RoomView) SetMouseCapture(fn func(room *RoomView, event *tcell.EventMouse) *tcell.EventMouse) *RoomView {
- view.input.SetMouseCapture(func(event *tcell.EventMouse) *tcell.EventMouse {
- return fn(view, event)
- })
- return view
-}
-
-func (view *RoomView) SetInputSubmitFunc(fn func(room *RoomView, text string)) *RoomView {
- view.input.SetDoneFunc(func(key tcell.Key) {
- if key == tcell.KeyEnter {
- fn(view, view.input.GetText())
- }
- })
- return view
-}
-
-func (view *RoomView) SetInputChangedFunc(fn func(room *RoomView, text string)) *RoomView {
- view.input.SetChangedFunc(func(text string) {
- fn(view, text)
- })
- return view
-}
-
-func (view *RoomView) SetInputText(newText string) *RoomView {
- view.input.SetText(newText)
- return view
-}
-
-func (view *RoomView) GetInputText() string {
- return view.input.GetText()
-}
-
-func (view *RoomView) GetInputField() *AdvancedInputField {
- return view.input
-}
-
-func (view *RoomView) Focus(delegate func(p tview.Primitive)) {
- delegate(view.input)
-}
-
-// Constants defining the size of the room view grid.
-const (
- UserListBorderWidth = 1
- UserListWidth = 20
- StaticHorizontalSpace = UserListBorderWidth + UserListWidth
-
- TopicBarHeight = 1
- StatusBarHeight = 1
- InputBarHeight = 1
- StaticVerticalSpace = TopicBarHeight + StatusBarHeight + InputBarHeight
-)
-
-func (view *RoomView) Draw(screen tcell.Screen) {
- x, y, width, height := view.GetInnerRect()
- if width <= 0 || height <= 0 {
- return
- }
-
- // Calculate actual grid based on view rectangle and constants defined above.
- var (
- contentHeight = height - StaticVerticalSpace
- contentWidth = width - StaticHorizontalSpace
-
- userListBorderColumn = x + contentWidth
- userListColumn = userListBorderColumn + UserListBorderWidth
-
- topicRow = y
- contentRow = topicRow + TopicBarHeight
- statusRow = contentRow + contentHeight
- inputRow = statusRow + StatusBarHeight
- )
-
- // Update the rectangles of all the children.
- view.topic.SetRect(x, topicRow, width, TopicBarHeight)
- view.content.SetRect(x, contentRow, contentWidth, contentHeight)
- view.status.SetRect(x, statusRow, width, StatusBarHeight)
- if userListColumn > x {
- view.userList.SetRect(userListColumn, contentRow, UserListWidth, contentHeight)
- view.ulBorder.SetRect(userListBorderColumn, contentRow, UserListBorderWidth, contentHeight)
- }
- view.input.SetRect(x, inputRow, width, InputBarHeight)
-
- // Draw everything
- view.Box.Draw(screen)
- view.topic.Draw(screen)
- view.content.Draw(screen)
- view.status.Draw(screen)
- view.input.Draw(screen)
- view.ulBorder.Draw(screen)
- view.userList.Draw(screen)
-}
-
-func (view *RoomView) SetStatus(status string) {
- view.status.SetText(status)
-}
-
-func (view *RoomView) SetTyping(users []string) {
- for index, user := range users {
- member := view.Room.GetMember(user)
- if member != nil {
- users[index] = member.DisplayName
- }
- }
- if len(users) == 0 {
- view.status.SetText("")
- } else if len(users) < 2 {
- view.status.SetText("Typing: " + strings.Join(users, " and "))
- } else {
- view.status.SetText(fmt.Sprintf(
- "Typing: %s and %s",
- strings.Join(users[:len(users)-1], ", "), users[len(users)-1]))
- }
-}
-
-func (view *RoomView) AutocompleteUser(existingText string) (completions []string) {
- textWithoutPrefix := existingText
- if strings.HasPrefix(existingText, "@") {
- textWithoutPrefix = existingText[1:]
- }
- for _, user := range view.Room.GetMembers() {
- if strings.HasPrefix(user.DisplayName, textWithoutPrefix) {
- completions = append(completions, user.DisplayName)
- } else if strings.HasPrefix(user.UserID, existingText) {
- completions = append(completions, user.UserID)
- }
- }
- return
-}
-
-func (view *RoomView) MessageView() *MessageView {
- return view.content
-}
-
-func (view *RoomView) UpdateUserList() {
- var joined strings.Builder
- var invited strings.Builder
- for _, user := range view.Room.GetMembers() {
- if user.Membership == "join" {
- joined.WriteString(AddHashColor(user.DisplayName))
- joined.WriteRune('\n')
- } else if user.Membership == "invite" {
- invited.WriteString(AddHashColor(user.DisplayName))
- invited.WriteRune('\n')
- }
- }
- view.userList.Clear()
- fmt.Fprintf(view.userList, "%s\n", joined.String())
- if invited.Len() > 0 {
- fmt.Fprintf(view.userList, "\nInvited:\n%s", invited.String())
- }
-}
-
-func (view *RoomView) NewMessage(id, sender, msgtype, text string, timestamp time.Time) *types.Message {
- member := view.Room.GetMember(sender)
- if member != nil {
- sender = member.DisplayName
- }
- 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 := ""
- if ownerMember := view.Room.GetSessionOwner(); ownerMember != nil {
- sender = ownerMember.DisplayName
- }
- message := view.NewMessage(id, sender, msgtype, text, now)
- message.State = types.MessageStateSending
- view.AddMessage(message, AppendMessage)
- return message
-}
-
-func (view *RoomView) AddMessage(message *types.Message, direction MessageDirection) {
- view.content.AddMessage(message, direction)
-}
diff --git a/ui/widget/util.go b/ui/widget/util.go
index 0888210..bd80903 100644
--- a/ui/widget/util.go
+++ b/ui/widget/util.go
@@ -22,19 +22,19 @@ import (
"maunium.net/go/tview"
)
-func writeLineSimple(screen tcell.Screen, line string, x, y int) {
- writeLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault)
+func WriteLineSimple(screen tcell.Screen, line string, x, y int) {
+ WriteLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault)
}
-func writeLineSimpleColor(screen tcell.Screen, line string, x, y int, color tcell.Color) {
- writeLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault.Foreground(color))
+func WriteLineSimpleColor(screen tcell.Screen, line string, x, y int, color tcell.Color) {
+ WriteLine(screen, tview.AlignLeft, line, x, y, 1<<30, tcell.StyleDefault.Foreground(color))
}
-func writeLineColor(screen tcell.Screen, align int, line string, x, y, maxWidth int, color tcell.Color) {
- writeLine(screen, align, line, x, y, maxWidth, tcell.StyleDefault.Foreground(color))
+func WriteLineColor(screen tcell.Screen, align int, line string, x, y, maxWidth int, color tcell.Color) {
+ WriteLine(screen, align, line, x, y, maxWidth, tcell.StyleDefault.Foreground(color))
}
-func writeLine(screen tcell.Screen, align int, line string, x, y, maxWidth int, style tcell.Style) {
+func WriteLine(screen tcell.Screen, align int, line string, x, y, maxWidth int, style tcell.Style) {
offsetX := 0
if align == tview.AlignRight {
offsetX = maxWidth - runewidth.StringWidth(line)