Fix #665: Add option to play albums in order on Albums page

This commit is contained in:
Drew Weymouth
2025-08-10 15:06:27 -07:00
parent 43670538b9
commit a317b382ff
5 changed files with 100 additions and 4 deletions
+71 -3
View File
@@ -6,7 +6,7 @@ import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/widget"
"fyne.io/fyne/v2/theme"
"github.com/dweymouth/supersonic/backend"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/ui/controller"
@@ -22,6 +22,9 @@ type albumsPageAdapter struct {
pm *backend.PlaybackManager
filter mediaprovider.AlbumFilter
filterBtn *widgets.AlbumFilterButton
// dependency injected from the GridViewPage
itemsFn func() []widgets.GridViewItemModel
}
func NewAlbumsPage(cfg *backend.AlbumsPageConfig, pool *util.WidgetPool, contr *controller.Controller, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, im *backend.ImageManager) Page {
@@ -29,6 +32,12 @@ func NewAlbumsPage(cfg *backend.AlbumsPageConfig, pool *util.WidgetPool, contr *
return NewGridViewPage(adapter, pool, mp, im)
}
var _ GridViewPageAdapterGetItems = (*albumsPageAdapter)(nil)
func (a *albumsPageAdapter) SetItemsFunc(f func() []widgets.GridViewItemModel) {
a.itemsFn = f
}
func (a *albumsPageAdapter) Title() string { return lang.L("Albums") }
func (a *albumsPageAdapter) Filter() mediaprovider.AlbumFilter {
@@ -66,7 +75,7 @@ func (a *albumsPageAdapter) SaveSortOrder(orderIdx int) {
}
func (a *albumsPageAdapter) ActionButton() fyne.CanvasObject {
fn := func() {
shuffleAlbumsFn := func() {
go func() {
if err := a.pm.PlayRandomAlbums(""); err != nil {
log.Printf("error playing random albums: %v", err)
@@ -77,7 +86,66 @@ func (a *albumsPageAdapter) ActionButton() fyne.CanvasObject {
}()
}
return widget.NewButtonWithIcon(lang.L("Play random"), myTheme.ShuffleIcon, fn)
playAlbumsFn := func() {
if a.itemsFn == nil {
a.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play albums"))
}
go func() {
for i, item := range a.itemsFn() {
if i >= 20 {
break // don't load more than first 20 albums
}
if i == 0 {
a.pm.LoadAlbum(item.ID, backend.Replace, false)
a.pm.PlayFromBeginning()
} else {
a.pm.LoadAlbum(item.ID, backend.Append, false)
}
}
}()
}
var btn *widgets.OptionButton
var inOrder, shuffled *fyne.MenuItem
inOrder = fyne.NewMenuItem(lang.L("In order"), func() {
shuffled.Checked = false
inOrder.Checked = true
a.cfg.PlayInOrder = true
btn.Text = lang.L("Play albums")
btn.Icon = theme.MediaPlayIcon()
btn.Refresh()
})
inOrder.Icon = myTheme.AlbumIcon
shuffled = fyne.NewMenuItem(lang.L("Shuffled"), func() {
inOrder.Checked = false
shuffled.Checked = true
a.cfg.PlayInOrder = false
btn.Text = lang.L("Shuffle albums")
btn.Icon = myTheme.ShuffleIcon
btn.Refresh()
})
shuffled.Icon = myTheme.ShuffleIcon
shuffled.Checked = !a.cfg.PlayInOrder
inOrder.Checked = a.cfg.PlayInOrder
menu := fyne.NewMenu("", inOrder, shuffled)
icon := myTheme.ShuffleIcon
textKey := "Shuffle albums"
if a.cfg.PlayInOrder {
textKey = "Play albums"
icon = theme.MediaPlayIcon()
}
btn = widgets.NewOptionButton(lang.L(textKey), menu, func() {
if a.cfg.PlayInOrder {
playAlbumsFn()
} else {
shuffleAlbumsFn()
}
})
btn.Icon = icon
return btn
}
func (a *albumsPageAdapter) Iter(sortOrderIdx int, filter mediaprovider.AlbumFilter) widgets.GridViewIterator {
+13
View File
@@ -76,6 +76,13 @@ type GridViewPageAdapter[M, F any] interface {
RefreshGrid(*widgets.GridView)
}
type GridViewPageAdapterGetItems interface {
// Optionally allows the GridViewPage to inject a function that
// can be used to retrieve the GridViewItemModels for the
// items currently loaded into the GridView.
SetItemsFunc(func() []widgets.GridViewItemModel)
}
type SortableGridViewPageAdapter interface {
// Returns the list of sort orders
// and the index of the initially selected sort order
@@ -113,6 +120,12 @@ func NewGridViewPage[M, F any](
}
gp.grid.DisableSharing = !canShare
adapter.InitGrid(gp.grid)
// If adapter supports SetItemsFunc, call it to inject the items dependency
if plfSetter, ok := adapter.(GridViewPageAdapterGetItems); ok {
plfSetter.SetItemsFunc(gp.grid.Items)
}
gp.createSearchAndFilter()
gp.createContainer()
return gp