package compose
import (
"bytes"
"time"
"github.com/miolini/datacounter"
"github.com/pkg/errors"
"git.sr.ht/~rjarry/aerc/log"
"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")
}
acct := aerc.SelectedAccount()
if acct == nil {
return errors.New("No account selected")
}
tab := aerc.SelectedTab()
if tab == nil {
return errors.New("No tab selected")
}
composer, _ := tab.Content.(*widgets.Composer)
config := composer.Config()
tabName := tab.Name
if config.Postpone == "" {
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 == 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() {
defer log.PanicHandler()
errStr := <-errChan
if errStr != "" {
aerc.PushError(errStr)
return
}
handleErr := func(err error) {
aerc.PushError(err.Error())
log.Errorf("Postponing failed: %v", err)
aerc.NewTab(composer, tabName)
}
aerc.RemoveTab(composer, false)
var buf bytes.Buffer
ctr := datacounter.NewWriterCounter(&buf)
err = composer.WriteMessage(header, ctr)
if err != nil {
handleErr(errors.Wrap(err, "WriteMessage"))
return
}
nbytes := int(ctr.Count())
worker.PostAction(&types.AppendMessage{
Destination: config.Postpone,
Flags: models.SeenFlag,
Date: time.Now(),
Reader: &buf,
Length: int(nbytes),
}, func(msg types.WorkerMessage) {
switch msg := msg.(type) {
case *types.Done:
aerc.PushStatus("Message postponed.", 10*time.Second)
composer.Close()
case *types.Error:
handleErr(msg.Error)
}
})
}()
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
}