4bd4f4664a
re-opens the review UI when the postpone operation fails. Before, the composer would close, even on error, and we would lose the email draft. Now, the user can decide on how to proceed when postponing fails. References: https://lists.sr.ht/~rjarry/aerc-devel/patches/28824 Signed-off-by: Koni Marti <koni.marti@gmail.com>
124 lines
2.7 KiB
Go
124 lines
2.7 KiB
Go
package compose
|
|
|
|
import (
|
|
"io"
|
|
"io/ioutil"
|
|
"time"
|
|
|
|
"github.com/miolini/datacounter"
|
|
"github.com/pkg/errors"
|
|
|
|
"git.sr.ht/~rjarry/aerc/models"
|
|
"git.sr.ht/~rjarry/aerc/widgets"
|
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
|
)
|
|
|
|
type Postpone struct{}
|
|
|
|
func init() {
|
|
register(Postpone{})
|
|
}
|
|
|
|
func (Postpone) Aliases() []string {
|
|
return []string{"postpone"}
|
|
}
|
|
|
|
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")
|
|
}
|
|
composer, _ := aerc.SelectedTab().(*widgets.Composer)
|
|
config := composer.Config()
|
|
tabName := aerc.TabNames()[aerc.SelectedTabIndex()]
|
|
|
|
if config.Postpone == "" {
|
|
return errors.New("No Postpone location configured")
|
|
}
|
|
|
|
aerc.Logger().Println("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 := aerc.SelectedAccount().Directories().List()
|
|
alreadyCreated := false
|
|
for _, dir := range dirs {
|
|
if dir == config.Postpone {
|
|
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() {
|
|
errStr := <-errChan
|
|
if errStr != "" {
|
|
aerc.PushError(errStr)
|
|
return
|
|
}
|
|
|
|
handleErr := func(err error) {
|
|
aerc.PushError(err.Error())
|
|
aerc.Logger().Println("Postponing failed:", err)
|
|
aerc.NewTab(composer, tabName)
|
|
}
|
|
|
|
aerc.RemoveTab(composer)
|
|
ctr := datacounter.NewWriterCounter(ioutil.Discard)
|
|
err = composer.WriteMessage(header, ctr)
|
|
if err != nil {
|
|
handleErr(errors.Wrap(err, "WriteMessage"))
|
|
return
|
|
}
|
|
nbytes := int(ctr.Count())
|
|
r, w := io.Pipe()
|
|
worker.PostAction(&types.AppendMessage{
|
|
Destination: config.Postpone,
|
|
Flags: []models.Flag{models.SeenFlag},
|
|
Date: time.Now(),
|
|
Reader: r,
|
|
Length: int(nbytes),
|
|
}, func(msg types.WorkerMessage) {
|
|
switch msg := msg.(type) {
|
|
case *types.Done:
|
|
aerc.PushStatus("Message postponed.", 10*time.Second)
|
|
r.Close()
|
|
composer.Close()
|
|
case *types.Error:
|
|
r.Close()
|
|
handleErr(msg.Error)
|
|
}
|
|
})
|
|
composer.WriteMessage(header, w)
|
|
w.Close()
|
|
}()
|
|
|
|
if !alreadyCreated {
|
|
// to synchronise the creating of the directory
|
|
worker.PostAction(&types.CreateDirectory{
|
|
Directory: config.Postpone,
|
|
}, func(msg types.WorkerMessage) {
|
|
switch msg := msg.(type) {
|
|
case *types.Done:
|
|
errChan <- ""
|
|
case *types.Error:
|
|
errChan <- msg.Error.Error()
|
|
}
|
|
})
|
|
} else {
|
|
errChan <- ""
|
|
}
|
|
|
|
return nil
|
|
}
|