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
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
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 -3Learn more about email & git
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
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
builds.sr.ht <builds@sr.ht>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