diff options
-rw-r--r-- | commands/account/import-mbox.go | 2 | ||||
-rw-r--r-- | commands/compose/postpone.go | 2 | ||||
-rw-r--r-- | commands/compose/send.go | 2 | ||||
-rw-r--r-- | commands/msg/read.go | 11 | ||||
-rw-r--r-- | lib/emlview.go | 4 | ||||
-rw-r--r-- | lib/format/format.go | 63 | ||||
-rw-r--r-- | lib/msgstore.go | 15 | ||||
-rw-r--r-- | models/models.go | 12 | ||||
-rw-r--r-- | widgets/account.go | 11 | ||||
-rw-r--r-- | widgets/dirlist.go | 12 | ||||
-rw-r--r-- | widgets/msglist.go | 16 | ||||
-rw-r--r-- | worker/imap/cache.go | 2 | ||||
-rw-r--r-- | worker/imap/flags.go | 3 | ||||
-rw-r--r-- | worker/imap/imap.go | 16 | ||||
-rw-r--r-- | worker/lib/maildir.go | 16 | ||||
-rw-r--r-- | worker/lib/parse.go | 2 | ||||
-rw-r--r-- | worker/lib/parse_test.go | 6 | ||||
-rw-r--r-- | worker/lib/search.go | 49 | ||||
-rw-r--r-- | worker/lib/sort.go | 10 | ||||
-rw-r--r-- | worker/maildir/message.go | 4 | ||||
-rw-r--r-- | worker/maildir/worker.go | 4 | ||||
-rw-r--r-- | worker/mbox/io.go | 2 | ||||
-rw-r--r-- | worker/mbox/models.go | 27 | ||||
-rw-r--r-- | worker/mbox/worker.go | 5 | ||||
-rw-r--r-- | worker/notmuch/message.go | 20 | ||||
-rw-r--r-- | worker/notmuch/worker.go | 5 | ||||
-rw-r--r-- | worker/types/messages.go | 4 | ||||
-rw-r--r-- | worker/types/worker.go | 2 |
28 files changed, 120 insertions, 207 deletions
diff --git a/commands/account/import-mbox.go b/commands/account/import-mbox.go index 7dab1958..b03d8d78 100644 --- a/commands/account/import-mbox.go +++ b/commands/account/import-mbox.go @@ -84,7 +84,7 @@ func (ImportMbox) Execute(aerc *widgets.Aerc, args []string) error { nbytes, _ := io.Copy(&buf, r) worker.PostAction(&types.AppendMessage{ Destination: folder, - Flags: []models.Flag{models.SeenFlag}, + Flags: models.SeenFlag, Date: time.Now(), Reader: &buf, Length: int(nbytes), diff --git a/commands/compose/postpone.go b/commands/compose/postpone.go index eb7bc0a3..cc709ff7 100644 --- a/commands/compose/postpone.go +++ b/commands/compose/postpone.go @@ -95,7 +95,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error { nbytes := int(ctr.Count()) worker.PostAction(&types.AppendMessage{ Destination: config.Postpone, - Flags: []models.Flag{models.SeenFlag}, + Flags: models.SeenFlag, Date: time.Now(), Reader: &buf, Length: int(nbytes), diff --git a/commands/compose/send.go b/commands/compose/send.go index c5f4be3b..4c2b0503 100644 --- a/commands/compose/send.go +++ b/commands/compose/send.go @@ -502,7 +502,7 @@ func copyToSent(worker *types.Worker, dest string, errCh := make(chan error) worker.PostAction(&types.AppendMessage{ Destination: dest, - Flags: []models.Flag{models.SeenFlag}, + Flags: models.SeenFlag, Date: time.Now(), Reader: msg, Length: n, diff --git a/commands/msg/read.go b/commands/msg/read.go index 878dc3c8..cffd2218 100644 --- a/commands/msg/read.go +++ b/commands/msg/read.go @@ -34,7 +34,7 @@ func (FlagMsg) Complete(aerc *widgets.Aerc, args []string) []string { // 'flag' or 'unflag', respectively, but the 'Seen' flag is affected. func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error { // The flag to change - var flag models.Flag + var flag models.Flags // User-readable name of the flag to change var flagName string // Whether to toggle the flag (true) or to enable/disable it (false) @@ -130,14 +130,7 @@ func (FlagMsg) Execute(aerc *widgets.Aerc, args []string) error { return err } for _, m := range msgs { - var enabled bool - for _, mFlag := range m.Flags { - if mFlag == flag { - enabled = true - break - } - } - if enabled { + if m.Flags.Has(flag) { toDisable = append(toDisable, m.Uid) } else { toEnable = append(toEnable, m.Uid) diff --git a/lib/emlview.go b/lib/emlview.go index e0dcb436..ab3ce87e 100644 --- a/lib/emlview.go +++ b/lib/emlview.go @@ -27,8 +27,8 @@ func (fm *EmlMessage) Labels() ([]string, error) { return nil, nil } -func (fm *EmlMessage) ModelFlags() ([]models.Flag, error) { - return []models.Flag{models.SeenFlag}, nil +func (fm *EmlMessage) ModelFlags() (models.Flags, error) { + return models.SeenFlag, nil } // NewEmlMessageView provides a MessageView for a full message that is not diff --git a/lib/format/format.go b/lib/format/format.go index 346702c6..3f00fe18 100644 --- a/lib/format/format.go +++ b/lib/format/format.go @@ -294,53 +294,36 @@ func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string, } case 'Z': // calculate all flags - readReplyFlag := "" - delFlag := "" - flaggedFlag := "" - markedFlag := "" - hasattachment := "" - seen := false - recent := false - answered := false - for _, flag := range ctx.MsgInfo.Flags { - switch flag { - case models.SeenFlag: - seen = true - case models.RecentFlag: - recent = true - case models.AnsweredFlag: - answered = true - } - if flag == models.DeletedFlag { - delFlag = "D" - // TODO: check if attachments - } - if flag == models.FlaggedFlag { - flaggedFlag = "!" - } - // TODO: check gpg stuff - } - if seen { - if answered { - readReplyFlag = "r" // message has been replied to - } - } else { - if recent { - readReplyFlag = "N" // message is new - } else { - readReplyFlag = "O" // message is old - } + flags := ctx.MsgInfo.Flags + f := "" + + switch { + case flags.Has(models.SeenFlag | models.AnsweredFlag): + f += "r" // message has been replied to + case flags.Has(models.SeenFlag): + break + case flags.Has(models.RecentFlag): + f += "N" // message is new + default: + f += "O" // message is old } - if ctx.MsgIsMarked { - markedFlag = "*" + if flags.Has(models.DeletedFlag) { + f += "D" } for _, bS := range ctx.MsgInfo.BodyStructure.Parts { if strings.ToLower(bS.Disposition) == "attachment" { - hasattachment = iconAttachment + f += iconAttachment + break } } + if flags.Has(models.FlaggedFlag) { + f += "!" + } + if ctx.MsgIsMarked { + f += "*" + } retval = append(retval, '4', 's') - args = append(args, readReplyFlag+delFlag+flaggedFlag+markedFlag+hasattachment) + args = append(args, f) // Move the below cases to proper alphabetical positions once // implemented diff --git a/lib/msgstore.go b/lib/msgstore.go index 8b2d0419..d2851db2 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -269,15 +269,8 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { store.Unlock() store.fetchFlags() } - seen := false - recent := false - for _, flag := range msg.Info.Flags { - if flag == models.RecentFlag { - recent = true - } else if flag == models.SeenFlag { - seen = true - } - } + seen := msg.Info.Flags.Has(models.RecentFlag) + recent := msg.Info.Flags.Has(models.SeenFlag) if !seen && recent { store.triggerNewEmail(msg.Info) } @@ -563,12 +556,12 @@ func (store *MessageStore) Move(uids []uint32, dest string, createDest bool, }) } -func (store *MessageStore) Flag(uids []uint32, flag models.Flag, +func (store *MessageStore) Flag(uids []uint32, flags models.Flags, enable bool, cb func(msg types.WorkerMessage), ) { store.worker.PostAction(&types.FlagMessages{ Enable: enable, - Flag: flag, + Flags: flags, Uids: uids, }, cb) } diff --git a/models/models.go b/models/models.go index fb628f63..ac2e170a 100644 --- a/models/models.go +++ b/models/models.go @@ -10,13 +10,13 @@ import ( "github.com/emersion/go-message/mail" ) -// Flag is an abstraction around the different flags which can be present in +// Flags is an abstraction around the different flags which can be present in // different email backends and represents a flag that we use in the UI. -type Flag int +type Flags uint32 const ( // SeenFlag marks a message as having been seen previously - SeenFlag Flag = iota + SeenFlag Flags = 1 << iota // RecentFlag marks a message as being recent RecentFlag @@ -31,6 +31,10 @@ const ( FlaggedFlag ) +func (f Flags) Has(flags Flags) bool { + return f&flags == flags +} + type Directory struct { Name string Attributes []string @@ -67,7 +71,7 @@ type Capabilities struct { type MessageInfo struct { BodyStructure *BodyStructure Envelope *Envelope - Flags []Flag + Flags Flags Labels []string InternalDate time.Time RFC822Headers *mail.Header diff --git a/widgets/account.go b/widgets/account.go index 8b3e6a18..73ee32d0 100644 --- a/widgets/account.go +++ b/widgets/account.go @@ -369,14 +369,9 @@ func (acct *AccountView) updateDirCounts(destination string, uids []uint32) { accurate = false break } - seen := false - for _, flag := range msg.Flags { - if flag == models.SeenFlag { - seen = true - } - if flag == models.RecentFlag { - recent++ - } + seen := msg.Flags.Has(models.SeenFlag) + if msg.Flags.Has(models.RecentFlag) { + recent++ } if !seen { unseen++ diff --git a/widgets/dirlist.go b/widgets/dirlist.go index 4d27def2..09a1155a 100644 --- a/widgets/dirlist.go +++ b/widgets/dirlist.go @@ -497,16 +497,10 @@ func countRUE(msgStore *lib.MessageStore) (recent, unread int) { if msg == nil { continue } - seen := false - for _, flag := range msg.Flags { - if flag == models.SeenFlag { - seen = true - } - if flag == models.RecentFlag { - recent++ - } + if msg.Flags.Has(models.RecentFlag) { + recent++ } - if !seen { + if !msg.Flags.Has(models.SeenFlag) { unread++ } } diff --git a/widgets/msglist.go b/widgets/msglist.go index 842e2911..c260da1c 100644 --- a/widgets/msglist.go +++ b/widgets/msglist.go @@ -208,25 +208,13 @@ func (ml *MessageList) drawRow(textWidth int, ctx *ui.Context, uid uint32, row i } msg_styles := []config.StyleObject{} - // unread message - seen := false - flagged := false - for _, flag := range msg.Flags { - switch flag { - case models.SeenFlag: - seen = true - case models.FlaggedFlag: - flagged = true - } - } - - if seen { + if msg.Flags.Has(models.SeenFlag) { msg_styles = append(msg_styles, config.STYLE_MSGLIST_READ) } else { msg_styles = append(msg_styles, config.STYLE_MSGLIST_UNREAD) } - if flagged { + if msg.Flags.Has(models.FlaggedFlag) { msg_styles = append(msg_styles, config.STYLE_MSGLIST_FLAGGED) } diff --git a/worker/imap/cache.go b/worker/imap/cache.go index a889f725..b8673ae7 100644 --- a/worker/imap/cache.go +++ b/worker/imap/cache.go @@ -114,7 +114,7 @@ func (w *IMAPWorker) getCachedHeaders(msg *types.FetchMessageHeaders) []uint32 { mi := &models.MessageInfo{ BodyStructure: &ch.BodyStructure, Envelope: &ch.Envelope, - Flags: []models.Flag{models.SeenFlag}, // Always return a SEEN flag + Flags: models.SeenFlag, // Always return a SEEN flag Uid: ch.Uid, RFC822Headers: hdr, } diff --git a/worker/imap/flags.go b/worker/imap/flags.go index 9d9ecc86..180bc261 100644 --- a/worker/imap/flags.go +++ b/worker/imap/flags.go @@ -34,7 +34,6 @@ func (imapw *IMAPWorker) handleAnsweredMessages(msg *types.AnsweredMessages) { flags := []interface{}{imap.AnsweredFlag} if !msg.Answered { item = imap.FormatFlagsOp(imap.RemoveFlags, false) - flags = []interface{}{imap.AnsweredFlag} } imapw.handleStoreOps(msg, msg.Uids, item, flags, func(_msg *imap.Message) error { @@ -50,7 +49,7 @@ func (imapw *IMAPWorker) handleAnsweredMessages(msg *types.AnsweredMessages) { } func (imapw *IMAPWorker) handleFlagMessages(msg *types.FlagMessages) { - flags := []interface{}{flagToImap[msg.Flag]} + flags := []interface{}{flagToImap[msg.Flags]} item := imap.FormatFlagsOp(imap.AddFlags, false) if !msg.Enable { item = imap.FormatFlagsOp(imap.RemoveFlags, false) diff --git a/worker/imap/imap.go b/worker/imap/imap.go index 6e1341b2..82ee2e2e 100644 --- a/worker/imap/imap.go +++ b/worker/imap/imap.go @@ -79,7 +79,7 @@ func translateAddresses(addrs []*imap.Address) []*mail.Address { return converted } -var imapToFlag = map[string]models.Flag{ +var imapToFlag = map[string]models.Flags{ imap.SeenFlag: models.SeenFlag, imap.RecentFlag: models.RecentFlag, imap.AnsweredFlag: models.AnsweredFlag, @@ -87,7 +87,7 @@ var imapToFlag = map[string]models.Flag{ imap.FlaggedFlag: models.FlaggedFlag, } -var flagToImap = map[models.Flag]string{ +var flagToImap = map[models.Flags]string{ models.SeenFlag: imap.SeenFlag, models.RecentFlag: imap.RecentFlag, models.AnsweredFlag: imap.AnsweredFlag, @@ -95,20 +95,20 @@ var flagToImap = map[models.Flag]string{ models.FlaggedFlag: imap.FlaggedFlag, } -func translateImapFlags(imapFlags []string) []models.Flag { - var flags []models.Flag +func translateImapFlags(imapFlags []string) models.Flags { + var flags models.Flags for _, imapFlag := range imapFlags { if flag, ok := imapToFlag[imapFlag]; ok { - flags = append(flags, flag) + flags |= flag } } return flags } -func translateFlags(flags []models.Flag) []string { +func translateFlags(flags models.Flags) []string { var imapFlags []string - for _, flag := range flags { - if imapFlag, ok := flagToImap[flag]; ok { + for flag, imapFlag := range flagToImap { + if flags.Has(flag) { imapFlags = append(imapFlags, imapFlag) } } diff --git a/worker/lib/maildir.go b/worker/lib/maildir.go index f3fe9415..43d3b820 100644 --- a/worker/lib/maildir.go +++ b/worker/lib/maildir.go @@ -113,7 +113,7 @@ func StripUIDFromMessageFilename(basename string) string { return uidReg.ReplaceAllString(basename, "") } -var MaildirToFlag = map[maildir.Flag]models.Flag{ +var MaildirToFlag = map[maildir.Flag]models.Flags{ maildir.FlagReplied: models.AnsweredFlag, maildir.FlagSeen: models.SeenFlag, maildir.FlagTrashed: models.DeletedFlag, @@ -122,7 +122,7 @@ var MaildirToFlag = map[maildir.Flag]models.Flag{ // maildir.FlagPassed Flag = 'P' } -var FlagToMaildir = map[models.Flag]maildir.Flag{ +var FlagToMaildir = map[models.Flags]maildir.Flag{ models.AnsweredFlag: maildir.FlagReplied, models.SeenFlag: maildir.FlagSeen, models.DeletedFlag: maildir.FlagTrashed, @@ -131,20 +131,20 @@ var FlagToMaildir = map[models.Flag]maildir.Flag{ // maildir.FlagPassed Flag = 'P' } -func FromMaildirFlags(maildirFlags []maildir.Flag) []models.Flag { - var flags []models.Flag +func FromMaildirFlags(maildirFlags []maildir.Flag) models.Flags { + var flags models.Flags for _, maildirFlag := range maildirFlags { if flag, ok := MaildirToFlag[maildirFlag]; ok { - flags = append(flags, flag) + flags |= flag } } return flags } -func ToMaildirFlags(flags []models.Flag) []maildir.Flag { +func ToMaildirFlags(flags models.Flags) []maildir.Flag { var maildirFlags []maildir.Flag - for _, flag := range flags { - if maildirFlag, ok := FlagToMaildir[flag]; ok { + for flag, maildirFlag := range FlagToMaildir { + if flags.Has(flag) { maildirFlags = append(maildirFlags, maildirFlag) } } diff --git a/worker/lib/parse.go b/worker/lib/parse.go index 67955c8f..89e79684 100644 --- a/worker/lib/parse.go +++ b/worker/lib/parse.go @@ -254,7 +254,7 @@ func parseAddressList(h *mail.Header, key string) ([]*mail.Address, error) { // RawMessage is an interface that describes a raw message type RawMessage interface { NewReader() (io.ReadCloser, error) - ModelFlags() ([]models.Flag, error) + ModelFlags() (models.Flags, error) Labels() ([]string, error) UID() uint32 } diff --git a/worker/lib/parse_test.go b/worker/lib/parse_test.go index 227b121e..4bf95431 100644 --- a/worker/lib/parse_test.go +++ b/worker/lib/parse_test.go @@ -72,9 +72,9 @@ func newMockRawMessageFromPath(p string) *mockRawMessage { func (m *mockRawMessage) NewReader() (io.ReadCloser, error) { return os.Open(m.path) } -func (m *mockRawMessage) ModelFlags() ([]models.Flag, error) { return nil, nil } -func (m *mockRawMessage) Labels() ([]string, error) { return nil, nil } -func (m *mockRawMessage) UID() uint32 { return 0 } +func (m *mockRawMessage) ModelFlags() (models.Flags, error) { return 0, nil } +func (m *mockRawMessage) Labels() ([]string, error) { return nil, nil } +func (m *mockRawMessage) UID() uint32 { return 0 } func die(err error) { if err != nil { diff --git a/worker/lib/search.go b/worker/lib/search.go index c09feff6..0a124e3c 100644 --- a/worker/lib/search.go +++ b/worker/lib/search.go @@ -18,8 +18,8 @@ type searchCriteria struct { Body []string Text []string - WithFlags []models.Flag - WithoutFlags []models.Flag + WithFlags models.Flags + WithoutFlags models.Flags startDate, endDate time.Time } @@ -36,13 +36,13 @@ func GetSearchCriteria(args []string) (*searchCriteria, error) { for _, opt := range opts { switch opt.Option { case 'r': - criteria.WithFlags = append(criteria.WithFlags, models.SeenFlag) + criteria.WithFlags |= models.SeenFlag case 'u': - criteria.WithoutFlags = append(criteria.WithoutFlags, models.SeenFlag) + criteria.WithoutFlags |= models.SeenFlag case 'x': - criteria.WithFlags = append(criteria.WithFlags, getParsedFlag(opt.Value)) + criteria.WithFlags |= getParsedFlag(opt.Value) case 'X': - criteria.WithoutFlags = append(criteria.WithoutFlags, getParsedFlag(opt.Value)) + criteria.WithoutFlags |= getParsedFlag(opt.Value) case 'H': // TODO case 'f': @@ -80,8 +80,8 @@ func GetSearchCriteria(args []string) (*searchCriteria, error) { return criteria, nil } -func getParsedFlag(name string) models.Flag { - var f models.Flag +func getParsedFlag(name string) models.Flags { + var f models.Flags switch strings.ToLower(name) { case "seen": f = models.SeenFlag @@ -117,7 +117,7 @@ func searchMessage(message RawMessage, criteria *searchCriteria, // setup parts of the message to use in the search // this is so that we try to minimise reading unnecessary parts var ( - flags []models.Flag + flags models.Flags header *models.MessageInfo body string all string @@ -188,18 +188,14 @@ func searchMessage(message RawMessage, criteria *searchCriteria, } } } - if criteria.WithFlags != nil { - for _, searchFlag := range criteria.WithFlags { - if !containsFlag(flags, searchFlag) { - return false, nil - } + if criteria.WithFlags != 0 { + if !flags.Has(criteria.WithFlags) { + return false, nil } } - if criteria.WithoutFlags != nil { - for _, searchFlag := range criteria.WithoutFlags { - if containsFlag(flags, searchFlag) { - return false, nil - } + if criteria.WithoutFlags != 0 { + if flags.Has(criteria.WithoutFlags) { + return false, nil } } if parts&DATE > 0 { @@ -221,17 +217,6 @@ func searchMessage(message RawMessage, criteria *searchCriteria, return true, nil } -// containsFlag returns true if searchFlag appears in flags -func containsFlag(flags []models.Flag, searchFlag models.Flag) bool { - match := false - for _, flag := range flags { - if searchFlag == flag { - match = true - } - } - return match -} - // containsSmartCase is a smarter version of strings.Contains for searching. // Is case-insensitive unless substr contains an upper case character func containsSmartCase(s string, substr string) bool { @@ -278,10 +263,10 @@ func getRequiredParts(criteria *searchCriteria) MsgParts { if criteria.Text != nil && len(criteria.Text) > 0 { required |= ALL } - if criteria.WithFlags != nil && len(criteria.WithFlags) > 0 { + if criteria.WithFlags != 0 { required |= FLAGS } - if criteria.WithoutFlags != nil && len(criteria.WithoutFlags) > 0 { + if criteria.WithoutFlags != 0 { required |= FLAGS } diff --git a/worker/lib/sort.go b/worker/lib/sort.go index 1a1bb47f..2828999c 100644 --- a/worker/lib/sort.go +++ b/worker/lib/sort.go @@ -90,18 +90,12 @@ func sortAddresses(messageInfos []*models.MessageInfo, criterion *types.SortCrit } func sortFlags(messageInfos []*models.MessageInfo, criterion *types.SortCriterion, - testFlag models.Flag, + testFlag models.Flags, ) { var slice []*boolStore for _, msgInfo := range messageInfos { - flagPresent := false - for _, flag := range msgInfo.Flags { - if flag == testFlag { - flagPresent = true - } - } slice = append(slice, &boolStore{ - Value: flagPresent, + Value: msgInfo.Flags.Has(testFlag), MsgInfo: msgInfo, }) } diff --git a/worker/maildir/message.go b/worker/maildir/message.go index d9433823..a941624a 100644 --- a/worker/maildir/message.go +++ b/worker/maildir/message.go @@ -28,10 +28,10 @@ func (m Message) Flags() ([]maildir.Flag, error) { } // ModelFlags fetches the set of models.flags currently applied to the message. -func (m Message) ModelFlags() ([]models.Flag, error) { +func (m Message) ModelFlags() (models.Flags, error) { flags, err := m.dir.Flags(m.key) if err != nil { - return nil, err + return 0, err } return lib.FromMaildirFlags(flags), nil } diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 8c4d78ab..54069538 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -712,7 +712,7 @@ func (w *Worker) handleFlagMessages(msg *types.FlagMessages) error { w.err(msg, err) continue } - flag := lib.FlagToMaildir[msg.Flag] + flag := lib.FlagToMaildir[msg.Flags] if err := m.SetOneFlag(flag, msg.Enable); err != nil { log.Errorf("could change flag %v to %v on message: %v", flag, msg.Enable, err) w.err(msg, err) @@ -817,7 +817,7 @@ func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) { return nil, err } if w.c.IsRecent(uid) { - info.Flags = append(info.Flags, models.RecentFlag) + info.Flags |= models.RecentFlag } return info, nil } diff --git a/worker/mbox/io.go b/worker/mbox/io.go index 31a906cc..2fe39813 100644 --- a/worker/mbox/io.go +++ b/worker/mbox/io.go @@ -28,7 +28,7 @@ func Read(r io.Reader) ([]lib.RawMessage, error) { } messages = append(messages, &message{ - uid: uid, flags: []models.Flag{models.SeenFlag}, content: content, + uid: uid, flags: models.SeenFlag, content: content, }) uid++ diff --git a/worker/mbox/models.go b/worker/mbox/models.go index eec73379..3af93a84 100644 --- a/worker/mbox/models.go +++ b/worker/mbox/models.go @@ -148,7 +148,7 @@ func (f *container) newUid() (next uint32) { return } -func (f *container) Append(r io.Reader, flags []models.Flag) error { +func (f *container) Append(r io.Reader, flags models.Flags) error { data, err := io.ReadAll(r) if err != nil { return err @@ -164,7 +164,7 @@ func (f *container) Append(r io.Reader, flags []models.Flag) error { // message implements the lib.RawMessage interface type message struct { uid uint32 - flags []models.Flag + flags models.Flags content []byte } @@ -172,7 +172,7 @@ func (m *message) NewReader() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(m.content)), nil } -func (m *message) ModelFlags() ([]models.Flag, error) { +func (m *message) ModelFlags() (models.Flags, error) { return m.flags, nil } @@ -184,22 +184,11 @@ func (m *message) UID() uint32 { return m.uid } -func (m *message) SetFlag(flag models.Flag, state bool) error { - flagSet := make(map[models.Flag]bool) - flags, err := m.ModelFlags() - if err != nil { - return err - } - for _, f := range flags { - flagSet[f] = true - } - flagSet[flag] = state - newFlags := make([]models.Flag, 0) - for flag, isSet := range flagSet { - if isSet { - newFlags = append(newFlags, flag) - } +func (m *message) SetFlag(flag models.Flags, state bool) error { + if state { + m.flags |= flag + } else { + m.flags &^= flag } - m.flags = newFlags return nil } diff --git a/worker/mbox/worker.go b/worker/mbox/worker.go index fcf1917d..c2cf9ecb 100644 --- a/worker/mbox/worker.go +++ b/worker/mbox/worker.go @@ -254,8 +254,9 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error { log.Errorf("could not get message: %v", err) continue } - if err := m.(*message).SetFlag(msg.Flag, msg.Enable); err != nil { - log.Errorf("could change flag %v to %t on message: %v", msg.Flag, msg.Enable, err) + if err := m.(*message).SetFlag(msg.Flags, msg.Enable); err != nil { + log.Errorf("could not change flag %v to %t on message: %v", + msg.Flags, msg.Enable, err) continue } info, err := lib.MessageInfo(m) diff --git a/worker/notmuch/message.go b/worker/notmuch/message.go index 0fc85b00..28731d3d 100644 --- a/worker/notmuch/message.go +++ b/worker/notmuch/message.go @@ -58,7 +58,7 @@ func (m *Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) { // SetFlag adds or removes a flag from the message. // Notmuch doesn't support all the flags, and for those this errors. -func (m *Message) SetFlag(flag models.Flag, enable bool) error { +func (m *Message) SetFlag(flag models.Flags, enable bool) error { // Translate the flag into a notmuch tag, ignoring no-op flags. var tag string switch flag { @@ -129,28 +129,22 @@ func (m *Message) Labels() ([]string, error) { return m.Tags() } -func (m *Message) ModelFlags() ([]models.Flag, error) { - var flags []models.Flag - seen := true +func (m *Message) ModelFlags() (models.Flags, error) { + var flags models.Flags = models.SeenFlag tags, err := m.Tags() if err != nil { - return nil, err + return 0, err } for _, tag := range tags { switch tag { case "replied": - flags = append(flags, models.AnsweredFlag) + flags |= models.AnsweredFlag case "flagged": - flags = append(flags, models.FlaggedFlag) + flags |= models.FlaggedFlag case "unread": - seen = false - default: - continue + flags &^= models.SeenFlag } } - if seen { - flags = append(flags, models.SeenFlag) - } return flags, nil } diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index a4f5b5c8..6d8e46d2 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -477,8 +477,9 @@ func (w *worker) handleFlagMessages(msg *types.FlagMessages) error { w.err(msg, err) continue } - if err := m.SetFlag(msg.Flag, msg.Enable); err != nil { - log.Errorf("could not set flag %v as %t for message: %v", msg.Flag, msg.Enable, err) + if err := m.SetFlag(msg.Flags, msg.Enable); err != nil { + log.Errorf("could not set flag %v as %t for message: %v", + msg.Flags, msg.Enable, err) w.err(msg, err) continue } diff --git a/worker/types/messages.go b/worker/types/messages.go index 26f29a24..7e3f8202 100644 --- a/worker/types/messages.go +++ b/worker/types/messages.go @@ -160,7 +160,7 @@ type DeleteMessages struct { type FlagMessages struct { Message Enable bool - Flag models.Flag + Flags models.Flags Uids []uint32 } @@ -185,7 +185,7 @@ type MoveMessages struct { type AppendMessage struct { Message Destination string - Flags []models.Flag + Flags models.Flags Date time.Time Reader io.Reader Length int diff --git a/worker/types/worker.go b/worker/types/worker.go index 97712afd..bd3553bc 100644 --- a/worker/types/worker.go +++ b/worker/types/worker.go @@ -170,7 +170,7 @@ func (worker *Worker) PostMessageInfoError(msg WorkerMessage, uid uint32, err er worker.PostMessage(&MessageInfo{ Info: &models.MessageInfo{ Envelope: &models.Envelope{}, - Flags: []models.Flag{models.SeenFlag}, + Flags: models.SeenFlag, Uid: uid, Error: err, }, |