aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/account/import-mbox.go2
-rw-r--r--commands/compose/postpone.go2
-rw-r--r--commands/compose/send.go2
-rw-r--r--commands/msg/read.go11
-rw-r--r--lib/emlview.go4
-rw-r--r--lib/format/format.go63
-rw-r--r--lib/msgstore.go15
-rw-r--r--models/models.go12
-rw-r--r--widgets/account.go11
-rw-r--r--widgets/dirlist.go12
-rw-r--r--widgets/msglist.go16
-rw-r--r--worker/imap/cache.go2
-rw-r--r--worker/imap/flags.go3
-rw-r--r--worker/imap/imap.go16
-rw-r--r--worker/lib/maildir.go16
-rw-r--r--worker/lib/parse.go2
-rw-r--r--worker/lib/parse_test.go6
-rw-r--r--worker/lib/search.go49
-rw-r--r--worker/lib/sort.go10
-rw-r--r--worker/maildir/message.go4
-rw-r--r--worker/maildir/worker.go4
-rw-r--r--worker/mbox/io.go2
-rw-r--r--worker/mbox/models.go27
-rw-r--r--worker/mbox/worker.go5
-rw-r--r--worker/notmuch/message.go20
-rw-r--r--worker/notmuch/worker.go5
-rw-r--r--worker/types/messages.go4
-rw-r--r--worker/types/worker.go2
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,
},