Refactoring, right-align users and fix join/leave messages
This commit is contained in:
parent
ba379a1b4a
commit
b0ebb4b9a4
61
matrix.go
61
matrix.go
@ -121,18 +121,19 @@ func (c *MatrixContainer) UpdateRoomList() {
|
|||||||
|
|
||||||
func (c *MatrixContainer) Start() {
|
func (c *MatrixContainer) Start() {
|
||||||
defer c.gmx.Recover()
|
defer c.gmx.Recover()
|
||||||
c.debug.Print("Starting sync...")
|
|
||||||
c.running = true
|
|
||||||
c.ui.SetView(ViewMain)
|
|
||||||
c.client.Store = c.config.Session
|
c.client.Store = c.config.Session
|
||||||
|
|
||||||
c.UpdateRoomList()
|
syncer := gomatrix.NewDefaultSyncer(c.config.Session.MXID, c.config.Session)
|
||||||
|
|
||||||
syncer := c.client.Syncer.(*gomatrix.DefaultSyncer)
|
|
||||||
syncer.OnEventType("m.room.message", c.HandleMessage)
|
syncer.OnEventType("m.room.message", c.HandleMessage)
|
||||||
syncer.OnEventType("m.room.member", c.HandleMembership)
|
syncer.OnEventType("m.room.member", c.HandleMembership)
|
||||||
syncer.OnEventType("m.typing", c.HandleTyping)
|
syncer.OnEventType("m.typing", c.HandleTyping)
|
||||||
|
c.client.Syncer = syncer
|
||||||
|
|
||||||
|
c.UpdateRoomList()
|
||||||
|
|
||||||
|
c.debug.Print("Starting sync...")
|
||||||
|
c.running = true
|
||||||
|
c.ui.SetView(ViewMain)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.stop:
|
case <-c.stop:
|
||||||
@ -152,17 +153,23 @@ func (c *MatrixContainer) Start() {
|
|||||||
func (c *MatrixContainer) HandleMessage(evt *gomatrix.Event) {
|
func (c *MatrixContainer) HandleMessage(evt *gomatrix.Event) {
|
||||||
message, _ := evt.Content["body"].(string)
|
message, _ := evt.Content["body"].(string)
|
||||||
|
|
||||||
timestamp := time.Now()
|
room := c.ui.MainView().GetRoom(evt.RoomID)
|
||||||
if evt.Timestamp != 0 {
|
if room != nil {
|
||||||
timestamp = time.Unix(evt.Timestamp/1000, evt.Timestamp%1000*1000)
|
room.AddMessage(evt.ID, evt.Sender, message, unixToTime(evt.Timestamp))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.ui.MainView().AddRealMessage(evt.RoomID, evt.ID, evt.Sender, message, timestamp)
|
func unixToTime(unix int64) time.Time {
|
||||||
|
timestamp := time.Now()
|
||||||
|
if unix != 0 {
|
||||||
|
timestamp = time.Unix(unix/1000, unix%1000*1000)
|
||||||
|
}
|
||||||
|
return timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MatrixContainer) HandleMembership(evt *gomatrix.Event) {
|
func (c *MatrixContainer) HandleMembership(evt *gomatrix.Event) {
|
||||||
|
membership, _ := evt.Content["membership"].(string)
|
||||||
if evt.StateKey != nil && *evt.StateKey == c.config.Session.MXID {
|
if evt.StateKey != nil && *evt.StateKey == c.config.Session.MXID {
|
||||||
membership, _ := evt.Content["membership"].(string)
|
|
||||||
prevMembership := "leave"
|
prevMembership := "leave"
|
||||||
if evt.Unsigned.PrevContent != nil {
|
if evt.Unsigned.PrevContent != nil {
|
||||||
prevMembership, _ = evt.Unsigned.PrevContent["membership"].(string)
|
prevMembership, _ = evt.Unsigned.PrevContent["membership"].(string)
|
||||||
@ -175,6 +182,34 @@ func (c *MatrixContainer) HandleMembership(evt *gomatrix.Event) {
|
|||||||
} else if membership == "leave" {
|
} else if membership == "leave" {
|
||||||
c.ui.MainView().RemoveRoom(evt.RoomID)
|
c.ui.MainView().RemoveRoom(evt.RoomID)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
room := c.ui.MainView().GetRoom(evt.RoomID)
|
||||||
|
|
||||||
|
// TODO this shouldn't be necessary
|
||||||
|
room.room.UpdateState(evt)
|
||||||
|
|
||||||
|
if room != nil {
|
||||||
|
var message, sender string
|
||||||
|
if membership == "invite" {
|
||||||
|
sender = "---"
|
||||||
|
message = fmt.Sprintf("%s invited %s.", evt.Sender, *evt.StateKey)
|
||||||
|
} else if membership == "join" {
|
||||||
|
sender = "-->"
|
||||||
|
message = fmt.Sprintf("%s joined the room.", *evt.StateKey)
|
||||||
|
} else if membership == "leave" {
|
||||||
|
sender = "<--"
|
||||||
|
if evt.Sender != *evt.StateKey {
|
||||||
|
reason, _ := evt.Content["reason"].(string)
|
||||||
|
message = fmt.Sprintf("%s kicked %s: %s", evt.Sender, *evt.StateKey, reason)
|
||||||
|
} else {
|
||||||
|
message = fmt.Sprintf("%s left the room.", *evt.StateKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
room.UpdateUserList()
|
||||||
|
room.AddMessage(evt.ID, sender, message, unixToTime(evt.Timestamp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +275,8 @@ func (c *MatrixContainer) getState(roomID string) []*gomatrix.Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *MatrixContainer) GetRoom(roomID string) *gomatrix.Room {
|
func (c *MatrixContainer) GetRoom(roomID string) *gomatrix.Room {
|
||||||
room := c.client.Store.LoadRoom(roomID)
|
room := c.config.Session.LoadRoom(roomID)
|
||||||
if len(room.State) == 0 {
|
if room != nil && len(room.State) == 0 {
|
||||||
events := c.getState(room.ID)
|
events := c.getState(room.ID)
|
||||||
if events != nil {
|
if events != nil {
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
|
@ -93,11 +93,9 @@ type MessageView struct {
|
|||||||
totalHeight int
|
totalHeight int
|
||||||
|
|
||||||
messages []*Message
|
messages []*Message
|
||||||
|
|
||||||
debug DebugPrinter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessageView(debug DebugPrinter) *MessageView {
|
func NewMessageView() *MessageView {
|
||||||
return &MessageView{
|
return &MessageView{
|
||||||
Box: tview.NewBox(),
|
Box: tview.NewBox(),
|
||||||
MaxSenderWidth: 20,
|
MaxSenderWidth: 20,
|
||||||
@ -113,8 +111,6 @@ func NewMessageView(debug DebugPrinter) *MessageView {
|
|||||||
firstDisplayMessage: -1,
|
firstDisplayMessage: -1,
|
||||||
lastDisplayMessage: -1,
|
lastDisplayMessage: -1,
|
||||||
totalHeight: -1,
|
totalHeight: -1,
|
||||||
|
|
||||||
debug: debug,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +203,24 @@ func (view *MessageView) writeLine(screen tcell.Screen, line string, x, y int, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *MessageView) writeLineRight(screen tcell.Screen, line string, x, y, maxWidth int, color tcell.Color) {
|
||||||
|
offsetX := maxWidth - runewidth.StringWidth(line)
|
||||||
|
if offsetX < 0 {
|
||||||
|
offsetX = 0
|
||||||
|
}
|
||||||
|
for _, ch := range line {
|
||||||
|
chWidth := runewidth.RuneWidth(ch)
|
||||||
|
if chWidth == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for localOffset := 0; localOffset < chWidth; localOffset++ {
|
||||||
|
screen.SetContent(x+offsetX+localOffset, y, ch, nil, tcell.StyleDefault.Foreground(color))
|
||||||
|
}
|
||||||
|
offsetX += chWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TimestampSenderGap = 1
|
TimestampSenderGap = 1
|
||||||
SenderSeparatorGap = 1
|
SenderSeparatorGap = 1
|
||||||
@ -246,7 +260,9 @@ func (view *MessageView) Draw(screen tcell.Screen) {
|
|||||||
}
|
}
|
||||||
view.writeLine(screen, message.Timestamp, x, senderAtLine, tcell.ColorDefault)
|
view.writeLine(screen, message.Timestamp, x, senderAtLine, tcell.ColorDefault)
|
||||||
if message.RenderSender || i == view.lastDisplayMessage {
|
if message.RenderSender || i == view.lastDisplayMessage {
|
||||||
view.writeLine(screen, message.Sender, x+usernameOffsetX, senderAtLine, message.senderColor)
|
view.writeLineRight(screen, message.Sender,
|
||||||
|
x+usernameOffsetX, senderAtLine,
|
||||||
|
view.widestSender, message.senderColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
for num, line := range message.buffer {
|
for num, line := range message.buffer {
|
||||||
|
64
room-view.go
64
room-view.go
@ -21,6 +21,7 @@ import (
|
|||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"maunium.net/go/gomatrix"
|
"maunium.net/go/gomatrix"
|
||||||
@ -36,7 +37,7 @@ type RoomView struct {
|
|||||||
userList *tview.TextView
|
userList *tview.TextView
|
||||||
room *gomatrix.Room
|
room *gomatrix.Room
|
||||||
|
|
||||||
debug DebugPrinter
|
parent *MainView
|
||||||
}
|
}
|
||||||
|
|
||||||
var colorNames []string
|
var colorNames []string
|
||||||
@ -51,15 +52,15 @@ func init() {
|
|||||||
sort.Sort(sort.StringSlice(colorNames))
|
sort.Sort(sort.StringSlice(colorNames))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRoomView(debug DebugPrinter, room *gomatrix.Room) *RoomView {
|
func NewRoomView(parent *MainView, room *gomatrix.Room) *RoomView {
|
||||||
view := &RoomView{
|
view := &RoomView{
|
||||||
Box: tview.NewBox(),
|
Box: tview.NewBox(),
|
||||||
topic: tview.NewTextView(),
|
topic: tview.NewTextView(),
|
||||||
content: NewMessageView(debug),
|
content: NewMessageView(),
|
||||||
status: tview.NewTextView(),
|
status: tview.NewTextView(),
|
||||||
userList: tview.NewTextView(),
|
userList: tview.NewTextView(),
|
||||||
room: room,
|
room: room,
|
||||||
debug: debug,
|
parent: parent,
|
||||||
}
|
}
|
||||||
view.topic.
|
view.topic.
|
||||||
SetText(strings.Replace(room.GetTopic(), "\n", " ", -1)).
|
SetText(strings.Replace(room.GetTopic(), "\n", " ", -1)).
|
||||||
@ -108,20 +109,38 @@ func (view *RoomView) SetTyping(users []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *RoomView) AutocompleteUser(existingText string) (completions []string) {
|
||||||
|
for _, user := range view.room.GetMembers() {
|
||||||
|
if strings.HasPrefix(user.DisplayName, existingText) {
|
||||||
|
completions = append(completions, user.DisplayName)
|
||||||
|
} else if strings.HasPrefix(user.UserID, existingText) {
|
||||||
|
completions = append(completions, user.UserID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (view *RoomView) MessageView() *MessageView {
|
func (view *RoomView) MessageView() *MessageView {
|
||||||
return view.content
|
return view.content
|
||||||
}
|
}
|
||||||
|
|
||||||
func getColorName(s string) string {
|
func getColorName(s string) string {
|
||||||
h := fnv.New32a()
|
switch s {
|
||||||
h.Write([]byte(s))
|
case "-->":
|
||||||
return colorNames[int(h.Sum32())%len(colorNames)]
|
return "green"
|
||||||
|
case "<--":
|
||||||
|
return "red"
|
||||||
|
case "---":
|
||||||
|
return "yellow"
|
||||||
|
default:
|
||||||
|
h := fnv.New32a()
|
||||||
|
h.Write([]byte(s))
|
||||||
|
return colorNames[int(h.Sum32())%len(colorNames)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getColor(s string) tcell.Color {
|
func getColor(s string) tcell.Color {
|
||||||
h := fnv.New32a()
|
return tcell.ColorNames[getColorName(s)]
|
||||||
h.Write([]byte(s))
|
|
||||||
return tcell.ColorNames[colorNames[int(h.Sum32())%len(colorNames)]]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func color(s string) string {
|
func color(s string) string {
|
||||||
@ -129,12 +148,29 @@ func color(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *RoomView) UpdateUserList() {
|
func (view *RoomView) UpdateUserList() {
|
||||||
var buf strings.Builder
|
var joined strings.Builder
|
||||||
|
var invited strings.Builder
|
||||||
for _, user := range view.room.GetMembers() {
|
for _, user := range view.room.GetMembers() {
|
||||||
if user.Membership == "join" {
|
if user.Membership == "join" {
|
||||||
buf.WriteString(color(user.DisplayName))
|
joined.WriteString(color(user.DisplayName))
|
||||||
buf.WriteRune('\n')
|
joined.WriteRune('\n')
|
||||||
|
} else if user.Membership == "invite" {
|
||||||
|
invited.WriteString(color(user.DisplayName))
|
||||||
|
invited.WriteRune('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view.userList.SetText(buf.String())
|
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) AddMessage(id, sender, message string, timestamp time.Time) {
|
||||||
|
member := view.room.GetMember(sender)
|
||||||
|
if member != nil {
|
||||||
|
sender = member.DisplayName
|
||||||
|
}
|
||||||
|
view.content.AddMessage(id, sender, message, timestamp)
|
||||||
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,8 @@ func (s *Session) LoadNextBatch(_ string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) LoadRoom(mxid string) *gomatrix.Room {
|
func (s *Session) LoadRoom(mxid string) *gomatrix.Room {
|
||||||
room, ok := s.Rooms[mxid]
|
room, _ := s.Rooms[mxid]
|
||||||
if !ok || room == nil {
|
if room == nil {
|
||||||
room = gomatrix.NewRoom(mxid)
|
room = gomatrix.NewRoom(mxid)
|
||||||
s.SaveRoom(room)
|
s.SaveRoom(room)
|
||||||
}
|
}
|
||||||
|
27
view-main.go
27
view-main.go
@ -111,15 +111,8 @@ func findWordToTabComplete(text string) string {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *RoomView) AutocompleteUser(existingText string) (completions []string) {
|
func (view *MainView) GetRoom(id string) *RoomView {
|
||||||
for _, user := range view.room.GetMembers() {
|
return view.rooms[id]
|
||||||
if strings.HasPrefix(user.DisplayName, existingText) {
|
|
||||||
completions = append(completions, user.DisplayName)
|
|
||||||
} else if strings.HasPrefix(user.UserID, existingText) {
|
|
||||||
completions = append(completions, user.UserID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) InputTabComplete(text string, cursorOffset int) string {
|
func (view *MainView) InputTabComplete(text string, cursorOffset int) string {
|
||||||
@ -231,7 +224,7 @@ func (view *MainView) addRoom(index int, room string) {
|
|||||||
view.SwitchRoom(index)
|
view.SwitchRoom(index)
|
||||||
})
|
})
|
||||||
if !view.roomView.HasPage(room) {
|
if !view.roomView.HasPage(room) {
|
||||||
roomView := NewRoomView(view.debug, roomStore)
|
roomView := NewRoomView(view, roomStore)
|
||||||
view.rooms[room] = roomView
|
view.rooms[room] = roomView
|
||||||
view.roomView.AddPage(room, roomView, true, false)
|
view.roomView.AddPage(room, roomView, true, false)
|
||||||
roomView.UpdateUserList()
|
roomView.UpdateUserList()
|
||||||
@ -285,17 +278,13 @@ func (view *MainView) SetTyping(room string, users []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (view *MainView) AddMessage(room, message string) {
|
func (view *MainView) AddMessage(room, message string) {
|
||||||
view.AddRealMessage(room, "", "*", message, time.Now())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (view *MainView) AddRealMessage(room, id, sender, message string, timestamp time.Time) {
|
|
||||||
roomView, ok := view.rooms[room]
|
roomView, ok := view.rooms[room]
|
||||||
if ok {
|
if ok {
|
||||||
member := roomView.room.GetMember(sender)
|
roomView.content.AddMessage("", "*", message, time.Now())
|
||||||
if member != nil {
|
|
||||||
sender = member.DisplayName
|
|
||||||
}
|
|
||||||
roomView.content.AddMessage(id, sender, message, timestamp)
|
|
||||||
view.parent.Render()
|
view.parent.Render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (view *MainView) Render() {
|
||||||
|
view.parent.Render()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user