Misc bugfixes

This commit is contained in:
Tulir Asokan 2018-03-16 16:24:11 +02:00
parent e69e494a52
commit c1bb107fa1
4 changed files with 128 additions and 65 deletions

View File

@ -19,6 +19,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"time" "time"
"maunium.net/go/gomatrix" "maunium.net/go/gomatrix"
@ -130,6 +131,7 @@ func (c *MatrixContainer) Start() {
syncer := c.client.Syncer.(*gomatrix.DefaultSyncer) 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.typing", c.HandleTyping) syncer.OnEventType("m.typing", c.HandleTyping)
for { for {
@ -155,15 +157,32 @@ func (c *MatrixContainer) HandleMessage(evt *gomatrix.Event) {
timestampInt64, _ := timestampNumber.Int64() timestampInt64, _ := timestampNumber.Int64()
timestamp := time.Now() timestamp := time.Now()
if timestampInt64 != 0 { if timestampInt64 != 0 {
timestamp = time.Unix(timestampInt64 / 1000, timestampInt64 % 1000 * 1000) timestamp = time.Unix(timestampInt64/1000, timestampInt64%1000*1000)
} }
c.ui.MainView().AddMessage(evt.RoomID, evt.Sender, message, timestamp) c.ui.MainView().AddMessage(evt.RoomID, evt.Sender, message, timestamp)
} }
func (c *MatrixContainer) HandleMembership(evt *gomatrix.Event) {
if evt.StateKey != nil && *evt.StateKey == c.config.Session.MXID {
membership, _ := evt.Content["membership"].(string)
prevMembership := "leave"
if evt.Unsigned.PrevContent != nil {
prevMembership, _ = evt.Unsigned.PrevContent["membership"].(string)
}
if membership == prevMembership {
return
}
if membership == "join" {
c.ui.MainView().AddRoom(evt.RoomID)
} else if membership == "leave" {
c.ui.MainView().RemoveRoom(evt.RoomID)
}
}
}
func (c *MatrixContainer) HandleTyping(evt *gomatrix.Event) { func (c *MatrixContainer) HandleTyping(evt *gomatrix.Event) {
users := evt.Content["user_ids"].([]interface{}) users := evt.Content["user_ids"].([]interface{})
c.debug.Print(users, "are typing")
strUsers := make([]string, len(users)) strUsers := make([]string, len(users))
for i, user := range users { for i, user := range users {
@ -173,11 +192,13 @@ func (c *MatrixContainer) HandleTyping(evt *gomatrix.Event) {
} }
func (c *MatrixContainer) SendMessage(roomID, message string) { func (c *MatrixContainer) SendMessage(roomID, message string) {
c.gmx.Recover()
c.SendTyping(roomID, false) c.SendTyping(roomID, false)
c.client.SendText(roomID, message) c.client.SendText(roomID, message)
} }
func (c *MatrixContainer) SendTyping(roomID string, typing bool) { func (c *MatrixContainer) SendTyping(roomID string, typing bool) {
c.gmx.Recover()
time := time.Now().Unix() time := time.Now().Unix()
if c.typing > time && typing { if c.typing > time && typing {
return return
@ -192,7 +213,26 @@ func (c *MatrixContainer) SendTyping(roomID string, typing bool) {
} }
} }
func (c *MatrixContainer) GetState(roomID string) []*gomatrix.Event { func (c *MatrixContainer) JoinRoom(roomID string) error {
if len(roomID) == 0 {
return fmt.Errorf("invalid room ID")
}
server := ""
if roomID[0] == '!' {
server = roomID[strings.Index(roomID, ":")+1:]
}
resp, err := c.client.JoinRoom(roomID, server, nil)
if err != nil {
return err
}
c.ui.MainView().AddRoom(resp.RoomID)
return nil
}
func (c *MatrixContainer) getState(roomID string) []*gomatrix.Event {
content := make([]*gomatrix.Event, 0) content := make([]*gomatrix.Event, 0)
err := c.client.StateEvent(roomID, "", "", &content) err := c.client.StateEvent(roomID, "", "", &content)
if err != nil { if err != nil {
@ -202,15 +242,15 @@ func (c *MatrixContainer) GetState(roomID string) []*gomatrix.Event {
return content return content
} }
func (c *MatrixContainer) UpdateState(roomID string) { func (c *MatrixContainer) GetRoom(roomID string) *gomatrix.Room {
room := c.client.Store.LoadRoom(roomID) room := c.client.Store.LoadRoom(roomID)
if room == nil { if len(room.State) == 0 {
return events := c.getState(room.ID)
} if events != nil {
events := c.GetState(room.ID) for _, event := range events {
if events != nil { room.UpdateState(event)
for _, event := range events { }
room.UpdateState(event)
} }
} }
return room
} }

View File

@ -20,11 +20,11 @@ import (
"fmt" "fmt"
"hash/fnv" "hash/fnv"
"regexp" "regexp"
"sort"
"strings" "strings"
"time" "time"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"maunium.net/go/gomatrix"
"maunium.net/go/tview" "maunium.net/go/tview"
) )
@ -35,7 +35,7 @@ type RoomView struct {
content *tview.TextView content *tview.TextView
status *tview.TextView status *tview.TextView
userList *tview.TextView userList *tview.TextView
users sort.StringSlice room *gomatrix.Room
} }
var colorNames []string var colorNames []string
@ -49,16 +49,17 @@ func init() {
} }
} }
func NewRoomView(topic string) *RoomView { func NewRoomView(room *gomatrix.Room) *RoomView {
view := &RoomView{ view := &RoomView{
Box: tview.NewBox(), Box: tview.NewBox(),
topic: tview.NewTextView(), topic: tview.NewTextView(),
content: tview.NewTextView(), content: tview.NewTextView(),
status: tview.NewTextView(), status: tview.NewTextView(),
userList: tview.NewTextView(), userList: tview.NewTextView(),
room: room,
} }
view.topic. view.topic.
SetText(strings.Replace(topic, "\n", " ", -1)). SetText(strings.Replace(room.GetTopic(), "\n", " ", -1)).
SetBackgroundColor(tcell.ColorDarkGreen) SetBackgroundColor(tcell.ColorDarkGreen)
view.status.SetBackgroundColor(tcell.ColorDimGray) view.status.SetBackgroundColor(tcell.ColorDimGray)
view.userList.SetDynamicColors(true) view.userList.SetDynamicColors(true)
@ -86,6 +87,12 @@ func (view *RoomView) Draw(screen tcell.Screen) {
} }
func (view *RoomView) SetTyping(users []string) { 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 { if len(users) == 0 {
view.status.SetText("") view.status.SetText("")
} else if len(users) < 2 { } else if len(users) < 2 {
@ -102,7 +109,7 @@ var colorPattern = regexp.MustCompile(`\[([a-zA-Z]+|#[0-9a-zA-Z]{6})\]`)
func color(s string) string { func color(s string) string {
h := fnv.New32a() h := fnv.New32a()
h.Write([]byte(s)) h.Write([]byte(s))
color := colorNames[int(h.Sum32()) % len(colorNames)] color := colorNames[int(h.Sum32())%len(colorNames)]
return fmt.Sprintf("[%s]%s[white]", color, s) return fmt.Sprintf("[%s]%s[white]", color, s)
} }
@ -111,29 +118,21 @@ func escapeColor(s string) string {
} }
func (view *RoomView) AddMessage(sender, message string, timestamp time.Time) { func (view *RoomView) AddMessage(sender, message string, timestamp time.Time) {
member := view.room.GetMember(sender)
if member != nil {
sender = member.DisplayName
}
fmt.Fprintf(view.content, "[%s] %s: %s\n", fmt.Fprintf(view.content, "[%s] %s: %s\n",
timestamp.Format("15:04:05"), color(sender), escapeColor(message)) timestamp.Format("15:04:05"), color(sender), escapeColor(message))
} }
func (view *RoomView) SetUsers(users []string) { func (view *RoomView) UpdateUserList() {
view.users = sort.StringSlice(users)
view.users.Sort()
var buf strings.Builder var buf strings.Builder
for _, user := range view.users { for _, user := range view.room.GetMembers() {
buf.WriteString(color(user)) if user.Membership == "join" {
buf.WriteRune('\n') buf.WriteString(color(user.DisplayName))
buf.WriteRune('\n')
}
} }
view.userList.SetText(buf.String()) view.userList.SetText(buf.String())
} }
func (view *RoomView) RemoveUser(user string) {
i := view.users.Search(user)
if i >= 0 {
view.users = append(view.users[:i], view.users[i+1:]...)
view.userList.SetText(strings.Join(view.users, "\n"))
}
}
func (view *RoomView) AddUser(user string) {
view.SetUsers(append(view.users, user))
}

View File

@ -88,7 +88,7 @@ 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, ok := s.Rooms[mxid]
if !ok || room == nil { if !ok || room == nil {
room := gomatrix.NewRoom(mxid) room = gomatrix.NewRoom(mxid)
s.SaveRoom(room) s.SaveRoom(room)
} }
return room return room

View File

@ -85,9 +85,9 @@ func (ui *GomuksUI) NewMainView() tview.Primitive {
func (view *MainView) InputChanged(text string) { func (view *MainView) InputChanged(text string) {
if len(text) == 0 { if len(text) == 0 {
view.matrix.SendTyping(view.CurrentRoomID(), false) go view.matrix.SendTyping(view.CurrentRoomID(), false)
} else if text[0] != '/' { } else if text[0] != '/' {
view.matrix.SendTyping(view.CurrentRoomID(), true) go view.matrix.SendTyping(view.CurrentRoomID(), true)
} }
} }
@ -100,15 +100,16 @@ func (view *MainView) InputDone(key tcell.Key) {
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:]
view.HandleCommand(room, command, args) go view.HandleCommand(room, command, args)
} else { } else {
view.matrix.SendMessage(room, text) go view.matrix.SendMessage(room, text)
} }
view.input.SetText("") view.input.SetText("")
} }
} }
func (view *MainView) HandleCommand(room, command string, args []string) { func (view *MainView) HandleCommand(room, command string, args []string) {
view.gmx.Recover()
view.debug.Print("Handling command", command, args) view.debug.Print("Handling command", command, args)
switch command { switch command {
case "/quit": case "/quit":
@ -120,6 +121,7 @@ func (view *MainView) HandleCommand(room, command string, args []string) {
view.config.Session.Save() view.config.Session.Save()
view.gmx.Stop() view.gmx.Stop()
case "/part": case "/part":
fallthrough
case "/leave": case "/leave":
view.matrix.client.LeaveRoom(room) view.matrix.client.LeaveRoom(room)
case "/join": case "/join":
@ -127,9 +129,9 @@ func (view *MainView) HandleCommand(room, command string, args []string) {
view.AddMessage(room, "*", "Usage: /join <room>", time.Now()) view.AddMessage(room, "*", "Usage: /join <room>", time.Now())
break break
} }
mxid := args[0] view.debug.Print(view.matrix.JoinRoom(args[0]))
server := mxid[strings.Index(mxid, ":")+1:] default:
view.matrix.client.JoinRoom(mxid, server, nil) view.AddMessage(room, "*", "Unknown command.", time.Now())
} }
} }
@ -165,36 +167,58 @@ func (view *MainView) SwitchRoom(roomIndex int) {
} }
view.currentRoomIndex = roomIndex % len(view.roomIDs) view.currentRoomIndex = roomIndex % len(view.roomIDs)
view.roomView.SwitchToPage(view.CurrentRoomID()) view.roomView.SwitchToPage(view.CurrentRoomID())
view.roomList.SetCurrentItem(roomIndex)
view.parent.Render() view.parent.Render()
} }
func (view *MainView) addRoom(index int, room string) {
roomStore := view.matrix.GetRoom(room)
view.roomList.AddItem(roomStore.GetTitle(), "", 0, func() {
view.SwitchRoom(index)
})
if !view.roomView.HasPage(room) {
roomView := NewRoomView(roomStore)
view.rooms[room] = roomView
view.roomView.AddPage(room, roomView, true, false)
roomView.UpdateUserList()
}
}
func (view *MainView) HasRoom(room string) bool {
for _, existingRoom := range view.roomIDs {
if existingRoom == room {
return true
}
}
return false
}
func (view *MainView) AddRoom(room string) {
if view.HasRoom(room) {
return
}
view.roomIDs = append(view.roomIDs, room)
view.addRoom(len(view.roomIDs) - 1, room)
}
func (view *MainView) RemoveRoom(room string) {
if !view.HasRoom(room) {
return
}
view.roomList.RemoveItem(view.currentRoomIndex)
if view.CurrentRoomID() == room {
view.SwitchRoom(view.currentRoomIndex - 1)
}
view.roomView.RemovePage(room)
}
func (view *MainView) SetRoomList(rooms []string) { func (view *MainView) SetRoomList(rooms []string) {
view.roomIDs = rooms view.roomIDs = rooms
view.roomList.Clear() view.roomList.Clear()
view.roomView.Clear()
for index, room := range rooms { for index, room := range rooms {
localRoomIndex := index view.addRoom(index, room)
view.matrix.UpdateState(room)
roomStore := view.matrix.config.Session.LoadRoom(room)
name := room
topic := ""
var users []string
if roomStore != nil {
name = roomStore.GetTitle()
topic = roomStore.GetTopic()
users = roomStore.GetMembers()
}
view.roomList.AddItem(name, "", 0, func() {
view.SwitchRoom(localRoomIndex)
})
if !view.roomView.HasPage(room) {
roomView := NewRoomView(topic)
roomView.SetUsers(users)
view.rooms[room] = roomView
view.roomView.AddPage(room, roomView, true, false)
}
} }
view.SwitchRoom(0) view.SwitchRoom(0)
} }