imap: properly update UI upon message (un)read in another client

I access my personal mailbox from at least 3 different clients, and have
noticed that aerc only half handles the read/unread actions made from
another client on messages in the currently selected directory. While
the message list is properly updated, the unread count is not, and I end
up again looking for unread messages that don't exist :-)

The problem is that in such scenarii, aerc receives a MessageUpdate
message from the IMAP server, and if it already has a message with the
same UID in its message store, happily replaces it... without looking at
the Seen status, that is materialized outside of the message table.

This patch detects when the Seen status changes, and updates the UI
accordingly.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Simon Martin
2025-03-24 19:32:08 +00:00
committed by Robin Jarry
parent b457f80470
commit b576ab281d

View File

@@ -466,6 +466,25 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
}
case *types.MessageInfo:
if store, ok := acct.dirlist.SelectedMsgStore(); ok {
if existing := store.Messages[msg.Info.Uid]; existing != nil {
// It this is an update of a message we already know, we'll
// have merged the update into the existing message already,
// but not the properties materialized outside of the Messages
// array, e.g. the Seen and Recent counters. Only consider Seen
// since it's the only one that can be altered as per
// https://datatracker.ietf.org/doc/html/rfc3501#section-2.3.2.
old_seen := existing.Flags.Has(models.SeenFlag)
new_seen := msg.Info.Flags.Has(models.SeenFlag)
dir := acct.dirlist.SelectedDirectory()
if old_seen != new_seen && dir != nil {
if old_seen && !new_seen {
dir.Unseen += 1
} else if !old_seen && new_seen {
dir.Unseen -= 1
}
}
}
store.Update(msg)
}
case *types.MessagesDeleted: