aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Ovchinnikov <v@postbox.nz>2023-08-29 08:50:06 +0300
committerRobin Jarry <robin@jarry.cc>2023-08-30 22:09:47 +0200
commitf1bb4767b04a84432cd8abd59d987a57b3cdbb7a (patch)
tree6a5523c897929ac85d3b1d28aea00dd854229818
parent608bc4fa7fa721ca1bef79e8d8a4630cd6124843 (diff)
downloadaerc-f1bb4767b04a84432cd8abd59d987a57b3cdbb7a.tar.gz
aerc-f1bb4767b04a84432cd8abd59d987a57b3cdbb7a.zip
postpone: change recall/postpone logic for custom folders
Change `:recall -f` behavior so it remembers the source folder the message is taken from and the further `:postpone` call can save it back to that folder. Change the `:recall` tab closing behavior, so it no longer asks if the recalled message needs to be deleted. This is now done automatically. Add an optional `-t <folder>` parameter to `:postpone`, so the message can be saved in a different folder. Change `:postpone` behavior, so it checks if the message was force-recalled from a different folder, and then it saves the message there. The "breaking" change is made to the closing handler of the recalled message tab. There was a confirmation dialog that asked if the recalled message needs to be deleted. This is now removed and replaced with a pretty simple logic: if the recalled message is either sent or re-postponed - it is safe to delete the original. Otherwise (if the recalled message editing is discarded, any other reasons?) the message is left intact, there is no need to ask for deleting it. If the user don't need that message - they can delete it manually. Another "breaking" change to the same handler is that it always works this way regardless of the curently selected folder. There was an `if` that checked that, but as the recalled messages are now only deleted if they are re-sent or re-postponed, it seems that there is no need to check the current folder anymore. Signed-off-by: Vitaly Ovchinnikov <v@postbox.nz> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--CHANGELOG.md1
-rw-r--r--commands/compose/postpone.go46
-rw-r--r--commands/msg/recall.go25
-rw-r--r--doc/aerc.1.scd22
-rw-r--r--widgets/compose.go19
5 files changed, 81 insertions, 32 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 50324992..21ff9425 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Add `%f` placeholder to `file-picker-cmd` which expands to a location of a
temporary file from which selected files will be read instead of the standard
output.
+- Save drafts in custom folders with `:postpone -t <folder>`.
### Fixed
diff --git a/commands/compose/postpone.go b/commands/compose/postpone.go
index dad76877..9cb337bc 100644
--- a/commands/compose/postpone.go
+++ b/commands/compose/postpone.go
@@ -7,6 +7,9 @@ import (
"github.com/miolini/datacounter"
"github.com/pkg/errors"
+ "git.sr.ht/~sircmpwn/getopt"
+
+ "git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/log"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/widgets"
@@ -23,14 +26,28 @@ func (Postpone) Aliases() []string {
return []string{"postpone"}
}
+func (Postpone) Options() string {
+ return "t:"
+}
+
+func (Postpone) CompleteOption(aerc *widgets.Aerc, r rune, arg string) []string {
+ var valid []string
+ if r == 't' {
+ valid = commands.GetFolders(aerc, []string{arg})
+ }
+ return commands.CompletionFromList(aerc, valid, []string{arg})
+}
+
func (Postpone) Complete(aerc *widgets.Aerc, args []string) []string {
return nil
}
-func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
- if len(args) != 1 {
- return errors.New("Usage: postpone")
+func (p Postpone) Execute(aerc *widgets.Aerc, args []string) error {
+ opts, optind, err := getopt.Getopts(args, p.Options())
+ if err != nil {
+ return err
}
+
acct := aerc.SelectedAccount()
if acct == nil {
return errors.New("No account selected")
@@ -43,7 +60,21 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
config := composer.Config()
tabName := tab.Name
- if config.Postpone == "" {
+ targetFolder := config.Postpone
+ if composer.RecalledFrom() != "" {
+ targetFolder = composer.RecalledFrom()
+ }
+ for _, opt := range opts {
+ if opt.Option == 't' {
+ targetFolder = opt.Value
+ }
+ }
+ args = args[optind:]
+
+ if len(args) != 0 {
+ return errors.New("Usage: postpone [-t <folder>]")
+ }
+ if targetFolder == "" {
return errors.New("No Postpone location configured")
}
@@ -59,7 +90,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
dirs := acct.Directories().List()
alreadyCreated := false
for _, dir := range dirs {
- if dir == config.Postpone {
+ if dir == targetFolder {
alreadyCreated = true
break
}
@@ -94,7 +125,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
}
nbytes := int(ctr.Count())
worker.PostAction(&types.AppendMessage{
- Destination: config.Postpone,
+ Destination: targetFolder,
Flags: models.SeenFlag,
Date: time.Now(),
Reader: &buf,
@@ -103,6 +134,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
switch msg := msg.(type) {
case *types.Done:
aerc.PushStatus("Message postponed.", 10*time.Second)
+ composer.SetPostponed()
composer.Close()
case *types.Error:
handleErr(msg.Error)
@@ -113,7 +145,7 @@ func (Postpone) Execute(aerc *widgets.Aerc, args []string) error {
if !alreadyCreated {
// to synchronise the creating of the directory
worker.PostAction(&types.CreateDirectory{
- Directory: config.Postpone,
+ Directory: targetFolder,
}, func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
diff --git a/commands/msg/recall.go b/commands/msg/recall.go
index c095caf1..e7579ca1 100644
--- a/commands/msg/recall.go
+++ b/commands/msg/recall.go
@@ -84,10 +84,6 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
worker := composer.Worker()
uids := []uint32{msgInfo.Uid}
- if acct.SelectedDirectory() != acct.AccountConfig().Postpone {
- return
- }
-
deleteMessage := func() {
worker.PostAction(&types.DeleteMessages{
Uids: uids,
@@ -101,23 +97,8 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
})
}
- if composer.Sent() {
+ if composer.Sent() || composer.Postponed() {
deleteMessage()
- } else {
- confirm := widgets.NewSelectorDialog(
- "Delete recalled message?",
- "If you proceed, the recalled message will be deleted.",
- []string{"Cancel", "Proceed"}, 0, aerc.SelectedAccountUiConfig(),
- func(option string, err error) {
- aerc.CloseDialog()
- switch option {
- case "Proceed":
- deleteMessage()
- default:
- }
- },
- )
- aerc.AddDialog(confirm)
}
})
}
@@ -183,6 +164,10 @@ func (Recall) Execute(aerc *widgets.Aerc, args []string) error {
})
}
+ if force {
+ composer.SetRecalledFrom(acct.SelectedDirectory())
+ }
+
// focus the terminal since the header fields are likely already done
composer.FocusTerminal()
addTab(composer)
diff --git a/doc/aerc.1.scd b/doc/aerc.1.scd
index ecaedfd6..440cfc29 100644
--- a/doc/aerc.1.scd
+++ b/doc/aerc.1.scd
@@ -199,16 +199,21 @@ message list, the message in the message viewer, etc).
*:recall* [*-f*] [*-e*|*-E*]
Opens the selected message for re-editing. Messages can only be
- recalled from the postpone directory. The original message is deleted.
+ recalled from the postpone directory.
*-f*: Open the message for re-editing even if it is not in the postpone
- directory. The original message will be deleted only if it is in the
- postpone directory.
+ directory. Aerc remembers the folder, so the further *:postpone* call will
+ save the message back there.
*-e*: Forces *[compose].edit-headers* = _true_ for this message only.
*-E*: Forces *[compose].edit-headers* = _false_ for this message only.
+ Original recalled messages are deleted if they are sent or postponed again.
+ In both cases you have another copy of the message somewhere. Otherwise the
+ recalled message is left intact. This happens if the recalled message is
+ discarded after editing. It can be deleted with *:rm* if it is not needed.
+
*:forward* [*-A*|*-F*] [*-T* _<template-file>_] [*-e*|*-E*] [_<address>_...]
Opens the composer to forward the selected message to another recipient.
@@ -619,9 +624,16 @@ message list, the message in the message viewer, etc).
*:prev-field*
Cycles between input fields in the compose window.
-*:postpone*
+*:postpone* [*-t* _<folder>_]
Saves the current state of the message to the *postpone* folder (from
- _accounts.conf_) for the current account.
+ _accounts.conf_) for the current account by default.
+
+ *-t*: Overrides the target folder for saving the message
+
+ If the message was force-recalled with *:recall -f* from a different folder,
+ the *:postpone* command will save it back to that folder instead of the
+ default *postpone* folder configured in settings. Use *-t* to override that
+ or use *:mv* to move the saved message to a different folder.
*:save* [*-p*] _<path>_
Saves the selected message part to the specified path. If *-p* is selected,
diff --git a/widgets/compose.go b/widgets/compose.go
index 05d06a7f..608b8532 100644
--- a/widgets/compose.go
+++ b/widgets/compose.go
@@ -63,6 +63,9 @@ type Composer struct {
sent bool
archive string
+ recalledFrom string
+ postponed bool
+
onClose []func(ti *Composer)
width int
@@ -301,6 +304,22 @@ func (c *Composer) Sent() bool {
return c.sent
}
+func (c *Composer) SetPostponed() {
+ c.postponed = true
+}
+
+func (c *Composer) Postponed() bool {
+ return c.postponed
+}
+
+func (c *Composer) SetRecalledFrom(folder string) {
+ c.recalledFrom = folder
+}
+
+func (c *Composer) RecalledFrom() string {
+ return c.recalledFrom
+}
+
func (c *Composer) Archive() string {
return c.archive
}