about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--commands/account/connection.go37
-rw-r--r--widgets/account.go59
-rw-r--r--worker/imap/worker.go16
3 files changed, 82 insertions, 30 deletions
diff --git a/commands/account/connection.go b/commands/account/connection.go
new file mode 100644
index 0000000..a87993b
--- /dev/null
+++ b/commands/account/connection.go
@@ -0,0 +1,37 @@
+package account
+
+import (
+	"errors"
+
+	"git.sr.ht/~rjarry/aerc/widgets"
+	"git.sr.ht/~rjarry/aerc/worker/types"
+)
+
+type Connection struct{}
+
+func init() {
+	register(Connection{})
+}
+
+func (Connection) Aliases() []string {
+	return []string{"connect", "disconnect"}
+}
+
+func (Connection) Complete(aerc *widgets.Aerc, args []string) []string {
+	return nil
+}
+
+func (Connection) Execute(aerc *widgets.Aerc, args []string) error {
+	acct := aerc.SelectedAccount()
+	if acct == nil {
+		return errors.New("No account selected")
+	}
+	if args[0] == "connect" {
+		acct.Worker().PostAction(&types.Connect{}, nil)
+		acct.SetStatus("Connecting...")
+	} else {
+		acct.Worker().PostAction(&types.Disconnect{}, nil)
+		acct.SetStatus("Disconnecting...")
+	}
+	return nil
+}
diff --git a/widgets/account.go b/widgets/account.go
index 891278a..2f126a3 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -85,7 +85,7 @@ func NewAccountView(aerc *Aerc, conf *config.AercConfig, acct *config.AccountCon
 	go worker.Backend.Run()
 
 	worker.PostAction(&types.Configure{Config: acct}, nil)
-	worker.PostAction(&types.Connect{}, view.connected)
+	worker.PostAction(&types.Connect{}, nil)
 	host.SetStatus("Connecting...")
 
 	return view, nil
@@ -105,6 +105,10 @@ func (acct *AccountView) Tick() bool {
 	}
 }
 
+func (acct *AccountView) SetStatus(msg string) {
+	acct.host.SetStatus(msg)
+}
+
 func (acct *AccountView) AccountConfig() *config.AccountConfig {
 	return acct.acct
 }
@@ -147,33 +151,6 @@ func (acct *AccountView) Focus(focus bool) {
 	// TODO: Unfocus children I guess
 }
 
-func (acct *AccountView) connected(msg types.WorkerMessage) {
-	switch msg.(type) {
-	case *types.Done:
-		acct.host.SetStatus("Listing mailboxes...")
-		acct.logger.Println("Listing mailboxes...")
-		acct.dirlist.UpdateList(func(dirs []string) {
-			var dir string
-			for _, _dir := range dirs {
-				if _dir == acct.acct.Default {
-					dir = _dir
-					break
-				}
-			}
-			if dir == "" && len(dirs) > 0 {
-				dir = dirs[0]
-			}
-			if dir != "" {
-				acct.dirlist.Select(dir)
-			}
-
-			acct.msglist.SetInitDone()
-			acct.logger.Println("Connected.")
-			acct.host.SetStatus("Connected.")
-		})
-	}
-}
-
 func (acct *AccountView) Directories() *DirectoryList {
 	return acct.dirlist
 }
@@ -225,6 +202,32 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
 	switch msg := msg.(type) {
 	case *types.Done:
 		switch msg.InResponseTo().(type) {
+		case *types.Connect:
+			acct.host.SetStatus("Listing mailboxes...")
+			acct.logger.Println("Listing mailboxes...")
+			acct.dirlist.UpdateList(func(dirs []string) {
+				var dir string
+				for _, _dir := range dirs {
+					if _dir == acct.acct.Default {
+						dir = _dir
+						break
+					}
+				}
+				if dir == "" && len(dirs) > 0 {
+					dir = dirs[0]
+				}
+				if dir != "" {
+					acct.dirlist.Select(dir)
+				}
+				acct.msglist.SetInitDone()
+				acct.logger.Println("Connected.")
+				acct.host.SetStatus("Connected.")
+			})
+		case *types.Disconnect:
+			acct.dirlist.UpdateList(nil)
+			acct.msglist.SetStore(nil)
+			acct.logger.Println("Disconnected.")
+			acct.host.SetStatus("Disconnected.")
 		case *types.OpenDirectory:
 			if store, ok := acct.dirlist.SelectedMsgStore(); ok {
 				// If we've opened this dir before, we can re-render it from
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index 82b81bd..cd52536 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -59,7 +59,7 @@ func NewIMAPWorker(worker *types.Worker) (types.Backend, error) {
 }
 
 func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
-	if w.idleStop != nil {
+	if w.client != nil && w.client.State() == imap.SelectedState {
 		close(w.idleStop)
 		if err := <-w.idleDone; err != nil {
 			w.worker.PostMessage(&types.Error{Error: err}, nil)
@@ -110,6 +110,9 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
 			c   *client.Client
 			err error
 		)
+		if w.client != nil {
+			return fmt.Errorf("Already connected")
+		}
 		switch w.config.scheme {
 		case "imap":
 			c, err = client.Dial(w.config.addr)
@@ -157,6 +160,15 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
 		c.Updates = w.updates
 		w.client = &imapClient{c, sortthread.NewSortClient(c)}
 		w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
+	case *types.Disconnect:
+		if w.client == nil {
+			return fmt.Errorf("Not connected")
+		}
+		if err := w.client.Logout(); err != nil {
+			return err
+		}
+		w.client = nil
+		w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
 	case *types.ListDirectories:
 		w.handleListDirectories(msg)
 	case *types.OpenDirectory:
@@ -189,7 +201,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
 		reterr = errUnsupported
 	}
 
-	if w.idleStop != nil {
+	if w.client != nil && w.client.State() == imap.SelectedState {
 		w.idleStop = make(chan struct{})
 		go func() {
 			w.idleDone <- w.client.Idle(w.idleStop, &client.IdleOptions{0, 0})