e4d418eed1
Add option to open a message in the message viewer without setting the seen flag. Enables the message viewer to be used as a preview pane without changing the message flags unintentionally. Before, the message viewer would set the seen flag by default. The IMAP backend will now always fetch the message body with the peek option enabled (same as we fetch the headers). An "auto-mark-read" option is added to the ui config which is set to true by default. If set the false, the seen flag is not set by the message viewer. Co-authored-by: "James Cook" <falsifian@falsifian.org> Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
131 lines
2.9 KiB
Go
131 lines
2.9 KiB
Go
package msg
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"git.sr.ht/~rjarry/aerc/lib"
|
|
"git.sr.ht/~rjarry/aerc/models"
|
|
"git.sr.ht/~rjarry/aerc/widgets"
|
|
"git.sr.ht/~rjarry/aerc/worker/types"
|
|
)
|
|
|
|
type Delete struct{}
|
|
|
|
func init() {
|
|
register(Delete{})
|
|
}
|
|
|
|
func (Delete) Aliases() []string {
|
|
return []string{"delete", "delete-message"}
|
|
}
|
|
|
|
func (Delete) Complete(aerc *widgets.Aerc, args []string) []string {
|
|
return nil
|
|
}
|
|
|
|
func (Delete) Execute(aerc *widgets.Aerc, args []string) error {
|
|
if len(args) != 1 {
|
|
return errors.New("Usage: :delete")
|
|
}
|
|
|
|
h := newHelper(aerc)
|
|
store, err := h.store()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uids, err := h.markedOrSelectedUids()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
acct, err := h.account()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sel := store.Selected()
|
|
marker := store.Marker()
|
|
marker.ClearVisualMark()
|
|
// caution, can be nil
|
|
next := findNextNonDeleted(uids, store)
|
|
store.Delete(uids, func(msg types.WorkerMessage) {
|
|
switch msg := msg.(type) {
|
|
case *types.Done:
|
|
aerc.PushStatus("Messages deleted.", 10*time.Second)
|
|
mv, isMsgView := h.msgProvider.(*widgets.MessageViewer)
|
|
if isMsgView {
|
|
if !aerc.Config().Ui.NextMessageOnDelete {
|
|
aerc.RemoveTab(h.msgProvider)
|
|
} else {
|
|
// no more messages in the list
|
|
if next == nil {
|
|
aerc.RemoveTab(h.msgProvider)
|
|
acct.Messages().Select(-1)
|
|
acct.Messages().Invalidate()
|
|
return
|
|
}
|
|
lib.NewMessageStoreView(next, acct.UiConfig().AutoMarkRead,
|
|
store, aerc.Crypto, aerc.DecryptKeys,
|
|
func(view lib.MessageView, err error) {
|
|
if err != nil {
|
|
aerc.PushError(err.Error())
|
|
return
|
|
}
|
|
nextMv := widgets.NewMessageViewer(acct, aerc.Config(), view)
|
|
aerc.ReplaceTab(mv, nextMv, next.Envelope.Subject)
|
|
})
|
|
}
|
|
} else {
|
|
if next == nil {
|
|
// We deleted the last message, select the new last message
|
|
// instead of the first message
|
|
acct.Messages().Select(-1)
|
|
}
|
|
}
|
|
case *types.Error:
|
|
marker.Remark()
|
|
store.Select(sel.Uid)
|
|
aerc.PushError(msg.Error.Error())
|
|
case *types.Unsupported:
|
|
marker.Remark()
|
|
store.Select(sel.Uid)
|
|
// notmuch doesn't support it, we want the user to know
|
|
aerc.PushError(" error, unsupported for this worker")
|
|
}
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func findNextNonDeleted(deleted []uint32, store *lib.MessageStore) *models.MessageInfo {
|
|
var next, previous *models.MessageInfo
|
|
stepper := []func(){store.Next, store.Prev}
|
|
for _, stepFn := range stepper {
|
|
previous = nil
|
|
for {
|
|
next = store.Selected()
|
|
if next != nil && !contains(deleted, next.Uid) {
|
|
if _, deleted := store.Deleted[next.Uid]; !deleted {
|
|
return next
|
|
}
|
|
}
|
|
if next == nil || previous == next {
|
|
break
|
|
}
|
|
stepFn()
|
|
previous = next
|
|
}
|
|
}
|
|
|
|
if next != nil {
|
|
store.Select(next.Uid)
|
|
}
|
|
return next
|
|
}
|
|
|
|
func contains(uids []uint32, uid uint32) bool {
|
|
for _, item := range uids {
|
|
if item == uid {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|