migrate to Fyne 2.6 - WIP - updates for new threading model

This commit is contained in:
Drew Weymouth
2025-02-08 08:34:39 -03:00
parent 3dcf8aa9d7
commit c60727f92a
13 changed files with 262 additions and 195 deletions
+4 -2
View File
@@ -316,8 +316,10 @@ func (a *AlbumPageHeader) Update(album *mediaprovider.AlbumWithTracks, im *backe
go func() {
if cover, err := im.GetCoverThumbnail(album.CoverArtID); err == nil {
a.cover.SetImage(cover, true)
a.cover.Refresh()
fyne.Do(func() {
a.cover.SetImage(cover, true)
a.cover.Refresh()
})
} else {
log.Printf("error fetching cover: %v", err)
}
+61 -40
View File
@@ -174,8 +174,10 @@ func (a *ArtistPage) playArtistRadio() {
go func() {
err := a.pm.PlaySimilarSongs(a.artistID)
if err != nil {
log.Println("error playing similar songs: %v", err)
a.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play artist radio"))
fyne.Do(func() {
log.Println("error playing similar songs: %v", err)
a.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play artist radio"))
})
}
}()
}
@@ -246,19 +248,23 @@ func (a *ArtistPage) load() {
if a.disposed {
return
}
a.artistInfo = artist
a.header.Update(artist, a.im)
if a.activeView == 0 {
a.showAlbumGrid(false /*reSort*/)
} else {
a.showTopTracks()
}
fyne.Do(func() {
a.artistInfo = artist
a.header.Update(artist, a.im)
if a.activeView == 0 {
a.showAlbumGrid(false /*reSort*/)
} else {
a.showTopTracks()
}
})
info, err := a.mp.GetArtistInfo(a.artistID)
if err != nil {
log.Printf("Failed to get artist info: %s", err.Error())
}
if !a.disposed {
a.header.UpdateInfo(info)
fyne.Do(func() { a.header.UpdateInfo(info) })
}
}
@@ -287,7 +293,15 @@ func (a *ArtistPage) showAlbumGrid(reSort bool) {
a.container.Objects[0].Refresh()
}
// should be called asynchronously
func (a *ArtistPage) showTopTracks() {
updated := false
updatePage := func() {
a.sortButton.Hide()
a.container.Objects[0].(*fyne.Container).Objects[0] = a.tracklistCtr
a.container.Objects[0].Refresh()
}
if a.tracklistCtr == nil {
if a.artistInfo == nil {
// page not loaded yet or invalid artist
@@ -302,33 +316,38 @@ func (a *ArtistPage) showTopTracks() {
if a.disposed {
return
}
var tl *widgets.Tracklist
if t := a.pool.Obtain(util.WidgetTypeTracklist); t != nil {
tl = t.(*widgets.Tracklist)
tl.Reset()
tl.SetTracks(ts)
} else {
tl = widgets.NewTracklist(ts, a.im, false)
}
tl.Options = widgets.TracklistOptions{AutoNumber: true}
_, canRate := a.mp.(mediaprovider.SupportsRating)
_, canShare := a.mp.(mediaprovider.SupportsSharing)
tl.Options.DisableRating = !canRate
tl.Options.DisableSharing = !canShare
tl.SetVisibleColumns(a.cfg.TracklistColumns)
tl.SetSorting(a.trackSort)
tl.OnVisibleColumnsChanged = func(cols []string) {
a.cfg.TracklistColumns = cols
}
tl.SetNowPlaying(a.nowPlayingID)
a.contr.ConnectTracklistActions(tl)
a.tracklistCtr = container.New(
&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 10},
tl)
updated = true // mark that updatePage() will be called here
fyne.Do(func() {
var tl *widgets.Tracklist
if t := a.pool.Obtain(util.WidgetTypeTracklist); t != nil {
tl = t.(*widgets.Tracklist)
tl.Reset()
tl.SetTracks(ts)
} else {
tl = widgets.NewTracklist(ts, a.im, false)
}
tl.Options = widgets.TracklistOptions{AutoNumber: true}
_, canRate := a.mp.(mediaprovider.SupportsRating)
_, canShare := a.mp.(mediaprovider.SupportsSharing)
tl.Options.DisableRating = !canRate
tl.Options.DisableSharing = !canShare
tl.SetVisibleColumns(a.cfg.TracklistColumns)
tl.SetSorting(a.trackSort)
tl.OnVisibleColumnsChanged = func(cols []string) {
a.cfg.TracklistColumns = cols
}
tl.SetNowPlaying(a.nowPlayingID)
a.contr.ConnectTracklistActions(tl)
a.tracklistCtr = container.New(
&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, BottomPadding: 10},
tl)
updatePage()
})
}
if !updated {
fyne.Do(updatePage)
}
a.sortButton.Hide()
a.container.Objects[0].(*fyne.Container).Objects[0] = a.tracklistCtr
a.container.Objects[0].Refresh()
}
func (a *ArtistPage) onViewChange(num int) {
@@ -512,10 +531,12 @@ func (a *ArtistPageHeader) UpdateInfo(info *mediaprovider.ArtistInfo) {
if a.artistImage.HaveImage() {
_ = a.artistPage.im.RefreshCachedArtistImageIfExpired(a.artistID, info.ImageURL)
} else {
im, err := a.artistPage.im.FetchAndCacheArtistImage(a.artistID, info.ImageURL)
if err == nil {
a.artistImage.SetImage(im, true /*tappable*/)
}
go func() {
im, err := a.artistPage.im.FetchAndCacheArtistImage(a.artistID, info.ImageURL)
if err == nil {
fyne.Do(func() { a.artistImage.SetImage(im, true /*tappable*/) })
}
}()
}
}
}
+63 -57
View File
@@ -207,22 +207,24 @@ func (a *FavoritesPage) Reload() {
if a.disposed {
return
}
if tr := a.tracklistOrNil(); tr != nil {
// refresh favorite songs view
tr.SetTracks(starred.Tracks)
if a.toggleBtns.ActivatedButtonIndex() == 2 {
// favorite songs view is visible
tr.Refresh()
fyne.Do(func() {
if tr := a.tracklistOrNil(); tr != nil {
// refresh favorite songs view
tr.SetTracks(starred.Tracks)
if a.toggleBtns.ActivatedButtonIndex() == 2 {
// favorite songs view is visible
tr.Refresh()
}
}
}
if a.artistGrid != nil {
// refresh favorite artists view
a.artistGrid.ResetFixed(buildArtistGridViewModel(starred.Artists))
if a.toggleBtns.ActivatedButtonIndex() == 1 {
// favorite artists view is visible
a.artistGrid.Refresh()
if a.artistGrid != nil {
// refresh favorite artists view
a.artistGrid.ResetFixed(buildArtistGridViewModel(starred.Artists))
if a.toggleBtns.ActivatedButtonIndex() == 1 {
// favorite artists view is visible
a.artistGrid.Refresh()
}
}
}
})
}()
}
}
@@ -354,23 +356,25 @@ func (a *FavoritesPage) onShowFavoriteArtists() {
if a.disposed {
return
}
model := buildArtistGridViewModel(fav.Artists)
if g := a.pool.Obtain(util.WidgetTypeGridView); g != nil {
a.artistGrid = g.(*widgets.GridView)
a.artistGrid.Placeholder = myTheme.ArtistIcon
a.artistGrid.ResetFixed(model)
} else {
a.artistGrid = widgets.NewFixedGridView(model, a.im, myTheme.ArtistIcon)
}
canShareArtists := false
if r, canShare := a.mp.(mediaprovider.SupportsSharing); canShare {
canShareArtists = r.CanShareArtists()
}
a.artistGrid.DisableSharing = !canShareArtists
a.contr.ConnectArtistGridActions(a.artistGrid)
a.container.Objects[0] = a.artistGrid
a.Refresh()
a.pendingViewSwitch = false
fyne.Do(func() {
model := buildArtistGridViewModel(fav.Artists)
if g := a.pool.Obtain(util.WidgetTypeGridView); g != nil {
a.artistGrid = g.(*widgets.GridView)
a.artistGrid.Placeholder = myTheme.ArtistIcon
a.artistGrid.ResetFixed(model)
} else {
a.artistGrid = widgets.NewFixedGridView(model, a.im, myTheme.ArtistIcon)
}
canShareArtists := false
if r, canShare := a.mp.(mediaprovider.SupportsSharing); canShare {
canShareArtists = r.CanShareArtists()
}
a.artistGrid.DisableSharing = !canShareArtists
a.contr.ConnectArtistGridActions(a.artistGrid)
a.container.Objects[0] = a.artistGrid
a.Refresh()
a.pendingViewSwitch = false
})
}()
} else {
a.container.Objects[0] = a.artistGrid
@@ -419,32 +423,34 @@ func (a *FavoritesPage) onShowFavoriteSongs() {
if a.disposed {
return
}
var tracklist *widgets.Tracklist
if tl := a.pool.Obtain(util.WidgetTypeTracklist); tl != nil {
tracklist = tl.(*widgets.Tracklist)
tracklist.Reset()
tracklist.SetTracks(fav.Tracks)
} else {
tracklist = widgets.NewTracklist(fav.Tracks, a.im, false)
}
tracklist.Options = widgets.TracklistOptions{AutoNumber: true}
_, canRate := a.mp.(mediaprovider.SupportsRating)
_, canShare := a.mp.(mediaprovider.SupportsSharing)
tracklist.Options.DisableRating = !canRate
tracklist.Options.DisableSharing = !canShare
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
tracklist.SetSorting(a.trackSort)
tracklist.OnVisibleColumnsChanged = func(cols []string) {
a.cfg.TracklistColumns = cols
}
tracklist.SetNowPlaying(a.nowPlayingID)
a.contr.ConnectTracklistActions(tracklist)
a.tracklistCtr = container.New(
&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 5, BottomPadding: 15},
tracklist)
a.container.Objects[0] = a.tracklistCtr
a.Refresh()
a.pendingViewSwitch = false
fyne.Do(func() {
var tracklist *widgets.Tracklist
if tl := a.pool.Obtain(util.WidgetTypeTracklist); tl != nil {
tracklist = tl.(*widgets.Tracklist)
tracklist.Reset()
tracklist.SetTracks(fav.Tracks)
} else {
tracklist = widgets.NewTracklist(fav.Tracks, a.im, false)
}
tracklist.Options = widgets.TracklistOptions{AutoNumber: true}
_, canRate := a.mp.(mediaprovider.SupportsRating)
_, canShare := a.mp.(mediaprovider.SupportsSharing)
tracklist.Options.DisableRating = !canRate
tracklist.Options.DisableSharing = !canShare
tracklist.SetVisibleColumns(a.cfg.TracklistColumns)
tracklist.SetSorting(a.trackSort)
tracklist.OnVisibleColumnsChanged = func(cols []string) {
a.cfg.TracklistColumns = cols
}
tracklist.SetNowPlaying(a.nowPlayingID)
a.contr.ConnectTracklistActions(tracklist)
a.tracklistCtr = container.New(
&layout.CustomPaddedLayout{LeftPadding: 15, RightPadding: 15, TopPadding: 5, BottomPadding: 15},
tracklist)
a.container.Objects[0] = a.tracklistCtr
a.Refresh()
a.pendingViewSwitch = false
})
}()
} else {
a.container.Objects[0] = a.tracklistCtr
+3 -1
View File
@@ -65,7 +65,9 @@ func (g *genrePageAdapter) ActionButton() *widget.Button {
err := g.pm.PlayRandomSongs(g.genre)
if err != nil {
log.Println("error playing random tracks: %v", err)
g.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play random tracks"))
fyne.Do(func() {
g.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play random tracks"))
})
}
}()
}
+16 -8
View File
@@ -193,20 +193,28 @@ func (a *PlaylistPage) doSetNewTrackOrder(ids []string, newPos int) {
}
}
newTracks := sharedutil.ReorderItems(a.tracks, idxs, newPos)
ids = sharedutil.TracksToIDs(newTracks)
// we can't block the UI waiting for the server so assume it will succeed
go func() {
ids = sharedutil.TracksToIDs(newTracks)
if err := a.sm.Server.ReplacePlaylistTracks(a.playlistID, ids); err != nil {
log.Printf("error updating playlist: %s", err.Error())
fyne.Do(func() {
a.contr.ToastProvider.ShowErrorToast(
lang.L("An error occurred updating the playlist"),
)
})
} else {
fyne.Do(func() {
renumberTracks(newTracks)
// force-switch back to unsorted view to show new track order
a.tracklist.SetSorting(widgets.TracklistSort{})
a.tracklist.SetTracks(newTracks)
a.tracklist.UnselectAll()
a.tracks = newTracks
})
}
}()
renumberTracks(newTracks)
// force-switch back to unsorted view to show new track order
a.tracklist.SetSorting(widgets.TracklistSort{})
a.tracklist.SetTracks(newTracks)
a.tracklist.UnselectAll()
a.tracks = newTracks
}
func (a *PlaylistPage) onRemoveSelectedFromPlaylist() {
+4 -2
View File
@@ -150,7 +150,9 @@ func (a *PlaylistsPage) createGridView(playlists []*mediaprovider.Playlist) {
log.Printf("error loading playlist: %s", err.Error())
return
}
a.contr.DoAddTracksToPlaylistWorkflow(sharedutil.TracksToIDs(pl.Tracks))
fyne.Do(func() {
a.contr.DoAddTracksToPlaylistWorkflow(sharedutil.TracksToIDs(pl.Tracks))
})
}()
}
a.gridView.OnDownload = func(id string) {
@@ -160,7 +162,7 @@ func (a *PlaylistsPage) createGridView(playlists []*mediaprovider.Playlist) {
log.Printf("error loading playlist: %s", err.Error())
return
}
a.contr.ShowDownloadDialog(pl.Tracks, pl.Name)
fyne.Do(func() { a.contr.ShowDownloadDialog(pl.Tracks, pl.Name) })
}()
}
}
+3 -1
View File
@@ -211,7 +211,9 @@ func (t *TracksPage) playRandomSongs() {
err := t.contr.App.PlaybackManager.PlayRandomSongs("")
if err != nil {
log.Println("error playing random tracks: %v", err)
t.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play random tracks"))
fyne.Do(func() {
t.contr.ToastProvider.ShowErrorToast(lang.L("Unable to play random tracks"))
})
}
}()
}