Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: tracks page supports selecting the sort order #450

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type PlaylistsPageConfig struct {

type TracksPageConfig struct {
TracklistColumns []string
SortOrder string
}

type NowPlayingPageConfig struct {
Expand Down Expand Up @@ -203,6 +204,7 @@ func DefaultConfig(appVersionTag string) *Config {
},
TracksPage: TracksPageConfig{
TracklistColumns: []string{"Album", "Time", "Plays"},
SortOrder: string("Recently Added"),
},
LocalPlayback: LocalPlaybackConfig{
// "auto" is the name to pass to MPV for autoselecting the output device
Expand Down
6 changes: 5 additions & 1 deletion backend/mediaprovider/jellyfin/iterators.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func (j *jellyfinMediaProvider) AlbumSortOrders() []string {
}
}

func (j *jellyfinMediaProvider) TrackSortOrders() []string {
return []string{}
}

func (j *jellyfinMediaProvider) IterateAlbums(sortOrder string, filter mediaprovider.AlbumFilter) mediaprovider.AlbumIterator {
var jfSort jellyfin.Sort
switch sortOrder {
Expand Down Expand Up @@ -83,7 +87,7 @@ func (j *jellyfinMediaProvider) SearchAlbums(searchQuery string, filter mediapro
return helpers.NewAlbumIterator(fetcher, filter, j.prefetchCoverCB)
}

func (j *jellyfinMediaProvider) IterateTracks(searchQuery string) mediaprovider.TrackIterator {
func (j *jellyfinMediaProvider) IterateTracks(sortOrder string, searchQuery string) mediaprovider.TrackIterator {
var fetcher helpers.TrackFetchFn
if searchQuery == "" {
fetcher = func(offs, limit int) ([]*mediaprovider.Track, error) {
Expand Down
4 changes: 3 additions & 1 deletion backend/mediaprovider/mediaprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ type MediaProvider interface {

IterateAlbums(sortOrder string, filter AlbumFilter) AlbumIterator

IterateTracks(searchQuery string) TrackIterator
IterateTracks(sortOrder string, searchQuery string) TrackIterator

SearchAlbums(searchQuery string, filter AlbumFilter) AlbumIterator

Expand All @@ -226,6 +226,8 @@ type MediaProvider interface {

ArtistSortOrders() []string

TrackSortOrders() []string

IterateArtists(sortOrder string, filter ArtistFilter) ArtistIterator

SearchArtists(searchQuery string, filter ArtistFilter) ArtistIterator
Expand Down
11 changes: 9 additions & 2 deletions backend/mediaprovider/subsonic/trackiterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import (
"github.com/dweymouth/supersonic/backend/mediaprovider"
)

func (s *subsonicMediaProvider) IterateTracks(searchQuery string) mediaprovider.TrackIterator {
func (s *subsonicMediaProvider) TrackSortOrders() []string {
return []string{
mediaprovider.AlbumSortRecentlyAdded,
mediaprovider.AlbumSortArtistAZ,
}
}

func (s *subsonicMediaProvider) IterateTracks(sortOrder string, searchQuery string) mediaprovider.TrackIterator {
if searchQuery == "" {
return &allTracksIterator{
s: s,
albumIter: s.IterateAlbums(
mediaprovider.AlbumSortArtistAZ,
sortOrder,
mediaprovider.NewAlbumFilter(mediaprovider.AlbumFilterOptions{}),
),
}
Expand Down
65 changes: 53 additions & 12 deletions ui/browsing/trackspage.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package browsing

import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
"github.com/dweymouth/supersonic/backend"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/sharedutil"
"github.com/dweymouth/supersonic/ui/controller"
"github.com/dweymouth/supersonic/ui/theme"
"github.com/dweymouth/supersonic/ui/util"
"github.com/dweymouth/supersonic/ui/widgets"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/lang"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
"slices"
)

type TracksPage struct {
Expand All @@ -24,6 +24,7 @@ type TracksPage struct {
nowPlayingID string

title *widget.RichText
sortOrder *sortOrderSelect
searcher *widgets.SearchEntry
tracklist *widgets.Tracklist
loader widgets.TracklistLoader
Expand All @@ -40,6 +41,7 @@ type tracksPageState struct {
conf *backend.TracksPageConfig
mp mediaprovider.MediaProvider
im *backend.ImageManager
sorterId int
canRate bool
canShare bool
}
Expand All @@ -66,9 +68,8 @@ func NewTracksPage(contr *controller.Controller, conf *backend.TracksPageConfig,
}
contr.ConnectTracklistActions(t.tracklist)

t.title = widget.NewRichTextWithText(lang.L("All Tracks"))
t.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
t.playRandom = widget.NewButtonWithIcon(lang.L("Play random"), theme.ShuffleIcon, t.playRandomSongs)
t.createTitleAndSort()

t.searcher = widgets.NewSearchEntry()
t.searcher.PlaceHolder = lang.L("Search page")
t.searcher.OnSearched = t.OnSearched
Expand All @@ -77,10 +78,50 @@ func NewTracksPage(contr *controller.Controller, conf *backend.TracksPageConfig,
return t
}

func (t *TracksPage) createTitleAndSort() {
t.title = widget.NewRichTextWithText(lang.L("All Tracks"))
sortOrders := t.mp.TrackSortOrders()
if len(sortOrders) > 1 {
sorts, selected := t.SortOrders()
t.sortOrder = NewSortOrderSelect(sorts, t.onSortOrderChanged)
t.sortOrder.SetSelectedIndex(selected)
t.sorterId = 0
}
t.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
t.playRandom = widget.NewButtonWithIcon(lang.L("Play random"), theme.ShuffleIcon, t.playRandomSongs)
}

func (t *TracksPage) SortOrders() ([]string, int) {
orders := t.mp.TrackSortOrders()
sortOrder := slices.Index(orders, t.conf.SortOrder)
if sortOrder < 0 {
sortOrder = 0
}

return util.LocalizeSlice(orders), sortOrder
}

func (t *TracksPage) onSortOrderChanged(_ string) {
t.conf.SortOrder = t.mp.TrackSortOrders()[t.getSortOrderIdx()]
t.Reload()
}

func (t *TracksPage) getSortOrderIdx() int {
if t.sortOrder != nil {
return t.sortOrder.SelectedIndex()
}
return 0
}

func (t *TracksPage) createContainer() {
playRandomVbox := container.NewVBox(layout.NewSpacer(), t.playRandom, layout.NewSpacer())
searchVbox := container.NewVBox(layout.NewSpacer(), t.searcher, layout.NewSpacer())
topRow := container.NewHBox(t.title, playRandomVbox, layout.NewSpacer(), searchVbox)
var topRow *fyne.Container
if t.sortOrder != nil {
topRow = container.NewHBox(t.title, container.NewCenter(t.sortOrder), playRandomVbox, layout.NewSpacer(), searchVbox)
} else {
topRow = container.NewHBox(t.title, playRandomVbox, layout.NewSpacer(), searchVbox)
}
t.container = container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 5, BottomPadding: 15},
container.NewBorder(topRow, nil, nil, nil, t.tracklist))
}
Expand All @@ -91,7 +132,7 @@ func (t *TracksPage) Route() controller.Route {

func (t *TracksPage) Reload() {
t.tracklist.Clear()
iter := t.mp.IterateTracks("")
iter := t.mp.IterateTracks(t.mp.TrackSortOrders()[t.getSortOrderIdx()], "")
// loads asynchronously
t.loader = widgets.NewTracklistLoader(t.tracklist, iter)
}
Expand Down Expand Up @@ -155,7 +196,7 @@ func (t *TracksPage) doSearch(query string) {
} else {
t.searchTracklist.Clear()
}
iter := t.mp.IterateTracks(query)
iter := t.mp.IterateTracks(t.mp.TrackSortOrders()[t.getSortOrderIdx()], query)
t.searchLoader = widgets.NewTracklistLoader(t.searchTracklist, iter)
t.container.Objects[0].(*fyne.Container).Objects[0] = t.searchTracklist
t.Refresh()
Expand Down
Loading