Code additions/edits

This commit is contained in:
Tulir Asokan 2018-03-13 21:58:43 +02:00
parent f0333df1b2
commit 90629c5c78
9 changed files with 506 additions and 113 deletions

View File

@ -29,14 +29,23 @@ type Config struct {
MXID string `yaml:"mxid"` MXID string `yaml:"mxid"`
HS string `yaml:"homeserver"` HS string `yaml:"homeserver"`
dir string `yaml:"-"` dir string `yaml:"-"`
Session *Session `yaml:"-"` gmx Gomuks `yaml:"-"`
debug DebugPrinter `yaml:"-"`
Session *Session `yaml:"-"`
} }
func (config *Config) Load(dir string) { func NewConfig(gmx Gomuks, dir string) *Config {
config.dir = dir return &Config{
os.MkdirAll(dir, 0700) gmx: gmx,
configPath := filepath.Join(dir, "config.yaml") 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) data, err := ioutil.ReadFile(configPath)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
@ -55,16 +64,17 @@ func (config *Config) Load(dir string) {
} }
func (config *Config) Save() { func (config *Config) Save() {
os.MkdirAll(config.dir, 0700)
data, err := yaml.Marshal(&config) data, err := yaml.Marshal(&config)
if err != nil { if err != nil {
debug.Print("Failed to marshal config") config.debug.Print("Failed to marshal config")
panic(err) panic(err)
} }
path := filepath.Join(config.dir, "config.yaml") path := filepath.Join(config.dir, "config.yaml")
err = ioutil.WriteFile(path, data, 0600) err = ioutil.WriteFile(path, data, 0600)
if err != nil { if err != nil {
debug.Print("Failed to write config to", path) config.debug.Print("Failed to write config to", path)
panic(err) panic(err)
} }
} }

View File

@ -22,35 +22,54 @@ import (
"github.com/rivo/tview" "github.com/rivo/tview"
) )
const DebugPaneHeight = 40
type DebugPrinter interface {
Printf(text string, args ...interface{})
Print(text ...interface{})
}
type DebugPane struct { type DebugPane struct {
text string
pane *tview.TextView pane *tview.TextView
num int 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{}) { func (db *DebugPane) Printf(text string, args ...interface{}) {
db.num++ db.Write(fmt.Sprintf(text, args...))
db.Write(fmt.Sprintf("[%d] %s\n", db.num, fmt.Sprintf(text, args...)))
} }
func (db *DebugPane) Print(text ...interface{}) { func (db *DebugPane) Print(text ...interface{}) {
db.num++ db.Write(fmt.Sprint(text...))
db.Write(fmt.Sprintf("[%d] %s", db.num, fmt.Sprintln(text...)))
} }
func (db *DebugPane) Write(text string) { func (db *DebugPane) Write(text string) {
if db.pane != nil { if db.pane != nil {
db.text += text db.num++
db.pane.SetText(db.text) fmt.Fprintf(db.pane, "[%d] %s\n", db.num, text)
} }
} }
func (db *DebugPane) Wrap(main *tview.Pages) tview.Primitive { func (db *DebugPane) Wrap(main tview.Primitive) tview.Primitive {
db.pane = tview.NewTextView() return tview.NewGrid().SetRows(0, DebugPaneHeight).SetColumns(0).
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).
AddItem(main, 0, 0, 1, 1, 1, 1, true). AddItem(main, 0, 0, 1, 1, 1, 1, true).
AddItem(db.pane, 1, 0, 1, 1, 1, 1, false) AddItem(db.pane, 1, 0, 1, 1, 1, 1, false)
} }

124
gomuks.go
View File

@ -20,94 +20,84 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/gdamore/tcell" "github.com/matrix-org/gomatrix"
"github.com/rivo/tview" "github.com/rivo/tview"
) )
var matrix = new(MatrixContainer) type Gomuks interface {
var config = new(Config) Debug() DebugPrinter
var debug = new(DebugPane) Matrix() *gomatrix.Client
MatrixContainer() *MatrixContainer
App() *tview.Application
UI() *GomuksUI
Config() *Config
}
func main() { type gomuks struct {
app *tview.Application
ui *GomuksUI
matrix *MatrixContainer
debug *DebugPane
config *Config
}
func NewGomuks(debug bool) *gomuks {
configDir := filepath.Join(os.Getenv("HOME"), ".config/gomuks") configDir := filepath.Join(os.Getenv("HOME"), ".config/gomuks")
os.MkdirAll(configDir, 0700) gmx := &gomuks{
config.Load(configDir) app: tview.NewApplication(),
views := tview.NewPages()
InitUI(views)
main := debug.Wrap(views)
if len(config.MXID) > 0 {
config.LoadSession(config.MXID)
} }
matrix.Init(config) gmx.debug = NewDebugPane(gmx)
gmx.config = NewConfig(gmx, configDir)
gmx.ui = NewGomuksUI(gmx)
gmx.matrix = NewMatrixContainer(gmx)
gmx.ui.matrix = gmx.matrix
if err := tview.NewApplication().SetRoot(main, true).Run(); err != nil { gmx.config.Load()
if len(gmx.config.MXID) > 0 {
gmx.config.LoadSession(gmx.config.MXID)
}
gmx.matrix.InitClient()
main := gmx.ui.InitViews()
if debug {
main = gmx.debug.Wrap(main)
}
gmx.app.SetRoot(main, true)
return gmx
}
func (gmx *gomuks) Start() {
if err := gmx.app.Run(); err != nil {
panic(err) panic(err)
} }
} }
func InitUI(views *tview.Pages) { func (gmx *gomuks) Debug() DebugPrinter {
views.AddPage("login", InitLoginUI(), true, true) return gmx.debug
} }
func Center(width, height int, p tview.Primitive) tview.Primitive { func (gmx *gomuks) Matrix() *gomatrix.Client {
return tview.NewFlex(). return gmx.matrix.client
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 { func (gmx *gomuks) MatrixContainer() *MatrixContainer {
*tview.TextView return gmx.matrix
} }
func (ftv *FormTextView) GetLabel() string { func (gmx *gomuks) App() *tview.Application {
return "" return gmx.app
} }
func (ftv *FormTextView) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) tview.FormItem { func (gmx *gomuks) Config() *Config {
return ftv return gmx.config
} }
func (ftv *FormTextView) GetFieldWidth() int { func (gmx *gomuks) UI() *GomuksUI {
_, _, w, _ := ftv.TextView.GetRect() return gmx.ui
return w
} }
func (ftv *FormTextView) SetFinishedFunc(handler func(key tcell.Key)) tview.FormItem { func main() {
ftv.SetDoneFunc(handler) NewGomuks(true).Start()
return ftv
}
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 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)
} }

View File

@ -23,27 +23,36 @@ import (
) )
type MatrixContainer struct { type MatrixContainer struct {
lient *gomatrix.Client client *gomatrix.Client
gmx Gomuks
ui *GomuksUI
debug DebugPrinter
config *Config config *Config
running bool running bool
stop chan bool stop chan bool
} }
func (c *MatrixContainer) Initialized() bool { func NewMatrixContainer(gmx Gomuks) *MatrixContainer {
return c.lient != nil c := &MatrixContainer{
} config: gmx.Config(),
debug: gmx.Debug(),
func (c *MatrixContainer) Init(config *Config) error { ui: gmx.UI(),
c.config = config gmx: gmx,
if c.lient != nil {
c.lient.StopSync()
} }
return c
}
func (c *MatrixContainer) InitClient() error {
if len(c.config.HS) == 0 { if len(c.config.HS) == 0 {
return fmt.Errorf("no homeserver in config") return fmt.Errorf("no homeserver in config")
} }
if c.client != nil {
c.Stop()
c.client = nil
}
var mxid, accessToken string var mxid, accessToken string
if c.config.Session != nil { if c.config.Session != nil {
accessToken = c.config.Session.AccessToken accessToken = c.config.Session.AccessToken
@ -51,7 +60,7 @@ func (c *MatrixContainer) Init(config *Config) error {
} }
var err 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 { if err != nil {
return err return err
} }
@ -64,8 +73,12 @@ func (c *MatrixContainer) Init(config *Config) error {
return nil return nil
} }
func (c *MatrixContainer) Initialized() bool {
return c.client != nil
}
func (c *MatrixContainer) Login(user, password string) error { 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", Type: "m.login.password",
User: user, User: user,
Password: password, Password: password,
@ -73,7 +86,7 @@ func (c *MatrixContainer) Login(user, password string) error {
if err != nil { if err != nil {
return err return err
} }
c.lient.SetCredentials(resp.UserID, resp.AccessToken) c.client.SetCredentials(resp.UserID, resp.AccessToken)
c.config.MXID = resp.UserID c.config.MXID = resp.UserID
c.config.Save() c.config.Save()
@ -88,31 +101,50 @@ func (c *MatrixContainer) Login(user, password string) error {
func (c *MatrixContainer) Stop() { func (c *MatrixContainer) Stop() {
c.stop <- true 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() { func (c *MatrixContainer) Start() {
debug.Print("Starting sync...") c.debug.Print("Starting sync...")
c.running = true c.running = true
c.lient.Store = c.config.Session c.ui.SetView(ViewMain)
c.client.Store = c.config.Session
syncer := c.lient.Syncer.(*gomatrix.DefaultSyncer) c.UpdateRoomList()
syncer := c.client.Syncer.(*gomatrix.DefaultSyncer)
syncer.OnEventType("m.room.message", c.HandleMessage) syncer.OnEventType("m.room.message", c.HandleMessage)
for { for {
select { select {
case <-c.stop: case <-c.stop:
debug.Print("Stopping sync...") c.debug.Print("Stopping sync...")
c.running = false c.running = false
return return
default: default:
if err := c.lient.Sync(); err != nil { if err := c.client.Sync(); err != nil {
debug.Print("Sync() errored", err) c.debug.Print("Sync() errored", err)
} else {
c.debug.Print("Sync() returned without error")
} }
} }
} }
} }
func (c *MatrixContainer) HandleMessage(evt *gomatrix.Event) { 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)
} }

View File

@ -31,6 +31,8 @@ type Session struct {
NextBatch string NextBatch string
FilterID string FilterID string
Rooms map[string]*gomatrix.Room Rooms map[string]*gomatrix.Room
debug DebugPrinter `json:"-"`
} }
func (config *Config) LoadSession(mxid string) { func (config *Config) LoadSession(mxid string) {
@ -43,19 +45,20 @@ func (config *Config) NewSession(mxid string) *Session {
MXID: mxid, MXID: mxid,
path: filepath.Join(config.dir, mxid+".session"), path: filepath.Join(config.dir, mxid+".session"),
Rooms: make(map[string]*gomatrix.Room), Rooms: make(map[string]*gomatrix.Room),
debug: config.debug,
} }
} }
func (s *Session) Load() { func (s *Session) Load() {
data, err := ioutil.ReadFile(s.path) data, err := ioutil.ReadFile(s.path)
if err != nil { if err != nil {
debug.Print("Failed to read session from", s.path) s.debug.Print("Failed to read session from", s.path)
panic(err) panic(err)
} }
err = json.Unmarshal(data, s) err = json.Unmarshal(data, s)
if err != nil { if err != nil {
debug.Print("Failed to parse session at", s.path) s.debug.Print("Failed to parse session at", s.path)
panic(err) panic(err)
} }
} }
@ -63,13 +66,13 @@ func (s *Session) Load() {
func (s *Session) Save() { func (s *Session) Save() {
data, err := json.Marshal(s) data, err := json.Marshal(s)
if err != nil { if err != nil {
debug.Print("Failed to marshal session of", s.MXID) s.debug.Print("Failed to marshal session of", s.MXID)
panic(err) panic(err)
} }
err = ioutil.WriteFile(s.path, data, 0600) err = ioutil.WriteFile(s.path, data, 0600)
if err != nil { if err != nil {
debug.Print("Failed to write session to", s.path) s.debug.Print("Failed to write session to", s.path)
panic(err) panic(err)
} }
} }

71
ui.go Normal file
View File

@ -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
}

55
uiutil.go Normal file
View File

@ -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
}

49
view-login.go Normal file
View File

@ -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))
}
}

164
view-main.go Normal file
View File

@ -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()
}
}