add loading indicator and err/timeout toast to Album and Playlist pages (todo: other pages)
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"All": "All",
|
"All": "All",
|
||||||
"All Tracks": "All Tracks",
|
"All Tracks": "All Tracks",
|
||||||
"Alt. URL": "Alt. URL",
|
"Alt. URL": "Alt. URL",
|
||||||
|
"An error occurred": "An error occurred",
|
||||||
"An error occurred adding tracks to the playlist": "An error occurred adding tracks to the playlist",
|
"An error occurred adding tracks to the playlist": "An error occurred adding tracks to the playlist",
|
||||||
"An error occurred updating the playlist": "An error occurred updating the playlist",
|
"An error occurred updating the playlist": "An error occurred updating the playlist",
|
||||||
"Are you sure you want to delete the server": "Are you sure you want to delete the server",
|
"Are you sure you want to delete the server": "Are you sure you want to delete the server",
|
||||||
@@ -196,6 +197,7 @@
|
|||||||
"Support the project": "Support the project",
|
"Support the project": "Support the project",
|
||||||
"Switch Servers": "Switch Servers",
|
"Switch Servers": "Switch Servers",
|
||||||
"Testing connection": "Testing connection",
|
"Testing connection": "Testing connection",
|
||||||
|
"The request timed out": "The request timed out",
|
||||||
"Theme": "Theme",
|
"Theme": "Theme",
|
||||||
"Time": "Time",
|
"Time": "Time",
|
||||||
"Title": "Title",
|
"Title": "Title",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package browsing
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
@@ -107,6 +108,7 @@ func newAlbumPage(
|
|||||||
container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 15, BottomPadding: 10}, a.header),
|
container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 15, BottomPadding: 10}, a.header),
|
||||||
nil, nil, nil, container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 15}, a.tracklist))
|
nil, nil, nil, container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 15}, a.tracklist))
|
||||||
|
|
||||||
|
a.tracklist.SetLoading(true)
|
||||||
go a.load()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
@@ -117,6 +119,7 @@ func (a *AlbumPage) CreateRenderer() fyne.WidgetRenderer {
|
|||||||
|
|
||||||
func (a *AlbumPage) Save() SavedPage {
|
func (a *AlbumPage) Save() SavedPage {
|
||||||
a.disposed = true
|
a.disposed = true
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
s := a.albumPageState
|
s := a.albumPageState
|
||||||
s.sort = a.tracklist.Sorting()
|
s.sort = a.tracklist.Sorting()
|
||||||
a.header.page = nil
|
a.header.page = nil
|
||||||
@@ -139,6 +142,7 @@ func (a *AlbumPage) OnSongChange(track mediaprovider.MediaItem, lastScrobbledIfA
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AlbumPage) Reload() {
|
func (a *AlbumPage) Reload() {
|
||||||
|
a.tracklist.SetLoading(true)
|
||||||
go a.load()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,13 +166,23 @@ func (a *AlbumPage) Scroll(scrollAmt float32) {
|
|||||||
func (a *AlbumPage) load() {
|
func (a *AlbumPage) load() {
|
||||||
album, err := a.mp.GetAlbum(a.albumID)
|
album, err := a.mp.GetAlbum(a.albumID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get album: %s", err.Error())
|
msg := err.Error()
|
||||||
|
log.Printf("Failed to get album: %s", msg)
|
||||||
|
toastMsg := "An error occurred"
|
||||||
|
if strings.Contains(msg, "deadline exceeded") {
|
||||||
|
toastMsg = "The request timed out"
|
||||||
|
}
|
||||||
|
fyne.Do(func() {
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
|
a.contr.ToastProvider.ShowErrorToast(lang.L(toastMsg))
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if a.disposed {
|
if a.disposed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fyne.Do(func() {
|
fyne.Do(func() {
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
a.header.Update(album, a.im)
|
a.header.Update(album, a.im)
|
||||||
a.tracklist.Options.ShowDiscNumber = len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber
|
a.tracklist.Options.ShowDiscNumber = len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber
|
||||||
a.tracks = album.Tracks
|
a.tracks = album.Tracks
|
||||||
@@ -376,7 +390,7 @@ func formatMiscLabelStr(a *mediaprovider.AlbumWithTracks) string {
|
|||||||
}
|
}
|
||||||
yearStr := util.FormatItemDate(a.Date)
|
yearStr := util.FormatItemDate(a.Date)
|
||||||
if y := a.ReissueDate.Year; y != nil && *y > a.YearOrZero() {
|
if y := a.ReissueDate.Year; y != nil && *y > a.YearOrZero() {
|
||||||
yearStr += fmt.Sprintf(" (%s %d)", lang.L("reissued"), util.FormatItemDate(a.ReissueDate))
|
yearStr += fmt.Sprintf(" (%s %s)", lang.L("reissued"), util.FormatItemDate(a.ReissueDate))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s · %d %s · %s%s", yearStr, a.TrackCount, tracks, discs, util.SecondsToTimeString(float64(a.Duration)))
|
return fmt.Sprintf("%s · %d %s · %s%s", yearStr, a.TrackCount, tracks, discs, util.SecondsToTimeString(float64(a.Duration)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package browsing
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||||
@@ -104,6 +105,8 @@ func newPlaylistPage(
|
|||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 15, BottomPadding: 10}, a.header),
|
container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 15, BottomPadding: 10}, a.header),
|
||||||
nil, nil, nil, container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 15}, a.tracklist))
|
nil, nil, nil, container.New(&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 15}, a.tracklist))
|
||||||
|
|
||||||
|
a.tracklist.SetLoading(true)
|
||||||
go a.load()
|
go a.load()
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
@@ -114,6 +117,7 @@ func (a *PlaylistPage) CreateRenderer() fyne.WidgetRenderer {
|
|||||||
|
|
||||||
func (a *PlaylistPage) Save() SavedPage {
|
func (a *PlaylistPage) Save() SavedPage {
|
||||||
a.disposed = true
|
a.disposed = true
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
p := a.playlistPageState
|
p := a.playlistPageState
|
||||||
p.trackSort = a.tracklist.Sorting()
|
p.trackSort = a.tracklist.Sorting()
|
||||||
p.widgetPool.Release(util.WidgetTypePlaylistPageHeader, a.header)
|
p.widgetPool.Release(util.WidgetTypePlaylistPageHeader, a.header)
|
||||||
@@ -136,6 +140,7 @@ func (a *PlaylistPage) OnSongChange(item mediaprovider.MediaItem, lastScrobbledI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *PlaylistPage) Reload() {
|
func (a *PlaylistPage) Reload() {
|
||||||
|
a.tracklist.SetLoading(true)
|
||||||
go a.load()
|
go a.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +164,16 @@ func (a *PlaylistPage) Scroll(scrollAmt float32) {
|
|||||||
func (a *PlaylistPage) load() {
|
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())
|
msg := err.Error()
|
||||||
|
log.Printf("Failed to get playlist: %s", msg)
|
||||||
|
toastMsg := "An error occurred"
|
||||||
|
if strings.Contains(msg, "deadline exceeded") {
|
||||||
|
toastMsg = "The request timed out"
|
||||||
|
}
|
||||||
|
fyne.Do(func() {
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
|
a.contr.ToastProvider.ShowErrorToast(lang.L(toastMsg))
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if a.disposed {
|
if a.disposed {
|
||||||
@@ -167,6 +181,7 @@ func (a *PlaylistPage) load() {
|
|||||||
}
|
}
|
||||||
renumberTracks(playlist.Tracks)
|
renumberTracks(playlist.Tracks)
|
||||||
fyne.Do(func() {
|
fyne.Do(func() {
|
||||||
|
a.tracklist.SetLoading(false)
|
||||||
a.tracks = playlist.Tracks
|
a.tracks = playlist.Tracks
|
||||||
a.tracklist.SetTracks(playlist.Tracks)
|
a.tracklist.SetTracks(playlist.Tracks)
|
||||||
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
a.tracklist.SetNowPlaying(a.nowPlayingID)
|
||||||
|
|||||||
+13
-1
@@ -102,6 +102,7 @@ type Tracklist struct {
|
|||||||
shareMenuItem *fyne.MenuItem
|
shareMenuItem *fyne.MenuItem
|
||||||
songRadioMenuItem *fyne.MenuItem
|
songRadioMenuItem *fyne.MenuItem
|
||||||
infoMenuItem *fyne.MenuItem
|
infoMenuItem *fyne.MenuItem
|
||||||
|
loadingDots *LoadingDots
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,17 +200,28 @@ func NewTracklist(tracks []*mediaprovider.Track, im *backend.ImageManager, useCo
|
|||||||
t.OnReorderTracks(t.SelectedTrackIDs(), insertPos)
|
t.OnReorderTracks(t.SelectedTrackIDs(), insertPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.container = container.NewBorder(t.hdr, nil, nil, nil, t.list)
|
t.loadingDots = NewLoadingDots()
|
||||||
|
t.container = container.NewBorder(t.hdr, nil, nil, nil,
|
||||||
|
container.NewStack(t.list, container.NewCenter(t.loadingDots)))
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracklist) Reset() {
|
func (t *Tracklist) Reset() {
|
||||||
|
t.SetLoading(false)
|
||||||
t.Clear()
|
t.Clear()
|
||||||
t.Options = TracklistOptions{}
|
t.Options = TracklistOptions{}
|
||||||
t.ctxMenu = nil
|
t.ctxMenu = nil
|
||||||
t.SetSorting(TracklistSort{})
|
t.SetSorting(TracklistSort{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tracklist) SetLoading(loading bool) {
|
||||||
|
if loading {
|
||||||
|
t.loadingDots.Start()
|
||||||
|
} else {
|
||||||
|
t.loadingDots.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tracklist) Scroll(amount float32) {
|
func (t *Tracklist) Scroll(amount float32) {
|
||||||
t.list.ScrollToOffset(t.list.GetScrollOffset() + amount)
|
t.list.ScrollToOffset(t.list.GetScrollOffset() + amount)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,12 +29,14 @@ func NewTracklistLoader(tracklist *Tracklist, iter mediaprovider.TrackIterator)
|
|||||||
}
|
}
|
||||||
t.tracklist.OnTrackShown = t.onTrackShown
|
t.tracklist.OnTrackShown = t.onTrackShown
|
||||||
t.fetching = true
|
t.fetching = true
|
||||||
|
t.tracklist.SetLoading(true)
|
||||||
go t.loadMoreTracks(25)
|
go t.loadMoreTracks(25)
|
||||||
return &t
|
return &t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancels all asynchronous loads so that they will no longer modify the tracklist.
|
// Cancels all asynchronous loads so that they will no longer modify the tracklist.
|
||||||
func (t *TracklistLoader) Dispose() {
|
func (t *TracklistLoader) Dispose() {
|
||||||
|
t.tracklist.SetLoading(false)
|
||||||
t.disposed.Store(true)
|
t.disposed.Store(true)
|
||||||
t.tracklist.OnTrackShown = nil
|
t.tracklist.OnTrackShown = nil
|
||||||
}
|
}
|
||||||
@@ -71,6 +73,7 @@ func (t *TracklistLoader) loadMoreTracks(num int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
fyne.Do(func() {
|
fyne.Do(func() {
|
||||||
|
t.tracklist.SetLoading(false)
|
||||||
t.tracklist.AppendTracks(t.trackBuffer)
|
t.tracklist.AppendTracks(t.trackBuffer)
|
||||||
t.len += len(t.trackBuffer)
|
t.len += len(t.trackBuffer)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user