aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTulir Asokan <tulir@maunium.net>2018-03-13 21:58:43 +0200
committerTulir Asokan <tulir@maunium.net>2018-03-13 21:58:43 +0200
commit90629c5c78916ba9be982afb9b8435ea58be166b (patch)
tree3c1720f695e43e4de8a0f68f0d3c9da65ffd82d1
parentf0333df1b2b6e0ef54a580668cb759a094b56010 (diff)
Code additions/edits
-rw-r--r--config.go26
-rw-r--r--debug.go45
-rw-r--r--gomuks.go120
-rw-r--r--matrix.go74
-rw-r--r--session.go11
-rw-r--r--ui.go71
-rw-r--r--uiutil.go55
-rw-r--r--view-login.go49
-rw-r--r--view-main.go164
9 files changed, 504 insertions, 111 deletions
diff --git a/config.go b/config.go
index 3510e4a..f8696a4 100644
--- a/config.go
+++ b/config.go
@@ -29,14 +29,23 @@ type Config struct {
MXID string `yaml:"mxid"`
HS string `yaml:"homeserver"`
- dir string `yaml:"-"`
- Session *Session `yaml:"-"`
+ dir string `yaml:"-"`
+ gmx Gomuks `yaml:"-"`
+ debug DebugPrinter `yaml:"-"`
+ Session *Session `yaml:"-"`
}
-func (config *Config) Load(dir string) {
- config.dir = dir
- os.MkdirAll(dir, 0700)
- configPath := filepath.Join(dir, "config.yaml")
+func NewConfig(gmx Gomuks, dir string) *Config {
+ return &Config{
+ gmx: gmx,
+ debug: gmx.Debug(),
+ dir: dir,
+ }
+}
+
+func (config *Config) Load() {
+ os.MkdirAll(config.dir, 0700)
+ configPath := filepath.Join(config.dir, "config.yaml")
data, err := ioutil.ReadFile(configPath)
if err != nil {
if os.IsNotExist(err) {
@@ -55,16 +64,17 @@ func (config *Config) Load(dir string) {
}
func (config *Config) Save() {
+ os.MkdirAll(config.dir, 0700)
data, err := yaml.Marshal(&config)
if err != nil {
- debug.Print("Failed to marshal config")
+ config.debug.Print("Failed to marshal config")
panic(err)
}
path := filepath.Join(config.dir, "config.yaml")
err = ioutil.WriteFile(path, data, 0600)
if err != nil {
- debug.Print("Failed to write config to", path)
+ config.debug.Print("Failed to write config to", path)
panic(err)
}
}
diff --git a/debug.go b/debug.go
index 2533d5c..2498f9d 100644
--- a/debug.go
+++ b/debug.go
@@ -22,35 +22,54 @@ import (
"github.com/rivo/tview"
)
+const DebugPaneHeight = 40
+
+type DebugPrinter interface {
+ Printf(text string, args ...interface{})
+ Print(text ...interface{})
+}
+
type DebugPane struct {
- text string
pane *tview.TextView
num int
+ gmx Gomuks
+}
+
+func NewDebugPane(gmx Gomuks) *DebugPane {
+ pane := tview.NewTextView()
+ pane.
+ SetScrollable(true).
+ SetWrap(true)
+ pane.SetChangedFunc(func() {
+ gmx.App().Draw()
+ })
+ pane.SetBorder(true).SetTitle("Debug output")
+ fmt.Fprintln(pane, "[0] Debug pane initialized")
+
+ return &DebugPane{
+ pane: pane,
+ num: 0,
+ gmx: gmx,
+ }
}
func (db *DebugPane) Printf(text string, args ...interface{}) {
- db.num++
- db.Write(fmt.Sprintf("[%d] %s\n", db.num, fmt.Sprintf(text, args...)))
+ db.Write(fmt.Sprintf(text, args...))
}
func (db *DebugPane) Print(text ...interface{}) {
- db.num++
- db.Write(fmt.Sprintf("[%d] %s", db.num, fmt.Sprintln(text...)))
+ db.Write(fmt.Sprint(text...))
}
func (db *DebugPane) Write(text string) {
if db.pane != nil {
- db.text += text
- db.pane.SetText(db.text)
+ db.num++
+ fmt.Fprintf(db.pane, "[%d] %s\n", db.num, text)
}
}
-func (db *DebugPane) Wrap(main *tview.Pages) tview.Primitive {
- db.pane = tview.NewTextView()
- db.pane.SetBorder(true).SetTitle("Debug output")
- db.text += "[0] Debug pane initialized\n"
- db.pane.SetText(db.text)
- return tview.NewGrid().SetRows(0, 20).SetColumns(0).
+func (db *DebugPane) Wrap(main tview.Primitive) tview.Primitive {
+ return tview.NewGrid().SetRows(0, DebugPaneHeight).SetColumns(0).
AddItem(main, 0, 0, 1, 1, 1, 1, true).
AddItem(db.pane, 1, 0, 1, 1, 1, 1, false)
}
diff --git a/gomuks.go b/gomuks.go
index 8ffc2e9..ac7d534 100644
--- a/gomuks.go
+++ b/gomuks.go
@@ -20,94 +20,84 @@ import (
"os"
"path/filepath"
- "github.com/gdamore/tcell"
+ "github.com/matrix-org/gomatrix"
"github.com/rivo/tview"
)
-var matrix = new(MatrixContainer)
-var config = new(Config)
-var debug = new(DebugPane)
-
-func main() {
- configDir := filepath.Join(os.Getenv("HOME"), ".config/gomuks")
- os.MkdirAll(configDir, 0700)
- config.Load(configDir)
-
- views := tview.NewPages()
- InitUI(views)
+type Gomuks interface {
+ Debug() DebugPrinter
+ Matrix() *gomatrix.Client
+ MatrixContainer() *MatrixContainer
+ App() *tview.Application
+ UI() *GomuksUI
+ Config() *Config
+}
- main := debug.Wrap(views)
+type gomuks struct {
+ app *tview.Application
+ ui *GomuksUI
+ matrix *MatrixContainer
+ debug *DebugPane
+ config *Config
+}
- if len(config.MXID) > 0 {
- config.LoadSession(config.MXID)
+func NewGomuks(debug bool) *gomuks {
+ configDir := filepath.Join(os.Getenv("HOME"), ".config/gomuks")
+ gmx := &gomuks{
+ app: tview.NewApplication(),
+ }
+ gmx.debug = NewDebugPane(gmx)
+ gmx.config = NewConfig(gmx, configDir)
+ gmx.ui = NewGomuksUI(gmx)
+ gmx.matrix = NewMatrixContainer(gmx)
+ gmx.ui.matrix = gmx.matrix
+
+ gmx.config.Load()
+ if len(gmx.config.MXID) > 0 {
+ gmx.config.LoadSession(gmx.config.MXID)
}
- matrix.Init(config)
- if err := tview.NewApplication().SetRoot(main, true).Run(); err != nil {
- panic(err)
+ gmx.matrix.InitClient()
+
+ main := gmx.ui.InitViews()
+ if debug {
+ main = gmx.debug.Wrap(main)
}
-}
+ gmx.app.SetRoot(main, true)
-func InitUI(views *tview.Pages) {
- views.AddPage("login", InitLoginUI(), true, true)
+ return gmx
}
-func Center(width, height int, p tview.Primitive) tview.Primitive {
- return tview.NewFlex().
- AddItem(tview.NewBox(), 0, 1, false).
- AddItem(tview.NewFlex().
- SetDirection(tview.FlexRow).
- AddItem(tview.NewBox(), 0, 1, false).
- AddItem(p, height, 1, true).
- AddItem(tview.NewBox(), 0, 1, false), width, 1, true).
- AddItem(tview.NewBox(), 0, 1, false)
+func (gmx *gomuks) Start() {
+ if err := gmx.app.Run(); err != nil {
+ panic(err)
+ }
}
-type FormTextView struct {
- *tview.TextView
+func (gmx *gomuks) Debug() DebugPrinter {
+ return gmx.debug
}
-func (ftv *FormTextView) GetLabel() string {
- return ""
+func (gmx *gomuks) Matrix() *gomatrix.Client {
+ return gmx.matrix.client
}
-func (ftv *FormTextView) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) tview.FormItem {
- return ftv
+func (gmx *gomuks) MatrixContainer() *MatrixContainer {
+ return gmx.matrix
}
-func (ftv *FormTextView) GetFieldWidth() int {
- _, _, w, _ := ftv.TextView.GetRect()
- return w
+func (gmx *gomuks) App() *tview.Application {
+ return gmx.app
}
-func (ftv *FormTextView) SetFinishedFunc(handler func(key tcell.Key)) tview.FormItem {
- ftv.SetDoneFunc(handler)
- return ftv
+func (gmx *gomuks) Config() *Config {
+ return gmx.config
}
-func login(form *tview.Form) func() {
- return func() {
- hs := form.GetFormItem(0).(*tview.InputField).GetText()
- mxid := form.GetFormItem(1).(*tview.InputField).GetText()
- password := form.GetFormItem(2).(*tview.InputField).GetText()
- debug.Printf("%s %s %s", hs, mxid, password)
- config.HS = hs
- debug.Print(matrix.Init(config))
- debug.Print(matrix.Login(mxid, password))
- }
+func (gmx *gomuks) UI() *GomuksUI {
+ return gmx.ui
}
-func InitLoginUI() tview.Primitive {
- form := tview.NewForm().SetButtonsAlign(tview.AlignCenter)
- hs := config.HS
- if len(hs) == 0 {
- hs = "https://matrix.org"
- }
- form.
- AddInputField("Homeserver", hs, 30, nil, nil).
- AddInputField("Username", config.MXID, 30, nil, nil).
- AddPasswordField("Password", "", 30, '*', nil).
- AddButton("Log in", login(form))
- form.SetBorder(true).SetTitle("Log in to Matrix")
- return Center(45, 13, form)
+func main() {
+ NewGomuks(true).Start()
}
diff --git a/matrix.go b/matrix.go
index b559f17..17147be 100644
--- a/matrix.go
+++ b/matrix.go
@@ -23,27 +23,36 @@ import (
)
type MatrixContainer struct {
- lient *gomatrix.Client
+ client *gomatrix.Client
+ gmx Gomuks
+ ui *GomuksUI
+ debug DebugPrinter
config *Config
running bool
stop chan bool
}
-func (c *MatrixContainer) Initialized() bool {
- return c.lient != nil
-}
-
-func (c *MatrixContainer) Init(config *Config) error {
- c.config = config
-
- if c.lient != nil {
- c.lient.StopSync()
+func NewMatrixContainer(gmx Gomuks) *MatrixContainer {
+ c := &MatrixContainer{
+ config: gmx.Config(),
+ debug: gmx.Debug(),
+ ui: gmx.UI(),
+ gmx: gmx,
}
+ return c
+}
+
+func (c *MatrixContainer) InitClient() error {
if len(c.config.HS) == 0 {
return fmt.Errorf("no homeserver in config")
}
+ if c.client != nil {
+ c.Stop()
+ c.client = nil
+ }
+
var mxid, accessToken string
if c.config.Session != nil {
accessToken = c.config.Session.AccessToken
@@ -51,7 +60,7 @@ func (c *MatrixContainer) Init(config *Config) error {
}
var err error
- c.lient, err = gomatrix.NewClient(c.config.HS, mxid, accessToken)
+ c.client, err = gomatrix.NewClient(c.config.HS, mxid, accessToken)
if err != nil {
return err
}
@@ -64,8 +73,12 @@ func (c *MatrixContainer) Init(config *Config) error {
return nil
}
+func (c *MatrixContainer) Initialized() bool {
+ return c.client != nil
+}
+
func (c *MatrixContainer) Login(user, password string) error {
- resp, err := c.lient.Login(&gomatrix.ReqLogin{
+ resp, err := c.client.Login(&gomatrix.ReqLogin{
Type: "m.login.password",
User: user,
Password: password,
@@ -73,7 +86,7 @@ func (c *MatrixContainer) Login(user, password string) error {
if err != nil {
return err
}
- c.lient.SetCredentials(resp.UserID, resp.AccessToken)
+ c.client.SetCredentials(resp.UserID, resp.AccessToken)
c.config.MXID = resp.UserID
c.config.Save()
@@ -88,31 +101,50 @@ func (c *MatrixContainer) Login(user, password string) error {
func (c *MatrixContainer) Stop() {
c.stop <- true
- c.lient.StopSync()
+ c.client.StopSync()
+}
+
+func (c *MatrixContainer) UpdateRoomList() {
+ rooms, err := c.client.JoinedRooms()
+ if err != nil {
+ c.debug.Print(err)
+ }
+
+ c.ui.SetRoomList(rooms.JoinedRooms)
}
func (c *MatrixContainer) Start() {
- debug.Print("Starting sync...")
+ c.debug.Print("Starting sync...")
c.running = true
- c.lient.Store = c.config.Session
+ c.ui.SetView(ViewMain)
+ c.client.Store = c.config.Session
+
+ c.UpdateRoomList()
- syncer := c.lient.Syncer.(*gomatrix.DefaultSyncer)
+ syncer := c.client.Syncer.(*gomatrix.DefaultSyncer)
syncer.OnEventType("m.room.message", c.HandleMessage)
for {
select {
case <-c.stop:
- debug.Print("Stopping sync...")
+ c.debug.Print("Stopping sync...")
c.running = false
return
default:
- if err := c.lient.Sync(); err != nil {
- debug.Print("Sync() errored", err)
+ if err := c.client.Sync(); err != nil {
+ c.debug.Print("Sync() errored", err)
+ } else {
+ c.debug.Print("Sync() returned without error")
}
}
}
}
func (c *MatrixContainer) HandleMessage(evt *gomatrix.Event) {
- debug.Print("Message received")
+ message, _ := evt.Content["body"].(string)
+ c.ui.Append(evt.RoomID, evt.Sender, message)
+}
+
+func (c *MatrixContainer) SendMessage(roomID, message string) {
+ c.client.SendText(roomID, message)
}
diff --git a/session.go b/session.go
index 8f0e5d8..77e4bfa 100644
--- a/session.go
+++ b/session.go
@@ -31,6 +31,8 @@ type Session struct {
NextBatch string
FilterID string
Rooms map[string]*gomatrix.Room
+
+ debug DebugPrinter `json:"-"`
}
func (config *Config) LoadSession(mxid string) {
@@ -43,19 +45,20 @@ func (config *Config) NewSession(mxid string) *Session {
MXID: mxid,
path: filepath.Join(config.dir, mxid+".session"),
Rooms: make(map[string]*gomatrix.Room),
+ debug: config.debug,
}
}
func (s *Session) Load() {
data, err := ioutil.ReadFile(s.path)
if err != nil {
- debug.Print("Failed to read session from", s.path)
+ s.debug.Print("Failed to read session from", s.path)
panic(err)
}
err = json.Unmarshal(data, s)
if err != nil {
- debug.Print("Failed to parse session at", s.path)
+ s.debug.Print("Failed to parse session at", s.path)
panic(err)
}
}
@@ -63,13 +66,13 @@ func (s *Session) Load() {
func (s *Session) Save() {
data, err := json.Marshal(s)
if err != nil {
- debug.Print("Failed to marshal session of", s.MXID)
+ s.debug.Print("Failed to marshal session of", s.MXID)
panic(err)
}
err = ioutil.WriteFile(s.path, data, 0600)
if err != nil {
- debug.Print("Failed to write session to", s.path)
+ s.debug.Print("Failed to write session to", s.path)
panic(err)
}
}
diff --git a/ui.go b/ui.go
new file mode 100644
index 0000000..99c64eb
--- /dev/null
+++ b/ui.go
@@ -0,0 +1,71 @@
+// 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 main
+
+import (
+ "github.com/rivo/tview"
+)
+
+// Allowed views in GomuksUI
+const (
+ ViewLogin = "login"
+ ViewMain = "main"
+)
+
+type GomuksUI struct {
+ gmx Gomuks
+ app *tview.Application
+ matrix *MatrixContainer
+ debug DebugPrinter
+ config *Config
+ views *tview.Pages
+
+ mainView *tview.Grid
+ mainViewRoomList *tview.List
+ mainViewRoomView *tview.Pages
+ mainViewInput *tview.InputField
+ mainViewRooms map[string]*RoomView
+ currentRoomIndex int
+ roomList []string
+}
+
+func NewGomuksUI(gmx Gomuks) (ui *GomuksUI) {
+ ui = &GomuksUI{
+ gmx: gmx,
+ app: gmx.App(),
+ matrix: gmx.MatrixContainer(),
+ debug: gmx.Debug(),
+ config: gmx.Config(),
+ views: tview.NewPages(),
+ }
+ ui.views.SetChangedFunc(ui.Render)
+ return
+}
+
+func (ui *GomuksUI) Render() {
+ ui.app.Draw()
+}
+
+func (ui *GomuksUI) SetView(name string) {
+ ui.views.SwitchToPage(name)
+}
+
+func (ui *GomuksUI) InitViews() tview.Primitive {
+ ui.views.AddPage(ViewLogin, ui.MakeLoginUI(), true, true)
+ ui.views.AddPage(ViewMain, ui.MakeMainUI(), true, false)
+ return ui.views
+}
diff --git a/uiutil.go b/uiutil.go
new file mode 100644
index 0000000..1b29ebf
--- /dev/null
+++ b/uiutil.go
@@ -0,0 +1,55 @@
+// 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 main
+
+import (
+ "github.com/gdamore/tcell"
+ "github.com/rivo/tview"
+)
+
+func Center(width, height int, p tview.Primitive) tview.Primitive {
+ return tview.NewFlex().
+ AddItem(tview.NewBox(), 0, 1, false).
+ AddItem(tview.NewFlex().
+ SetDirection(tview.FlexRow).
+ AddItem(tview.NewBox(), 0, 1, false).
+ AddItem(p, height, 1, true).
+ AddItem(tview.NewBox(), 0, 1, false), width, 1, true).
+ AddItem(tview.NewBox(), 0, 1, false)
+}
+
+type FormTextView struct {
+ *tview.TextView
+}
+
+func (ftv *FormTextView) GetLabel() string {
+ return ""
+}
+
+func (ftv *FormTextView) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) tview.FormItem {
+ return ftv
+}
+
+func (ftv *FormTextView) GetFieldWidth() int {
+ _, _, w, _ := ftv.TextView.GetRect()
+ return w
+}
+
+func (ftv *FormTextView) SetFinishedFunc(handler func(key tcell.Key)) tview.FormItem {
+ ftv.SetDoneFunc(handler)
+ return ftv
+}
diff --git a/view-login.go b/view-login.go
new file mode 100644
index 0000000..78981a9
--- /dev/null
+++ b/view-login.go
@@ -0,0 +1,49 @@
+// 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 main
+
+import (
+ "github.com/rivo/tview"
+)
+
+func (ui *GomuksUI) MakeLoginUI() tview.Primitive {
+ form := tview.NewForm().SetButtonsAlign(tview.AlignCenter)
+ hs := ui.config.HS
+ if len(hs) == 0 {
+ hs = "https://matrix.org"
+ }
+ form.
+ AddInputField("Homeserver", hs, 30, nil, nil).
+ AddInputField("Username", ui.config.MXID, 30, nil, nil).
+ AddPasswordField("Password", "", 30, '*', nil).
+ AddButton("Log in", ui.login(form))
+ form.SetBorder(true).SetTitle("Log in to Matrix")
+ return Center(45, 13, form)
+}
+
+func (ui *GomuksUI) login(form *tview.Form) func() {
+ return func() {
+ hs := form.GetFormItem(0).(*tview.InputField).GetText()
+ mxid := form.GetFormItem(1).(*tview.InputField).GetText()
+ password := form.GetFormItem(2).(*tview.InputField).GetText()
+
+ ui.debug.Printf("Logging into %s as %s...", hs, mxid)
+ ui.config.HS = hs
+ ui.debug.Print(ui.matrix.InitClient())
+ ui.debug.Print(ui.matrix.Login(mxid, password))
+ }
+}
diff --git a/view-main.go b/view-main.go
new file mode 100644
index 0000000..acacddb
--- /dev/null
+++ b/view-main.go
@@ -0,0 +1,164 @@
+// 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 main
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/gdamore/tcell"
+ "github.com/rivo/tview"
+)
+
+type RoomView struct {
+ *tview.Grid
+
+ sender, message *tview.TextView
+}
+
+func NewRoomView() *RoomView {
+ view := &RoomView{
+ tview.NewGrid(),
+ tview.NewTextView(),
+ tview.NewTextView(),
+ }
+ view.SetColumns(30, 0).SetRows(0)
+
+ view.sender.SetTextAlign(tview.AlignRight)
+ view.sender.SetScrollable(true)
+ view.message.SetScrollable(true)
+
+ view.AddItem(view.sender, 0, 0, 1, 1, 1, 1, false)
+ view.AddItem(view.message, 0, 1, 1, 1, 1, 1, false)
+
+ return view
+}
+
+func (ui *GomuksUI) MakeMainUI() tview.Primitive {
+ ui.mainView = tview.NewGrid().SetColumns(40, 0).SetRows(0, 2)
+
+ ui.mainViewRoomList = tview.NewList().ShowSecondaryText(false)
+ ui.mainViewRoomList.SetBorderPadding(1, 1, 1, 1)
+ ui.mainView.AddItem(ui.mainViewRoomList, 0, 0, 2, 1, 2, 1, false)
+
+ ui.mainViewRoomView = tview.NewPages()
+ ui.mainViewRoomView.SetChangedFunc(ui.Render)
+ ui.mainView.AddItem(ui.mainViewRoomView, 0, 1, 1, 1, 1, 1, false)
+
+ ui.mainViewInput = tview.NewInputField()
+ ui.mainViewInput.SetDoneFunc(func(key tcell.Key) {
+ if key == tcell.KeyEnter {
+ room, text := ui.currentRoom(), ui.mainViewInput.GetText()
+ if len(text) == 0 {
+ return
+ } else if text[0] == '/' {
+ args := strings.SplitN(text, " ", 2)
+ command := strings.ToLower(args[0])
+ args = args[1:]
+ ui.HandleCommand(room, command, args)
+ } else {
+ ui.matrix.SendMessage(room, text)
+ }
+ ui.mainViewInput.SetText("")
+ }
+ })
+ ui.mainView.AddItem(ui.mainViewInput, 1, 1, 1, 1, 1, 1, true)
+
+ ui.debug.Print(ui.mainViewInput.SetInputCapture(ui.MainUIKeyHandler))
+
+ ui.mainViewRooms = make(map[string]*RoomView)
+
+ return ui.mainView
+}
+
+func (ui *GomuksUI) HandleCommand(room, command string, args []string) {
+ switch command {
+ case "quit":
+ ui.matrix.Stop()
+ ui.app.Stop()
+ case "part":
+ case "leave":
+ ui.matrix.client.LeaveRoom(room)
+ case "join":
+ if len(args) == 0 {
+ ui.Append(room, "*", "Usage: /join <room>")
+ }
+ mxid := args[0]
+ server := mxid[strings.Index(mxid, ":")+1:]
+ ui.matrix.client.JoinRoom(mxid, server, nil)
+ }
+}
+
+func (ui *GomuksUI) MainUIKeyHandler(key *tcell.EventKey) *tcell.EventKey {
+ ui.debug.Print(key)
+ if key.Modifiers() == tcell.ModCtrl {
+ if key.Key() == tcell.KeyDown {
+ ui.SwitchRoom(ui.currentRoomIndex + 1)
+ ui.mainViewRoomList.SetCurrentItem(ui.currentRoomIndex)
+ } else if key.Key() == tcell.KeyUp {
+ ui.SwitchRoom(ui.currentRoomIndex - 1)
+ ui.mainViewRoomList.SetCurrentItem(ui.currentRoomIndex)
+ }
+ } else if key.Key() == tcell.KeyPgUp || key.Key() == tcell.KeyPgDn {
+ ui.mainViewRooms[ui.currentRoom()].sender.InputHandler()(key, nil)
+ ui.mainViewRooms[ui.currentRoom()].message.InputHandler()(key, nil)
+ } else {
+ return key
+ }
+ return nil
+}
+
+func (ui *GomuksUI) SetRoomList(rooms []string) {
+ ui.roomList = rooms
+ ui.mainViewRoomList.Clear()
+ for index, room := range rooms {
+ localRoomIndex := index
+ ui.mainViewRoomList.AddItem(room, "", 0, func() {
+ ui.SwitchRoom(localRoomIndex)
+ })
+ if !ui.mainViewRoomView.HasPage(room) {
+ roomView := NewRoomView()
+ ui.mainViewRooms[room] = roomView
+ ui.mainViewRoomView.AddPage(room, roomView, true, false)
+ }
+ }
+ ui.SwitchRoom(0)
+}
+
+func (ui *GomuksUI) currentRoom() string {
+ if len(ui.roomList) == 0 {
+ return ""
+ }
+ return ui.roomList[ui.currentRoomIndex]
+}
+
+func (ui *GomuksUI) SwitchRoom(roomIndex int) {
+ if roomIndex < 0 {
+ roomIndex = len(ui.roomList) - 1
+ }
+ ui.currentRoomIndex = roomIndex % len(ui.roomList)
+ ui.mainViewRoomView.SwitchToPage(ui.roomList[ui.currentRoomIndex])
+}
+
+func (ui *GomuksUI) Append(room, sender, message string) {
+ roomView, ok := ui.mainViewRooms[room]
+ if ok {
+ fmt.Fprintf(roomView.sender, sender)
+ fmt.Fprintf(roomView.message, sender)
+ ui.Render()
+ }
+}