Fetch valid UIDs from server after opening dir

This commit is contained in:
Drew DeVault 2019-03-10 23:45:00 -04:00
parent 289e3b09ea
commit b3896476a0
6 changed files with 141 additions and 100 deletions

View file

@ -21,6 +21,7 @@ type AccountView struct {
interactive ui.Interactive interactive ui.Interactive
onInvalidate func(d ui.Drawable) onInvalidate func(d ui.Drawable)
runCmd func(cmd string) error runCmd func(cmd string) error
msgStores map[string]*MessageStore
statusline *StatusLine statusline *StatusLine
statusbar *ui.Stack statusbar *ui.Stack
worker *types.Worker worker *types.Worker
@ -64,9 +65,10 @@ func NewAccountView(conf *config.AccountConfig,
dirlist: dirlist, dirlist: dirlist,
grid: grid, grid: grid,
logger: logger, logger: logger,
msgStores: make(map[string]*MessageStore),
runCmd: runCmd, runCmd: runCmd,
statusline: statusline,
statusbar: statusbar, statusbar: statusbar,
statusline: statusline,
worker: worker, worker: worker,
} }
@ -157,10 +159,6 @@ func (acct *AccountView) connected(msg types.WorkerMessage) {
Message: types.RespondTo(msg), Message: types.RespondTo(msg),
Approved: true, Approved: true,
}, acct.connected) }, acct.connected)
case *types.Error:
acct.logger.Printf("%v", msg.Error)
acct.statusline.Set(fmt.Sprintf("%v", msg.Error)).
Color(tcell.ColorRed, tcell.ColorDefault)
} }
} }
@ -169,5 +167,30 @@ func (acct *AccountView) Directories() *DirectoryList {
} }
func (acct *AccountView) onMessage(msg types.WorkerMessage) { func (acct *AccountView) onMessage(msg types.WorkerMessage) {
// TODO switch msg := msg.(type) {
case *types.Done:
switch msg.InResponseTo().(type) {
case *types.OpenDirectory:
acct.worker.PostAction(&types.FetchDirectoryContents{},
func(msg types.WorkerMessage) {
// TODO: Do we care
})
}
case *types.DirectoryInfo:
if store, ok := acct.msgStores[msg.Name]; ok {
store.Update(msg)
} else {
acct.msgStores[msg.Name] = NewMessageStore(msg)
}
case *types.DirectoryContents:
store := acct.msgStores[acct.dirlist.selected]
store.Update(msg)
case *types.MessageInfo:
store := acct.msgStores[acct.dirlist.selected]
store.Update(msg)
case *types.Error:
acct.logger.Printf("%v", msg.Error)
acct.statusline.Set(fmt.Sprintf("%v", msg.Error)).
Color(tcell.ColorRed, tcell.ColorDefault)
}
} }

36
widgets/msglist.go Normal file
View file

@ -0,0 +1,36 @@
package widgets
import (
"git.sr.ht/~sircmpwn/aerc2/worker/types"
)
type MessageStore struct {
DirInfo types.DirectoryInfo
Messages map[uint64]*types.MessageInfo
}
func NewMessageStore(dirInfo *types.DirectoryInfo) *MessageStore {
return &MessageStore{DirInfo: *dirInfo}
}
func (store *MessageStore) Update(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.DirectoryInfo:
store.DirInfo = *msg
break
case *types.DirectoryContents:
newMap := make(map[uint64]*types.MessageInfo)
for _, uid := range msg.Uids {
if msg, ok := store.Messages[uid]; ok {
newMap[uid] = msg
} else {
newMap[uid] = nil
}
}
store.Messages = newMap
break
case *types.MessageInfo:
store.Messages[msg.Uid] = msg
break
}
}

View file

@ -1,6 +1,8 @@
package imap package imap
import ( import (
"github.com/emersion/go-imap"
"git.sr.ht/~sircmpwn/aerc2/worker/types" "git.sr.ht/~sircmpwn/aerc2/worker/types"
) )
@ -18,3 +20,35 @@ func (imapw *IMAPWorker) handleOpenDirectory(msg *types.OpenDirectory) {
} }
}() }()
} }
func (imapw *IMAPWorker) handleFetchDirectoryContents(
msg *types.FetchDirectoryContents) {
imapw.worker.Logger.Printf("Fetching UID list")
go func() {
seqSet := &imap.SeqSet{}
seqSet.AddRange(1, imapw.selected.Messages)
uid32, err := imapw.client.UidSearch(&imap.SearchCriteria{
SeqNum: seqSet,
})
if err != nil {
imapw.worker.PostMessage(&types.Error{
Message: types.RespondTo(msg),
Error: err,
}, nil)
} else {
imapw.worker.Logger.Printf("Found %d UIDs", len(uid32))
var uids []uint64
for _, uid := range uid32 {
uids = append(uids,
(uint64(imapw.selected.UidValidity)<<32)|uint64(uid))
}
imapw.worker.PostMessage(&types.DirectoryContents{
Message: types.RespondTo(msg),
Uids: uids,
}, nil)
imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
}
}()
}

View file

@ -29,9 +29,10 @@ type IMAPWorker struct {
user *url.Userinfo user *url.Userinfo
} }
worker *types.Worker client *imapClient
client *imapClient selected imap.MailboxStatus
updates chan client.Update updates chan client.Update
worker *types.Worker
} }
func NewIMAPWorker(worker *types.Worker) *IMAPWorker { func NewIMAPWorker(worker *types.Worker) *IMAPWorker {
@ -151,6 +152,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
w.handleListDirectories(msg) w.handleListDirectories(msg)
case *types.OpenDirectory: case *types.OpenDirectory:
w.handleOpenDirectory(msg) w.handleOpenDirectory(msg)
case *types.FetchDirectoryContents:
w.handleFetchDirectoryContents(msg)
default: default:
return errUnsupported return errUnsupported
} }
@ -162,6 +165,9 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
switch update := update.(type) { switch update := update.(type) {
case *client.MailboxUpdate: case *client.MailboxUpdate:
status := update.Mailbox status := update.Mailbox
if w.selected.Name == status.Name {
w.selected = *status
}
w.worker.PostMessage(&types.DirectoryInfo{ w.worker.PostMessage(&types.DirectoryInfo{
Flags: status.Flags, Flags: status.Flags,
Name: status.Name, Name: status.Name,

View file

@ -1,91 +0,0 @@
package worker
import (
"crypto/x509"
"git.sr.ht/~sircmpwn/aerc2/config"
)
type WorkerMessage interface {
InResponseTo() WorkerMessage
}
type Message struct {
inResponseTo WorkerMessage
}
func RespondTo(msg WorkerMessage) Message {
return Message{
inResponseTo: msg,
}
}
func (m Message) InResponseTo() WorkerMessage {
return m.inResponseTo
}
// Meta-messages
type Done struct {
Message
}
type Error struct {
Message
Error error
}
type Unsupported struct {
Message
}
// Actions
type ApproveCertificate struct {
Message
Approved bool
}
type Configure struct {
Message
Config *config.AccountConfig
}
type Connect struct {
Message
}
type Disconnect struct {
Message
}
type ListDirectories struct {
Message
}
type OpenDirectory struct {
Message
Directory string
}
// Messages
type CertificateApprovalRequest struct {
Message
CertPool *x509.CertPool
}
type Directory struct {
Message
Attributes []string
Name string
}
type DirectoryInfo struct {
Message
Flags []string
Name string
ReadOnly bool
Exists, Recent, Unseen int
}

View file

@ -2,6 +2,10 @@ package types
import ( import (
"crypto/x509" "crypto/x509"
"net/mail"
"time"
"github.com/emersion/go-imap"
"git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/config"
) )
@ -68,6 +72,20 @@ type OpenDirectory struct {
Directory string Directory string
} }
type FetchDirectoryContents struct {
Message
}
type FetchMessageHeaders struct {
Message
Uids imap.SeqSet
}
type FetchMessageBodies struct {
Message
Uids imap.SeqSet
}
// Messages // Messages
type CertificateApprovalRequest struct { type CertificateApprovalRequest struct {
@ -89,3 +107,18 @@ type DirectoryInfo struct {
Exists, Recent, Unseen int Exists, Recent, Unseen int
} }
type DirectoryContents struct {
Message
Uids []uint64
}
type MessageInfo struct {
Message
Envelope *imap.Envelope
Flags []string
InternalDate time.Time
Mail *mail.Message
Size uint32
Uid uint64
}