begin reuse of widgets across pages
This commit is contained in:
+42
-17
@@ -33,29 +33,32 @@ type AlbumPage struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type albumPageState struct {
|
type albumPageState struct {
|
||||||
albumID string
|
albumID string
|
||||||
sort widgets.TracklistSort
|
sort widgets.TracklistSort
|
||||||
cfg *backend.AlbumPageConfig
|
cfg *backend.AlbumPageConfig
|
||||||
mp mediaprovider.MediaProvider
|
widgetCache *util.WidgetCache
|
||||||
pm *backend.PlaybackManager
|
mp mediaprovider.MediaProvider
|
||||||
im *backend.ImageManager
|
pm *backend.PlaybackManager
|
||||||
contr *controller.Controller
|
im *backend.ImageManager
|
||||||
|
contr *controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAlbumPage(
|
func NewAlbumPage(
|
||||||
albumID string,
|
albumID string,
|
||||||
cfg *backend.AlbumPageConfig,
|
cfg *backend.AlbumPageConfig,
|
||||||
|
cache *util.WidgetCache,
|
||||||
pm *backend.PlaybackManager,
|
pm *backend.PlaybackManager,
|
||||||
mp mediaprovider.MediaProvider,
|
mp mediaprovider.MediaProvider,
|
||||||
im *backend.ImageManager,
|
im *backend.ImageManager,
|
||||||
contr *controller.Controller,
|
contr *controller.Controller,
|
||||||
) *AlbumPage {
|
) *AlbumPage {
|
||||||
return newAlbumPage(albumID, cfg, pm, mp, im, contr, widgets.TracklistSort{})
|
return newAlbumPage(albumID, cfg, cache, pm, mp, im, contr, widgets.TracklistSort{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAlbumPage(
|
func newAlbumPage(
|
||||||
albumID string,
|
albumID string,
|
||||||
cfg *backend.AlbumPageConfig,
|
cfg *backend.AlbumPageConfig,
|
||||||
|
cache *util.WidgetCache,
|
||||||
pm *backend.PlaybackManager,
|
pm *backend.PlaybackManager,
|
||||||
mp mediaprovider.MediaProvider,
|
mp mediaprovider.MediaProvider,
|
||||||
im *backend.ImageManager,
|
im *backend.ImageManager,
|
||||||
@@ -64,16 +67,23 @@ func newAlbumPage(
|
|||||||
) *AlbumPage {
|
) *AlbumPage {
|
||||||
a := &AlbumPage{
|
a := &AlbumPage{
|
||||||
albumPageState: albumPageState{
|
albumPageState: albumPageState{
|
||||||
albumID: albumID,
|
albumID: albumID,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
pm: pm,
|
widgetCache: cache,
|
||||||
mp: mp,
|
pm: pm,
|
||||||
im: im,
|
mp: mp,
|
||||||
contr: contr,
|
im: im,
|
||||||
|
contr: contr,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.header = NewAlbumPageHeader(a)
|
if h := a.widgetCache.Obtain(util.WidgetTypeAlbumPageHeader); h != nil {
|
||||||
|
a.header = h.(*AlbumPageHeader)
|
||||||
|
a.header.Clear()
|
||||||
|
} else {
|
||||||
|
a.header = NewAlbumPageHeader(a)
|
||||||
|
}
|
||||||
|
a.header.page = a
|
||||||
a.tracklist = widgets.NewTracklist(nil)
|
a.tracklist = widgets.NewTracklist(nil)
|
||||||
a.tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
a.tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
a.tracklist.SetSorting(sort)
|
a.tracklist.SetSorting(sort)
|
||||||
@@ -97,6 +107,7 @@ func (a *AlbumPage) CreateRenderer() fyne.WidgetRenderer {
|
|||||||
func (a *AlbumPage) Save() SavedPage {
|
func (a *AlbumPage) Save() SavedPage {
|
||||||
s := a.albumPageState
|
s := a.albumPageState
|
||||||
s.sort = a.tracklist.Sorting()
|
s.sort = a.tracklist.Sorting()
|
||||||
|
a.widgetCache.Release(util.WidgetTypeAlbumPageHeader, a.header)
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +145,9 @@ func (a *AlbumPage) load() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.header.Update(album, a.im)
|
a.header.Update(album, a.im)
|
||||||
a.tracklist.ShowDiscNumber = album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber
|
a.tracklist.Options = widgets.TracklistOptions{
|
||||||
|
ShowDiscNumber: album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber,
|
||||||
|
}
|
||||||
a.tracks = album.Tracks
|
a.tracks = album.Tracks
|
||||||
a.tracklist.SetTracks(album.Tracks)
|
a.tracklist.SetTracks(album.Tracks)
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
@@ -256,6 +269,18 @@ func (a *AlbumPageHeader) Update(album *mediaprovider.AlbumWithTracks, im *backe
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *AlbumPageHeader) Clear() {
|
||||||
|
a.albumID = ""
|
||||||
|
a.coverID = ""
|
||||||
|
a.artistID = ""
|
||||||
|
a.titleLabel.Segments[0].(*widget.TextSegment).Text = ""
|
||||||
|
a.artistLabel.SetText("")
|
||||||
|
a.genreLabel.SetText("")
|
||||||
|
a.miscLabel.SetText("")
|
||||||
|
a.toggleFavButton.IsFavorited = false
|
||||||
|
a.cover.Image.Image = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *AlbumPageHeader) toggleFavorited() {
|
func (a *AlbumPageHeader) toggleFavorited() {
|
||||||
params := mediaprovider.RatingFavoriteParameters{AlbumIDs: []string{a.albumID}}
|
params := mediaprovider.RatingFavoriteParameters{AlbumIDs: []string{a.albumID}}
|
||||||
a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited)
|
a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited)
|
||||||
@@ -283,5 +308,5 @@ func formatMiscLabelStr(a *mediaprovider.AlbumWithTracks) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *albumPageState) Restore() Page {
|
func (s *albumPageState) Restore() Page {
|
||||||
return newAlbumPage(s.albumID, s.cfg, s.pm, s.mp, s.im, s.contr, s.sort)
|
return newAlbumPage(s.albumID, s.cfg, s.widgetCache, s.pm, s.mp, s.im, s.contr, s.sort)
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-20
@@ -28,11 +28,12 @@ type artistPageState struct {
|
|||||||
activeView int
|
activeView int
|
||||||
trackSort widgets.TracklistSort
|
trackSort widgets.TracklistSort
|
||||||
|
|
||||||
cfg *backend.ArtistPageConfig
|
widgetCache *util.WidgetCache
|
||||||
pm *backend.PlaybackManager
|
cfg *backend.ArtistPageConfig
|
||||||
mp mediaprovider.MediaProvider
|
pm *backend.PlaybackManager
|
||||||
im *backend.ImageManager
|
mp mediaprovider.MediaProvider
|
||||||
contr *controller.Controller
|
im *backend.ImageManager
|
||||||
|
contr *controller.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArtistPage struct {
|
type ArtistPage struct {
|
||||||
@@ -49,27 +50,34 @@ type ArtistPage struct {
|
|||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArtistPage(artistID string, cfg *backend.ArtistPageConfig, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, im *backend.ImageManager, contr *controller.Controller) *ArtistPage {
|
func NewArtistPage(artistID string, cfg *backend.ArtistPageConfig, cache *util.WidgetCache, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, im *backend.ImageManager, contr *controller.Controller) *ArtistPage {
|
||||||
activeView := 0
|
activeView := 0
|
||||||
if cfg.InitialView == "Top Tracks" {
|
if cfg.InitialView == "Top Tracks" {
|
||||||
activeView = 1
|
activeView = 1
|
||||||
}
|
}
|
||||||
return newArtistPage(artistID, cfg, pm, mp, im, contr, activeView, widgets.TracklistSort{})
|
return newArtistPage(artistID, cfg, cache, pm, mp, im, contr, activeView, widgets.TracklistSort{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArtistPage(artistID string, cfg *backend.ArtistPageConfig, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, im *backend.ImageManager, contr *controller.Controller, activeView int, sort widgets.TracklistSort) *ArtistPage {
|
func newArtistPage(artistID string, cfg *backend.ArtistPageConfig, cache *util.WidgetCache, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, im *backend.ImageManager, contr *controller.Controller, activeView int, sort widgets.TracklistSort) *ArtistPage {
|
||||||
a := &ArtistPage{artistPageState: artistPageState{
|
a := &ArtistPage{artistPageState: artistPageState{
|
||||||
artistID: artistID,
|
artistID: artistID,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
pm: pm,
|
widgetCache: cache,
|
||||||
mp: mp,
|
pm: pm,
|
||||||
im: im,
|
mp: mp,
|
||||||
contr: contr,
|
im: im,
|
||||||
activeView: activeView,
|
contr: contr,
|
||||||
trackSort: sort,
|
activeView: activeView,
|
||||||
|
trackSort: sort,
|
||||||
}}
|
}}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.header = NewArtistPageHeader(a)
|
if h := a.widgetCache.Obtain(util.WidgetTypeArtistPageHeader); h != nil {
|
||||||
|
a.header = h.(*ArtistPageHeader)
|
||||||
|
} else {
|
||||||
|
a.header = NewArtistPageHeader(a)
|
||||||
|
}
|
||||||
|
a.header.artistPage = a
|
||||||
|
a.header.Clear()
|
||||||
if img, ok := im.GetCachedArtistImage(artistID); ok {
|
if img, ok := im.GetCachedArtistImage(artistID); ok {
|
||||||
a.header.artistImage.SetImage(img, true /*tappable*/)
|
a.header.artistImage.SetImage(img, true /*tappable*/)
|
||||||
}
|
}
|
||||||
@@ -116,6 +124,7 @@ func (a *ArtistPage) Save() SavedPage {
|
|||||||
if a.tracklistCtr != nil {
|
if a.tracklistCtr != nil {
|
||||||
s.trackSort = a.tracklistCtr.Objects[0].(*widgets.Tracklist).Sorting()
|
s.trackSort = a.tracklistCtr.Objects[0].(*widgets.Tracklist).Sorting()
|
||||||
}
|
}
|
||||||
|
a.widgetCache.Release(util.WidgetTypeArtistPageHeader, a.header)
|
||||||
return &s
|
return &s
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +199,7 @@ func (a *ArtistPage) showTopTracks() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tl := widgets.NewTracklist(ts)
|
tl := widgets.NewTracklist(ts)
|
||||||
tl.AutoNumber = true
|
tl.Options = widgets.TracklistOptions{AutoNumber: true}
|
||||||
tl.SetVisibleColumns(a.cfg.TracklistColumns)
|
tl.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
tl.SetSorting(a.trackSort)
|
tl.SetSorting(a.trackSort)
|
||||||
tl.OnVisibleColumnsChanged = func(cols []string) {
|
tl.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
@@ -228,9 +237,11 @@ func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *artistPageState) Restore() Page {
|
func (s *artistPageState) Restore() Page {
|
||||||
return newArtistPage(s.artistID, s.cfg, s.pm, s.mp, s.im, s.contr, s.activeView, s.trackSort)
|
return newArtistPage(s.artistID, s.cfg, s.widgetCache, s.pm, s.mp, s.im, s.contr, s.activeView, s.trackSort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const artistBioNotAvailableStr = "Artist biography not available."
|
||||||
|
|
||||||
type ArtistPageHeader struct {
|
type ArtistPageHeader struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
@@ -250,7 +261,7 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader {
|
|||||||
a := &ArtistPageHeader{
|
a := &ArtistPageHeader{
|
||||||
artistPage: page,
|
artistPage: page,
|
||||||
titleDisp: widget.NewRichTextWithText(""),
|
titleDisp: widget.NewRichTextWithText(""),
|
||||||
biographyDisp: widget.NewRichTextWithText("Artist biography not available."),
|
biographyDisp: widget.NewRichTextWithText(artistBioNotAvailableStr),
|
||||||
similarArtists: container.NewHBox(),
|
similarArtists: container.NewHBox(),
|
||||||
}
|
}
|
||||||
a.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
a.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
||||||
@@ -273,6 +284,15 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPageHeader) Clear() {
|
||||||
|
a.artistID = ""
|
||||||
|
a.favoriteBtn.IsFavorited = false
|
||||||
|
a.titleDisp.Segments[0].(*widget.TextSegment).Text = ""
|
||||||
|
a.biographyDisp.Segments[0].(*widget.TextSegment).Text = artistBioNotAvailableStr
|
||||||
|
a.similarArtists.RemoveAll()
|
||||||
|
a.artistImage.SetImage(nil, false)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ArtistPageHeader) Update(artist *mediaprovider.ArtistWithAlbums) {
|
func (a *ArtistPageHeader) Update(artist *mediaprovider.ArtistWithAlbums) {
|
||||||
if artist == nil {
|
if artist == nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -233,17 +233,21 @@ func (b *BrowsingPane) GoHome() {
|
|||||||
|
|
||||||
func (b *BrowsingPane) GoBack() {
|
func (b *BrowsingPane) GoBack() {
|
||||||
if b.historyIdx > 0 {
|
if b.historyIdx > 0 {
|
||||||
|
// due to widget reuse between pages,
|
||||||
|
// we must create the new page before calling addPageToHistory
|
||||||
|
p := b.history[b.historyIdx-1].Restore()
|
||||||
b.addPageToHistory(b.curPage, false)
|
b.addPageToHistory(b.curPage, false)
|
||||||
b.historyIdx -= 2
|
b.historyIdx -= 2
|
||||||
b.doSetPage(b.history[b.historyIdx].Restore())
|
b.doSetPage(p)
|
||||||
b.updateHistoryButtons()
|
b.updateHistoryButtons()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BrowsingPane) GoForward() {
|
func (b *BrowsingPane) GoForward() {
|
||||||
if b.historyIdx < len(b.history)-1 {
|
if b.historyIdx < len(b.history)-1 {
|
||||||
|
p := b.history[b.historyIdx+1].Restore()
|
||||||
b.addPageToHistory(b.curPage, false)
|
b.addPageToHistory(b.curPage, false)
|
||||||
b.doSetPage(b.history[b.historyIdx].Restore())
|
b.doSetPage(p)
|
||||||
b.updateHistoryButtons()
|
b.updateHistoryButtons()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ func (a *FavoritesPage) onShowFavoriteSongs() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
tracklist := widgets.NewTracklist(fav.Tracks)
|
tracklist := widgets.NewTracklist(fav.Tracks)
|
||||||
tracklist.AutoNumber = true
|
tracklist.Options = widgets.TracklistOptions{AutoNumber: true}
|
||||||
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
|
||||||
tracklist.SetSorting(a.trackSort)
|
tracklist.SetSorting(a.trackSort)
|
||||||
tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
|
|||||||
@@ -62,14 +62,16 @@ func NewNowPlayingPage(
|
|||||||
a.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
a.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
a.conf.TracklistColumns = cols
|
a.conf.TracklistColumns = cols
|
||||||
}
|
}
|
||||||
a.tracklist.AutoNumber = true
|
a.tracklist.Options = widgets.TracklistOptions{
|
||||||
a.tracklist.DisablePlaybackMenu = true
|
AutoNumber: true,
|
||||||
|
DisablePlaybackMenu: true,
|
||||||
|
AuxiliaryMenuItems: []*fyne.MenuItem{
|
||||||
|
fyne.NewMenuItem("Remove from queue", a.onRemoveSelectedFromQueue),
|
||||||
|
},
|
||||||
|
}
|
||||||
contr.ConnectTracklistActions(a.tracklist)
|
contr.ConnectTracklistActions(a.tracklist)
|
||||||
// override the default OnPlayTrackAt handler b/c we don't need to re-load the tracks into the queue
|
// override the default OnPlayTrackAt handler b/c we don't need to re-load the tracks into the queue
|
||||||
a.tracklist.OnPlayTrackAt = a.onPlayTrackAt
|
a.tracklist.OnPlayTrackAt = a.onPlayTrackAt
|
||||||
a.tracklist.AuxiliaryMenuItems = []*fyne.MenuItem{
|
|
||||||
fyne.NewMenuItem("Remove from queue", a.onRemoveSelectedFromQueue),
|
|
||||||
}
|
|
||||||
a.title = widget.NewRichTextWithText("Now Playing")
|
a.title = widget.NewRichTextWithText("Now Playing")
|
||||||
a.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
|
a.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
|
||||||
a.statusLabel = widget.NewRichTextWithText("Stopped")
|
a.statusLabel = widget.NewRichTextWithText("Stopped")
|
||||||
|
|||||||
@@ -77,8 +77,10 @@ func newPlaylistPage(
|
|||||||
fyne.NewMenuItem("Move down", a.onMoveSelectedDown),
|
fyne.NewMenuItem("Move down", a.onMoveSelectedDown),
|
||||||
fyne.NewMenuItem("Move to bottom", a.onMoveSelectedToBottom),
|
fyne.NewMenuItem("Move to bottom", a.onMoveSelectedToBottom),
|
||||||
}...)
|
}...)
|
||||||
a.tracklist.AuxiliaryMenuItems = []*fyne.MenuItem{reorderMenu,
|
a.tracklist.Options = widgets.TracklistOptions{
|
||||||
fyne.NewMenuItem("Remove from playlist", a.onRemoveSelectedFromPlaylist)}
|
AuxiliaryMenuItems: []*fyne.MenuItem{reorderMenu,
|
||||||
|
fyne.NewMenuItem("Remove from playlist", a.onRemoveSelectedFromPlaylist)},
|
||||||
|
}
|
||||||
// connect tracklist actions
|
// connect tracklist actions
|
||||||
a.contr.ConnectTracklistActions(a.tracklist)
|
a.contr.ConnectTracklistActions(a.tracklist)
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -3,6 +3,7 @@ package browsing
|
|||||||
import (
|
import (
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/ui/controller"
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
|
"github.com/dweymouth/supersonic/ui/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NavigationHandler interface {
|
type NavigationHandler interface {
|
||||||
@@ -11,16 +12,18 @@ type NavigationHandler interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Router struct {
|
type Router struct {
|
||||||
App *backend.App
|
App *backend.App
|
||||||
Controller *controller.Controller
|
Controller *controller.Controller
|
||||||
Nav NavigationHandler
|
Nav NavigationHandler
|
||||||
|
widgetCache util.WidgetCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(app *backend.App, controller *controller.Controller, nav NavigationHandler) Router {
|
func NewRouter(app *backend.App, controller *controller.Controller, nav NavigationHandler) Router {
|
||||||
r := Router{
|
r := Router{
|
||||||
App: app,
|
App: app,
|
||||||
Controller: controller,
|
Controller: controller,
|
||||||
Nav: nav,
|
Nav: nav,
|
||||||
|
widgetCache: util.NewWidgetCache(),
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -28,11 +31,11 @@ func NewRouter(app *backend.App, controller *controller.Controller, nav Navigati
|
|||||||
func (r Router) CreatePage(rte controller.Route) Page {
|
func (r Router) CreatePage(rte controller.Route) Page {
|
||||||
switch rte.Page {
|
switch rte.Page {
|
||||||
case controller.Album:
|
case controller.Album:
|
||||||
return NewAlbumPage(rte.Arg, &r.App.Config.AlbumPage, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager, r.Controller)
|
return NewAlbumPage(rte.Arg, &r.App.Config.AlbumPage, &r.widgetCache, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager, r.Controller)
|
||||||
case controller.Albums:
|
case controller.Albums:
|
||||||
return NewAlbumsPage(&r.App.Config.AlbumsPage, r.Controller, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager)
|
return NewAlbumsPage(&r.App.Config.AlbumsPage, r.Controller, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager)
|
||||||
case controller.Artist:
|
case controller.Artist:
|
||||||
return NewArtistPage(rte.Arg, &r.App.Config.ArtistPage, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager, r.Controller)
|
return NewArtistPage(rte.Arg, &r.App.Config.ArtistPage, &r.widgetCache, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager, r.Controller)
|
||||||
case controller.Artists:
|
case controller.Artists:
|
||||||
return NewArtistsPage(r.Controller, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager)
|
return NewArtistsPage(r.Controller, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager)
|
||||||
case controller.Favorites:
|
case controller.Favorites:
|
||||||
|
|||||||
@@ -44,8 +44,10 @@ func NewTracksPage(contr *controller.Controller, conf *backend.TracksPageConfig,
|
|||||||
t.ExtendBaseWidget(t)
|
t.ExtendBaseWidget(t)
|
||||||
|
|
||||||
t.tracklist = widgets.NewTracklist(nil)
|
t.tracklist = widgets.NewTracklist(nil)
|
||||||
t.tracklist.DisableSorting = true
|
t.tracklist.Options = widgets.TracklistOptions{
|
||||||
t.tracklist.AutoNumber = true
|
DisableSorting: true,
|
||||||
|
AutoNumber: true,
|
||||||
|
}
|
||||||
t.tracklist.SetVisibleColumns(conf.TracklistColumns)
|
t.tracklist.SetVisibleColumns(conf.TracklistColumns)
|
||||||
t.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
t.tracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
t.conf.TracklistColumns = cols
|
t.conf.TracklistColumns = cols
|
||||||
@@ -119,7 +121,7 @@ func (t *TracksPage) OnSearched(query string) {
|
|||||||
func (t *TracksPage) doSearch(query string) {
|
func (t *TracksPage) doSearch(query string) {
|
||||||
if t.searchTracklist == nil {
|
if t.searchTracklist == nil {
|
||||||
t.searchTracklist = widgets.NewTracklist(nil)
|
t.searchTracklist = widgets.NewTracklist(nil)
|
||||||
t.searchTracklist.AutoNumber = true
|
t.searchTracklist.Options = widgets.TracklistOptions{AutoNumber: true}
|
||||||
t.searchTracklist.SetVisibleColumns(t.conf.TracklistColumns)
|
t.searchTracklist.SetVisibleColumns(t.conf.TracklistColumns)
|
||||||
t.searchTracklist.SetNowPlaying(t.nowPlayingID)
|
t.searchTracklist.SetNowPlaying(t.nowPlayingID)
|
||||||
t.searchTracklist.OnVisibleColumnsChanged = func(cols []string) {
|
t.searchTracklist.OnVisibleColumnsChanged = func(cols []string) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WidgetType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
WidgetTypeAlbumPageHeader WidgetType = "AlbumPageHeader"
|
||||||
|
WidgetTypeArtistPageHeader WidgetType = "ArtistPageHeader"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WidgetCache struct {
|
||||||
|
cache map[WidgetType][]cachedWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
type cachedWidget struct {
|
||||||
|
widget fyne.CanvasObject
|
||||||
|
releasedAt int64 // unixMillis
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWidgetCache() WidgetCache {
|
||||||
|
return WidgetCache{
|
||||||
|
cache: make(map[WidgetType][]cachedWidget),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WidgetCache) Obtain(typ WidgetType) fyne.CanvasObject {
|
||||||
|
var widget fyne.CanvasObject
|
||||||
|
if ws, ok := w.cache[typ]; ok && len(ws) > 0 {
|
||||||
|
i := len(ws) - 1
|
||||||
|
widget = ws[i].widget
|
||||||
|
ws[i].widget = nil
|
||||||
|
w.cache[typ] = ws[:i]
|
||||||
|
}
|
||||||
|
return widget
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WidgetCache) Release(typ WidgetType, wid fyne.CanvasObject) {
|
||||||
|
if _, ok := w.cache[typ]; !ok {
|
||||||
|
w.cache[typ] = make([]cachedWidget, 0)
|
||||||
|
}
|
||||||
|
w.cache[typ] = append(w.cache[typ], cachedWidget{
|
||||||
|
widget: wid,
|
||||||
|
releasedAt: time.Now().UnixMilli(),
|
||||||
|
})
|
||||||
|
}
|
||||||
+20
-9
@@ -47,9 +47,7 @@ type TracklistSort struct {
|
|||||||
ColumnName string
|
ColumnName string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Tracklist struct {
|
type TracklistOptions struct {
|
||||||
widget.BaseWidget
|
|
||||||
|
|
||||||
// AutoNumber sets whether to auto-number the tracks 1..N in display order,
|
// AutoNumber sets whether to auto-number the tracks 1..N in display order,
|
||||||
// or to use the number from the track's metadata
|
// or to use the number from the track's metadata
|
||||||
AutoNumber bool
|
AutoNumber bool
|
||||||
@@ -68,6 +66,12 @@ type Tracklist struct {
|
|||||||
|
|
||||||
// Disables sorting the tracklist by clicking individual columns.
|
// Disables sorting the tracklist by clicking individual columns.
|
||||||
DisableSorting bool
|
DisableSorting bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tracklist struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
Options TracklistOptions
|
||||||
|
|
||||||
// user action callbacks
|
// user action callbacks
|
||||||
OnPlayTrackAt func(int)
|
OnPlayTrackAt func(int)
|
||||||
@@ -141,7 +145,7 @@ func NewTracklist(tracks []*mediaprovider.Track) *Tracklist {
|
|||||||
tr := item.(*TrackRow)
|
tr := item.(*TrackRow)
|
||||||
tr.trackIdx = itemID
|
tr.trackIdx = itemID
|
||||||
i := -1 // signal that we want to display the actual track num.
|
i := -1 // signal that we want to display the actual track num.
|
||||||
if t.AutoNumber {
|
if t.Options.AutoNumber {
|
||||||
i = itemID + 1
|
i = itemID + 1
|
||||||
}
|
}
|
||||||
tr.Update(t.trackModelAt(itemID), i)
|
tr.Update(t.trackModelAt(itemID), i)
|
||||||
@@ -153,6 +157,13 @@ func NewTracklist(tracks []*mediaprovider.Track) *Tracklist {
|
|||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tracklist) Reset() {
|
||||||
|
t.Clear()
|
||||||
|
t.Options = TracklistOptions{}
|
||||||
|
t.ctxMenu = nil
|
||||||
|
t.SetSorting(TracklistSort{})
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tracklist) buildHeader() {
|
func (t *Tracklist) buildHeader() {
|
||||||
t.hdr = NewListHeader([]ListColumn{
|
t.hdr = NewListHeader([]ListColumn{
|
||||||
{Text: "#", Alignment: fyne.TextAlignTrailing, CanToggleVisible: false},
|
{Text: "#", Alignment: fyne.TextAlignTrailing, CanToggleVisible: false},
|
||||||
@@ -331,7 +342,7 @@ func (t *Tracklist) CreateRenderer() fyne.WidgetRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracklist) Refresh() {
|
func (t *Tracklist) Refresh() {
|
||||||
t.hdr.DisableSorting = t.DisableSorting
|
t.hdr.DisableSorting = t.Options.DisableSorting
|
||||||
t.BaseWidget.Refresh()
|
t.BaseWidget.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +498,7 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) {
|
|||||||
t.list.Refresh()
|
t.list.Refresh()
|
||||||
if t.ctxMenu == nil {
|
if t.ctxMenu == nil {
|
||||||
t.ctxMenu = fyne.NewMenu("")
|
t.ctxMenu = fyne.NewMenu("")
|
||||||
if !t.DisablePlaybackMenu {
|
if !t.Options.DisablePlaybackMenu {
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items,
|
t.ctxMenu.Items = append(t.ctxMenu.Items,
|
||||||
fyne.NewMenuItem("Play", func() {
|
fyne.NewMenuItem("Play", func() {
|
||||||
if t.OnPlaySelection != nil {
|
if t.OnPlaySelection != nil {
|
||||||
@@ -530,9 +541,9 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) {
|
|||||||
t.onSetRatings(t.selectedTracks(), rating, true)
|
t.onSetRatings(t.selectedTracks(), rating, true)
|
||||||
})
|
})
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items, ratingMenu)
|
t.ctxMenu.Items = append(t.ctxMenu.Items, ratingMenu)
|
||||||
if len(t.AuxiliaryMenuItems) > 0 {
|
if len(t.Options.AuxiliaryMenuItems) > 0 {
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items, fyne.NewMenuItemSeparator())
|
t.ctxMenu.Items = append(t.ctxMenu.Items, fyne.NewMenuItemSeparator())
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items, t.AuxiliaryMenuItems...)
|
t.ctxMenu.Items = append(t.ctxMenu.Items, t.Options.AuxiliaryMenuItems...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widget.ShowPopUpMenuAtPosition(t.ctxMenu, fyne.CurrentApp().Driver().CanvasForObject(t), e.AbsolutePosition)
|
widget.ShowPopUpMenuAtPosition(t.ctxMenu, fyne.CurrentApp().Driver().CanvasForObject(t), e.AbsolutePosition)
|
||||||
@@ -754,7 +765,7 @@ func (t *TrackRow) Update(tm *trackModel, rowNum int) {
|
|||||||
var str string
|
var str string
|
||||||
if rowNum < 0 {
|
if rowNum < 0 {
|
||||||
rowNum = tr.TrackNumber
|
rowNum = tr.TrackNumber
|
||||||
if t.tracklist.ShowDiscNumber {
|
if t.tracklist.Options.ShowDiscNumber {
|
||||||
discNum = tr.DiscNumber
|
discNum = tr.DiscNumber
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user