From fe86cfda472d8a2ceb0334fcfbc9a76018fa0e9a Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 28 Jan 2023 09:04:17 -0800 Subject: [PATCH] batch-add albums to infinite scroll grid to slightly improve smoothness --- backend/albumiterator.go | 55 +++++++++++++++------------------------- ui/widgets/albumgrid.go | 33 ++++++++++-------------- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/backend/albumiterator.go b/backend/albumiterator.go index c065434..6ef2c76 100644 --- a/backend/albumiterator.go +++ b/backend/albumiterator.go @@ -10,7 +10,6 @@ import ( type AlbumIterator interface { Next() *subsonic.AlbumID3 - NextN(int, func(*subsonic.AlbumID3)) } type LibraryManager struct { @@ -164,18 +163,6 @@ func (r *baseIter) Next() *subsonic.AlbumID3 { return r.prefetched[0] } -func (r *baseIter) NextN(n int, cb func(*subsonic.AlbumID3)) { - go func() { - for i := 0; i < n; i++ { - a := r.Next() - cb(a) - if a == nil { - break - } - } - }() -} - type searchIter struct { query string artistOffset int @@ -263,18 +250,6 @@ func (s *searchIter) Next() *subsonic.AlbumID3 { return nil } -func (s *searchIter) NextN(n int, cb func(*subsonic.AlbumID3)) { - go func() { - for i := 0; i < n; i++ { - a := s.Next() - cb(a) - if a == nil { - break - } - } - }() -} - func (s *searchIter) addNewAlbums(al []*subsonic.AlbumID3) { for _, album := range al { if _, have := s.albumIDset[album.ID]; have { @@ -386,14 +361,24 @@ func (r *randomIter) Next() *subsonic.AlbumID3 { return nil } -func (r *randomIter) NextN(n int, cb func(*subsonic.AlbumID3)) { - go func() { - for i := 0; i < n; i++ { - a := r.Next() - cb(a) - if a == nil { - break - } - } - }() +type BatchingIterator struct { + iter AlbumIterator +} + +func NewBatchingIterator(iter AlbumIterator) *BatchingIterator { + return &BatchingIterator{iter} +} + +func (b *BatchingIterator) NextN(n int) []*subsonic.AlbumID3 { + results := make([]*subsonic.AlbumID3, 0, n) + i := 0 + for i < n { + album := b.iter.Next() + if album == nil { + break + } + results = append(results, album) + i++ + } + return results } diff --git a/ui/widgets/albumgrid.go b/ui/widgets/albumgrid.go index 64ecd0e..ba1d6e0 100644 --- a/ui/widgets/albumgrid.go +++ b/ui/widgets/albumgrid.go @@ -4,6 +4,7 @@ import ( "context" "image" "log" + "supersonic/backend" "fyne.io/fyne/v2" "fyne.io/fyne/v2/widget" @@ -15,10 +16,6 @@ type ImageFetcher interface { GetAlbumThumbnail(string) (image.Image, error) } -type AlbumIterator interface { - NextN(int, func(*subsonic.AlbumID3)) -} - type AlbumGrid struct { widget.BaseWidget @@ -29,7 +26,7 @@ type AlbumGrid struct { type AlbumGridState struct { albums []*subsonic.AlbumID3 - iter AlbumIterator + iter *backend.BatchingIterator fetching bool done bool showYear bool @@ -58,10 +55,10 @@ func NewFixedAlbumGrid(albums []*subsonic.AlbumID3, fetch ImageFetcher, showYear return ag } -func NewAlbumGrid(iter AlbumIterator, fetch ImageFetcher, showYear bool) *AlbumGrid { +func NewAlbumGrid(iter backend.AlbumIterator, fetch ImageFetcher, showYear bool) *AlbumGrid { ag := &AlbumGrid{ AlbumGridState: AlbumGridState{ - iter: iter, + iter: backend.NewBatchingIterator(iter), imageFetcher: fetch, }, } @@ -94,11 +91,11 @@ func (ag *AlbumGrid) Clear() { ag.done = true } -func (ag *AlbumGrid) Reset(iter AlbumIterator) { +func (ag *AlbumGrid) Reset(iter backend.AlbumIterator) { ag.albums = nil ag.fetching = false ag.done = false - ag.iter = iter + ag.iter = backend.NewBatchingIterator(iter) ag.fetchMoreAlbums(36) } @@ -182,20 +179,18 @@ func (a *AlbumGrid) fetchMoreAlbums(count int) { if a.iter == nil { a.done = true } - i := 0 a.fetching = true - a.iter.NextN(count, func(al *subsonic.AlbumID3) { - if al == nil { + go func() { + albums := a.iter.NextN(count) + a.albums = append(a.albums, albums...) + if len(albums) < count { a.done = true - return } - a.albums = append(a.albums, al) - i++ - if i == count { - a.fetching = false + a.fetching = false + if len(albums) > 0 { + a.Refresh() } - a.Refresh() - }) + }() } func (a *AlbumGrid) CreateRenderer() fyne.WidgetRenderer {