~poldi1405/aerc

cb3090956cfdc0ff4c2f06e4ef3c5eb73b73f9c0 — Koni Marti 6 months ago eafb537
dirlist: skip unnecessary change-folder action

when traversing the directory list, aerc will fetch the contents for
every directory even though the user might just move on to the next.
This causes an unnecessary delay (and load on the worker) and can be
avoided by skipping the old change-folder action when a newer one
arrives within a predefined time interval.

Signed-off-by: Koni Marti <koni.marti@gmail.com>
1 files changed, 55 insertions(+), 39 deletions(-)

M widgets/dirlist.go
M widgets/dirlist.go => widgets/dirlist.go +55 -39
@@ 6,6 6,7 @@ import (
	"math"
	"regexp"
	"sort"
	"time"

	"github.com/gdamore/tcell/v2"
	"github.com/mattn/go-runewidth"


@@ 20,27 21,29 @@ import (

type DirectoryList struct {
	ui.Invalidatable
	aercConf  *config.AercConfig
	acctConf  *config.AccountConfig
	store     *lib.DirStore
	dirs      []string
	logger    *log.Logger
	selecting string
	selected  string
	scroll    int
	spinner   *Spinner
	worker    *types.Worker
	aercConf   *config.AercConfig
	acctConf   *config.AccountConfig
	store      *lib.DirStore
	dirs       []string
	logger     *log.Logger
	selecting  string
	selected   string
	scroll     int
	spinner    *Spinner
	worker     *types.Worker
	skipSelect chan bool
}

func NewDirectoryList(conf *config.AercConfig, acctConf *config.AccountConfig,
	logger *log.Logger, worker *types.Worker) *DirectoryList {

	dirlist := &DirectoryList{
		aercConf: conf,
		acctConf: acctConf,
		logger:   logger,
		store:    lib.NewDirStore(),
		worker:   worker,
		aercConf:   conf,
		acctConf:   acctConf,
		logger:     logger,
		store:      lib.NewDirStore(),
		worker:     worker,
		skipSelect: make(chan bool),
	}
	uiConf := dirlist.UiConfig()
	dirlist.spinner = NewSpinner(&uiConf)


@@ 87,32 90,45 @@ func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) {

func (dirlist *DirectoryList) Select(name string) {
	dirlist.selecting = name
	dirlist.worker.PostAction(&types.OpenDirectory{Directory: name},
		func(msg types.WorkerMessage) {
			switch msg.(type) {
			case *types.Error:
				dirlist.selecting = ""
			case *types.Done:
				dirlist.selected = dirlist.selecting
				dirlist.filterDirsByFoldersConfig()
				hasSelected := false
				for _, d := range dirlist.dirs {
					if d == dirlist.selected {
						hasSelected = true
						break

	close(dirlist.skipSelect)
	dirlist.skipSelect = make(chan bool)

	go func() {
		select {
		case <-time.After(1 * time.Second):
			dirlist.worker.PostAction(&types.OpenDirectory{Directory: name},
				func(msg types.WorkerMessage) {
					switch msg.(type) {
					case *types.Error:
						dirlist.selecting = ""
						dirlist.selected = ""
					case *types.Done:
						dirlist.selected = dirlist.selecting
						dirlist.filterDirsByFoldersConfig()
						hasSelected := false
						for _, d := range dirlist.dirs {
							if d == dirlist.selected {
								hasSelected = true
								break
							}
						}
						if !hasSelected && dirlist.selected != "" {
							dirlist.dirs = append(dirlist.dirs, dirlist.selected)
						}
						if dirlist.acctConf.EnableFoldersSort {
							sort.Strings(dirlist.dirs)
						}
						dirlist.sortDirsByFoldersSortConfig()
					}
				}
				if !hasSelected && dirlist.selected != "" {
					dirlist.dirs = append(dirlist.dirs, dirlist.selected)
				}
				if dirlist.acctConf.EnableFoldersSort {
					sort.Strings(dirlist.dirs)
				}
				dirlist.sortDirsByFoldersSortConfig()
			}
					dirlist.Invalidate()
				})
			dirlist.Invalidate()
		})
	dirlist.Invalidate()
		case <-dirlist.skipSelect:
			dirlist.logger.Println("dirlist: skip", name)
			return
		}
	}()
}

func (dirlist *DirectoryList) Selected() string {