Add UI preferences and simplify config save/load (ref #43)
This commit is contained in:
parent
a4d07e9a81
commit
b76c8d0147
187
config/config.go
187
config/config.go
@ -21,15 +21,27 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"encoding/json"
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"maunium.net/go/gomatrix"
|
"maunium.net/go/gomatrix"
|
||||||
"maunium.net/go/gomuks/debug"
|
"maunium.net/go/gomuks/debug"
|
||||||
"maunium.net/go/gomuks/matrix/pushrules"
|
"maunium.net/go/gomuks/matrix/pushrules"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"strings"
|
"strings"
|
||||||
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AuthCache struct {
|
||||||
|
NextBatch string `yaml:"next_batch"`
|
||||||
|
FilterID string `yaml:"filter_id"`
|
||||||
|
InitialSyncDone bool `yaml:"initial_sync_done"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserPreferences struct {
|
||||||
|
HideUserList bool `yaml:"hide_user_list",json:"hide_user_list"`
|
||||||
|
HideRoomList bool `yaml:"hide_room_list",json:"hide_room_list"`
|
||||||
|
BareMessageView bool `yaml:"bare_message_view",json:"bare_message_view"`
|
||||||
|
}
|
||||||
|
|
||||||
// Config contains the main config of gomuks.
|
// Config contains the main config of gomuks.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
UserID string `yaml:"mxid"`
|
UserID string `yaml:"mxid"`
|
||||||
@ -42,12 +54,8 @@ type Config struct {
|
|||||||
MediaDir string `yaml:"media_dir"`
|
MediaDir string `yaml:"media_dir"`
|
||||||
StateDir string `yaml:"state_dir"`
|
StateDir string `yaml:"state_dir"`
|
||||||
|
|
||||||
AuthCache struct {
|
Preferences UserPreferences `yaml:"-"`
|
||||||
NextBatch string `yaml:"next_batch"`
|
AuthCache AuthCache `yaml:"-"`
|
||||||
FilterID string `yaml:"filter_id"`
|
|
||||||
InitialSyncDone bool `yaml:"initial_sync_done"`
|
|
||||||
} `yaml:"-"`
|
|
||||||
|
|
||||||
Rooms map[string]*rooms.Room `yaml:"-"`
|
Rooms map[string]*rooms.Room `yaml:"-"`
|
||||||
PushRules *pushrules.PushRuleset `yaml:"-"`
|
PushRules *pushrules.PushRuleset `yaml:"-"`
|
||||||
|
|
||||||
@ -98,29 +106,13 @@ func (config *Config) LoadAll() {
|
|||||||
config.Load()
|
config.Load()
|
||||||
config.LoadAuthCache()
|
config.LoadAuthCache()
|
||||||
config.LoadPushRules()
|
config.LoadPushRules()
|
||||||
|
config.LoadPreferences()
|
||||||
config.LoadRooms()
|
config.LoadRooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load loads the config from config.yaml in the directory given to the config struct.
|
// Load loads the config from config.yaml in the directory given to the config struct.
|
||||||
func (config *Config) Load() {
|
func (config *Config) Load() {
|
||||||
os.MkdirAll(config.Dir, 0700)
|
config.load("config", config.Dir, "config.yaml", config)
|
||||||
|
|
||||||
configPath := filepath.Join(config.Dir, "config.yaml")
|
|
||||||
data, err := ioutil.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
config.CreateCacheDirs()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
debug.Print("Failed to read config from", configPath)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = yaml.Unmarshal(data, &config)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to parse config at", configPath)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
config.CreateCacheDirs()
|
config.CreateCacheDirs()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,109 +120,40 @@ func (config *Config) SaveAll() {
|
|||||||
config.Save()
|
config.Save()
|
||||||
config.SaveAuthCache()
|
config.SaveAuthCache()
|
||||||
config.SavePushRules()
|
config.SavePushRules()
|
||||||
|
config.SavePreferences()
|
||||||
config.SaveRooms()
|
config.SaveRooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save saves this config to config.yaml in the directory given to the config struct.
|
// Save saves this config to config.yaml in the directory given to the config struct.
|
||||||
func (config *Config) Save() {
|
func (config *Config) Save() {
|
||||||
if config.nosave {
|
config.save("config", config.Dir, "config.yaml", config)
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
os.MkdirAll(config.Dir, 0700)
|
func (config *Config) LoadPreferences() {
|
||||||
data, err := yaml.Marshal(&config)
|
config.load("user preferences", config.CacheDir, "preferences.yaml", &config.Preferences)
|
||||||
if err != nil {
|
}
|
||||||
debug.Print("Failed to marshal config")
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
path := filepath.Join(config.Dir, "config.yaml")
|
func (config *Config) SavePreferences() {
|
||||||
err = ioutil.WriteFile(path, data, 0600)
|
config.save("user preferences", config.CacheDir, "preferences.yaml", &config.Preferences)
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to write config to", path)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) LoadAuthCache() {
|
func (config *Config) LoadAuthCache() {
|
||||||
os.MkdirAll(config.Dir, 0700)
|
config.load("auth cache", config.CacheDir, "auth-cache.yaml", &config.AuthCache)
|
||||||
|
|
||||||
configPath := filepath.Join(config.CacheDir, "auth-cache.yaml")
|
|
||||||
data, err := ioutil.ReadFile(configPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
debug.Print("Failed to read auth cache from", configPath)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = yaml.Unmarshal(data, &config.AuthCache)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to parse auth cache at", configPath)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) SaveAuthCache() {
|
func (config *Config) SaveAuthCache() {
|
||||||
if config.nosave {
|
config.save("auth cache", config.CacheDir, "auth-cache.yaml", &config.AuthCache)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
os.MkdirAll(config.CacheDir, 0700)
|
|
||||||
data, err := yaml.Marshal(&config.AuthCache)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to marshal auth cache")
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
path := filepath.Join(config.CacheDir, "auth-cache.yaml")
|
|
||||||
err = ioutil.WriteFile(path, data, 0600)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to write auth cache to", path)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) LoadPushRules() {
|
func (config *Config) LoadPushRules() {
|
||||||
os.MkdirAll(config.CacheDir, 0700)
|
config.load("push rules", config.CacheDir, "pushrules.json", &config.PushRules)
|
||||||
|
|
||||||
pushRulesPath := filepath.Join(config.CacheDir, "pushrules.json")
|
|
||||||
data, err := ioutil.ReadFile(pushRulesPath)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
debug.Print("Failed to read push rules from", pushRulesPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
config.PushRules = &pushrules.PushRuleset{}
|
|
||||||
err = json.Unmarshal(data, &config.PushRules)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to parse push rules at", pushRulesPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) SavePushRules() {
|
func (config *Config) SavePushRules() {
|
||||||
if config.nosave || config.PushRules == nil {
|
if config.PushRules == nil {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
os.MkdirAll(config.CacheDir, 0700)
|
|
||||||
data, err := json.Marshal(&config.PushRules)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to marshal push rules")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
path := filepath.Join(config.CacheDir, "pushrules.json")
|
|
||||||
err = ioutil.WriteFile(path, data, 0600)
|
|
||||||
if err != nil {
|
|
||||||
debug.Print("Failed to write config to", path)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
config.save("push rules", config.CacheDir, "pushrules.json", &config.PushRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) LoadRooms() {
|
func (config *Config) LoadRooms() {
|
||||||
@ -272,6 +195,56 @@ func (config *Config) SaveRooms() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) load(name, dir, file string, target interface{}) {
|
||||||
|
os.MkdirAll(dir, 0700)
|
||||||
|
|
||||||
|
path := filepath.Join(dir, file)
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
debug.Print("Failed to read", name, "from", path)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(file, ".yaml") {
|
||||||
|
err = yaml.Unmarshal(data, target)
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal(data, target)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
debug.Print("Failed to parse", name, "at", path)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (config *Config) save(name, dir, file string, source interface{}) {
|
||||||
|
if config.nosave {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
os.MkdirAll(dir, 0700)
|
||||||
|
var data []byte
|
||||||
|
var err error
|
||||||
|
if strings.HasSuffix(file, ".yaml") {
|
||||||
|
data, err = yaml.Marshal(source)
|
||||||
|
} else {
|
||||||
|
data, err = json.Marshal(source)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
debug.Print("Failed to marshal", name)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(dir, file)
|
||||||
|
err = ioutil.WriteFile(path, data, 0600)
|
||||||
|
if err != nil {
|
||||||
|
debug.Print("Failed to write", name, "to", path)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (config *Config) GetUserID() string {
|
func (config *Config) GetUserID() string {
|
||||||
return config.UserID
|
return config.UserID
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ type MatrixContainer interface {
|
|||||||
Login(user, password string) error
|
Login(user, password string) error
|
||||||
Logout()
|
Logout()
|
||||||
|
|
||||||
|
SendPreferencesToMatrix()
|
||||||
SendMessage(roomID, msgtype, message string) (string, error)
|
SendMessage(roomID, msgtype, message string) (string, error)
|
||||||
SendMarkdownMessage(roomID, msgtype, message string) (string, error)
|
SendMarkdownMessage(roomID, msgtype, message string) (string, error)
|
||||||
SendTyping(roomID string, typing bool)
|
SendTyping(roomID string, typing bool)
|
||||||
|
@ -29,6 +29,7 @@ type UIProvider func(gmx Gomuks) GomuksUI
|
|||||||
|
|
||||||
type GomuksUI interface {
|
type GomuksUI interface {
|
||||||
Render()
|
Render()
|
||||||
|
HandleNewPreferences()
|
||||||
OnLogin()
|
OnLogin()
|
||||||
OnLogout()
|
OnLogout()
|
||||||
MainView() MainView
|
MainView() MainView
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"maunium.net/go/gomuks/matrix/pushrules"
|
"maunium.net/go/gomuks/matrix/pushrules"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Container is a wrapper for a gomatrix Client and some other stuff.
|
// Container is a wrapper for a gomatrix Client and some other stuff.
|
||||||
@ -188,6 +189,7 @@ func (c *Container) OnLogin() {
|
|||||||
c.syncer.OnEventType("m.direct", c.HandleDirectChatInfo)
|
c.syncer.OnEventType("m.direct", c.HandleDirectChatInfo)
|
||||||
c.syncer.OnEventType("m.push_rules", c.HandlePushRules)
|
c.syncer.OnEventType("m.push_rules", c.HandlePushRules)
|
||||||
c.syncer.OnEventType("m.tag", c.HandleTag)
|
c.syncer.OnEventType("m.tag", c.HandleTag)
|
||||||
|
c.syncer.OnEventType("net.maunium.gomuks.preferences", c.HandlePreferences)
|
||||||
c.syncer.InitDoneCallback = func() {
|
c.syncer.InitDoneCallback = func() {
|
||||||
c.config.AuthCache.InitialSyncDone = true
|
c.config.AuthCache.InitialSyncDone = true
|
||||||
c.config.SaveAuthCache()
|
c.config.SaveAuthCache()
|
||||||
@ -235,6 +237,24 @@ func (c *Container) Start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) HandlePreferences(source EventSource, evt *gomatrix.Event) {
|
||||||
|
orig := c.config.Preferences
|
||||||
|
rt, _ := json.Marshal(&evt.Content)
|
||||||
|
json.Unmarshal(rt, &c.config.Preferences)
|
||||||
|
debug.Print("Updated preferences:", orig, "->", c.config.Preferences)
|
||||||
|
c.ui.HandleNewPreferences()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Container) SendPreferencesToMatrix() {
|
||||||
|
defer debug.Recover()
|
||||||
|
debug.Print("Sending updated preferences:", c.config.Preferences)
|
||||||
|
u := c.client.BuildURL("user", c.config.UserID, "account_data", "net.maunium.gomuks.preferences")
|
||||||
|
_, err := c.client.MakeRequest("PUT", u, &c.config.Preferences, nil)
|
||||||
|
if err != nil {
|
||||||
|
debug.Print("Failed to update preferences:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// HandleMessage is the event handler for the m.room.message timeline event.
|
// HandleMessage is the event handler for the m.room.message timeline event.
|
||||||
func (c *Container) HandleMessage(source EventSource, evt *gomatrix.Event) {
|
func (c *Container) HandleMessage(source EventSource, evt *gomatrix.Event) {
|
||||||
if source&EventSourceLeave != 0 {
|
if source&EventSourceLeave != 0 {
|
||||||
|
@ -184,7 +184,7 @@ func (s *GomuksSyncer) GetFilterJSON(userID string) json.RawMessage {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
AccountData: gomatrix.FilterPart{
|
AccountData: gomatrix.FilterPart{
|
||||||
Types: []string{"m.push_rules", "m.direct"},
|
Types: []string{"m.push_rules", "m.direct", "net.maunium.gomuks.preferences"},
|
||||||
},
|
},
|
||||||
Presence: gomatrix.FilterPart{
|
Presence: gomatrix.FilterPart{
|
||||||
Types: []string{},
|
Types: []string{},
|
||||||
|
@ -491,7 +491,7 @@ func (view *MessageView) Draw(screen tcell.Screen) {
|
|||||||
|
|
||||||
bareMode := view.parent.parent.bareMessages
|
bareMode := view.parent.parent.bareMessages
|
||||||
if bareMode {
|
if bareMode {
|
||||||
messageX = 0
|
messageX = x
|
||||||
}
|
}
|
||||||
|
|
||||||
indexOffset := view.getIndexOffset(screen, height, messageX)
|
indexOffset := view.getIndexOffset(screen, height, messageX)
|
||||||
|
8
ui/ui.go
8
ui/ui.go
@ -86,6 +86,14 @@ func (ui *GomuksUI) OnLogout() {
|
|||||||
ui.app.SetFocus(ui.loginView)
|
ui.app.SetFocus(ui.loginView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ui *GomuksUI) HandleNewPreferences() {
|
||||||
|
prefs := ui.gmx.Config().Preferences
|
||||||
|
ui.mainView.bareMessages = prefs.BareMessageView
|
||||||
|
ui.mainView.hideUserList = prefs.HideUserList
|
||||||
|
ui.mainView.hideRoomList = prefs.HideRoomList
|
||||||
|
ui.Render()
|
||||||
|
}
|
||||||
|
|
||||||
func (ui *GomuksUI) SetView(name View) {
|
func (ui *GomuksUI) SetView(name View) {
|
||||||
ui.views.SwitchToPage(string(name))
|
ui.views.SwitchToPage(string(name))
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ type MainView struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ui *GomuksUI) NewMainView() tview.Primitive {
|
func (ui *GomuksUI) NewMainView() tview.Primitive {
|
||||||
|
prefs := ui.gmx.Config().Preferences
|
||||||
mainView := &MainView{
|
mainView := &MainView{
|
||||||
Flex: tview.NewFlex(),
|
Flex: tview.NewFlex(),
|
||||||
roomList: NewRoomList(),
|
roomList: NewRoomList(),
|
||||||
@ -67,6 +68,10 @@ func (ui *GomuksUI) NewMainView() tview.Primitive {
|
|||||||
gmx: ui.gmx,
|
gmx: ui.gmx,
|
||||||
config: ui.gmx.Config(),
|
config: ui.gmx.Config(),
|
||||||
parent: ui,
|
parent: ui,
|
||||||
|
|
||||||
|
hideUserList: prefs.HideUserList,
|
||||||
|
hideRoomList: prefs.HideRoomList,
|
||||||
|
bareMessages: prefs.BareMessageView,
|
||||||
}
|
}
|
||||||
|
|
||||||
mainView.
|
mainView.
|
||||||
@ -185,6 +190,28 @@ func (view *MainView) HandleCommand(roomView *RoomView, command string, args []s
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
view.RemoveRoom(roomView.Room)
|
view.RemoveRoom(roomView.Room)
|
||||||
}
|
}
|
||||||
|
case "/uitoggle":
|
||||||
|
if len(args) == 0 {
|
||||||
|
roomView.AddServiceMessage("Usage: /uitoggle <rooms/users/baremessages>")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch args[0] {
|
||||||
|
case "rooms":
|
||||||
|
view.hideRoomList = !view.hideRoomList
|
||||||
|
view.config.Preferences.HideRoomList = view.hideRoomList
|
||||||
|
case "users":
|
||||||
|
view.hideUserList = !view.hideUserList
|
||||||
|
view.config.Preferences.HideUserList = view.hideUserList
|
||||||
|
case "baremessages":
|
||||||
|
view.bareMessages = !view.bareMessages
|
||||||
|
view.config.Preferences.BareMessageView = view.bareMessages
|
||||||
|
default:
|
||||||
|
roomView.AddServiceMessage("Usage: /uitoggle <rooms/users/baremessages>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
view.parent.Render()
|
||||||
|
view.parent.Render()
|
||||||
|
go view.matrix.SendPreferencesToMatrix()
|
||||||
case "/join":
|
case "/join":
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
roomView.AddServiceMessage("Usage: /join <room>")
|
roomView.AddServiceMessage("Usage: /join <room>")
|
||||||
|
Loading…
Reference in New Issue
Block a user