maildir: track the recent flag correctly
In the maildir worker we manually need to track the Recent flag in order for the notification command etc to work. Push that responsibility to the container, we must make sure to manually add the flag though if one grabs the message info.
This commit is contained in:
parent
8d4c6e1adf
commit
bc48628839
2 changed files with 55 additions and 31 deletions
|
@ -15,9 +15,10 @@ import (
|
|||
// A Container is a directory which contains other directories which adhere to
|
||||
// the Maildir spec
|
||||
type Container struct {
|
||||
dir string
|
||||
log *log.Logger
|
||||
uids *uidstore.Store
|
||||
dir string
|
||||
log *log.Logger
|
||||
uids *uidstore.Store
|
||||
recentUIDS map[uint32]struct{} // used to set the recent flag
|
||||
}
|
||||
|
||||
// NewContainer creates a new container at the specified directory
|
||||
|
@ -34,7 +35,8 @@ func NewContainer(dir string, l *log.Logger) (*Container, error) {
|
|||
if !s.IsDir() {
|
||||
return nil, fmt.Errorf("Given maildir '%s' not a directory", dir)
|
||||
}
|
||||
return &Container{dir: dir, uids: uidstore.NewStore(), log: l}, nil
|
||||
return &Container{dir: dir, uids: uidstore.NewStore(), log: l,
|
||||
recentUIDS: make(map[uint32]struct{})}, nil
|
||||
}
|
||||
|
||||
// ListFolders returns a list of maildir folders in the container
|
||||
|
@ -72,17 +74,26 @@ func (c *Container) ListFolders() ([]string, error) {
|
|||
return folders, err
|
||||
}
|
||||
|
||||
// SyncNewMail adds emails from new to cur, tracking them
|
||||
func (c *Container) SyncNewMail(dir maildir.Dir) error {
|
||||
keys, err := dir.Unseen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, key := range keys {
|
||||
uid := c.uids.GetOrInsert(key)
|
||||
c.recentUIDS[uid] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OpenDirectory opens an existing maildir in the container by name, moves new
|
||||
// messages into cur, and registers the new keys in the UIDStore.
|
||||
func (c *Container) OpenDirectory(name string) (maildir.Dir, error) {
|
||||
dir := c.Dir(name)
|
||||
keys, err := dir.Unseen()
|
||||
if err != nil {
|
||||
if err := c.SyncNewMail(dir); err != nil {
|
||||
return dir, err
|
||||
}
|
||||
for _, key := range keys {
|
||||
c.uids.GetOrInsert(key)
|
||||
}
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
|
@ -91,6 +102,17 @@ func (c *Container) Dir(name string) maildir.Dir {
|
|||
return maildir.Dir(filepath.Join(c.dir, name))
|
||||
}
|
||||
|
||||
// IsRecent returns if a uid has the Recent flag set
|
||||
func (c *Container) IsRecent(uid uint32) bool {
|
||||
_, ok := c.recentUIDS[uid]
|
||||
return ok
|
||||
}
|
||||
|
||||
// ClearRecentFlag removes the Recent flag from the message with the given uid
|
||||
func (c *Container) ClearRecentFlag(uid uint32) {
|
||||
delete(c.recentUIDS, uid)
|
||||
}
|
||||
|
||||
// UIDs fetches the unique message identifiers for the maildir
|
||||
func (c *Container) UIDs(d maildir.Dir) ([]uint32, error) {
|
||||
keys, err := d.Keys()
|
||||
|
|
|
@ -79,11 +79,12 @@ func (w *Worker) handleFSEvent(ev fsnotify.Event) {
|
|||
if w.selected == nil {
|
||||
return
|
||||
}
|
||||
newUnseen, err := w.selected.Unseen()
|
||||
err := w.c.SyncNewMail(*w.selected)
|
||||
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)
|
||||
|
@ -98,7 +99,6 @@ func (w *Worker) handleFSEvent(ev fsnotify.Event) {
|
|||
Uids: sortedUids,
|
||||
}, nil)
|
||||
dirInfo := w.getDirectoryInfo(w.selectedName)
|
||||
dirInfo.Recent = len(newUnseen)
|
||||
w.worker.PostMessage(&types.DirectoryInfo{
|
||||
Info: dirInfo,
|
||||
}, nil)
|
||||
|
@ -138,12 +138,6 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo {
|
|||
return dirInfo
|
||||
}
|
||||
|
||||
recent, err := dir.UnseenCount()
|
||||
if err != nil {
|
||||
w.worker.Logger.Printf("could not get unseen count: %v", err)
|
||||
}
|
||||
dirInfo.Recent = recent
|
||||
|
||||
for _, uid := range uids {
|
||||
message, err := w.c.Message(dir, uid)
|
||||
if err != nil {
|
||||
|
@ -164,9 +158,12 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo {
|
|||
if !seen {
|
||||
dirInfo.Unseen++
|
||||
}
|
||||
if w.c.IsRecent(uid) {
|
||||
dirInfo.Recent++
|
||||
}
|
||||
}
|
||||
dirInfo.Unseen += dirInfo.Recent
|
||||
dirInfo.Exists = len(uids) + recent
|
||||
dirInfo.Exists = len(uids) + dirInfo.Recent
|
||||
return dirInfo
|
||||
}
|
||||
|
||||
|
@ -332,12 +329,7 @@ func (w *Worker) sort(uids []uint32, criteria []*types.SortCriterion) ([]uint32,
|
|||
}
|
||||
var msgInfos []*models.MessageInfo
|
||||
for _, uid := range uids {
|
||||
m, err := w.c.Message(*w.selected, uid)
|
||||
if err != nil {
|
||||
w.worker.Logger.Printf("could not get message: %v", err)
|
||||
continue
|
||||
}
|
||||
info, err := m.MessageInfo()
|
||||
info, err := w.msgInfoFromUid(uid)
|
||||
if err != nil {
|
||||
w.worker.Logger.Printf("could not get message info: %v", err)
|
||||
continue
|
||||
|
@ -375,13 +367,7 @@ func (w *Worker) handleRemoveDirectory(msg *types.RemoveDirectory) error {
|
|||
func (w *Worker) handleFetchMessageHeaders(
|
||||
msg *types.FetchMessageHeaders) error {
|
||||
for _, uid := range msg.Uids {
|
||||
m, err := w.c.Message(*w.selected, uid)
|
||||
if err != nil {
|
||||
w.worker.Logger.Printf("could not get message: %v", err)
|
||||
w.err(msg, err)
|
||||
continue
|
||||
}
|
||||
info, err := m.MessageInfo()
|
||||
info, err := w.msgInfoFromUid(uid)
|
||||
if err != nil {
|
||||
w.worker.Logger.Printf("could not get message info: %v", err)
|
||||
w.err(msg, err)
|
||||
|
@ -391,6 +377,7 @@ func (w *Worker) handleFetchMessageHeaders(
|
|||
Message: types.RespondTo(msg),
|
||||
Info: info,
|
||||
}, nil)
|
||||
w.c.ClearRecentFlag(uid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -588,3 +575,18 @@ func (w *Worker) handleSearchDirectory(msg *types.SearchDirectory) error {
|
|||
}, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) {
|
||||
m, err := w.c.Message(*w.selected, uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := m.MessageInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w.c.IsRecent(uid) {
|
||||
info.Flags = append(info.Flags, models.RecentFlag)
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue