diff options
-rw-r--r-- | commands/account/search.go | 1 | ||||
-rw-r--r-- | commands/completion_helpers.go | 2 | ||||
-rw-r--r-- | commands/compose/postpone.go | 2 | ||||
-rw-r--r-- | commands/msg/read.go | 5 | ||||
-rw-r--r-- | commands/msg/recall.go | 12 | ||||
-rw-r--r-- | config/templates.go | 1 | ||||
-rw-r--r-- | config/ui.go | 3 | ||||
-rw-r--r-- | doc/aerc-config.5.scd | 7 | ||||
-rw-r--r-- | doc/aerc-search.1.scd | 2 | ||||
-rw-r--r-- | doc/aerc-templates.7.scd | 3 | ||||
-rw-r--r-- | doc/aerc.1.scd | 2 | ||||
-rw-r--r-- | lib/state/templates.go | 10 | ||||
-rw-r--r-- | models/models.go | 3 | ||||
-rw-r--r-- | models/templates.go | 1 | ||||
-rw-r--r-- | worker/imap/imap.go | 2 | ||||
-rw-r--r-- | worker/jmap/jmap.go | 5 | ||||
-rw-r--r-- | worker/lib/maildir.go | 4 | ||||
-rw-r--r-- | worker/notmuch/notmuch.go | 3 | ||||
-rw-r--r-- | worker/notmuch/worker.go | 27 |
19 files changed, 82 insertions, 13 deletions
diff --git a/commands/account/search.go b/commands/account/search.go index be3b125f..0246a9eb 100644 --- a/commands/account/search.go +++ b/commands/account/search.go @@ -73,6 +73,7 @@ var flagValues = map[string]models.Flags{ "seen": models.SeenFlag, "answered": models.AnsweredFlag, "flagged": models.FlaggedFlag, + "draft": models.DraftFlag, } func (s *SearchFilter) ParseFlag(arg string) error { diff --git a/commands/completion_helpers.go b/commands/completion_helpers.go index e4556594..b7ba6780 100644 --- a/commands/completion_helpers.go +++ b/commands/completion_helpers.go @@ -45,7 +45,7 @@ func GetAddress(search string) []string { // GetFlagList returns a list of available flags for completion func GetFlagList() []string { - return []string{"Seen", "Answered", "Flagged"} + return []string{"Seen", "Answered", "Flagged", "Draft"} } // GetDateList returns a list of date terms for completion diff --git a/commands/compose/postpone.go b/commands/compose/postpone.go index a869417b..3c23eda3 100644 --- a/commands/compose/postpone.go +++ b/commands/compose/postpone.go @@ -108,7 +108,7 @@ func (p Postpone) Execute(args []string) error { } store.Append( targetFolder, - models.SeenFlag, + models.SeenFlag|models.DraftFlag, time.Now(), buf, buf.Len(), diff --git a/commands/msg/read.go b/commands/msg/read.go index b487d8a8..5b4bd073 100644 --- a/commands/msg/read.go +++ b/commands/msg/read.go @@ -41,13 +41,16 @@ func (f *FlagMsg) ParseFlag(arg string) error { case "flagged": f.Flag = models.FlaggedFlag f.FlagName = "flagged" + case "draft": + f.Flag = models.DraftFlag + f.FlagName = "draft" default: return fmt.Errorf("Unknown flag %q", arg) } return nil } -var validFlags = []string{"seen", "answered", "flagged"} +var validFlags = []string{"seen", "answered", "flagged", "draft"} func (*FlagMsg) CompleteFlag(arg string) []string { return commands.FilterList(validFlags, arg, nil) diff --git a/commands/msg/recall.go b/commands/msg/recall.go index 059fe558..e5cd2ed1 100644 --- a/commands/msg/recall.go +++ b/commands/msg/recall.go @@ -15,6 +15,7 @@ import ( "git.sr.ht/~rjarry/aerc/config" "git.sr.ht/~rjarry/aerc/lib" "git.sr.ht/~rjarry/aerc/log" + "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/types" ) @@ -44,10 +45,6 @@ func (r Recall) Execute(args []string) error { if acct == nil { return errors.New("No account selected") } - if acct.SelectedDirectory() != acct.AccountConfig().Postpone && !r.Force { - return errors.New("Use -f to recall from outside the " + - acct.AccountConfig().Postpone + " directory.") - } store := widget.Store() if store == nil { return errors.New("Cannot perform action. Messages still loading") @@ -57,6 +54,13 @@ func (r Recall) Execute(args []string) error { if err != nil { return errors.Wrap(err, "Recall failed") } + + if acct.SelectedDirectory() != acct.AccountConfig().Postpone && + !msgInfo.Flags.Has(models.DraftFlag) && !r.Force { + return errors.New("Use -f to recall non-draft messages from outside the " + + acct.AccountConfig().Postpone + " directory.") + } + log.Debugf("Recalling message <%s>", msgInfo.Envelope.MessageId) addTab := func(composer *app.Composer) { diff --git a/config/templates.go b/config/templates.go index c5d11478..61c411fb 100644 --- a/config/templates.go +++ b/config/templates.go @@ -94,6 +94,7 @@ func (d *dummyData) HasAttachment() bool { return true } func (d *dummyData) IsRecent() bool { return false } func (d *dummyData) IsUnread() bool { return false } func (d *dummyData) IsFlagged() bool { return false } +func (d *dummyData) IsDraft() bool { return false } func (d *dummyData) IsMarked() bool { return false } func (d *dummyData) MessageId() string { return "123456789@foo.org" } func (d *dummyData) Size() int { return 420 } diff --git a/config/ui.go b/config/ui.go index ed0b4a33..83b45230 100644 --- a/config/ui.go +++ b/config/ui.go @@ -55,9 +55,10 @@ type UIConfig struct { IconReplied string `ini:"icon-replied" default:"r"` IconNew string `ini:"icon-new" default:"N"` IconOld string `ini:"icon-old" default:"O"` + IconDraft string `ini:"icon-draft" default:"d"` IconFlagged string `ini:"icon-flagged" default:"!"` IconMarked string `ini:"icon-marked" default:"*"` - IconDeleted string `ini:"icon-deleted" default:"D"` + IconDeleted string `ini:"icon-deleted" default:"X"` DirListDelay time.Duration `ini:"dirlist-delay" default:"200ms"` DirListTree bool `ini:"dirlist-tree"` DirListCollapse int `ini:"dirlist-collapse"` diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd index 043b738a..1aa9da5f 100644 --- a/doc/aerc-config.5.scd +++ b/doc/aerc-config.5.scd @@ -405,10 +405,15 @@ These options are configured in the *[ui]* section of _aerc.conf_. Default: _\*_ +*icon-draft* = _<string>_ + The icon to display in *column-flags* when the message is a draft. + + Default: _d_ + *icon-deleted* = _<string>_ The icon to display in *column-flags* when the message has been deleted. - Default: _D_ + Default: _X_ *fuzzy-complete* = _true_|_false_ When typing a command or option, the popover will now show not only the diff --git a/doc/aerc-search.1.scd b/doc/aerc-search.1.scd index 161a632f..fa630c1d 100644 --- a/doc/aerc-search.1.scd +++ b/doc/aerc-search.1.scd @@ -34,6 +34,8 @@ This syntax is common to all backends. Replied messages _Flagged_ Flagged messages + _Draft_ + Draft messages *-H*: Search in the headers of the messages, for a specific header Syntax: _Header: Value_ diff --git a/doc/aerc-templates.7.scd b/doc/aerc-templates.7.scd index 160fb77f..6e87c616 100644 --- a/doc/aerc-templates.7.scd +++ b/doc/aerc-templates.7.scd @@ -116,7 +116,8 @@ available always. {{.Flags | join ""}} ``` -*IsReplied*, *HasAttachment*, *IsFlagged*, *IsRecent*, *IsUnread*, *IsMarked* +*IsReplied*, *HasAttachment*, *IsFlagged*, *IsRecent*, *IsUnread*, *IsMarked*, +*IsDraft* Individual boolean flags. not available when composing, replying nor forwarding. diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd index d77bbf03..1ee61060 100644 --- a/doc/aerc.1.scd +++ b/doc/aerc.1.scd @@ -418,6 +418,8 @@ message list, the message in the message viewer, etc). Message has been answered _Flagged_ Message is flagged for urgent/special attention + _Draft_ + Message is a draft *:unflag* [*-t*] _<flag>_ Operates exactly like *:flag*, defaulting to unsetting (disabling) flags. diff --git a/lib/state/templates.go b/lib/state/templates.go index ac701e9f..d039f1b6 100644 --- a/lib/state/templates.go +++ b/lib/state/templates.go @@ -393,6 +393,9 @@ func (d *templateData) Flags() []string { default: flags = append(flags, d.ui().IconOld) // message is unread and old } + if d.info.Flags.Has(models.DraftFlag) { + flags = append(flags, d.ui().IconDraft) + } if d.info.Flags.Has(models.DeletedFlag) { flags = append(flags, d.ui().IconDeleted) } @@ -452,6 +455,13 @@ func (d *templateData) IsFlagged() bool { return false } +func (d *templateData) IsDraft() bool { + if d.info != nil && d.info.Flags.Has(models.DraftFlag) { + return true + } + return false +} + func (d *templateData) IsMarked() bool { return d.marked } diff --git a/models/models.go b/models/models.go index 55dd2347..80bc0db1 100644 --- a/models/models.go +++ b/models/models.go @@ -30,6 +30,9 @@ const ( // FlaggedFlag marks a message with a user flag FlaggedFlag + + // DraftFlag marks a message as a draft + DraftFlag ) func (f Flags) Has(flags Flags) bool { diff --git a/models/templates.go b/models/templates.go index a6a85371..5caed158 100644 --- a/models/templates.go +++ b/models/templates.go @@ -38,6 +38,7 @@ type TemplateData interface { IsRecent() bool IsUnread() bool IsMarked() bool + IsDraft() bool MessageId() string Role() string Size() int diff --git a/worker/imap/imap.go b/worker/imap/imap.go index 82ee2e2e..fbdcb2b9 100644 --- a/worker/imap/imap.go +++ b/worker/imap/imap.go @@ -85,6 +85,7 @@ var imapToFlag = map[string]models.Flags{ imap.AnsweredFlag: models.AnsweredFlag, imap.DeletedFlag: models.DeletedFlag, imap.FlaggedFlag: models.FlaggedFlag, + imap.DraftFlag: models.DraftFlag, } var flagToImap = map[models.Flags]string{ @@ -93,6 +94,7 @@ var flagToImap = map[models.Flags]string{ models.AnsweredFlag: imap.AnsweredFlag, models.DeletedFlag: imap.DeletedFlag, models.FlaggedFlag: imap.FlaggedFlag, + models.DraftFlag: imap.DraftFlag, } func translateImapFlags(imapFlags []string) models.Flags { diff --git a/worker/jmap/jmap.go b/worker/jmap/jmap.go index 8012b6e4..bb0f75f9 100644 --- a/worker/jmap/jmap.go +++ b/worker/jmap/jmap.go @@ -67,6 +67,9 @@ func flagsToKeywords(flags models.Flags) map[string]bool { if flags.Has(models.FlaggedFlag) { kw["$flagged"] = true } + if flags.Has(models.DraftFlag) { + kw["$draft"] = true + } return kw } @@ -81,6 +84,8 @@ func keywordsToFlags(kw map[string]bool) models.Flags { f |= models.AnsweredFlag case "$flagged": f |= models.FlaggedFlag + case "$draft": + f |= models.DraftFlag } } } diff --git a/worker/lib/maildir.go b/worker/lib/maildir.go index 43d3b820..a4a0ecd5 100644 --- a/worker/lib/maildir.go +++ b/worker/lib/maildir.go @@ -118,7 +118,7 @@ var MaildirToFlag = map[maildir.Flag]models.Flags{ maildir.FlagSeen: models.SeenFlag, maildir.FlagTrashed: models.DeletedFlag, maildir.FlagFlagged: models.FlaggedFlag, - // maildir.FlagDraft Flag = 'D' + maildir.FlagDraft: models.DraftFlag, // maildir.FlagPassed Flag = 'P' } @@ -127,7 +127,7 @@ var FlagToMaildir = map[models.Flags]maildir.Flag{ models.SeenFlag: maildir.FlagSeen, models.DeletedFlag: maildir.FlagTrashed, models.FlaggedFlag: maildir.FlagFlagged, - // maildir.FlagDraft Flag = 'D' + models.DraftFlag: maildir.FlagDraft, // maildir.FlagPassed Flag = 'P' } diff --git a/worker/notmuch/notmuch.go b/worker/notmuch/notmuch.go index 5610cac0..1d064fd2 100644 --- a/worker/notmuch/notmuch.go +++ b/worker/notmuch/notmuch.go @@ -8,17 +8,20 @@ import "git.sr.ht/~rjarry/aerc/models" var tagToFlag = map[string]models.Flags{ "unread": models.SeenFlag, "replied": models.AnsweredFlag, + "draft": models.DraftFlag, "flagged": models.FlaggedFlag, } var flagToTag = map[models.Flags]string{ models.SeenFlag: "unread", models.AnsweredFlag: "replied", + models.DraftFlag: "draft", models.FlaggedFlag: "flagged", } var flagToInvert = map[models.Flags]bool{ models.SeenFlag: true, models.AnsweredFlag: false, + models.DraftFlag: false, models.FlaggedFlag: false, } diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go index 374a20b7..80a8d720 100644 --- a/worker/notmuch/worker.go +++ b/worker/notmuch/worker.go @@ -894,9 +894,16 @@ func (w *worker) handleAppendMessage(msg *types.AppendMessage) error { return err } writer.Close() - if _, err := w.db.IndexFile(filename); err != nil { + id, err := w.db.IndexFile(filename) + if err != nil { return err } + + err = w.addFlags(id, msg.Flags) + if err != nil { + return err + } + w.w.PostMessage(&types.DirectoryInfo{ Info: w.getDirectoryInfo(w.currentQueryName, w.query), }, nil) @@ -973,3 +980,21 @@ func (w *worker) processNewMaildirFiles(dir string) error { return nil } + +func (w *worker) addFlags(id string, flags models.Flags) error { + addTags := []string{} + removeTags := []string{} + for flag, tag := range flagToTag { + if !flags.Has(flag) { + continue + } + + if flagToInvert[flag] { + removeTags = append(removeTags, tag) + } else { + addTags = append(addTags, tag) + } + } + + return w.db.MsgModifyTags(id, addTags, removeTags) +} |