aerc/commands/msg/read.go

147 lines
2.8 KiB
Go
Raw Normal View History

2019-06-09 20:55:34 +02:00
package msg
import (
"errors"
2019-12-22 12:05:28 +01:00
"sync"
2019-06-09 20:55:34 +02:00
"time"
"git.sr.ht/~sircmpwn/getopt"
2019-12-22 12:05:28 +01:00
"git.sr.ht/~sircmpwn/aerc/lib"
"git.sr.ht/~sircmpwn/aerc/models"
2019-06-09 20:55:34 +02:00
"git.sr.ht/~sircmpwn/aerc/widgets"
"git.sr.ht/~sircmpwn/aerc/worker/types"
)
type Read struct{}
2019-06-09 20:55:34 +02:00
func init() {
register(Read{})
}
func (Read) Aliases() []string {
return []string{"read", "unread"}
}
func (Read) Complete(aerc *widgets.Aerc, args []string) []string {
return nil
2019-06-09 20:55:34 +02:00
}
func (Read) Execute(aerc *widgets.Aerc, args []string) error {
opts, optind, err := getopt.Getopts(args, "t")
if err != nil {
return err
}
if optind != len(args) {
2019-07-23 20:46:32 +02:00
return errors.New("Usage: " + args[0] + " [-t]")
}
var toggle bool
for _, opt := range opts {
switch opt.Option {
case 't':
toggle = true
}
2019-06-09 20:55:34 +02:00
}
2019-12-22 12:05:28 +01:00
h := newHelper(aerc)
store, err := h.store()
if err != nil {
return err
}
2019-12-22 12:05:28 +01:00
if toggle {
2019-12-22 12:05:28 +01:00
// ignore commmand given, simply toggle all the read states
return submitToggle(aerc, store, h)
}
msgUids, err := h.messageUids()
if err != nil {
return err
}
switch args[0] {
case "read":
submitReadChange(aerc, store, msgUids, true)
case "unread":
submitReadChange(aerc, store, msgUids, false)
}
return nil
}
func splitMessages(msgs []*models.MessageInfo) (read []uint32, unread []uint32) {
for _, m := range msgs {
var seen bool
for _, flag := range m.Flags {
if flag == models.SeenFlag {
2019-12-22 12:05:28 +01:00
seen = true
break
}
}
2019-12-22 12:05:28 +01:00
if seen {
read = append(read, m.Uid)
} else {
unread = append(unread, m.Uid)
}
}
2019-12-22 12:05:28 +01:00
return read, unread
}
2019-06-09 20:55:34 +02:00
2019-12-22 12:05:28 +01:00
func submitReadChange(aerc *widgets.Aerc, store *lib.MessageStore,
uids []uint32, newState bool) {
store.Read(uids, newState, func(msg types.WorkerMessage) {
2019-06-09 20:55:34 +02:00
switch msg := msg.(type) {
case *types.Done:
2019-12-22 12:05:28 +01:00
aerc.PushStatus(msg_success, 10*time.Second)
2019-06-09 20:55:34 +02:00
case *types.Error:
2020-04-24 18:59:40 +02:00
aerc.PushError(" " + msg.Error.Error())
2019-06-09 20:55:34 +02:00
}
})
2019-12-22 12:05:28 +01:00
}
func submitReadChangeWg(aerc *widgets.Aerc, store *lib.MessageStore,
uids []uint32, newState bool, wg sync.WaitGroup, success *bool) {
store.Read(uids, newState, func(msg types.WorkerMessage) {
wg.Add(1)
switch msg := msg.(type) {
case *types.Done:
wg.Done()
case *types.Error:
2020-04-24 18:59:40 +02:00
aerc.PushError(" " + msg.Error.Error())
2019-12-22 12:05:28 +01:00
*success = false
wg.Done()
}
})
}
func submitToggle(aerc *widgets.Aerc, store *lib.MessageStore, h *helper) error {
msgs, err := h.messages()
if err != nil {
return err
}
read, unread := splitMessages(msgs)
var wg sync.WaitGroup
success := true
if len(read) != 0 {
newState := false
submitReadChangeWg(aerc, store, read, newState, wg, &success)
}
if len(unread) != 0 {
newState := true
submitReadChangeWg(aerc, store, unread, newState, wg, &success)
}
// we need to do that in the background, else we block the main thread
go func() {
wg.Wait()
if success {
aerc.PushStatus(msg_success, 10*time.Second)
}
}()
2019-06-09 20:55:34 +02:00
return nil
2019-12-22 12:05:28 +01:00
2019-06-09 20:55:34 +02:00
}
2019-12-22 12:05:28 +01:00
const msg_success = "read state set successfully"