From 85eb790cd1ae16a9544dfb5631953a7820ec5589 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 17 May 2023 15:03:31 -0700 Subject: [PATCH] add multi-server functionality pt. 1 - add server --- backend/app.go | 2 +- backend/servermanager.go | 10 ++++++---- ui/controller/controller.go | 28 ++++++++++++++++++++++++++-- ui/dialogs/logindialog.go | 29 +++++++++++++++++++++++++---- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/backend/app.go b/backend/app.go index 2de52aa..59997e5 100644 --- a/backend/app.go +++ b/backend/app.go @@ -60,7 +60,7 @@ func StartupApp(appName, appVersionTag, configFile, latestReleaseURL string) (*A return nil, err } - a.ServerManager = NewServerManager(appName) + a.ServerManager = NewServerManager(appName, a.Config) a.PlaybackManager = NewPlaybackManager(a.bgrndCtx, a.ServerManager, a.Player, &a.Config.Scrobbling) a.ImageManager = NewImageManager(a.bgrndCtx, a.ServerManager, configdir.LocalCache(a.appName)) a.ServerManager.SetPrefetchAlbumCoverCallback(func(coverID string) { diff --git a/backend/servermanager.go b/backend/servermanager.go index 0cc44b0..4dd3749 100644 --- a/backend/servermanager.go +++ b/backend/servermanager.go @@ -20,14 +20,15 @@ type ServerManager struct { prefetchCoverCB func(string) appName string + config *Config onServerConnected []func() onLogout []func() } var ErrUnreachable = errors.New("server is unreachable") -func NewServerManager(appName string) *ServerManager { - return &ServerManager{appName: appName} +func NewServerManager(appName string, config *Config) *ServerManager { + return &ServerManager{appName: appName, config: config} } func (s *ServerManager) SetPrefetchAlbumCoverCallback(cb func(string)) { @@ -46,6 +47,7 @@ func (s *ServerManager) ConnectToServer(conf *ServerConfig, password string) err s.Server.SetPrefetchCoverCallback(s.prefetchCoverCB) s.LoggedInUser = conf.Username s.ServerID = conf.ID + s.config.SetDefaultServer(s.ServerID) for _, cb := range s.onServerConnected { cb() } @@ -144,8 +146,8 @@ func (s *ServerManager) OnLogout(cb func()) { s.onLogout = append(s.onLogout, cb) } -func (s *ServerManager) GetServerPassword(server *ServerConfig) (string, error) { - return keyring.Get(s.appName, server.ID.String()) +func (s *ServerManager) GetServerPassword(serverID uuid.UUID) (string, error) { + return keyring.Get(s.appName, serverID.String()) } func (s *ServerManager) SetServerPassword(server *ServerConfig, password string) error { diff --git a/ui/controller/controller.go b/ui/controller/controller.go index 52c7665..b597c9d 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -250,7 +250,7 @@ func (m *Controller) DoEditPlaylistWorkflow(playlist *mediaprovider.Playlist) { } func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) { - pass, err := c.App.ServerManager.GetServerPassword(server) + pass, err := c.App.ServerManager.GetServerPassword(server.ID) if err != nil { log.Printf("error getting password from keyring: %v", err) c.PromptForLoginAndConnect() @@ -269,7 +269,7 @@ func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) { func (m *Controller) PromptForLoginAndConnect() { // TODO: this will need to be rewritten a bit when we support multi servers // need to make sure the intended server is first in the list passed to NewLoginDialog - d := dialogs.NewLoginDialog(m.App.Config.Servers) + d := dialogs.NewLoginDialog(m.App.Config.Servers, m.App.ServerManager.GetServerPassword) pop := widget.NewModalPopUp(d, m.MainWindow.Canvas()) d.OnSubmit = func(server *backend.ServerConfig, password string) { d.DisableSubmit() @@ -311,6 +311,30 @@ func (m *Controller) PromptForLoginAndConnect() { } editPop.Show() } + d.OnNewServer = func() { + pop.Hide() + newD := dialogs.NewAddEditServerDialog("Add server", nil, m.MainWindow.Canvas().Focus) + newPop := widget.NewModalPopUp(newD, m.MainWindow.Canvas()) + newD.OnSubmit = func() { + d.DisableSubmit() + go func() { + if m.testConnectionAndUpdateDialogText(newD) { + newPop.Hide() + conn := backend.ServerConnection{ + Hostname: newD.Host, + AltHostname: newD.AltHost, + Username: newD.Username, + LegacyAuth: newD.LegacyAuth, + } + server := m.App.Config.AddServer(newD.Nickname, conn) + m.trySetPasswordAndConnectToServer(server, newD.Password) + m.doModalClosed() + } + d.EnableSubmit() + }() + } + newPop.Show() + } m.haveModal = true pop.Show() } diff --git a/ui/dialogs/logindialog.go b/ui/dialogs/logindialog.go index 9ef4a1f..292f9e7 100644 --- a/ui/dialogs/logindialog.go +++ b/ui/dialogs/logindialog.go @@ -2,6 +2,7 @@ package dialogs import ( "github.com/dweymouth/supersonic/backend" + "github.com/google/uuid" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" @@ -10,11 +11,14 @@ import ( "fyne.io/fyne/v2/widget" ) +type PasswordFetchFunc func(serverID uuid.UUID) (string, error) + type LoginDialog struct { widget.BaseWidget OnSubmit func(server *backend.ServerConfig, password string) OnEditServer func(server *backend.ServerConfig) + OnNewServer func() servers []*backend.ServerConfig serverSelect *widget.Select @@ -27,7 +31,7 @@ type LoginDialog struct { var _ fyne.Widget = (*LoginDialog)(nil) -func NewLoginDialog(servers []*backend.ServerConfig) *LoginDialog { +func NewLoginDialog(servers []*backend.ServerConfig, pwFetch PasswordFetchFunc) *LoginDialog { l := &LoginDialog{servers: servers} l.ExtendBaseWidget(l) titleLabel := widget.NewLabel("Login to Server") @@ -36,9 +40,20 @@ func NewLoginDialog(servers []*backend.ServerConfig) *LoginDialog { for i, s := range servers { serverNames[i] = s.Nickname } - l.serverSelect = widget.NewSelect(serverNames, func(_ string) {}) + l.serverSelect = widget.NewSelect(serverNames, func(_ string) { + if l.passField == nil { + return + } + if pwFetch != nil { + if pw, err := pwFetch(servers[l.serverSelect.SelectedIndex()].ID); err == nil { + l.passField.SetText(pw) + return + } + } + }) l.serverSelect.SetSelectedIndex(0) editBtn := widget.NewButtonWithIcon("", theme.DocumentCreateIcon(), l.onEditServer) + newBtn := widget.NewButtonWithIcon("", theme.ContentAddIcon(), l.onNewServer) l.passField = widget.NewPasswordEntry() l.passField.OnSubmitted = func(_ string) { l.onSubmit() } l.submitBtn = widget.NewButton("OK", l.onSubmit) @@ -51,7 +66,7 @@ func NewLoginDialog(servers []*backend.ServerConfig) *LoginDialog { container.NewHBox(layout.NewSpacer(), titleLabel, layout.NewSpacer()), container.New(layout.NewFormLayout(), widget.NewLabel("Server"), - container.NewBorder(nil, nil, nil, editBtn, l.serverSelect), + container.NewBorder(nil, nil, nil, container.NewHBox(editBtn, newBtn), l.serverSelect), widget.NewLabel("Password"), l.passField), widget.NewSeparator(), @@ -96,7 +111,7 @@ func (l *LoginDialog) CreateRenderer() fyne.WidgetRenderer { func (l *LoginDialog) MinSize() fyne.Size { l.ExtendBaseWidget(l) - return fyne.NewSize(300, l.container.MinSize().Height) + return fyne.NewSize(330, l.container.MinSize().Height) } func (l *LoginDialog) onSubmit() { @@ -110,3 +125,9 @@ func (l *LoginDialog) onEditServer() { l.OnEditServer(l.servers[l.serverSelect.SelectedIndex()]) } } + +func (l *LoginDialog) onNewServer() { + if l.OnNewServer != nil { + l.OnNewServer() + } +}