~sircmpwn/aerc

026e8a17ca40955652949584388b38566fef66e7 — Drew DeVault 2 years ago bb46b2b
Handle incoming emails gracefully
5 files changed, 36 insertions(+), 9 deletions(-)

M lib/msgstore.go
M widgets/account.go
M widgets/msglist.go
M worker/imap/open.go
M worker/imap/worker.go
M lib/msgstore.go => lib/msgstore.go +6 -0
@@ 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)

M widgets/account.go => widgets/account.go +6 -6
@@ 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]

M widgets/msglist.go => widgets/msglist.go +1 -0
@@ 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
	}

M worker/imap/open.go => worker/imap/open.go +3 -0
@@ 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{})
		}
	}
}


M worker/imap/worker.go => worker/imap/worker.go +20 -3
@@ 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
}