diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-05-13 20:16:55 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-05-13 20:16:55 -0400 |
commit | 026e8a17ca40955652949584388b38566fef66e7 (patch) | |
tree | a6430ec16308dc35ddeb1bc7f381a27124427739 | |
parent | bb46b2b7e15ba839475973ae44d5a833c6f2b265 (diff) |
Handle incoming emails gracefully
-rw-r--r-- | lib/msgstore.go | 6 | ||||
-rw-r--r-- | widgets/account.go | 12 | ||||
-rw-r--r-- | widgets/msglist.go | 1 | ||||
-rw-r--r-- | worker/imap/open.go | 3 | ||||
-rw-r--r-- | worker/imap/worker.go | 23 |
5 files changed, 36 insertions, 9 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go index b39d0bb..fb13346 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -1,6 +1,7 @@ package lib import ( + "fmt" "io" "sync" "time" @@ -140,6 +141,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { switch msg := msg.(type) { case *types.DirectoryInfo: store.DirInfo = *msg + fmt.Printf("got dirinfo, %d exists, %d known\n", + store.DirInfo.Exists, len(store.Uids)) + if store.DirInfo.Exists != len(store.Uids) { + store.worker.PostAction(&types.FetchDirectoryContents{}, nil) + } update = true case *types.DirectoryContents: newMap := make(map[uint32]*types.MessageInfo) diff --git a/widgets/account.go b/widgets/account.go index c01b15f..ba2b8d3 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -161,17 +161,17 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) { } else { acct.msglist.SetStore(nil) } - acct.worker.PostAction(&types.FetchDirectoryContents{}, - func(msg types.WorkerMessage) { - store := acct.msgStores[acct.dirlist.selected] - acct.msglist.SetStore(store) - }) } case *types.DirectoryInfo: if store, ok := acct.msgStores[msg.Name]; ok { store.Update(msg) } else { - acct.msgStores[msg.Name] = lib.NewMessageStore(acct.worker, msg) + store = lib.NewMessageStore(acct.worker, msg) + acct.msgStores[msg.Name] = store + store.OnUpdate(func(_ *lib.MessageStore) { + store.OnUpdate(nil) + acct.msglist.SetStore(store) + }) } case *types.DirectoryContents: store := acct.msgStores[acct.dirlist.selected] diff --git a/widgets/msglist.go b/widgets/msglist.go index eeadec7..65473a8 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -109,6 +109,7 @@ func (ml *MessageList) Height() int { } func (ml *MessageList) storeUpdate(store *lib.MessageStore) { + ml.logger.Println("message store updated") if ml.Store() != store { return } diff --git a/worker/imap/open.go b/worker/imap/open.go index dc5d6d1..ab54e88 100644 --- a/worker/imap/open.go +++ b/worker/imap/open.go @@ -17,6 +17,9 @@ func (imapw *IMAPWorker) handleOpenDirectory(msg *types.OpenDirectory) { }, nil) } else { imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil) + if imapw.idleStop == nil { + imapw.idleStop = make(chan struct{}) + } } } diff --git a/worker/imap/worker.go b/worker/imap/worker.go index 4354ab9..3d4555f 100644 --- a/worker/imap/worker.go +++ b/worker/imap/worker.go @@ -18,7 +18,7 @@ var errUnsupported = fmt.Errorf("unsupported command") type imapClient struct { *client.Client - *idle.IdleClient + idle *idle.IdleClient } type IMAPWorker struct { @@ -30,6 +30,8 @@ type IMAPWorker struct { } client *imapClient + idleStop chan struct{} + idleDone chan error selected imap.MailboxStatus updates chan client.Update worker *types.Worker @@ -39,8 +41,9 @@ type IMAPWorker struct { func NewIMAPWorker(worker *types.Worker) *IMAPWorker { return &IMAPWorker{ - updates: make(chan client.Update, 50), - worker: worker, + idleDone: make(chan error), + updates: make(chan client.Update, 50), + worker: worker, } } @@ -80,6 +83,13 @@ func (w *IMAPWorker) verifyPeerCert(msg types.WorkerMessage) func( } func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { + if w.idleStop != nil { + close(w.idleStop) + if err := <-w.idleDone; err != nil { + w.worker.PostMessage(&types.Error{Error: err}, nil) + } + } + switch msg := msg.(type) { case *types.Unsupported: // No-op @@ -167,6 +177,13 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error { default: return errUnsupported } + + if w.idleStop != nil { + w.idleStop = make(chan struct{}) + go func() { + w.idleDone <- w.client.idle.IdleWithFallback(w.idleStop, 0) + }() + } return nil } |