From 9c0e54f9d9afb5f4a9d91ca9766fc2ef2cfd82de Mon Sep 17 00:00:00 2001
From: kt programs <ktprograms@gmail.com>
Date: Sun, 25 Sep 2022 09:55:21 +0800
Subject: [PATCH] imap: stop checkmail if there are pending actions

Pass message containing remaining directories to check. Account widget
will recursively call CheckMail with the remaining directories until
a Done message is returned.

Only needed for IMAP worker as other workers run check-mail-cmd in
a separate goroutine.

Suggested-By: Tim Culverhouse <tim@timculverhouse.com>
Signed-off-by: kt programs <ktprograms@gmail.com>
Tested-by: Tim Culverhouse <tim@timculverhouse.com>
---
 widgets/account.go       | 25 +++++++++++++++++++------
 worker/imap/checkmail.go | 13 +++++++++++++
 worker/types/messages.go |  5 +++++
 3 files changed, 37 insertions(+), 6 deletions(-)

diff --git a/widgets/account.go b/widgets/account.go
index 382a07a..c131f33 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -438,12 +438,25 @@ func (acct *AccountView) CheckMail() {
 		Timeout:     acct.acct.CheckMailTimeout,
 	}
 	acct.checkingMail = true
-	acct.worker.PostAction(msg, func(_ types.WorkerMessage) {
-		acct.SetStatus(statusline.ConnectionActivity(""))
-		acct.Lock()
-		acct.checkingMail = false
-		acct.Unlock()
-	})
+
+	var cb func(types.WorkerMessage)
+	cb = func(response types.WorkerMessage) {
+		dirsMsg, ok := response.(*types.CheckMailDirectories)
+		if ok {
+			checkMailMsg := &types.CheckMail{
+				Directories: dirsMsg.Directories,
+				Command:     acct.acct.CheckMailCmd,
+				Timeout:     acct.acct.CheckMailTimeout,
+			}
+			acct.worker.PostAction(checkMailMsg, cb)
+		} else { // Done
+			acct.SetStatus(statusline.ConnectionActivity(""))
+			acct.Lock()
+			acct.checkingMail = false
+			acct.Unlock()
+		}
+	}
+	acct.worker.PostAction(msg, cb)
 }
 
 // CheckMailReset resets the check-mail timer
diff --git a/worker/imap/checkmail.go b/worker/imap/checkmail.go
index 21f2e4b..e0aef71 100644
--- a/worker/imap/checkmail.go
+++ b/worker/imap/checkmail.go
@@ -13,7 +13,13 @@ func (w *IMAPWorker) handleCheckMailMessage(msg *types.CheckMail) {
 		imap.StatusRecent,
 		imap.StatusUnseen,
 	}
+	var remaining []string
 	for _, dir := range msg.Directories {
+		if len(w.worker.Actions) > 0 {
+			remaining = append(remaining, dir)
+			continue
+		}
+
 		logging.Debugf("Getting status of directory %s", dir)
 		status, err := w.client.Status(dir, items)
 		if err != nil {
@@ -38,5 +44,12 @@ func (w *IMAPWorker) handleCheckMailMessage(msg *types.CheckMail) {
 			}, nil)
 		}
 	}
+	if len(remaining) > 0 {
+		w.worker.PostMessage(&types.CheckMailDirectories{
+			Message:     types.RespondTo(msg),
+			Directories: remaining,
+		}, nil)
+		return
+	}
 	w.worker.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil)
 }
diff --git a/worker/types/messages.go b/worker/types/messages.go
index 9194cbe..00a1a78 100644
--- a/worker/types/messages.go
+++ b/worker/types/messages.go
@@ -255,3 +255,8 @@ type LabelList struct {
 	Message
 	Labels []string
 }
+
+type CheckMailDirectories struct {
+	Message
+	Directories []string
+}