Fix #161: ensure gridview doesn't have concurrent fetch tasks on reset

This commit is contained in:
Drew Weymouth
2023-05-18 17:35:52 -07:00
parent 44c5074d12
commit 8f4f13733a
+28 -15
View File
@@ -82,7 +82,7 @@ type GridViewState struct {
iter GridViewIterator iter GridViewIterator
imageFetcher ImageFetcher imageFetcher ImageFetcher
highestShown int highestShown int
fetching bool fetchCancel context.CancelFunc
done bool done bool
OnPlay func(id string, shuffle bool) OnPlay func(id string, shuffle bool)
@@ -148,9 +148,12 @@ func (g *GridView) Clear() {
} }
func (g *GridView) Reset(iter GridViewIterator) { func (g *GridView) Reset(iter GridViewIterator) {
if g.fetchCancel != nil {
g.fetchCancel()
g.fetchCancel = nil
}
g.itemsMutex.Lock() g.itemsMutex.Lock()
g.items = nil g.items = nil
g.fetching = false
g.done = false g.done = false
g.highestShown = 0 g.highestShown = 0
g.iter = iter g.iter = iter
@@ -159,10 +162,13 @@ func (g *GridView) Reset(iter GridViewIterator) {
} }
func (g *GridView) ResetFixed(items []GridViewItemModel) { func (g *GridView) ResetFixed(items []GridViewItemModel) {
if g.fetchCancel != nil {
g.fetchCancel()
g.fetchCancel = nil
}
g.itemsMutex.Lock() g.itemsMutex.Lock()
g.items = items g.items = items
g.itemsMutex.Unlock() g.itemsMutex.Unlock()
g.fetching = false
g.done = true g.done = true
g.highestShown = 0 g.highestShown = 0
g.iter = nil g.iter = nil
@@ -262,7 +268,7 @@ func (g *GridView) doUpdateItemCard(itemIdx int, card *GridViewItem) {
} }
// if user has scrolled near the bottom, fetch more // if user has scrolled near the bottom, fetch more
if !g.done && !g.fetching && itemIdx > g.lenItems()-10 { if !g.done && g.fetchCancel == nil && itemIdx > g.lenItems()-10 {
g.fetchMoreItems(20) g.fetchMoreItems(20)
} }
} }
@@ -277,8 +283,10 @@ func (g *GridView) lenItems() int {
func (g *GridView) fetchMoreItems(count int) { func (g *GridView) fetchMoreItems(count int) {
if g.iter == nil { if g.iter == nil {
g.done = true g.done = true
return
} }
g.fetching = true ctx, cancel := context.WithCancel(context.Background())
g.fetchCancel = cancel
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
@@ -286,19 +294,24 @@ func (g *GridView) fetchMoreItems(count int) {
n := 0 n := 0
for !g.done && n < count { for !g.done && n < count {
items := g.iter.NextN(batchFetchSize) items := g.iter.NextN(batchFetchSize)
g.itemsMutex.Lock() select {
g.items = append(g.items, items...) case <-ctx.Done():
g.itemsMutex.Unlock() return
if len(items) < batchFetchSize { default:
g.done = true g.itemsMutex.Lock()
} g.items = append(g.items, items...)
n += len(items) g.itemsMutex.Unlock()
if len(items) > 0 { if len(items) < batchFetchSize {
g.Refresh() g.done = true
}
n += len(items)
if len(items) > 0 {
g.Refresh()
}
} }
} }
} }
g.fetching = false g.fetchCancel = nil
}() }()
} }