Updates #415: Make artist's discography sort order configurable

This commit is contained in:
Drew Weymouth
2024-07-26 08:00:12 -07:00
parent fdd449584b
commit 3c70513cb4
2 changed files with 73 additions and 16 deletions
+1
View File
@@ -64,6 +64,7 @@ type AlbumsPageConfig struct {
type ArtistPageConfig struct {
InitialView string
DiscographySort string
TracklistColumns []string
}
+72 -16
View File
@@ -21,6 +21,11 @@ import (
"fyne.io/fyne/v2/widget"
)
// these strings should be keys in the translation dictionaries
var (
discographySorts = []string{"Year (ascending)", "Year (descending)", "Name (A-Z)"}
)
var _ fyne.Widget = (*ArtistPage)(nil)
type artistPageState struct {
@@ -46,6 +51,7 @@ type ArtistPage struct {
albumGrid *widgets.GridView
tracklistCtr *fyne.Container
sortButton *widgets.IconButton
nowPlayingID string
header *ArtistPageHeader
container *fyne.Container
@@ -90,9 +96,10 @@ func newArtistPage(artistID string, cfg *backend.ArtistPageConfig, pool *util.Wi
viewToggle := widgets.NewToggleText(0, []string{lang.L("Discography"), lang.L("Top Tracks")})
viewToggle.SetActivatedLabel(a.activeView)
viewToggle.OnChanged = a.onViewChange
//line := canvas.NewLine(theme.TextColor())
a.sortButton = widgets.NewIconButton(myTheme.SortIcon, a.showAlbumSortMenu)
viewToggleRow := container.NewBorder(nil, nil,
container.NewHBox(util.NewHSpace(5), viewToggle), nil,
container.NewHBox(util.NewHSpace(5), viewToggle),
container.NewHBox(a.sortButton, util.NewHSpace(10)),
layout.NewSpacer(),
)
a.container = container.NewBorder(
@@ -166,6 +173,60 @@ func (a *ArtistPage) playArtistRadio() {
go a.pm.PlaySimilarSongs(a.artistID)
}
func (a *ArtistPage) showAlbumSortMenu() {
m := fyne.NewMenu("")
oneChecked := false
for i, s := range util.LocalizeSlice(discographySorts) {
_i := i
item := fyne.NewMenuItem(s, func() {
a.cfg.DiscographySort = discographySorts[_i]
a.showAlbumGrid(true /*reSort*/)
})
if discographySorts[i] == a.cfg.DiscographySort {
item.Checked = true
oneChecked = true
}
m.Items = append(m.Items, item)
}
if !oneChecked {
m.Items[0].Checked = true
}
btnPos := fyne.CurrentApp().Driver().AbsolutePositionForObject(a.sortButton)
btnSize := a.sortButton.Size()
pop := widget.NewPopUpMenu(m, fyne.CurrentApp().Driver().CanvasForObject(a))
menuW := pop.MinSize().Width
pop.ShowAtPosition(fyne.NewPos(btnPos.X+btnSize.Width-menuW, btnPos.Y+btnSize.Height))
}
func (a *ArtistPage) getGridViewAlbumsModel() []widgets.GridViewItemModel {
if a.artistInfo == nil {
return nil
}
sortFunc := func(x, y int) bool {
return a.artistInfo.Albums[x].Year < a.artistInfo.Albums[y].Year
}
switch a.cfg.DiscographySort {
case discographySorts[1]: /*year descending*/
sortFunc = func(x, y int) bool {
return a.artistInfo.Albums[x].Year > a.artistInfo.Albums[y].Year
}
case discographySorts[2]: /*name*/
sortFunc = func(x, y int) bool {
return a.artistInfo.Albums[x].Name < a.artistInfo.Albums[y].Name
}
}
sort.Slice(a.artistInfo.Albums, sortFunc)
return sharedutil.MapSlice(a.artistInfo.Albums, func(al *mediaprovider.Album) widgets.GridViewItemModel {
return widgets.GridViewItemModel{
Name: al.Name,
ID: al.ID,
CoverArtID: al.CoverArtID,
Secondary: []string{strconv.Itoa(al.Year)},
}
})
}
// should be called asynchronously
func (a *ArtistPage) load() {
artist, err := a.mp.GetArtist(a.artistID)
@@ -179,7 +240,7 @@ func (a *ArtistPage) load() {
a.artistInfo = artist
a.header.Update(artist)
if a.activeView == 0 {
a.showAlbumGrid()
a.showAlbumGrid(false /*reSort*/)
} else {
a.showTopTracks()
}
@@ -192,24 +253,14 @@ func (a *ArtistPage) load() {
}
}
func (a *ArtistPage) showAlbumGrid() {
func (a *ArtistPage) showAlbumGrid(reSort bool) {
if a.albumGrid == nil {
if a.artistInfo == nil {
// page not loaded yet or invalid artist
a.activeView = 0 // if page still loading, will show discography view first
return
}
sort.Slice(a.artistInfo.Albums, func(x, y int) bool {
return a.artistInfo.Albums[x].Year < a.artistInfo.Albums[y].Year
})
model := sharedutil.MapSlice(a.artistInfo.Albums, func(al *mediaprovider.Album) widgets.GridViewItemModel {
return widgets.GridViewItemModel{
Name: al.Name,
ID: al.ID,
CoverArtID: al.CoverArtID,
Secondary: []string{strconv.Itoa(al.Year)},
}
})
model := a.getGridViewAlbumsModel()
if g := a.pool.Obtain(util.WidgetTypeGridView); g != nil {
a.albumGrid = g.(*widgets.GridView)
a.albumGrid.Placeholder = myTheme.AlbumIcon
@@ -218,7 +269,11 @@ func (a *ArtistPage) showAlbumGrid() {
a.albumGrid = widgets.NewFixedGridView(model, a.im, myTheme.AlbumIcon)
}
a.contr.ConnectAlbumGridActions(a.albumGrid)
} else if reSort {
model := a.getGridViewAlbumsModel()
a.albumGrid.ResetFixed(model)
}
a.sortButton.Show()
a.container.Objects[0].(*fyne.Container).Objects[0] = a.albumGrid
a.container.Objects[0].Refresh()
}
@@ -262,13 +317,14 @@ func (a *ArtistPage) showTopTracks() {
&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 10},
tl)
}
a.sortButton.Hide()
a.container.Objects[0].(*fyne.Container).Objects[0] = a.tracklistCtr
a.container.Objects[0].Refresh()
}
func (a *ArtistPage) onViewChange(num int) {
if num == 0 {
a.showAlbumGrid()
a.showAlbumGrid(false /*reSort*/)
} else {
// needs to request info from server if first time,
// so call it asynchronously