add TracklistLoader for infinite scrolling tracklist

This commit is contained in:
Drew Weymouth
2023-04-20 19:24:44 -07:00
parent 88d4322ecd
commit b21b1ce6ba
2 changed files with 85 additions and 0 deletions
+18
View File
@@ -67,6 +67,7 @@ type Tracklist struct {
OnShowAlbumPage func(albumID string)
OnColumnVisibilityMenuShown func(*widget.PopUp)
OnTrackShown func(tracknum int)
visibleColumns []bool
@@ -113,6 +114,9 @@ func NewTracklist(tracks []*subsonic.Child) *Tracklist {
i = itemID + 1
}
tr.Update(t.TrackAt(itemID), itemID == t.nowPlayingIdx, i)
if t.OnTrackShown != nil {
t.OnTrackShown(itemID)
}
})
t.container = container.NewBorder(t.hdr, nil, nil, nil, t.list)
return t
@@ -203,6 +207,20 @@ func (t *Tracklist) IncrementPlayCount(trackID string) {
}
}
// Remove all tracks from the tracklist. Thread-safe.
func (t *Tracklist) Clear() {
t.tracksMutex.Lock()
defer t.tracksMutex.Unlock()
t.Tracks = nil
}
// Append more tracks to the tracklist. Thread-safe.
func (t *Tracklist) AppendTracks(trs []*subsonic.Child) {
t.tracksMutex.Lock()
defer t.tracksMutex.Unlock()
t.Tracks = append(t.Tracks, trs...)
}
func (t *Tracklist) SelectAll() {
t.selectionMgr.SelectAll()
t.list.Refresh()
+67
View File
@@ -0,0 +1,67 @@
package widgets
import (
"log"
"supersonic/backend"
"github.com/dweymouth/go-subsonic/subsonic"
)
// Component that manages lazily loading more tracks into a Tracklist
// as the user scrolls near the bottom.
type TracklistLoader struct {
tracklist *Tracklist
iter backend.TrackIterator
trackBuffer []*subsonic.Child
fetching bool
done bool
len int
highestShown int
}
func NewTracklistLoader(tracklist *Tracklist, iter backend.TrackIterator) TracklistLoader {
t := TracklistLoader{
tracklist: tracklist,
iter: iter,
}
t.tracklist.OnTrackShown = t.onTrackShown
t.fetching = true
go t.loadMoreTracks(25)
return t
}
func (t *TracklistLoader) onTrackShown(tracknum int) {
if tracknum > t.highestShown {
t.highestShown = tracknum
}
if t.highestShown >= t.len-25 && !t.fetching && !t.done {
t.fetching = true
go t.loadMoreTracks(25)
}
}
func (t *TracklistLoader) loadMoreTracks(num int) {
// repeat fetch task as long as user has scrolled near bottom
for !t.done && t.highestShown >= t.len-25 {
log.Println("fetching more tracks")
if t.trackBuffer == nil {
t.trackBuffer = make([]*subsonic.Child, 0, num)
}
t.trackBuffer = t.trackBuffer[:0]
for i := 0; i < num; i++ {
tr := t.iter.Next()
if tr == nil {
t.done = true
t.trackBuffer = nil
break
}
t.trackBuffer = append(t.trackBuffer, tr)
}
t.tracklist.AppendTracks(t.trackBuffer)
t.tracklist.Refresh()
log.Printf("appended %d tracks", len(t.trackBuffer))
t.len += len(t.trackBuffer)
}
t.fetching = false
}