dirlist: update RUE counts for imap/maildir on move|copy|delete|archive

When moving/copying/deleting/archiving a message in imap, the RUE counts
displayed in the dirlist would not update properly. Maildir has (had) an
implementation that recounts the entire directory and updates the
DirectoryInfo after one of these actions.

This patch implements a more efficient method of updating, and also
enables it to apply to IMAP without any additional requests. Upon
completion of the action, the counts are manually updated with the count
of messages in the action and recent and/or unseen states of those
messages. This is more efficient for maildir, because we aren't counting
everything in the store. For IMAP, we get the updates for free because
we are only performing the update after confirmation from the server
that the action has happened.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Tim Culverhouse 2022-06-01 19:24:53 -05:00 committed by Robin Jarry
parent 4985d1bab8
commit 8b6f9719a8
5 changed files with 53 additions and 21 deletions

View File

@ -331,8 +331,42 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
} }
case *types.MessagesDeleted: case *types.MessagesDeleted:
if store, ok := acct.dirlist.SelectedMsgStore(); ok { if store, ok := acct.dirlist.SelectedMsgStore(); ok {
store.DirInfo.Exists -= len(msg.Uids)
// False to trigger recount of recent/unseen
store.DirInfo.AccurateCounts = false
store.Update(msg) store.Update(msg)
} }
case *types.MessagesCopied:
// Only update the destination destStore if it is initialized
if destStore, ok := acct.dirlist.MsgStore(msg.Destination); ok {
var recent, unseen int
for _, uid := range msg.Uids {
// Get the message from the originating store
msg, ok := acct.Store().Messages[uid]
if !ok {
continue
}
seen := false
for _, flag := range msg.Flags {
if flag == models.SeenFlag {
seen = true
}
if flag == models.RecentFlag {
recent = recent + 1
}
}
if !seen {
unseen = unseen + 1
}
}
destStore.DirInfo.Recent += recent
destStore.DirInfo.Unseen += unseen
destStore.DirInfo.Exists += len(msg.Uids)
// True. For imap, we don't have the message in the store until we
// Select so we need to rely on the math we just did for accurate
// counts
destStore.DirInfo.AccurateCounts = true
}
case *types.LabelList: case *types.LabelList:
acct.labels = msg.Labels acct.labels = msg.Labels
case *types.ConnError: case *types.ConnError:

View File

@ -244,16 +244,12 @@ func (dirlist *DirectoryList) getRUEString(name string) string {
return "" return ""
} }
var totalRecent, totalUnseen, totalExists int var totalRecent, totalUnseen, totalExists int
if msgStore.DirInfo.AccurateCounts { if !msgStore.DirInfo.AccurateCounts {
totalRecent = msgStore.DirInfo.Recent
totalUnseen = msgStore.DirInfo.Unseen
totalExists = msgStore.DirInfo.Exists
} else {
totalRecent, totalUnseen = countRUE(msgStore) totalRecent, totalUnseen = countRUE(msgStore)
// use the total count from the dirinfo, else we only count already msgStore.DirInfo.Recent = totalRecent
// fetched messages msgStore.DirInfo.Unseen = totalUnseen
totalExists = msgStore.DirInfo.Exists
} }
totalExists = msgStore.DirInfo.Exists
rueString := "" rueString := ""
if totalRecent > 0 { if totalRecent > 0 {
rueString = fmt.Sprintf("%d/%d/%d", totalRecent, totalUnseen, totalExists) rueString = fmt.Sprintf("%d/%d/%d", totalRecent, totalUnseen, totalExists)

View File

@ -14,6 +14,11 @@ func (imapw *IMAPWorker) handleCopyMessages(msg *types.CopyMessages) {
Error: err, Error: err,
}, nil) }, nil)
} else { } else {
imapw.worker.PostMessage(&types.MessagesCopied{
Message: types.RespondTo(msg),
Destination: msg.Destination,
Uids: msg.Uids,
}, nil)
imapw.worker.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil) imapw.worker.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil)
} }
} }

View File

@ -536,11 +536,6 @@ func (w *Worker) handleDeleteMessages(msg *types.DeleteMessages) error {
w.worker.Logger.Printf("error removing some messages: %v", err) w.worker.Logger.Printf("error removing some messages: %v", err)
return err return err
} }
w.worker.PostMessage(&types.DirectoryInfo{
Info: w.getDirectoryInfo(w.selectedName),
}, nil)
return nil return nil
} }
@ -617,15 +612,11 @@ func (w *Worker) handleCopyMessages(msg *types.CopyMessages) error {
if err != nil { if err != nil {
return err return err
} }
w.worker.PostMessage(&types.MessagesCopied{
w.worker.PostMessage(&types.DirectoryInfo{ Message: types.RespondTo(msg),
Info: w.getDirectoryInfo(w.selectedName), Destination: msg.Destination,
Uids: msg.Uids,
}, nil) }, nil)
w.worker.PostMessage(&types.DirectoryInfo{
Info: w.getDirectoryInfo(msg.Destination),
}, nil)
return nil return nil
} }

View File

@ -218,6 +218,12 @@ type MessagesDeleted struct {
Uids []uint32 Uids []uint32
} }
type MessagesCopied struct {
Message
Destination string
Uids []uint32
}
type ModifyLabels struct { type ModifyLabels struct {
Message Message
Uids []uint32 Uids []uint32