+17
-17
@@ -77,7 +77,7 @@ func NewAlbumPage(
|
|||||||
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
||||||
nil, nil, nil, container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadBottom: 15}, a.tracklist))
|
nil, nil, nil, container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadBottom: 15}, a.tracklist))
|
||||||
|
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ func (a *AlbumPage) OnSongChange(song *subsonic.Child, lastScrobbledIfAny *subso
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumPage) Reload() {
|
func (a *AlbumPage) Reload() {
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumPage) Tapped(*fyne.PointEvent) {
|
func (a *AlbumPage) Tapped(*fyne.PointEvent) {
|
||||||
@@ -117,20 +117,20 @@ func (a *AlbumPage) SelectAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumPage) onPlayTrackAt(tracknum int) {
|
func (a *AlbumPage) onPlayTrackAt(tracknum int) {
|
||||||
a.pm.PlayAlbum(a.albumID, tracknum)
|
a.pm.LoadTracks(a.tracklist.Tracks, false, false)
|
||||||
|
a.pm.PlayTrackAt(tracknum)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumPage) loadAsync() {
|
// should be called asynchronously
|
||||||
go func() {
|
func (a *AlbumPage) load() {
|
||||||
album, err := a.lm.GetAlbum(a.albumID)
|
album, err := a.lm.GetAlbum(a.albumID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get album: %s", err.Error())
|
log.Printf("Failed to get album: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.header.Update(album, a.im)
|
a.header.Update(album, a.im)
|
||||||
a.tracklist.Tracks = album.Song
|
a.tracklist.Tracks = album.Song
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlbumPageHeader struct {
|
type AlbumPageHeader struct {
|
||||||
@@ -156,7 +156,7 @@ type AlbumPageHeader struct {
|
|||||||
func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
||||||
a := &AlbumPageHeader{page: page}
|
a := &AlbumPageHeader{page: page}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.cover = widgets.NewTappableImage(a.showPopUpCover)
|
a.cover = widgets.NewTappableImage(func() { go a.showPopUpCover() })
|
||||||
a.cover.FillMode = canvas.ImageFillContain
|
a.cover.FillMode = canvas.ImageFillContain
|
||||||
a.cover.SetMinSize(fyne.NewSize(225, 225))
|
a.cover.SetMinSize(fyne.NewSize(225, 225))
|
||||||
// due to cache warming we can probably immediately set the cover
|
// due to cache warming we can probably immediately set the cover
|
||||||
@@ -182,10 +182,10 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
|||||||
page.onPlayTrackAt(0)
|
page.onPlayTrackAt(0)
|
||||||
})
|
})
|
||||||
shuffleBtn := widget.NewButtonWithIcon(" Shuffle", res.ResShuffleInvertSvg, func() {
|
shuffleBtn := widget.NewButtonWithIcon(" Shuffle", res.ResShuffleInvertSvg, func() {
|
||||||
page.pm.LoadAlbum(page.albumID, false, true)
|
page.pm.LoadTracks(page.tracklist.Tracks, false, true)
|
||||||
page.pm.PlayFromBeginning()
|
page.pm.PlayFromBeginning()
|
||||||
})
|
})
|
||||||
a.toggleFavButton = widgets.NewFavoriteButton(a.toggleFavorited)
|
a.toggleFavButton = widgets.NewFavoriteButton(func() { go a.toggleFavorited() })
|
||||||
|
|
||||||
// Todo: there's got to be a way to make this less convoluted. Custom layout?
|
// Todo: there's got to be a way to make this less convoluted. Custom layout?
|
||||||
a.container = container.NewBorder(nil, nil, a.cover, nil,
|
a.container = container.NewBorder(nil, nil, a.cover, nil,
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func (a *AlbumsPage) doSearch(query string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumsPage) onPlayAlbum(albumID string) {
|
func (a *AlbumsPage) onPlayAlbum(albumID string) {
|
||||||
a.pm.PlayAlbum(albumID, 0)
|
go a.pm.PlayAlbum(albumID, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumsPage) onShowArtistPage(artistID string) {
|
func (a *AlbumsPage) onShowArtistPage(artistID string) {
|
||||||
|
|||||||
+20
-21
@@ -54,7 +54,7 @@ func NewArtistPage(artistID string, sm *backend.ServerManager, im *backend.Image
|
|||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
||||||
nil, nil, nil, layout.NewSpacer())
|
nil, nil, nil, layout.NewSpacer())
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ func (a *ArtistPage) SetPlayAlbumCallback(cb func(string, int)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) Reload() {
|
func (a *ArtistPage) Reload() {
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) Save() SavedPage {
|
func (a *ArtistPage) Save() SavedPage {
|
||||||
@@ -85,25 +85,24 @@ func (a *ArtistPage) onShowAlbumPage(albumID string) {
|
|||||||
a.nav(AlbumRoute(albumID))
|
a.nav(AlbumRoute(albumID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) loadAsync() {
|
// should be called asynchronously
|
||||||
go func() {
|
func (a *ArtistPage) load() {
|
||||||
artist, err := a.sm.Server.GetArtist(a.artistID)
|
artist, err := a.sm.Server.GetArtist(a.artistID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get artist: %s", err.Error())
|
log.Printf("Failed to get artist: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.header.Update(artist)
|
a.header.Update(artist)
|
||||||
ag := widgets.NewFixedAlbumGrid(artist.Album, a.im, true /*showYear*/)
|
ag := widgets.NewFixedAlbumGrid(artist.Album, a.im, true /*showYear*/)
|
||||||
ag.OnPlayAlbum = a.onPlayAlbum
|
ag.OnPlayAlbum = a.onPlayAlbum
|
||||||
ag.OnShowAlbumPage = a.onShowAlbumPage
|
ag.OnShowAlbumPage = a.onShowAlbumPage
|
||||||
a.container.Objects[0] = ag
|
a.container.Objects[0] = ag
|
||||||
a.container.Refresh()
|
a.container.Refresh()
|
||||||
info, err := a.sm.Server.GetArtistInfo2(a.artistID, nil)
|
info, err := a.sm.Server.GetArtistInfo2(a.artistID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get artist info: %s", err.Error())
|
log.Printf("Failed to get artist info: %s", err.Error())
|
||||||
}
|
}
|
||||||
a.header.UpdateInfo(info)
|
a.header.UpdateInfo(info)
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
|||||||
@@ -51,11 +51,12 @@ func NewArtistsGenresPage(isGenresPage bool, sm *backend.ServerManager, nav func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.buildContainer()
|
a.buildContainer()
|
||||||
go a.loadAsync()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistsGenresPage) loadAsync() {
|
// should be called asynchronously
|
||||||
|
func (a *ArtistsGenresPage) load() {
|
||||||
if a.isGenresPage {
|
if a.isGenresPage {
|
||||||
genres, err := a.sm.Server.GetGenres()
|
genres, err := a.sm.Server.GetGenres()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -80,7 +81,7 @@ func (a *ArtistsGenresPage) Route() Route {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistsGenresPage) Reload() {
|
func (a *ArtistsGenresPage) Reload() {
|
||||||
go a.loadAsync()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistsGenresPage) Save() SavedPage {
|
func (a *ArtistsGenresPage) Save() SavedPage {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ func (a *FavoritesPage) doSearch(query string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *FavoritesPage) onPlayAlbum(albumID string) {
|
func (a *FavoritesPage) onPlayAlbum(albumID string) {
|
||||||
a.pm.PlayAlbum(albumID, 0)
|
go a.pm.PlayAlbum(albumID, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *FavoritesPage) onShowAlbumPage(albumID string) {
|
func (a *FavoritesPage) onShowAlbumPage(albumID string) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type GenrePage struct {
|
|||||||
|
|
||||||
genre string
|
genre string
|
||||||
im *backend.ImageManager
|
im *backend.ImageManager
|
||||||
|
pm *backend.PlaybackManager
|
||||||
lm *backend.LibraryManager
|
lm *backend.LibraryManager
|
||||||
nav func(Route)
|
nav func(Route)
|
||||||
grid *widgets.AlbumGrid
|
grid *widgets.AlbumGrid
|
||||||
@@ -31,9 +32,10 @@ type GenrePage struct {
|
|||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGenrePage(genre string, lm *backend.LibraryManager, im *backend.ImageManager, nav func(Route)) *GenrePage {
|
func NewGenrePage(genre string, pm *backend.PlaybackManager, lm *backend.LibraryManager, im *backend.ImageManager, nav func(Route)) *GenrePage {
|
||||||
g := &GenrePage{
|
g := &GenrePage{
|
||||||
genre: genre,
|
genre: genre,
|
||||||
|
pm: pm,
|
||||||
lm: lm,
|
lm: lm,
|
||||||
im: im,
|
im: im,
|
||||||
nav: nav,
|
nav: nav,
|
||||||
@@ -74,6 +76,7 @@ func (g *GenrePage) createContainer(searchGrid bool) {
|
|||||||
func restoreGenrePage(saved *savedGenrePage) *GenrePage {
|
func restoreGenrePage(saved *savedGenrePage) *GenrePage {
|
||||||
g := &GenrePage{
|
g := &GenrePage{
|
||||||
genre: saved.genre,
|
genre: saved.genre,
|
||||||
|
pm: saved.pm,
|
||||||
lm: saved.lm,
|
lm: saved.lm,
|
||||||
im: saved.im,
|
im: saved.im,
|
||||||
nav: saved.nav,
|
nav: saved.nav,
|
||||||
@@ -121,6 +124,7 @@ func (g *GenrePage) Save() SavedPage {
|
|||||||
sg := &savedGenrePage{
|
sg := &savedGenrePage{
|
||||||
genre: g.genre,
|
genre: g.genre,
|
||||||
searchText: g.searchText,
|
searchText: g.searchText,
|
||||||
|
pm: g.pm,
|
||||||
lm: g.lm,
|
lm: g.lm,
|
||||||
im: g.im,
|
im: g.im,
|
||||||
nav: g.nav,
|
nav: g.nav,
|
||||||
@@ -139,9 +143,7 @@ func (g *GenrePage) SearchWidget() fyne.Focusable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *GenrePage) onPlayAlbum(albumID string) {
|
func (a *GenrePage) onPlayAlbum(albumID string) {
|
||||||
if a.OnPlayAlbum != nil {
|
go a.pm.PlayAlbum(albumID, 0)
|
||||||
a.OnPlayAlbum(albumID, 0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *GenrePage) onShowArtistPage(artistID string) {
|
func (a *GenrePage) onShowArtistPage(artistID string) {
|
||||||
@@ -184,6 +186,7 @@ func (g *GenrePage) doSearch(query string) {
|
|||||||
type savedGenrePage struct {
|
type savedGenrePage struct {
|
||||||
genre string
|
genre string
|
||||||
searchText string
|
searchText string
|
||||||
|
pm *backend.PlaybackManager
|
||||||
lm *backend.LibraryManager
|
lm *backend.LibraryManager
|
||||||
im *backend.ImageManager
|
im *backend.ImageManager
|
||||||
nav func(Route)
|
nav func(Route)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func NewNowPlayingPage(
|
|||||||
a.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
|
a.title.Segments[0].(*widget.TextSegment).Style.SizeName = widget.RichTextStyleHeading.SizeName
|
||||||
a.container = container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 5, PadBottom: 15},
|
a.container = container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 5, PadBottom: 15},
|
||||||
container.NewBorder(a.title, nil, nil, nil, a.tracklist))
|
container.NewBorder(a.title, nil, nil, nil, a.tracklist))
|
||||||
a.loadAsync()
|
a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ func (a *NowPlayingPage) OnSongChange(song *subsonic.Child, lastScrobbledIfAny *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *NowPlayingPage) Reload() {
|
func (a *NowPlayingPage) Reload() {
|
||||||
a.loadAsync()
|
a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *NowPlayingPage) onPlayTrackAt(tracknum int) {
|
func (a *NowPlayingPage) onPlayTrackAt(tracknum int) {
|
||||||
@@ -98,15 +98,14 @@ func (a *NowPlayingPage) onPlayTrackAt(tracknum int) {
|
|||||||
func (a *NowPlayingPage) onRemoveSelectedFromQueue() {
|
func (a *NowPlayingPage) onRemoveSelectedFromQueue() {
|
||||||
a.pm.RemoveTracksFromQueue(a.tracklist.SelectedTrackIndexes())
|
a.pm.RemoveTracksFromQueue(a.tracklist.SelectedTrackIndexes())
|
||||||
a.tracklist.UnselectAll()
|
a.tracklist.UnselectAll()
|
||||||
go a.Reload()
|
a.Reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *NowPlayingPage) loadAsync() {
|
// does not make calls to server - can safely be run in UI callbacks
|
||||||
go func() {
|
func (a *NowPlayingPage) load() {
|
||||||
queue := a.pm.GetPlayQueue()
|
queue := a.pm.GetPlayQueue()
|
||||||
a.tracklist.Tracks = queue
|
a.tracklist.Tracks = queue
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *nowPlayingPageState) Restore() Page {
|
func (s *nowPlayingPageState) Restore() Page {
|
||||||
|
|||||||
+16
-16
@@ -67,7 +67,7 @@ func NewPlaylistPage(
|
|||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadTop: 15, PadBottom: 10}, a.header),
|
||||||
nil, nil, nil, container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadBottom: 15}, a.tracklist))
|
nil, nil, nil, container.New(&layouts.MaxPadLayout{PadLeft: 15, PadRight: 15, PadBottom: 15}, a.tracklist))
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ func (a *PlaylistPage) OnSongChange(song *subsonic.Child, lastScrobbledIfAny *su
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) Reload() {
|
func (a *PlaylistPage) Reload() {
|
||||||
a.loadAsync()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) Tapped(*fyne.PointEvent) {
|
func (a *PlaylistPage) Tapped(*fyne.PointEvent) {
|
||||||
@@ -107,21 +107,21 @@ func (a *PlaylistPage) SelectAll() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) onPlayTrackAt(tracknum int) {
|
func (a *PlaylistPage) onPlayTrackAt(tracknum int) {
|
||||||
a.pm.PlayPlaylist(a.playlistID, tracknum)
|
a.pm.LoadTracks(a.tracklist.Tracks, false, false)
|
||||||
|
a.pm.PlayTrackAt(tracknum)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) loadAsync() {
|
// should be called asynchronously
|
||||||
go func() {
|
func (a *PlaylistPage) load() {
|
||||||
playlist, err := a.sm.Server.GetPlaylist(a.playlistID)
|
playlist, err := a.sm.Server.GetPlaylist(a.playlistID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get playlist: %s", err.Error())
|
log.Printf("Failed to get playlist: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
a.tracklist.Tracks = playlist.Entry
|
a.tracklist.Tracks = playlist.Entry
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
a.tracklist.Refresh()
|
a.tracklist.Refresh()
|
||||||
a.header.Update(playlist)
|
a.header.Update(playlist)
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) onRemoveSelectedFromPlaylist() {
|
func (a *PlaylistPage) onRemoveSelectedFromPlaylist() {
|
||||||
@@ -165,7 +165,7 @@ func NewPlaylistPageHeader(page *PlaylistPage) *PlaylistPageHeader {
|
|||||||
})
|
})
|
||||||
// TODO: find way to pad shuffle svg rather than using a space in the label string
|
// TODO: find way to pad shuffle svg rather than using a space in the label string
|
||||||
shuffleBtn := widget.NewButtonWithIcon(" Shuffle", res.ResShuffleInvertSvg, func() {
|
shuffleBtn := widget.NewButtonWithIcon(" Shuffle", res.ResShuffleInvertSvg, func() {
|
||||||
page.pm.LoadPlaylist(page.playlistID, false /*append*/, true /*shuffle*/)
|
page.pm.LoadTracks(page.tracklist.Tracks, false /*append*/, true /*shuffle*/)
|
||||||
page.pm.PlayFromBeginning()
|
page.pm.PlayFromBeginning()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func (r Router) CreatePage(rte Route) Page {
|
|||||||
case Favorites:
|
case Favorites:
|
||||||
return NewFavoritesPage(r.App.ServerManager, r.App.PlaybackManager, r.App.LibraryManager, r.App.ImageManager, r.OpenRoute)
|
return NewFavoritesPage(r.App.ServerManager, r.App.PlaybackManager, r.App.LibraryManager, r.App.ImageManager, r.OpenRoute)
|
||||||
case Genre:
|
case Genre:
|
||||||
return NewGenrePage(rte.Arg, r.App.LibraryManager, r.App.ImageManager, r.OpenRoute)
|
return NewGenrePage(rte.Arg, r.App.PlaybackManager, r.App.LibraryManager, r.App.ImageManager, r.OpenRoute)
|
||||||
case Genres:
|
case Genres:
|
||||||
return NewArtistsGenresPage(true, r.App.ServerManager, r.OpenRoute)
|
return NewArtistsGenresPage(true, r.App.ServerManager, r.OpenRoute)
|
||||||
case NowPlaying:
|
case NowPlaying:
|
||||||
|
|||||||
Reference in New Issue
Block a user