diff options
author | Tim Culverhouse <tim@timculverhouse.com> | 2023-04-28 09:43:36 -0500 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-04-28 20:58:24 +0200 |
commit | ef4504e6baf513713779b1e1af40848e746e704b (patch) | |
tree | cd8006d32dcc199e2fd825e51fedd1aed951064e /worker | |
parent | e02479ad9ab802d5ab8da1ea614a579fc126ece6 (diff) | |
download | aerc-ef4504e6baf513713779b1e1af40848e746e704b.tar.gz |
maildir: fix handling of FSEvents
Maildir uses a filesystem watcher to watch the currently selected
directory for changes, updating the UI as necessary. Not all changes get
updated based on the current logic. Send a MessageInfo if the event was
a Rename. Send a MessagesDeleted if the event was a Remove. Tell the UI
to refetch the list if the event was a Create.
Note: This leads to some unnecessary fetching in the UI, as renames also
come with a Create event in most cases. Koni suggested sending the
MessageInfo and having the UI perform a binary search and inserting the
message in the proper position. This is optimization is left out of this
series, with a TODO left in the code.
Fixes: https://todo.sr.ht/~rjarry/aerc/171
Fixes: 91ac21ac6155 ("msgstore: fetch message list based on OpenDirectory msg")
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'worker')
-rw-r--r-- | worker/maildir/container.go | 9 | ||||
-rw-r--r-- | worker/maildir/worker.go | 43 |
2 files changed, 44 insertions, 8 deletions
diff --git a/worker/maildir/container.go b/worker/maildir/container.go index f9fb507b..946de74d 100644 --- a/worker/maildir/container.go +++ b/worker/maildir/container.go @@ -93,6 +93,15 @@ func (c *Container) Message(d maildir.Dir, uid uint32) (*Message, error) { uid, d) } +func (c *Container) MessageFromKey(d maildir.Dir, key string) *Message { + uid := c.uids.GetOrInsert(key) + return &Message{ + dir: d, + uid: uid, + key: key, + } +} + // DeleteAll deletes a set of messages by UID and returns the subset of UIDs // which were successfully deleted, stopping upon the first error. func (c *Container) DeleteAll(d maildir.Dir, uids []uint32) ([]uint32, error) { diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 69d39fa8..ded0faac 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -132,15 +132,42 @@ func (w *Worker) handleFSEvent(ev *types.FSEvent) { return } - dirInfo := w.getDirectoryInfo(w.selectedName) - var refetch bool - if dirInfo.Exists > w.selectedInfo.Exists { - refetch = true + w.selectedInfo = w.getDirectoryInfo(w.selectedName) + dirInfoMsg := &types.DirectoryInfo{ + Info: w.selectedInfo, } - w.worker.PostMessage(&types.DirectoryInfo{ - Info: dirInfo, - Refetch: refetch, - }, nil) + + base := filepath.Base(ev.Path) + parts := strings.SplitN(base, ":", 2) + if len(parts) != 2 { + log.Errorf("Couldn't parse key from file: %s", ev.Path) + return + } + msg := w.c.MessageFromKey(*w.selected, parts[0]) + + switch ev.Operation { + case types.FSCreate: + // TODO for FSCreate we should send a new message type that + // creates the message in the UI, does a binary search based on + // current sort criteria and inserts message at proper index + // For now, we just refetch the list. + dirInfoMsg.Refetch = true + case types.FSRename: + msgInfo, err := msg.MessageInfo() + if err != nil { + log.Errorf(err.Error()) + return + } + w.worker.PostMessage(&types.MessageInfo{ + Info: msgInfo, + }, nil) + case types.FSRemove: + w.worker.PostMessage(&types.MessagesDeleted{ + Uids: []uint32{msg.uid}, + }, nil) + } + + w.worker.PostMessage(dirInfoMsg, nil) } func (w *Worker) done(msg types.WorkerMessage) { |