aboutsummaryrefslogblamecommitdiffstats
path: root/commands/msg/read.go
blob: 5b4bd0730da089df20c12f208c7d214c5cbbf5a1 (plain) (tree)
1
2
3
4
5
6
7
8
9


           
             
                 
              
 
                                    
                                         
                                       
                                             

 


                                                              
                                                                                                         

                       
 
             




                                                  

 

                                                           

 










                                               


                                         





                                                         
                                                                 

                                                   
                                                        

 






                                                                      
                                               

                                                            
 




                                        



                                                    


                                                   
                 

         
                        
                               


                          
 


                                                              
 
                     






                                                                      
                                                




                                                                    
                                       



                                                        
                 

                                    
                                          

                                              
                                           
                                                
                 
         
 

                                                                              
                               
                                                                                  

                                                  
                                                                      

                                                                
                                                                

                         

                                
                                                                                    

                                                  
                                                                      

                                                                
                                                                

                         
         
                  
 
package msg

import (
	"fmt"
	"strings"
	"time"

	"git.sr.ht/~rjarry/aerc/app"
	"git.sr.ht/~rjarry/aerc/commands"
	"git.sr.ht/~rjarry/aerc/models"
	"git.sr.ht/~rjarry/aerc/worker/types"
)

type FlagMsg struct {
	Toggle   bool         `opt:"-t"`
	Answered bool         `opt:"-a" aliases:"flag,unflag"`
	Flag     models.Flags `opt:"-x" aliases:"flag,unflag" action:"ParseFlag" complete:"CompleteFlag"`
	FlagName string
}

func init() {
	commands.Register(FlagMsg{})
}

func (FlagMsg) Context() commands.CommandContext {
	return commands.MESSAGE
}

func (FlagMsg) Aliases() []string {
	return []string{"flag", "unflag", "read", "unread"}
}

func (f *FlagMsg) ParseFlag(arg string) error {
	switch strings.ToLower(arg) {
	case "seen":
		f.Flag = models.SeenFlag
		f.FlagName = "seen"
	case "answered":
		f.Flag = models.AnsweredFlag
		f.FlagName = "answered"
	case "flagged":
		f.Flag = models.FlaggedFlag
		f.FlagName = "flagged"
	case "draft":
		f.Flag = models.DraftFlag
		f.FlagName = "draft"
	default:
		return fmt.Errorf("Unknown flag %q", arg)
	}
	return nil
}

var validFlags = []string{"seen", "answered", "flagged", "draft"}

func (*FlagMsg) CompleteFlag(arg string) []string {
	return commands.FilterList(validFlags, arg, nil)
}

// If this was called as 'flag' or 'unflag', without the toggle (-t)
// option, then it will flag the corresponding messages with the given
// flag.  If the toggle option was given, it will individually toggle
// the given flag for the corresponding messages.
//
// If this was called as 'read' or 'unread', it has the same effect as
// 'flag' or 'unflag', respectively, but the 'Seen' flag is affected.
func (f FlagMsg) Execute(args []string) error {
	// User-readable name for the action being performed
	var actionName string

	switch args[0] {
	case "read", "unread":
		f.Flag = models.SeenFlag
		f.FlagName = "seen"
	case "flag", "unflag":
		if f.Answered {
			f.Flag = models.AnsweredFlag
			f.FlagName = "answered"
		}
		if f.Flag == 0 {
			f.Flag = models.FlaggedFlag
			f.FlagName = "flagged"
		}
	}

	h := newHelper()
	store, err := h.store()
	if err != nil {
		return err
	}

	// UIDs of messages to enable or disable the flag for.
	var toEnable []uint32
	var toDisable []uint32

	if f.Toggle {
		// If toggling, split messages into those that need to
		// be enabled / disabled.
		msgs, err := h.messages()
		if err != nil {
			return err
		}
		for _, m := range msgs {
			if m.Flags.Has(f.Flag) {
				toDisable = append(toDisable, m.Uid)
			} else {
				toEnable = append(toEnable, m.Uid)
			}
		}
		actionName = "Toggling"
	} else {
		msgUids, err := h.markedOrSelectedUids()
		if err != nil {
			return err
		}
		switch args[0] {
		case "read", "flag":
			toEnable = msgUids
			actionName = "Setting"
		default:
			toDisable = msgUids
			actionName = "Unsetting"
		}
	}

	status := fmt.Sprintf("%s flag %q successful", actionName, f.FlagName)

	if len(toEnable) != 0 {
		store.Flag(toEnable, f.Flag, true, func(msg types.WorkerMessage) {
			switch msg := msg.(type) {
			case *types.Done:
				app.PushStatus(status, 10*time.Second)
				store.Marker().ClearVisualMark()
			case *types.Error:
				app.PushError(msg.Error.Error())
			}
		})
	}
	if len(toDisable) != 0 {
		store.Flag(toDisable, f.Flag, false, func(msg types.WorkerMessage) {
			switch msg := msg.(type) {
			case *types.Done:
				app.PushStatus(status, 10*time.Second)
				store.Marker().ClearVisualMark()
			case *types.Error:
				app.PushError(msg.Error.Error())
			}
		})
	}
	return nil
}