save only page state in history and reconstruct page UI
This commit is contained in:
@@ -52,6 +52,15 @@ func (a *AlbumPage) SetPlayAlbumCallback(cb func(string, int)) {
|
||||
a.OnPlayAlbum = cb
|
||||
}
|
||||
|
||||
func (a *AlbumPage) Save() SavedPage {
|
||||
return &savedAlbumPage{
|
||||
albumID: a.albumID,
|
||||
lm: a.lm,
|
||||
im: a.im,
|
||||
nav: a.nav,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AlbumPage) Route() Route {
|
||||
return AlbumRoute(a.albumID)
|
||||
}
|
||||
@@ -175,3 +184,14 @@ func (a *AlbumPageHeader) Update(album *subsonic.AlbumID3, im *backend.ImageMana
|
||||
func formatMiscLabelStr(a *subsonic.AlbumID3) string {
|
||||
return fmt.Sprintf("%d · %d tracks · %s", a.Year, a.SongCount, util.SecondsToTimeString(float64(a.Duration)))
|
||||
}
|
||||
|
||||
type savedAlbumPage struct {
|
||||
albumID string
|
||||
lm *backend.LibraryManager
|
||||
im *backend.ImageManager
|
||||
nav func(Route)
|
||||
}
|
||||
|
||||
func (s *savedAlbumPage) Restore() Page {
|
||||
return NewAlbumPage(s.albumID, s.lm, s.im, s.nav)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ var _ fyne.Widget = (*AlbumsPage)(nil)
|
||||
type AlbumsPage struct {
|
||||
widget.BaseWidget
|
||||
|
||||
title string
|
||||
im *backend.ImageManager
|
||||
lm *backend.LibraryManager
|
||||
nav func(Route)
|
||||
@@ -52,9 +53,10 @@ func (s *selectWidget) MinSize() fyne.Size {
|
||||
|
||||
func NewAlbumsPage(title string, sortOrder string, lm *backend.LibraryManager, im *backend.ImageManager, nav func(Route)) *AlbumsPage {
|
||||
a := &AlbumsPage{
|
||||
lm: lm,
|
||||
im: im,
|
||||
nav: nav,
|
||||
title: title,
|
||||
lm: lm,
|
||||
im: im,
|
||||
nav: nav,
|
||||
}
|
||||
a.ExtendBaseWidget(a)
|
||||
|
||||
@@ -65,7 +67,6 @@ func NewAlbumsPage(title string, sortOrder string, lm *backend.LibraryManager, i
|
||||
a.sortOrder = NewSelect(backend.AlbumSortOrders, nil)
|
||||
a.sortOrder.Selected = sortOrder
|
||||
a.sortOrder.OnChanged = a.onSortOrderChanged
|
||||
sortVbox := container.NewVBox(layout.NewSpacer(), a.sortOrder, layout.NewSpacer())
|
||||
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected))
|
||||
a.grid = widgets.NewAlbumGrid(iter, im, false /*showYear*/)
|
||||
a.grid.OnPlayAlbum = a.onPlayAlbum
|
||||
@@ -73,7 +74,14 @@ func NewAlbumsPage(title string, sortOrder string, lm *backend.LibraryManager, i
|
||||
a.grid.OnShowAlbumPage = a.onShowAlbumPage
|
||||
a.searcher = widgets.NewSearcher()
|
||||
a.searcher.OnSearched = a.OnSearched
|
||||
a.createContainer()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *AlbumsPage) createContainer() {
|
||||
searchVbox := container.NewVBox(layout.NewSpacer(), a.searcher.Entry, layout.NewSpacer())
|
||||
sortVbox := container.NewVBox(layout.NewSpacer(), a.sortOrder, layout.NewSpacer())
|
||||
a.container = container.NewBorder(
|
||||
container.NewHBox(widgets.NewHSpace(9), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, widgets.NewHSpace(15)),
|
||||
nil,
|
||||
@@ -81,6 +89,29 @@ func NewAlbumsPage(title string, sortOrder string, lm *backend.LibraryManager, i
|
||||
nil,
|
||||
a.grid,
|
||||
)
|
||||
}
|
||||
|
||||
func restoreAlbumsPage(saved *savedAlbumsPage) *AlbumsPage {
|
||||
a := &AlbumsPage{
|
||||
title: saved.title,
|
||||
lm: saved.lm,
|
||||
im: saved.im,
|
||||
nav: saved.nav,
|
||||
}
|
||||
a.ExtendBaseWidget(a)
|
||||
|
||||
a.titleDisp = widget.NewRichTextWithText(a.title)
|
||||
a.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
||||
SizeName: theme.SizeNameHeadingText,
|
||||
}
|
||||
a.sortOrder = NewSelect(backend.AlbumSortOrders, nil)
|
||||
a.sortOrder.Selected = saved.sortOrder
|
||||
a.sortOrder.OnChanged = a.onSortOrderChanged
|
||||
a.grid = widgets.NewAlbumGridFromState(saved.gridState)
|
||||
a.searcher = widgets.NewSearcher()
|
||||
a.searcher.OnSearched = a.OnSearched
|
||||
a.createContainer()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -114,6 +145,17 @@ func (a *AlbumsPage) Reload() {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AlbumsPage) Save() SavedPage {
|
||||
return &savedAlbumsPage{
|
||||
title: a.title,
|
||||
lm: a.lm,
|
||||
im: a.im,
|
||||
nav: a.nav,
|
||||
sortOrder: a.sortOrder.Selected,
|
||||
gridState: a.grid.SaveToState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AlbumsPage) doSearch(query string) {
|
||||
if a.searchGrid == nil {
|
||||
a.searchGrid = widgets.NewAlbumGrid(a.lm.SearchIter(query), a.im, false /*showYear*/)
|
||||
@@ -153,3 +195,16 @@ func (a *AlbumsPage) CreateRenderer() fyne.WidgetRenderer {
|
||||
a.ExtendBaseWidget(a)
|
||||
return widget.NewSimpleRenderer(a.container)
|
||||
}
|
||||
|
||||
type savedAlbumsPage struct {
|
||||
title string
|
||||
lm *backend.LibraryManager
|
||||
im *backend.ImageManager
|
||||
nav func(Route)
|
||||
sortOrder string
|
||||
gridState widgets.AlbumGridState
|
||||
}
|
||||
|
||||
func (s *savedAlbumsPage) Restore() Page {
|
||||
return restoreAlbumsPage(s)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,15 @@ func (a *ArtistPage) Reload() {
|
||||
a.loadAsync()
|
||||
}
|
||||
|
||||
func (a *ArtistPage) Save() SavedPage {
|
||||
return &savedArtistPage{
|
||||
artistID: a.artistID,
|
||||
sm: a.sm,
|
||||
im: a.im,
|
||||
nav: a.nav,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *ArtistPage) onPlayAlbum(albumID string) {
|
||||
if a.OnPlayAlbum != nil {
|
||||
a.OnPlayAlbum(albumID, 0)
|
||||
@@ -88,3 +97,14 @@ func (a *ArtistPage) CreateRenderer() fyne.WidgetRenderer {
|
||||
a.ExtendBaseWidget(a)
|
||||
return widget.NewSimpleRenderer(a.container)
|
||||
}
|
||||
|
||||
type savedArtistPage struct {
|
||||
artistID string
|
||||
sm *backend.ServerManager
|
||||
im *backend.ImageManager
|
||||
nav func(Route)
|
||||
}
|
||||
|
||||
func (s *savedArtistPage) Restore() Page {
|
||||
return NewArtistPage(s.artistID, s.sm, s.im, s.nav)
|
||||
}
|
||||
|
||||
+31
-15
@@ -2,6 +2,7 @@ package browsing
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"log"
|
||||
"supersonic/backend"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
@@ -16,10 +17,15 @@ import (
|
||||
type Page interface {
|
||||
fyne.CanvasObject
|
||||
|
||||
Save() SavedPage
|
||||
Reload()
|
||||
Route() Route
|
||||
}
|
||||
|
||||
type SavedPage interface {
|
||||
Restore() Page
|
||||
}
|
||||
|
||||
type CanPlayAlbum interface {
|
||||
SetPlayAlbumCallback(func(albumID string, startingTrack int))
|
||||
}
|
||||
@@ -42,7 +48,7 @@ type BrowsingPane struct {
|
||||
forward *widget.Button
|
||||
back *widget.Button
|
||||
reload *widget.Button
|
||||
history []Page
|
||||
history []SavedPage
|
||||
historyIdx int
|
||||
|
||||
pageContainer *fyne.Container
|
||||
@@ -67,8 +73,9 @@ func NewBrowsingPane(app *backend.App) *BrowsingPane {
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) SetPage(p Page) {
|
||||
if b.doSetPage(p) {
|
||||
b.addPageToHistory(p)
|
||||
oldPage := b.curPage
|
||||
if b.doSetPage(p) && oldPage != nil {
|
||||
b.addPageToHistory(oldPage, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,13 +106,19 @@ func (b *BrowsingPane) onSongChange(song *subsonic.Child) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) addPageToHistory(p Page) {
|
||||
// allow garbage collection of pages that will be removed from the history
|
||||
for i := b.historyIdx; i < len(b.history); i++ {
|
||||
b.history[i] = nil
|
||||
func (b *BrowsingPane) addPageToHistory(p Page, truncate bool) {
|
||||
if truncate {
|
||||
// allow garbage collection of pages that will be removed from the history
|
||||
for i := b.historyIdx; i < len(b.history); i++ {
|
||||
b.history[i] = nil
|
||||
}
|
||||
b.history = b.history[:b.historyIdx]
|
||||
}
|
||||
if b.historyIdx < len(b.history) {
|
||||
b.history[b.historyIdx] = p.Save()
|
||||
} else {
|
||||
b.history = append(b.history, p.Save())
|
||||
}
|
||||
b.history = b.history[:b.historyIdx]
|
||||
b.history = append(b.history, p)
|
||||
b.historyIdx++
|
||||
}
|
||||
|
||||
@@ -116,16 +129,19 @@ func (b *BrowsingPane) goHome() {
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) GoBack() {
|
||||
if b.historyIdx > 1 {
|
||||
b.historyIdx -= 1
|
||||
b.doSetPage(b.history[b.historyIdx-1])
|
||||
log.Printf("goBack called! historyIdx=%d, len=%d", b.historyIdx, len(b.history))
|
||||
if b.historyIdx > 0 {
|
||||
b.addPageToHistory(b.curPage, false)
|
||||
b.historyIdx -= 2
|
||||
b.doSetPage(b.history[b.historyIdx].Restore())
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BrowsingPane) GoForward() {
|
||||
if b.historyIdx < len(b.history) {
|
||||
b.historyIdx++
|
||||
b.doSetPage(b.history[b.historyIdx-1])
|
||||
log.Printf("goForward called! historyIdx=%d, len=%d", b.historyIdx, len(b.history))
|
||||
if b.historyIdx < len(b.history)-1 {
|
||||
b.addPageToHistory(b.curPage, false)
|
||||
b.doSetPage(b.history[b.historyIdx].Restore())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,12 @@ func NewGenrePage(genre string, lm *backend.LibraryManager, im *backend.ImageMan
|
||||
g.grid.OnShowAlbumPage = g.onShowAlbumPage
|
||||
g.searcher = widgets.NewSearcher()
|
||||
g.searcher.OnSearched = g.OnSearched
|
||||
g.createContainer()
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GenrePage) createContainer() {
|
||||
searchVbox := container.NewVBox(layout.NewSpacer(), g.searcher.Entry, layout.NewSpacer())
|
||||
g.container = container.NewBorder(
|
||||
container.NewHBox(widgets.NewHSpace(9), g.titleDisp, layout.NewSpacer(), searchVbox, widgets.NewHSpace(15)),
|
||||
@@ -59,6 +65,26 @@ func NewGenrePage(genre string, lm *backend.LibraryManager, im *backend.ImageMan
|
||||
nil,
|
||||
g.grid,
|
||||
)
|
||||
}
|
||||
|
||||
func restoreGenrePage(saved *savedGenrePage) *GenrePage {
|
||||
g := &GenrePage{
|
||||
genre: saved.genre,
|
||||
lm: saved.lm,
|
||||
im: saved.im,
|
||||
nav: saved.nav,
|
||||
}
|
||||
g.ExtendBaseWidget(g)
|
||||
|
||||
g.titleDisp = widget.NewRichTextWithText(g.genre)
|
||||
g.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
||||
SizeName: theme.SizeNameHeadingText,
|
||||
}
|
||||
g.grid = widgets.NewAlbumGridFromState(saved.gridState)
|
||||
g.searcher = widgets.NewSearcher()
|
||||
g.searcher.OnSearched = g.OnSearched
|
||||
g.createContainer()
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
@@ -83,6 +109,16 @@ func (g *GenrePage) Reload() {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GenrePage) Save() SavedPage {
|
||||
return &savedGenrePage{
|
||||
genre: g.genre,
|
||||
lm: g.lm,
|
||||
im: g.im,
|
||||
nav: g.nav,
|
||||
gridState: g.grid.SaveToState(),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *GenrePage) onPlayAlbum(albumID string) {
|
||||
if a.OnPlayAlbum != nil {
|
||||
a.OnPlayAlbum(albumID, 0)
|
||||
@@ -125,3 +161,15 @@ func (g *GenrePage) doSearch(query string) {
|
||||
g.container.Objects[0] = g.searchGrid
|
||||
g.Refresh()
|
||||
}
|
||||
|
||||
type savedGenrePage struct {
|
||||
genre string
|
||||
lm *backend.LibraryManager
|
||||
im *backend.ImageManager
|
||||
nav func(Route)
|
||||
gridState widgets.AlbumGridState
|
||||
}
|
||||
|
||||
func (s *savedGenrePage) Restore() Page {
|
||||
return restoreGenrePage(s)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user