1
0
Fork 0
mirror of https://git.sr.ht/~rjarry/aerc synced 2025-02-22 23:23:57 +01:00
aerc/commands/compose/postpone.go
Robin Jarry fa0b99800e compose: differentiate between edit and review commands
Split the compose commands into two categories: edit and review. Some
commands can belong to both categories and be available whether the text
editor or the review screen is visible.

Update man page to reflect that. Remove duplicate (and misplaced) :save
command from the COMPOSE section.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Bence Ferdinandy <bence@ferdinandy.com>
2025-01-14 15:00:56 +01:00

149 lines
3.1 KiB
Go

package compose
import (
"bytes"
"time"
"github.com/pkg/errors"
"git.sr.ht/~rjarry/aerc/app"
"git.sr.ht/~rjarry/aerc/commands"
"git.sr.ht/~rjarry/aerc/lib/log"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/types"
)
type Postpone struct {
Folder string `opt:"-t" complete:"CompleteFolder" desc:"Override the target folder."`
}
func init() {
commands.Register(Postpone{})
}
func (Postpone) Description() string {
return "Save the current state of the message to the postpone folder."
}
func (Postpone) Context() commands.CommandContext {
return commands.COMPOSE_REVIEW
}
func (Postpone) Aliases() []string {
return []string{"postpone"}
}
func (*Postpone) CompleteFolder(arg string) []string {
return commands.GetFolders(arg)
}
func (p Postpone) Execute(args []string) error {
acct := app.SelectedAccount()
if acct == nil {
return errors.New("No account selected")
}
store := acct.Store()
if store == nil {
return errors.New("No message store selected")
}
tab := app.SelectedTab()
if tab == nil {
return errors.New("No tab selected")
}
composer, _ := tab.Content.(*app.Composer)
config := composer.Config()
tabName := tab.Name
targetFolder := config.Postpone
if composer.RecalledFrom() != "" {
targetFolder = composer.RecalledFrom()
}
if p.Folder != "" {
targetFolder = p.Folder
}
if targetFolder == "" {
return errors.New("No Postpone location configured")
}
log.Tracef("Postponing mail")
header, err := composer.PrepareHeader()
if err != nil {
return errors.Wrap(err, "PrepareHeader")
}
header.SetContentType("text/plain", map[string]string{"charset": "UTF-8"})
header.Set("Content-Transfer-Encoding", "quoted-printable")
worker := composer.Worker()
dirs := acct.Directories().List()
alreadyCreated := false
for _, dir := range dirs {
if dir == targetFolder {
alreadyCreated = true
break
}
}
errChan := make(chan string)
// run this as a goroutine so we can make other progress. The message
// will be saved once the directory is created.
go func() {
defer log.PanicHandler()
errStr := <-errChan
if errStr != "" {
app.PushError(errStr)
return
}
handleErr := func(err error) {
app.PushError(err.Error())
log.Errorf("Postponing failed: %v", err)
app.NewTab(composer, tabName)
}
app.RemoveTab(composer, false)
buf := &bytes.Buffer{}
err = composer.WriteMessage(header, buf)
if err != nil {
handleErr(errors.Wrap(err, "WriteMessage"))
return
}
store.Append(
targetFolder,
models.SeenFlag|models.DraftFlag,
time.Now(),
buf,
buf.Len(),
func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
app.PushStatus("Message postponed.", 10*time.Second)
composer.SetPostponed()
composer.Close()
case *types.Error:
handleErr(msg.Error)
}
},
)
}()
if !alreadyCreated {
// to synchronise the creating of the directory
worker.PostAction(&types.CreateDirectory{
Directory: targetFolder,
}, func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
errChan <- ""
case *types.Error:
errChan <- msg.Error.Error()
}
})
} else {
errChan <- ""
}
return nil
}