From db195bebf061d793ff34ba209059fe3f43e189e2 Mon Sep 17 00:00:00 2001
From: Tim Culverhouse <tim@timculverhouse.com>
Date: Fri, 29 Jul 2022 13:30:02 -0500
Subject: [PATCH] commands: add check-mail command

Add :check-mail command for ad-hoc checking of mail. Reset timer for
automatic checking if it is enabled.

Suggested-by: staceee
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
---
 CHANGELOG.md                   |  1 +
 commands/account/check-mail.go | 31 +++++++++++++++++++++++++++++++
 doc/aerc.1.scd                 |  5 +++++
 widgets/account.go             | 21 +++++++++++++++++++--
 4 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 commands/account/check-mail.go

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5434870..4b46fdc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Read-only mbox backend support.
 - Import/Export mbox files with `:import-mbox` and `:export-mbox`.
 - `address-book-cmd` can now also be specified in `accounts.conf`.
+- Run `check-mail-cmd` with `:check-mail`.
 
 ### Changed
 
diff --git a/commands/account/check-mail.go b/commands/account/check-mail.go
new file mode 100644
index 0000000..eb57c0c
--- /dev/null
+++ b/commands/account/check-mail.go
@@ -0,0 +1,31 @@
+package account
+
+import (
+	"errors"
+
+	"git.sr.ht/~rjarry/aerc/widgets"
+)
+
+type CheckMail struct{}
+
+func init() {
+	register(CheckMail{})
+}
+
+func (CheckMail) Aliases() []string {
+	return []string{"check-mail"}
+}
+
+func (CheckMail) Complete(aerc *widgets.Aerc, args []string) []string {
+	return nil
+}
+
+func (CheckMail) Execute(aerc *widgets.Aerc, args []string) error {
+	acct := aerc.SelectedAccount()
+	if acct == nil {
+		return errors.New("No account selected")
+	}
+	acct.CheckMailReset()
+	acct.CheckMail()
+	return nil
+}
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index b06dd43..ea3897b 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -259,6 +259,11 @@ message list, the message in the message viewer, etc).
 *cf* <folder>
 	Change the folder shown in the message list.
 
+*check-mail*
+	Check for new mail on the selected account. Non-imap backends require
+	check-mail-cmd in order to check for new mail. Issuing a manual
+	:check-mail command will reset the timer for automatic checking.
+
 *compose* [-H] [<body>] [-T <template-file>]
 	Open the compose window to send a new email. The new email will be sent with
 	the current account's outgoing transport configuration. For details on
diff --git a/widgets/account.go b/widgets/account.go
index 50b0fab..e5087ef 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -33,6 +33,10 @@ type AccountView struct {
 	state   *statusline.State
 	newConn bool // True if this is a first run after a new connection/reconnection
 	uiConf  *config.UIConfig
+
+	// Check-mail ticker
+	ticker       *time.Ticker
+	checkingMail bool
 }
 
 func (acct *AccountView) UiConfig() *config.UIConfig {
@@ -407,6 +411,9 @@ func (acct *AccountView) GetSortCriteria() []*types.SortCriterion {
 }
 
 func (acct *AccountView) CheckMail() {
+	if acct.checkingMail {
+		return
+	}
 	// Exclude selected mailbox, per IMAP specification
 	exclude := append(acct.AccountConfig().CheckMailExclude, acct.dirlist.Selected())
 	dirs := acct.dirlist.List()
@@ -419,11 +426,21 @@ func (acct *AccountView) CheckMail() {
 		Command:     acct.acct.CheckMailCmd,
 		Timeout:     acct.acct.CheckMailTimeout,
 	}
+	acct.checkingMail = true
 	acct.worker.PostAction(msg, func(_ types.WorkerMessage) {
 		acct.SetStatus(statusline.ConnectionActivity(""))
+		acct.checkingMail = false
 	})
 }
 
+// CheckMailReset resets the check-mail timer
+func (acct *AccountView) CheckMailReset() {
+	if acct.ticker != nil {
+		d := acct.AccountConfig().CheckMail
+		acct.ticker = time.NewTicker(d)
+	}
+}
+
 func (acct *AccountView) checkMailOnStartup() {
 	if acct.AccountConfig().CheckMail.Minutes() > 0 {
 		acct.newConn = false
@@ -432,9 +449,9 @@ func (acct *AccountView) checkMailOnStartup() {
 }
 
 func (acct *AccountView) CheckMailTimer(d time.Duration) {
-	ticker := time.NewTicker(d)
+	acct.ticker = time.NewTicker(d)
 	go func() {
-		for range ticker.C {
+		for range acct.ticker.C {
 			if !acct.state.Connected() {
 				continue
 			}