aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Culverhouse <tim@timculverhouse.com>2023-04-28 09:43:36 -0500
committerRobin Jarry <robin@jarry.cc>2023-04-28 20:58:24 +0200
commitef4504e6baf513713779b1e1af40848e746e704b (patch)
treecd8006d32dcc199e2fd825e51fedd1aed951064e
parente02479ad9ab802d5ab8da1ea614a579fc126ece6 (diff)
downloadaerc-ef4504e6baf513713779b1e1af40848e746e704b.tar.gz
aerc-ef4504e6baf513713779b1e1af40848e746e704b.zip
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>
-rw-r--r--worker/maildir/container.go9
-rw-r--r--worker/maildir/worker.go43
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) {