more fyne.Do updates

This commit is contained in:
Drew Weymouth
2025-02-08 08:35:33 -03:00
parent 89012a8fe8
commit ff78a79906
7 changed files with 34 additions and 76 deletions
+4 -4
View File
@@ -75,17 +75,17 @@ func main() {
fyneApp.SetIcon(res.ResAppicon256Png) fyneApp.SetIcon(res.ResAppicon256Png)
mainWindow := ui.NewMainWindow(fyneApp, res.AppName, res.DisplayName, res.AppVersion, myApp) mainWindow := ui.NewMainWindow(fyneApp, res.AppName, res.DisplayName, res.AppVersion, myApp)
mainWindow.Window.SetMaster()
myApp.OnReactivate = mainWindow.Show myApp.OnReactivate = mainWindow.Show
myApp.OnExit = mainWindow.Quit myApp.OnExit = mainWindow.Quit
go func() { fyneApp.Lifecycle().SetOnEnteredForeground(sync.OnceFunc(func() {
defaultServer := myApp.ServerManager.GetDefaultServer() defaultServer := myApp.ServerManager.GetDefaultServer()
if defaultServer == nil { if defaultServer == nil {
fyne.Do(mainWindow.Controller.PromptForFirstServer) mainWindow.Controller.PromptForFirstServer()
} else { } else {
fyne.Do(func() { mainWindow.Controller.DoConnectToServerWorkflow(defaultServer) }) mainWindow.Controller.DoConnectToServerWorkflow(defaultServer)
} }
}()
startupOnceTasks := sync.OnceFunc(func() { startupOnceTasks := sync.OnceFunc(func() {
mainWindow.Window.(driver.NativeWindow).RunNative(func(ctx any) { mainWindow.Window.(driver.NativeWindow).RunNative(func(ctx any) {
+9 -6
View File
@@ -168,11 +168,13 @@ func (a *AlbumPage) load() {
if a.disposed { if a.disposed {
return return
} }
a.header.Update(album, a.im) fyne.Do(func() {
a.tracklist.Options.ShowDiscNumber = len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber a.header.Update(album, a.im)
a.tracks = album.Tracks a.tracklist.Options.ShowDiscNumber = len(album.Tracks) > 0 && album.Tracks[0].DiscNumber != album.Tracks[len(album.Tracks)-1].DiscNumber
a.tracklist.SetTracks(album.Tracks) a.tracks = album.Tracks
a.tracklist.SetNowPlaying(a.nowPlayingID) a.tracklist.SetTracks(album.Tracks)
a.tracklist.SetNowPlaying(a.nowPlayingID)
})
} }
type AlbumPageHeader struct { type AlbumPageHeader struct {
@@ -344,6 +346,7 @@ func (a *AlbumPageHeader) toggleFavorited() {
a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited) a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited)
} }
// should be called asynchronously
func (a *AlbumPageHeader) showPopUpCover() { func (a *AlbumPageHeader) showPopUpCover() {
if a.fullSizeCoverFetching { if a.fullSizeCoverFetching {
return return
@@ -356,7 +359,7 @@ func (a *AlbumPageHeader) showPopUpCover() {
return return
} }
if a.page != nil { if a.page != nil {
a.page.contr.ShowPopUpImage(cover) fyne.Do(func() { a.page.contr.ShowPopUpImage(cover) })
} }
} }
+1 -1
View File
@@ -259,7 +259,7 @@ func (b *BrowsingPane) onSongChange(song mediaprovider.MediaItem, lastScrobbledI
return return
} }
if p, ok := b.curPage.(CanShowNowPlaying); ok { if p, ok := b.curPage.(CanShowNowPlaying); ok {
p.OnSongChange(song, lastScrobbledIfAny) fyne.Do(func() { p.OnSongChange(song, lastScrobbledIfAny) })
} }
} }
+7 -5
View File
@@ -166,10 +166,12 @@ func (a *PlaylistPage) load() {
return return
} }
renumberTracks(playlist.Tracks) renumberTracks(playlist.Tracks)
a.tracks = playlist.Tracks fyne.Do(func() {
a.tracklist.SetTracks(playlist.Tracks) a.tracks = playlist.Tracks
a.tracklist.SetNowPlaying(a.nowPlayingID) a.tracklist.SetTracks(playlist.Tracks)
a.header.Update(playlist) a.tracklist.SetNowPlaying(a.nowPlayingID)
a.header.Update(playlist)
})
} }
func renumberTracks(tracks []*mediaprovider.Track) { func renumberTracks(tracks []*mediaprovider.Track) {
@@ -205,8 +207,8 @@ func (a *PlaylistPage) doSetNewTrackOrder(ids []string, newPos int) {
) )
}) })
} else { } else {
renumberTracks(newTracks)
fyne.Do(func() { fyne.Do(func() {
renumberTracks(newTracks)
// force-switch back to unsorted view to show new track order // force-switch back to unsorted view to show new track order
a.tracklist.SetSorting(widgets.TracklistSort{}) a.tracklist.SetSorting(widgets.TracklistSort{})
a.tracklist.SetTracks(newTracks) a.tracklist.SetTracks(newTracks)
+3 -3
View File
@@ -152,7 +152,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
if app.Config.Application.CloseToSystemTray && m.HaveSystemTray() { if app.Config.Application.CloseToSystemTray && m.HaveSystemTray() {
m.Window.Hide() m.Window.Hide()
} else { } else {
fyneApp.Quit() m.Window.Close()
} }
}) })
@@ -314,8 +314,8 @@ func (m *MainWindow) SetupSystemTrayMenu(appName string, fyneApp fyne.App) {
m.App.PlaybackManager.SetVolume(vol) m.App.PlaybackManager.SetVolume(vol)
}), }),
fyne.NewMenuItemSeparator(), fyne.NewMenuItemSeparator(),
fyne.NewMenuItem(lang.L("Show"), m.Window.Show), fyne.NewMenuItem(lang.L("Show"), func() { fyne.Do(m.Window.Show) }),
fyne.NewMenuItem(lang.L("Hide"), m.Window.Hide), fyne.NewMenuItem(lang.L("Hide"), func() { fyne.Do(m.Window.Hide) }),
) )
desk.SetSystemTrayMenu(menu) desk.SetSystemTrayMenu(menu)
desk.SetSystemTrayIcon(res.ResAppicon256Png) desk.SetSystemTrayIcon(res.ResAppicon256Png)
+5 -55
View File
@@ -5,7 +5,6 @@ import (
"slices" "slices"
"sort" "sort"
"strings" "strings"
"sync"
"fyne.io/fyne/v2/lang" "fyne.io/fyne/v2/lang"
@@ -91,7 +90,6 @@ type Tracklist struct {
visibleColumns []bool visibleColumns []bool
sorting TracklistSort sorting TracklistSort
tracksMutex sync.RWMutex
tracks []*util.TrackListModel tracks []*util.TrackListModel
tracksOrigOrder []*util.TrackListModel tracksOrigOrder []*util.TrackListModel
@@ -148,7 +146,7 @@ func NewTracklist(tracks []*mediaprovider.Track, im *backend.ImageManager, useCo
} }
t.list = NewFocusList( t.list = NewFocusList(
t.lenTracks, func() int { return len(t.tracks) },
func() fyne.CanvasObject { func() fyne.CanvasObject {
var tr TracklistRow var tr TracklistRow
if t.compactRows { if t.compactRows {
@@ -169,16 +167,13 @@ func NewTracklist(tracks []*mediaprovider.Track, im *backend.ImageManager, useCo
return tr return tr
}, },
func(itemID widget.ListItemID, item fyne.CanvasObject) { func(itemID widget.ListItemID, item fyne.CanvasObject) {
t.tracksMutex.RLock()
// we could have removed tracks from the list in between // we could have removed tracks from the list in between
// Fyne calling the length callback and this update callback // Fyne calling the length callback and this update callback
// so the itemID may be out of bounds. if so, do nothing. // so the itemID may be out of bounds. if so, do nothing.
if itemID >= len(t.tracks) { if itemID >= len(t.tracks) {
t.tracksMutex.RUnlock()
return return
} }
model := t.tracks[itemID] model := t.tracks[itemID]
t.tracksMutex.RUnlock()
tr := item.(TracklistRow) tr := item.(TracklistRow)
if tr.TrackID() != model.Item.Metadata().ID || tr.ItemID() != itemID { if tr.TrackID() != model.Item.Metadata().ID || tr.ItemID() != itemID {
@@ -219,10 +214,8 @@ func (t *Tracklist) Scroll(amount float32) {
t.list.ScrollToOffset(t.list.GetScrollOffset() + amount) t.list.ScrollToOffset(t.list.GetScrollOffset() + amount)
} }
// Gets the track at the given index. Thread-safe. // Gets the track at the given index.
func (t *Tracklist) TrackAt(idx int) *mediaprovider.Track { func (t *Tracklist) TrackAt(idx int) *mediaprovider.Track {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
if idx >= len(t.tracks) { if idx >= len(t.tracks) {
log.Println("error: Tracklist.TrackAt: index out of range") log.Println("error: Tracklist.TrackAt: index out of range")
return nil return nil
@@ -291,10 +284,8 @@ func (t *Tracklist) SetSorting(sorting TracklistSort) {
// Sets the currently playing track ID and updates the list rendering // Sets the currently playing track ID and updates the list rendering
func (t *Tracklist) SetNowPlaying(trackID string) { func (t *Tracklist) SetNowPlaying(trackID string) {
prevNowPlaying := t.nowPlayingID prevNowPlaying := t.nowPlayingID
t.tracksMutex.RLock()
trPrev, idxPrev := util.FindItemByID(t.tracks, prevNowPlaying) trPrev, idxPrev := util.FindItemByID(t.tracks, prevNowPlaying)
tr, idx := util.FindItemByID(t.tracks, trackID) tr, idx := util.FindItemByID(t.tracks, trackID)
t.tracksMutex.RUnlock()
t.nowPlayingID = trackID t.nowPlayingID = trackID
if trPrev != nil { if trPrev != nil {
t.list.RefreshItem(idxPrev) t.list.RefreshItem(idxPrev)
@@ -306,58 +297,46 @@ func (t *Tracklist) SetNowPlaying(trackID string) {
// Increments the play count of the given track and updates the list rendering // Increments the play count of the given track and updates the list rendering
func (t *Tracklist) IncrementPlayCount(trackID string) { func (t *Tracklist) IncrementPlayCount(trackID string) {
t.tracksMutex.RLock()
tr, idx := util.FindItemByID(t.tracks, trackID) tr, idx := util.FindItemByID(t.tracks, trackID)
t.tracksMutex.RUnlock()
if tr != nil { if tr != nil {
tr.(*mediaprovider.Track).PlayCount += 1 tr.(*mediaprovider.Track).PlayCount += 1
t.list.RefreshItem(idx) t.list.RefreshItem(idx)
} }
} }
// Remove all tracks from the tracklist. Does not issue Refresh call. Thread-safe. // Remove all tracks from the tracklist. Does not issue Refresh call.
func (t *Tracklist) Clear() { func (t *Tracklist) Clear() {
t.tracksMutex.Lock()
defer t.tracksMutex.Unlock()
t.tracks = nil t.tracks = nil
t.tracksOrigOrder = nil t.tracksOrigOrder = nil
} }
// Sets the tracks in the tracklist. Thread-safe. // Sets the tracks in the tracklist.
func (t *Tracklist) SetTracks(trs []*mediaprovider.Track) { func (t *Tracklist) SetTracks(trs []*mediaprovider.Track) {
t._setTracks(trs) t._setTracks(trs)
t.Refresh() t.Refresh()
} }
func (t *Tracklist) _setTracks(trs []*mediaprovider.Track) { func (t *Tracklist) _setTracks(trs []*mediaprovider.Track) {
t.tracksMutex.Lock()
defer t.tracksMutex.Unlock()
t.tracksOrigOrder = util.ToTrackListModels(trs) t.tracksOrigOrder = util.ToTrackListModels(trs)
t.doSortTracks() t.doSortTracks()
} }
// Returns the tracks in the tracklist in the current display order. // Returns the tracks in the tracklist in the current display order.
func (t *Tracklist) GetTracks() []*mediaprovider.Track { func (t *Tracklist) GetTracks() []*mediaprovider.Track {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
return sharedutil.MapSlice(t.tracks, func(tm *util.TrackListModel) *mediaprovider.Track { return sharedutil.MapSlice(t.tracks, func(tm *util.TrackListModel) *mediaprovider.Track {
return tm.Track() return tm.Track()
}) })
} }
// Append more tracks to the tracklist. Thread-safe. // Append more tracks to the tracklist.
func (t *Tracklist) AppendTracks(trs []*mediaprovider.Track) { func (t *Tracklist) AppendTracks(trs []*mediaprovider.Track) {
t.tracksMutex.Lock()
t.tracksOrigOrder = append(t.tracks, util.ToTrackListModels(trs)...) t.tracksOrigOrder = append(t.tracks, util.ToTrackListModels(trs)...)
t.doSortTracks() t.doSortTracks()
t.tracksMutex.Unlock()
t.list.Refresh() t.list.Refresh()
} }
func (t *Tracklist) SelectAll() { func (t *Tracklist) SelectAll() {
t.tracksMutex.RLock()
util.SelectAllItems(t.tracks) util.SelectAllItems(t.tracks)
t.tracksMutex.RUnlock()
t.list.Refresh() t.list.Refresh()
} }
@@ -367,13 +346,10 @@ func (t *Tracklist) UnselectAll() {
} }
func (t *Tracklist) unselectAll() { func (t *Tracklist) unselectAll() {
t.tracksMutex.RLock()
util.UnselectAllItems(t.tracks) util.UnselectAllItems(t.tracks)
t.tracksMutex.RUnlock()
} }
func (t *Tracklist) SelectAndScrollToTrack(trackID string) { func (t *Tracklist) SelectAndScrollToTrack(trackID string) {
t.tracksMutex.RLock()
idx := -1 idx := -1
for i, tr := range t.tracks { for i, tr := range t.tracks {
if tr.Item.Metadata().ID == trackID { if tr.Item.Metadata().ID == trackID {
@@ -383,7 +359,6 @@ func (t *Tracklist) SelectAndScrollToTrack(trackID string) {
tr.Selected = false tr.Selected = false
} }
} }
t.tracksMutex.RUnlock()
if idx >= 0 { if idx >= 0 {
t.list.ScrollTo(idx) t.list.ScrollTo(idx)
} }
@@ -474,9 +449,7 @@ func (t *Tracklist) doSortTracks() {
func (t *Tracklist) onSorted(sort ListHeaderSort) { func (t *Tracklist) onSorted(sort ListHeaderSort) {
t.sorting = TracklistSort{ColumnName: t.colName(sort.ColNumber), SortOrder: sort.Type} t.sorting = TracklistSort{ColumnName: t.colName(sort.ColNumber), SortOrder: sort.Type}
t.tracksMutex.Lock()
t.doSortTracks() t.doSortTracks()
t.tracksMutex.Unlock()
t.Refresh() t.Refresh()
} }
@@ -503,20 +476,14 @@ func (t *Tracklist) onSelectTrack(idx int) {
} }
func (t *Tracklist) selectAddOrRemove(idx int) { func (t *Tracklist) selectAddOrRemove(idx int) {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
t.tracks[idx].Selected = !t.tracks[idx].Selected t.tracks[idx].Selected = !t.tracks[idx].Selected
} }
func (t *Tracklist) selectTrack(idx int) { func (t *Tracklist) selectTrack(idx int) {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
util.SelectItem(t.tracks, idx) util.SelectItem(t.tracks, idx)
} }
func (t *Tracklist) selectRange(idx int) { func (t *Tracklist) selectRange(idx int) {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
util.SelectItemRange(t.tracks, idx) util.SelectItemRange(t.tracks, idx)
} }
@@ -606,9 +573,7 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) {
} }
func (t *Tracklist) onSetFavorite(trackID string, fav bool) { func (t *Tracklist) onSetFavorite(trackID string, fav bool) {
t.tracksMutex.RLock()
item, _ := util.FindItemByID(t.tracks, trackID) item, _ := util.FindItemByID(t.tracks, trackID)
t.tracksMutex.RUnlock()
t.onSetFavorites([]*mediaprovider.Track{item.(*mediaprovider.Track)}, fav, false) t.onSetFavorites([]*mediaprovider.Track{item.(*mediaprovider.Track)}, fav, false)
} }
@@ -627,9 +592,7 @@ func (t *Tracklist) onSetFavorites(tracks []*mediaprovider.Track, fav bool, need
func (t *Tracklist) onSetRating(trackID string, rating int) { func (t *Tracklist) onSetRating(trackID string, rating int) {
// update our own track model // update our own track model
t.tracksMutex.RLock()
item, _ := util.FindItemByID(t.tracks, trackID) item, _ := util.FindItemByID(t.tracks, trackID)
t.tracksMutex.RUnlock()
t.onSetRatings([]*mediaprovider.Track{item.(*mediaprovider.Track)}, rating, false) t.onSetRatings([]*mediaprovider.Track{item.(*mediaprovider.Track)}, rating, false)
} }
@@ -681,14 +644,10 @@ func (t *Tracklist) onPlaySongRadio(tracks []*mediaprovider.Track) {
} }
func (t *Tracklist) selectedTracks() []*mediaprovider.Track { func (t *Tracklist) selectedTracks() []*mediaprovider.Track {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
return util.SelectedTracks(t.tracks) return util.SelectedTracks(t.tracks)
} }
func (t *Tracklist) SelectedTrackIDs() []string { func (t *Tracklist) SelectedTrackIDs() []string {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
return util.SelectedItemIDs(t.tracks) return util.SelectedItemIDs(t.tracks)
} }
@@ -696,9 +655,6 @@ func (t *Tracklist) SelectedTrackIDs() []string {
// original sort order (ie if tracklist is sorted by some column), the indexes // original sort order (ie if tracklist is sorted by some column), the indexes
// returned will correspond to the order of tracks when the list was initialized. // returned will correspond to the order of tracks when the list was initialized.
func (t *Tracklist) SelectedTrackIndexes() []int { func (t *Tracklist) SelectedTrackIndexes() []int {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
idx := -1 idx := -1
return sharedutil.FilterMapSlice(t.tracksOrigOrder, func(t *util.TrackListModel) (int, bool) { return sharedutil.FilterMapSlice(t.tracksOrigOrder, func(t *util.TrackListModel) (int, bool) {
idx++ idx++
@@ -706,12 +662,6 @@ func (t *Tracklist) SelectedTrackIndexes() []int {
}) })
} }
func (t *Tracklist) lenTracks() int {
t.tracksMutex.RLock()
defer t.tracksMutex.RUnlock()
return len(t.tracks)
}
func (t *Tracklist) ColNumber(colName string) int { func (t *Tracklist) ColNumber(colName string) int {
i := slices.IndexFunc(t.columns, func(c TracklistColumn) bool { i := slices.IndexFunc(t.columns, func(c TracklistColumn) bool {
return c.Name == colName return c.Name == colName
+5 -2
View File
@@ -3,6 +3,7 @@ package widgets
import ( import (
"sync/atomic" "sync/atomic"
"fyne.io/fyne/v2"
"github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/backend/mediaprovider"
) )
@@ -69,8 +70,10 @@ func (t *TracklistLoader) loadMoreTracks(num int) {
if t.disposed.Load() { if t.disposed.Load() {
return return
} }
t.tracklist.AppendTracks(t.trackBuffer) fyne.Do(func() {
t.len += len(t.trackBuffer) t.tracklist.AppendTracks(t.trackBuffer)
t.len += len(t.trackBuffer)
})
} }
if t.done { if t.done {
t.trackBuffer = nil t.trackBuffer = nil