diff --git a/border.go b/border.go
new file mode 100644
index 0000000..cd0b8a1
--- /dev/null
+++ b/border.go
@@ -0,0 +1,44 @@
+// 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 .
+
+package main
+
+import (
+ "github.com/gdamore/tcell"
+ "maunium.net/go/tview"
+)
+
+type Border struct {
+ *tview.Box
+}
+
+func NewBorder() *Border {
+ return &Border{tview.NewBox()}
+}
+
+func (border *Border) Draw(screen tcell.Screen) {
+ background := tcell.StyleDefault.Background(border.GetBackgroundColor()).Foreground(border.GetBorderColor())
+ x, y, width, height := border.GetRect()
+ if width == 1 {
+ for borderY := y; borderY < y+height; borderY++ {
+ screen.SetContent(x, borderY, tview.GraphicsVertBar, nil, background)
+ }
+ } else if height == 1 {
+ for borderX := x; borderX < x+width; borderX++ {
+ screen.SetContent(borderX, y, tview.GraphicsHoriBar, nil, background)
+ }
+ }
+}
diff --git a/matrix.go b/matrix.go
index c763852..7ef4b06 100644
--- a/matrix.go
+++ b/matrix.go
@@ -162,50 +162,44 @@ func (c *MatrixContainer) HandleTyping(evt *gomatrix.Event) {
}
func (c *MatrixContainer) SendMessage(roomID, message string) {
- c.client.UserTyping(roomID, false, 0)
+ c.SendTyping(roomID, false)
c.client.SendText(roomID, message)
}
-func (c *MatrixContainer) SendTyping(roomID string) {
+func (c *MatrixContainer) SendTyping(roomID string, typing bool) {
time := time.Now().Unix()
- if c.typing > time {
+ if c.typing > time && typing {
return
}
- c.client.UserTyping(roomID, true, 5000)
- c.typing = time + 5000
+ if typing {
+ c.client.UserTyping(roomID, true, 5000)
+ c.typing = time + 5
+ } else {
+ c.client.UserTyping(roomID, false, 0)
+ c.typing = 0
+ }
}
-func (c *MatrixContainer) GetStateEvent(roomID, eventType, stateKey string) *gomatrix.Event {
- content := make(map[string]interface{})
- c.client.StateEvent(roomID, eventType, stateKey, &content)
- if len(content) == 0 {
+func (c *MatrixContainer) GetState(roomID string) []*gomatrix.Event {
+ content := make([]*gomatrix.Event, 0)
+ err := c.client.StateEvent(roomID, "", "", &content)
+ if err != nil {
+ c.debug.Print(err)
return nil
}
- return &gomatrix.Event{
- StateKey: &stateKey,
- Sender: "",
- Type: eventType,
- Timestamp: 0,
- ID: "",
- RoomID: roomID,
- Content: content,
- }
+ return content
}
-func (c *MatrixContainer) GetAndUpdateStateEvent(room *gomatrix.Room, eventType, stateKey string) {
+func (c *MatrixContainer) UpdateState(roomID string) {
+ room := c.client.Store.LoadRoom(roomID)
if room == nil {
return
}
- event := c.GetStateEvent(room.ID, eventType, stateKey)
- if event != nil {
- room.UpdateState(event)
+ events := c.GetState(room.ID)
+ if events != nil {
+ for _, event := range events {
+ room.UpdateState(event)
+ }
}
}
-
-func (c *MatrixContainer) UpdateRoomInfo(roomID string) {
- room := c.client.Store.LoadRoom(roomID)
- c.GetAndUpdateStateEvent(room, "m.room.name", "")
- c.GetAndUpdateStateEvent(room, "m.room.canonical_alias", "")
- c.GetAndUpdateStateEvent(room, "m.room.topic", "")
-}
diff --git a/room-view.go b/room-view.go
new file mode 100644
index 0000000..8e8d9db
--- /dev/null
+++ b/room-view.go
@@ -0,0 +1,104 @@
+// 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 .
+
+package main
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+
+ "github.com/gdamore/tcell"
+ "maunium.net/go/tview"
+)
+
+type RoomView struct {
+ *tview.Box
+
+ topic *tview.TextView
+ content *tview.TextView
+ status *tview.TextView
+ userlist *tview.TextView
+ users sort.StringSlice
+}
+
+func NewRoomView(topic string) *RoomView {
+ view := &RoomView{
+ Box: tview.NewBox(),
+ topic: tview.NewTextView(),
+ content: tview.NewTextView(),
+ status: tview.NewTextView(),
+ userlist: tview.NewTextView(),
+ }
+ view.topic.
+ SetText(strings.Replace(topic, "\n", " ", -1)).
+ SetBackgroundColor(tcell.ColorDarkGreen)
+ view.status.SetBackgroundColor(tcell.ColorDimGray)
+ return view
+}
+
+func (view *RoomView) Draw(screen tcell.Screen) {
+ x, y, width, height := view.GetRect()
+ view.topic.SetRect(x, y, width, 1)
+ view.content.SetRect(x, y+1, width-30, height-2)
+ view.status.SetRect(x, y+height-1, width, 1)
+ view.userlist.SetRect(x+width-29, y+1, 29, height-2)
+
+ view.topic.Draw(screen)
+ view.content.Draw(screen)
+ view.status.Draw(screen)
+
+ borderX := x + width - 30
+ background := tcell.StyleDefault.Background(view.GetBackgroundColor()).Foreground(view.GetBorderColor())
+ for borderY := y + 1; borderY < y+height-1; borderY++ {
+ screen.SetContent(borderX, borderY, tview.GraphicsVertBar, nil, background)
+ }
+ view.userlist.Draw(screen)
+}
+
+func (view *RoomView) SetTyping(users []string) {
+ 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) AddMessage(sender, message string) {
+ fmt.Fprintf(view.content, "<%s> %s\n", sender, message)
+}
+
+func (view *RoomView) SetUsers(users []string) {
+ view.users = sort.StringSlice(users)
+ view.users.Sort()
+ view.userlist.SetText(strings.Join(view.users, "\n"))
+}
+
+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))
+}
diff --git a/view-main.go b/view-main.go
index f23b039..79dd023 100644
--- a/view-main.go
+++ b/view-main.go
@@ -17,7 +17,6 @@
package main
import (
- "fmt"
"strings"
"github.com/gdamore/tcell"
@@ -25,72 +24,6 @@ import (
"maunium.net/go/tview"
)
-type RoomView struct {
- *tview.Box
-
- topic *tview.TextView
- content *tview.TextView
- status *tview.TextView
- userlist *tview.TextView
- name string
-}
-
-func NewRoomView(name, topic string) *RoomView {
- view := &RoomView{
- Box: tview.NewBox(),
- topic: tview.NewTextView(),
- content: tview.NewTextView(),
- status: tview.NewTextView(),
- userlist: tview.NewTextView(),
- name: name,
- }
- view.topic.SetText(topic).SetBackgroundColor(tcell.ColorDarkGreen)
- view.status.SetBackgroundColor(tcell.ColorDimGray)
- view.userlist.SetText("@tulir:maunium.net\n@tulir_test:maunium.net")
- return view
-}
-
-func (view *RoomView) Draw(screen tcell.Screen) {
- x, y, width, height := view.GetRect()
- view.topic.SetRect(x, y, width, 1)
- view.content.SetRect(x, y+1, width-30, height-2)
- view.status.SetRect(x, y+height-1, width,1)
- view.userlist.SetRect(x+width-29, y+1, 29, height - 2)
-
- view.topic.Draw(screen)
- view.content.Draw(screen)
- view.status.Draw(screen)
-
- borderX := x+width-30
- background := tcell.StyleDefault.Background(view.GetBackgroundColor()).Foreground(view.GetBorderColor())
- for borderY := y + 1; borderY < y + height - 1; borderY++ {
- screen.SetContent(borderX, borderY, tview.GraphicsVertBar, nil, background)
- }
- view.userlist.Draw(screen)
-}
-
-type Border struct {
- *tview.Box
-}
-
-func NewBorder() *Border {
- return &Border{tview.NewBox()}
-}
-
-func (border *Border) Draw(screen tcell.Screen) {
- background := tcell.StyleDefault.Background(border.GetBackgroundColor()).Foreground(border.GetBorderColor())
- x, y, width, height := border.GetRect()
- if width == 1 {
- for borderY := y; borderY < y + height; borderY++ {
- screen.SetContent(x, borderY, tview.GraphicsVertBar, nil, background)
- }
- } else if height == 1 {
- for borderX := x; borderX < x + width; borderX++ {
- screen.SetContent(borderX, y, tview.GraphicsHoriBar, nil, background)
- }
- }
-}
-
func (ui *GomuksUI) MakeMainUI() tview.Primitive {
ui.mainView = tview.NewGrid()
ui.mainView.SetColumns(30, 1, 0).SetRows(0, 1)
@@ -106,8 +39,8 @@ func (ui *GomuksUI) MakeMainUI() tview.Primitive {
ui.mainView.AddItem(ui.mainViewRoomView, 0, 2, 1, 1, 0, 0, false)
ui.mainViewInput = tview.NewInputField()
- ui.mainViewInput.SetChangedFunc(func(_ string) {
- ui.matrix.SendTyping(ui.currentRoom())
+ ui.mainViewInput.SetChangedFunc(func(text string) {
+ ui.matrix.SendTyping(ui.currentRoom(), len(text) > 0)
})
ui.mainViewInput.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEnter {
@@ -183,32 +116,24 @@ func (ui *GomuksUI) SetRoomList(rooms []string) {
for index, room := range rooms {
localRoomIndex := index
- ui.matrix.UpdateRoomInfo(room)
+ ui.matrix.UpdateState(room)
roomStore := ui.matrix.config.Session.LoadRoom(room)
name := room
topic := ""
+ var users []string
if roomStore != nil {
- nameEvt := roomStore.GetStateEvent("m.room.title", "")
- if nameEvt != nil {
- name, _ = nameEvt.Content["title"].(string)
- } else {
- nameEvt = roomStore.GetStateEvent("m.room.canonical_alias", "")
- if nameEvt != nil {
- name, _ = nameEvt.Content["alias"].(string)
- }
- }
- topicEvt := roomStore.GetStateEvent("m.room.topic", "")
- if topicEvt != nil {
- topic, _ = topicEvt.Content["topic"].(string)
- topic = strings.Replace(topic, "\n", " ", -1)
- }
+ name = roomStore.GetTitle()
+ topic = roomStore.GetTopic()
+ users = roomStore.GetMembers()
}
+
ui.mainViewRoomList.AddItem(name, "", 0, func() {
ui.SwitchRoom(localRoomIndex)
})
if !ui.mainViewRoomView.HasPage(room) {
- roomView := NewRoomView(name, topic)
+ roomView := NewRoomView(topic)
+ roomView.SetUsers(users)
ui.mainViewRooms[room] = roomView
ui.mainViewRoomView.AddPage(room, roomView, true, false)
}
@@ -234,11 +159,7 @@ func (ui *GomuksUI) SwitchRoom(roomIndex int) {
func (ui *GomuksUI) SetTyping(room string, users ...string) {
roomView, ok := ui.mainViewRooms[room]
if ok {
- if len(users) > 0 {
- roomView.status.SetText("Typing: " + strings.Join(users, ", "))
- } else {
- roomView.status.SetText("")
- }
+ roomView.SetTyping(users)
ui.Render()
}
}
@@ -246,7 +167,7 @@ func (ui *GomuksUI) SetTyping(room string, users ...string) {
func (ui *GomuksUI) Append(room, sender, message string) {
roomView, ok := ui.mainViewRooms[room]
if ok {
- fmt.Fprintf(roomView.content, "<%s> %s\n", sender, message)
+ roomView.AddMessage(sender, message)
ui.Render()
}
}