~rjarry/aerc-devel

aerc: ui responsiveness when changing folders v1 APPLIED

this patch series addresses the ui responsiveness of the directory list.
There's an unpleasent lag when changing folders. This happens with IMAP,
maildir and notmuch. The lag is the result of changing the highlighted
directory entry in a call-back function. 

- Patch 1/2 gives a fast visual feedback to the user while loading the
  contents

- Patch 2/2 skips unnecessary opening actions when the user cycles through
  the directory list

I tested this with IMAP, maildir and notmuch. 

Koni Marti (2):
  dirlist: improve change-folder responsiveness
  dirlist: skip unnecessary change-folder action

 widgets/dirlist.go | 98 +++++++++++++++++++++++++++-------------------
 1 file changed, 57 insertions(+), 41 deletions(-)

-- 
2.34.1
#678747 alpine-edge.yml success
#678748 archlinux.yml success
#678749 debian-stable.yml success
#678750 fedora-latest.yml success
aerc/patches: SUCCESS in 5m29s

[ui responsiveness when changing folders][0] from [Koni Marti][1]

[0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/28632
[1]: mailto:koni.marti@gmail.com

✓ #678748 SUCCESS aerc/patches/archlinux.yml     https://builds.sr.ht/~rjarry/job/678748
✓ #678750 SUCCESS aerc/patches/fedora-latest.yml https://builds.sr.ht/~rjarry/job/678750
✓ #678747 SUCCESS aerc/patches/alpine-edge.yml   https://builds.sr.ht/~rjarry/job/678747
✓ #678749 SUCCESS aerc/patches/debian-stable.yml https://builds.sr.ht/~rjarry/job/678749
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~rjarry/aerc-devel/patches/28632/mbox | git am -3
Learn more about email & git

[PATCH aerc 1/2] dirlist: improve change-folder responsiveness Export this patch

improves change-folder responsiveness. When changing folders, the
highlighted directory is currently updated in a callback function to the
open-directory action. This creates an unpleasent lag in the ui until
the entire operation is done. Instead, we should provide an immediate
visual feedback of the selection to the user and keep loading the
directory contents in the background.

Signed-off-by: Koni Marti <koni.marti@gmail.com>
---
 widgets/dirlist.go | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/widgets/dirlist.go b/widgets/dirlist.go
index 0345380..e6f95e1 100644
--- a/widgets/dirlist.go
+++ b/widgets/dirlist.go
@@ -238,7 +238,7 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) {
		}

		style := dirlist.UiConfig().GetStyle(config.STYLE_DIRLIST_DEFAULT)
		if name == dirlist.selected {
		if name == dirlist.selecting {
			style = dirlist.UiConfig().GetStyleSelected(config.STYLE_DIRLIST_DEFAULT)
		}
		ctx.Fill(0, row, textWidth, 1, ' ', style)
@@ -332,7 +332,7 @@ func (dirlist *DirectoryList) Clicked(x int, y int) (string, bool) {
}

func (dirlist *DirectoryList) NextPrev(delta int) {
	curIdx := findString(dirlist.dirs, dirlist.selected)
	curIdx := findString(dirlist.dirs, dirlist.selecting)
	if curIdx == len(dirlist.dirs) {
		return
	}
-- 
2.34.1

[PATCH aerc 2/2] dirlist: skip unnecessary change-folder action Export this patch

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>
---
 widgets/dirlist.go | 94 +++++++++++++++++++++++++++-------------------
 1 file changed, 55 insertions(+), 39 deletions(-)

diff --git a/widgets/dirlist.go b/widgets/dirlist.go
index e6f95e1..53afc1d 100644
--- a/widgets/dirlist.go
+++ b/widgets/dirlist.go
@@ -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 {
-- 
2.34.1
aerc/patches: SUCCESS in 5m29s

[ui responsiveness when changing folders][0] from [Koni Marti][1]

[0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/28632
[1]: mailto:koni.marti@gmail.com

✓ #678748 SUCCESS aerc/patches/archlinux.yml     https://builds.sr.ht/~rjarry/job/678748
✓ #678750 SUCCESS aerc/patches/fedora-latest.yml https://builds.sr.ht/~rjarry/job/678750
✓ #678747 SUCCESS aerc/patches/alpine-edge.yml   https://builds.sr.ht/~rjarry/job/678747
✓ #678749 SUCCESS aerc/patches/debian-stable.yml https://builds.sr.ht/~rjarry/job/678749