Files
supersonic/ui/util/thumbnailloader.go
Inevitabby 9a8bc6c936 fix: clear stale cover art and backgrounds on tracks without art (#957)
* fix: ensure load callback fires on error

Calls callOnLoaded(nil) when image loading fails.

This fixes the bottomplayer silently retaining stale images by ensuring consumers always get a callback and can clear their display state.

* fix: clear background layers on missing art

nil state now hides the blurred background widgets or animates the gradient to transparent, depending on the active configuration
2026-06-19 08:05:34 -07:00

71 lines
1.8 KiB
Go

package util
import (
"context"
"image"
"log"
"fyne.io/fyne/v2"
)
// ThumbnailLoader is a utility type that exposes a single API to load
// a cover thumbnail by ID. If the image is immediately available in
// the cache, OnLoaded will be called immediately. If it is not,
// OnBeforeLoad will be called first, then OnLoaded will be called async
// once the image is available.
// Any subsequent calls to Load will cancel the previous load if not yet completed.
type ThumbnailLoader struct {
prevLoadCancel context.CancelFunc
im ImageFetcher
OnBeforeLoad func()
OnLoaded func(image.Image)
}
// Image backend interface for the ThumbnailLoader
// impl: backend.ImageManager
type ImageFetcher interface {
GetCoverThumbnailFromCache(string) (image.Image, bool)
GetCoverThumbnailAsync(string, func(image.Image, error)) context.CancelFunc
}
func NewThumbnailLoader(im ImageFetcher, onLoaded func(image.Image)) ThumbnailLoader {
return ThumbnailLoader{im: im, OnLoaded: onLoaded}
}
func (i *ThumbnailLoader) Load(coverID string) {
if i.prevLoadCancel != nil {
i.prevLoadCancel()
}
if coverID == "" {
i.callOnLoaded(nil)
return
}
if img, ok := i.im.GetCoverThumbnailFromCache(coverID); ok {
i.callOnLoaded(img)
return
}
if i.OnBeforeLoad != nil {
i.OnBeforeLoad()
}
i.prevLoadCancel = i.im.GetCoverThumbnailAsync(coverID, func(img image.Image, err error) {
fyne.Do(func() {
if err != nil {
log.Printf("Error loading cover image: %s", err.Error())
i.callOnLoaded(nil)
} else {
i.callOnLoaded(img)
}
if i.prevLoadCancel != nil {
i.prevLoadCancel() // Cancel the context to release resources if not already cancelled
}
})
})
}
func (i *ThumbnailLoader) callOnLoaded(im image.Image) {
if i.OnLoaded != nil {
i.OnLoaded(im)
}
}