aboutsummaryrefslogtreecommitdiff
path: root/worker/maildir
diff options
context:
space:
mode:
Diffstat (limited to 'worker/maildir')
-rw-r--r--worker/maildir/worker.go81
1 files changed, 68 insertions, 13 deletions
diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go
index a5416cc..1e68a2e 100644
--- a/worker/maildir/worker.go
+++ b/worker/maildir/worker.go
@@ -8,6 +8,7 @@ import (
"path/filepath"
"github.com/emersion/go-maildir"
+ "github.com/fsnotify/fsnotify"
"git.sr.ht/~sircmpwn/aerc/models"
"git.sr.ht/~sircmpwn/aerc/worker/types"
@@ -20,31 +21,68 @@ type Worker struct {
c *Container
selected *maildir.Dir
worker *types.Worker
+ watcher *fsnotify.Watcher
}
// NewWorker creates a new maildir worker with the provided worker.
-func NewWorker(worker *types.Worker) *Worker {
- return &Worker{worker: worker}
+func NewWorker(worker *types.Worker) (*Worker, error) {
+ watch, err := fsnotify.NewWatcher()
+ if err != nil {
+ return nil, fmt.Errorf("could not create file system watcher: %v", err)
+ }
+ return &Worker{worker: worker, watcher: watch}, nil
}
// Run starts the worker's message handling loop.
func (w *Worker) Run() {
for {
- action := <-w.worker.Actions
- msg := w.worker.ProcessAction(action)
- if err := w.handleMessage(msg); err == errUnsupported {
- w.worker.PostMessage(&types.Unsupported{
- Message: types.RespondTo(msg),
- }, nil)
- } else if err != nil {
- w.worker.PostMessage(&types.Error{
- Message: types.RespondTo(msg),
- Error: err,
- }, nil)
+ select {
+ case action := <-w.worker.Actions:
+ w.handleAction(action)
+ case ev := <-w.watcher.Events:
+ w.handleFSEvent(ev)
}
}
}
+func (w *Worker) handleAction(action types.WorkerMessage) {
+ msg := w.worker.ProcessAction(action)
+ if err := w.handleMessage(msg); err == errUnsupported {
+ w.worker.PostMessage(&types.Unsupported{
+ Message: types.RespondTo(msg),
+ }, nil)
+ } else if err != nil {
+ w.worker.PostMessage(&types.Error{
+ Message: types.RespondTo(msg),
+ Error: err,
+ }, nil)
+ }
+}
+
+func (w *Worker) handleFSEvent(ev fsnotify.Event) {
+ // we only care about files being created
+ if ev.Op != fsnotify.Create {
+ return
+ }
+ // if there's not a selected directory to rescan, ignore
+ if w.selected == nil {
+ return
+ }
+ _, err := w.selected.Unseen()
+ if err != nil {
+ w.worker.Logger.Printf("could not move new to cur : %v", err)
+ return
+ }
+ uids, err := w.c.UIDs(*w.selected)
+ if err != nil {
+ w.worker.Logger.Printf("could not scan UIDs: %v", err)
+ return
+ }
+ w.worker.PostMessage(&types.DirectoryContents{
+ Uids: uids,
+ }, nil)
+}
+
func (w *Worker) done(msg types.WorkerMessage) {
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
}
@@ -139,11 +177,28 @@ func (w *Worker) handleListDirectories(msg *types.ListDirectories) error {
func (w *Worker) handleOpenDirectory(msg *types.OpenDirectory) error {
defer w.done(msg)
w.worker.Logger.Printf("opening %s", msg.Directory)
+
+ // remove existing watch path
+ if w.selected != nil {
+ prevDir := filepath.Join(string(*w.selected), "new")
+ if err := w.watcher.Remove(prevDir); err != nil {
+ return fmt.Errorf("could not unwatch previous directory: %v", err)
+ }
+ }
+
+ // open the directory
dir, err := w.c.OpenDirectory(msg.Directory)
if err != nil {
return err
}
w.selected = &dir
+
+ // add watch path
+ newDir := filepath.Join(string(*w.selected), "new")
+ if err := w.watcher.Add(newDir); err != nil {
+ return fmt.Errorf("could not add watch to directory: %v", err)
+ }
+
// TODO: why does this need to be sent twice??
info := &types.DirectoryInfo{
Info: &models.DirectoryInfo{