make infinite scroll album loading thread-safe
This commit is contained in:
+19
-3
@@ -6,6 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"supersonic/backend"
|
"supersonic/backend"
|
||||||
"supersonic/res"
|
"supersonic/res"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/widget"
|
"fyne.io/fyne/v2/widget"
|
||||||
@@ -29,6 +30,7 @@ type AlbumGrid struct {
|
|||||||
|
|
||||||
type AlbumGridState struct {
|
type AlbumGridState struct {
|
||||||
albums []*subsonic.AlbumID3
|
albums []*subsonic.AlbumID3
|
||||||
|
albumsMutex sync.RWMutex
|
||||||
iter *backend.BatchingIterator
|
iter *backend.BatchingIterator
|
||||||
highestShown int
|
highestShown int
|
||||||
fetching bool
|
fetching bool
|
||||||
@@ -91,12 +93,16 @@ func NewAlbumGridFromState(state AlbumGridState) *AlbumGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ag *AlbumGrid) Clear() {
|
func (ag *AlbumGrid) Clear() {
|
||||||
|
ag.albumsMutex.Lock()
|
||||||
|
defer ag.albumsMutex.Unlock()
|
||||||
ag.albums = nil
|
ag.albums = nil
|
||||||
ag.done = true
|
ag.done = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ag *AlbumGrid) Reset(iter backend.AlbumIterator) {
|
func (ag *AlbumGrid) Reset(iter backend.AlbumIterator) {
|
||||||
|
ag.albumsMutex.Lock()
|
||||||
ag.albums = nil
|
ag.albums = nil
|
||||||
|
ag.albumsMutex.Unlock()
|
||||||
ag.fetching = false
|
ag.fetching = false
|
||||||
ag.done = false
|
ag.done = false
|
||||||
ag.highestShown = 0
|
ag.highestShown = 0
|
||||||
@@ -107,7 +113,7 @@ func (ag *AlbumGrid) Reset(iter backend.AlbumIterator) {
|
|||||||
func (ag *AlbumGrid) createGridWrapList() {
|
func (ag *AlbumGrid) createGridWrapList() {
|
||||||
g := widget.NewGridWrapList(
|
g := widget.NewGridWrapList(
|
||||||
func() int {
|
func() int {
|
||||||
return len(ag.albums)
|
return ag.lenAlbums()
|
||||||
},
|
},
|
||||||
// create func
|
// create func
|
||||||
func() fyne.CanvasObject {
|
func() fyne.CanvasObject {
|
||||||
@@ -142,7 +148,9 @@ func (ag *AlbumGrid) doUpdateAlbumCard(albumIdx int, ac *AlbumCard) {
|
|||||||
if albumIdx > ag.highestShown {
|
if albumIdx > ag.highestShown {
|
||||||
ag.highestShown = albumIdx
|
ag.highestShown = albumIdx
|
||||||
}
|
}
|
||||||
|
ag.albumsMutex.RLock()
|
||||||
album := ag.albums[albumIdx]
|
album := ag.albums[albumIdx]
|
||||||
|
ag.albumsMutex.RUnlock()
|
||||||
if ac.PrevAlbumID == album.ID {
|
if ac.PrevAlbumID == album.ID {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return
|
return
|
||||||
@@ -177,11 +185,17 @@ func (ag *AlbumGrid) doUpdateAlbumCard(albumIdx int, ac *AlbumCard) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if user has scrolled near the bottom, fetch more
|
// if user has scrolled near the bottom, fetch more
|
||||||
if !ag.done && !ag.fetching && albumIdx > len(ag.albums)-10 {
|
if !ag.done && !ag.fetching && albumIdx > ag.lenAlbums()-10 {
|
||||||
ag.fetchMoreAlbums(20)
|
ag.fetchMoreAlbums(20)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *AlbumGrid) lenAlbums() int {
|
||||||
|
a.albumsMutex.RLock()
|
||||||
|
defer a.albumsMutex.RUnlock()
|
||||||
|
return len(a.albums)
|
||||||
|
}
|
||||||
|
|
||||||
// fetches at least count more albums
|
// fetches at least count more albums
|
||||||
func (a *AlbumGrid) fetchMoreAlbums(count int) {
|
func (a *AlbumGrid) fetchMoreAlbums(count int) {
|
||||||
if a.iter == nil {
|
if a.iter == nil {
|
||||||
@@ -191,11 +205,13 @@ func (a *AlbumGrid) fetchMoreAlbums(count int) {
|
|||||||
go func() {
|
go func() {
|
||||||
// keep repeating the fetch task as long as the user
|
// keep repeating the fetch task as long as the user
|
||||||
// has scrolled near the bottom
|
// has scrolled near the bottom
|
||||||
for !a.done && a.highestShown >= len(a.albums)-10 {
|
for !a.done && a.highestShown >= a.lenAlbums()-10 {
|
||||||
n := 0
|
n := 0
|
||||||
for !a.done && n < count {
|
for !a.done && n < count {
|
||||||
albums := a.iter.NextN(albumFetchBatchSize)
|
albums := a.iter.NextN(albumFetchBatchSize)
|
||||||
|
a.albumsMutex.Lock()
|
||||||
a.albums = append(a.albums, albums...)
|
a.albums = append(a.albums, albums...)
|
||||||
|
a.albumsMutex.Unlock()
|
||||||
if len(albums) < albumFetchBatchSize {
|
if len(albums) < albumFetchBatchSize {
|
||||||
a.done = true
|
a.done = true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user