Fix #319: show cancelable modal dialog while connecting to server on startup

This commit is contained in:
Drew Weymouth
2024-02-15 09:04:14 -08:00
parent 6ac9337625
commit b61afb1ba5
2 changed files with 43 additions and 11 deletions
+2 -4
View File
@@ -58,7 +58,7 @@ func (s *ServerManager) ConnectToServer(conf *ServerConfig, password string) err
} }
func (s *ServerManager) TestConnectionAndAuth( func (s *ServerManager) TestConnectionAndAuth(
connection ServerConnection, password string, timeout time.Duration, ctx context.Context, connection ServerConnection, password string,
) error { ) error {
err := ErrUnreachable err := ErrUnreachable
done := make(chan bool) done := make(chan bool)
@@ -66,10 +66,8 @@ func (s *ServerManager) TestConnectionAndAuth(
_, err = s.connect(connection, password) _, err = s.connect(connection, password)
close(done) close(done)
}() }()
t := time.NewTimer(timeout)
defer t.Stop()
select { select {
case <-t.C: case <-ctx.Done():
return err return err
case <-done: case <-done:
return err return err
+41 -7
View File
@@ -2,6 +2,7 @@ package controller
import ( import (
"archive/zip" "archive/zip"
"context"
"fmt" "fmt"
"image" "image"
"io" "io"
@@ -348,13 +349,35 @@ func (m *Controller) DoEditPlaylistWorkflow(playlist *mediaprovider.Playlist) {
pop.Show() pop.Show()
} }
// DoConnectToServerWorkflow does the workflow for connecting to the last active server on startup
func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) { func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) {
pass, err := c.App.ServerManager.GetServerPassword(server.ID) pass, err := c.App.ServerManager.GetServerPassword(server.ID)
if err != nil { if err != nil {
log.Printf("error getting password from keyring: %v", err) log.Printf("error getting password from keyring: %v", err)
c.PromptForLoginAndConnect() c.PromptForLoginAndConnect()
} else { return
if err := c.tryConnectToServer(server, pass); err != nil { }
// try connecting to last used server - set up cancelable modal dialog
canceled := false
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
dlg := dialog.NewCustom("Connecting", "Cancel",
widget.NewLabel(fmt.Sprintf("Connecting to %s", server.Nickname)), c.MainWindow)
dlg.SetOnClosed(func() {
canceled = true
cancel()
})
c.haveModal = true
dlg.Show()
// try to connect
if err := c.tryConnectToServer(ctx, server, pass); err != nil {
dlg.Hide()
c.haveModal = false
if canceled {
c.PromptForLoginAndConnect()
} else {
// connection failure
dlg := dialog.NewError(err, c.MainWindow) dlg := dialog.NewError(err, c.MainWindow)
dlg.SetOnClosed(func() { dlg.SetOnClosed(func() {
c.PromptForLoginAndConnect() c.PromptForLoginAndConnect()
@@ -362,6 +385,9 @@ func (c *Controller) DoConnectToServerWorkflow(server *backend.ServerConfig) {
c.haveModal = true c.haveModal = true
dlg.Show() dlg.Show()
} }
} else {
dlg.Hide()
c.haveModal = false
} }
} }
@@ -372,7 +398,10 @@ func (m *Controller) PromptForLoginAndConnect() {
d.DisableSubmit() d.DisableSubmit()
d.SetInfoText("Testing connection...") d.SetInfoText("Testing connection...")
go func() { go func() {
err := m.App.ServerManager.TestConnectionAndAuth(server.ServerConnection, password, 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := m.App.ServerManager.TestConnectionAndAuth(ctx, server.ServerConnection, password)
if err == backend.ErrUnreachable { if err == backend.ErrUnreachable {
d.SetErrorText("Server unreachable") d.SetErrorText("Server unreachable")
} else if err != nil { } else if err != nil {
@@ -560,11 +589,14 @@ func (c *Controller) trySetPasswordAndConnectToServer(server *backend.ServerConf
// Don't return an error; fall back to just using the password in-memory // Don't return an error; fall back to just using the password in-memory
// User will need to log in with the password on subsequent runs. // User will need to log in with the password on subsequent runs.
} }
return c.tryConnectToServer(server, password) return c.tryConnectToServer(context.Background(), server, password)
} }
func (c *Controller) tryConnectToServer(server *backend.ServerConfig, password string) error { // try to connect to the given server, with a 10 second timeout added to the context
if err := c.App.ServerManager.TestConnectionAndAuth(server.ServerConnection, password, 10*time.Second); err != nil { func (c *Controller) tryConnectToServer(ctx context.Context, server *backend.ServerConfig, password string) error {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
if err := c.App.ServerManager.TestConnectionAndAuth(ctx, server.ServerConnection, password); err != nil {
return err return err
} }
if err := c.App.ServerManager.ConnectToServer(server, password); err != nil { if err := c.App.ServerManager.ConnectToServer(server, password); err != nil {
@@ -583,7 +615,9 @@ func (c *Controller) testConnectionAndUpdateDialogText(dlg *dialogs.AddEditServe
Username: dlg.Username, Username: dlg.Username,
LegacyAuth: dlg.LegacyAuth, LegacyAuth: dlg.LegacyAuth,
} }
err := c.App.ServerManager.TestConnectionAndAuth(conn, dlg.Password, 5*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := c.App.ServerManager.TestConnectionAndAuth(ctx, conn, dlg.Password)
if err == backend.ErrUnreachable { if err == backend.ErrUnreachable {
dlg.SetErrorText("Could not reach server (wrong hostname?)") dlg.SetErrorText("Could not reach server (wrong hostname?)")
return false return false