mirror of
https://git.sr.ht/~rjarry/aerc
synced 2026-03-06 18:23:44 +01:00
model: change flags array to bitmask
Using a list of integers is not optimal. Use a bit mask instead. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
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 seen {
|
||||
if answered {
|
||||
readReplyFlag = "r" // message has been replied to
|
||||
}
|
||||
} else {
|
||||
if recent {
|
||||
readReplyFlag = "N" // message is new
|
||||
} else {
|
||||
readReplyFlag = "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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -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++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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++
|
||||
|
||||
@@ -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
|
||||
func (m *message) SetFlag(flag models.Flags, state bool) error {
|
||||
if state {
|
||||
m.flags |= flag
|
||||
} else {
|
||||
m.flags &^= flag
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
m.flags = newFlags
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user