From 6f74b5a2b81c1b2a9ccd9abbcb0d41a80293ccbe Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 24 Jul 2024 17:36:33 -0700 Subject: [PATCH] Add pop up plqy queue button to lower right --- res/bundled.go | 5 + res/bundled_gen.sh | 1 + res/icons/publicdomain/playqueue.svg | 12 ++ ui/bottompanel.go | 1 + ui/browsing/nowplayingpage.go | 23 +--- ui/controller/connectactions.go | 171 ++++++++++++++++++++++++ ui/controller/controller.go | 190 ++++++++------------------- ui/controller/visualizations.go | 2 +- ui/mainwindow.go | 7 +- ui/theme/theme.go | 1 + ui/widgets/auxcontrols.go | 11 +- ui/widgets/playqueuelist.go | 16 +++ 12 files changed, 282 insertions(+), 158 deletions(-) create mode 100644 res/icons/publicdomain/playqueue.svg create mode 100644 ui/controller/connectactions.go diff --git a/res/bundled.go b/res/bundled.go index 3e1b5d0..4fef63c 100644 --- a/res/bundled.go +++ b/res/bundled.go @@ -55,6 +55,11 @@ var ResPlaylistSvg = &fyne.StaticResource{ StaticContent: []byte( "\n"), } +var ResPlayqueueSvg = &fyne.StaticResource{ + StaticName: "playqueue.svg", + StaticContent: []byte( + "\n\n\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r"), +} var ResStarOutlineSvg = &fyne.StaticResource{ StaticName: "star-outline.svg", StaticContent: []byte( diff --git a/res/bundled_gen.sh b/res/bundled_gen.sh index 66a1745..aa21d2e 100755 --- a/res/bundled_gen.sh +++ b/res/bundled_gen.sh @@ -10,6 +10,7 @@ fyne bundle -append -prefix Res icons/publicdomain/heart-outline.svg >> bundled. fyne bundle -append -prefix Res icons/publicdomain/musicnotes.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/people.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/playlist.svg >> bundled.go +fyne bundle -append -prefix Res icons/publicdomain/playqueue.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/star-outline.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/star-filled.svg >> bundled.go fyne bundle -append -prefix Res icons/publicdomain/theatermasks.svg >> bundled.go diff --git a/res/icons/publicdomain/playqueue.svg b/res/icons/publicdomain/playqueue.svg new file mode 100644 index 0000000..707c2d7 --- /dev/null +++ b/res/icons/publicdomain/playqueue.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/bottompanel.go b/ui/bottompanel.go index 652f0f6..c3960de 100644 --- a/ui/bottompanel.go +++ b/ui/bottompanel.go @@ -106,6 +106,7 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr bp.AuxControls.OnChangeLoopMode(func() { pm.SetNextLoopMode() }) + bp.AuxControls.OnShowPlayQueue(contr.ShowPopUpPlayQueue) bp.imageLoader = util.NewThumbnailLoader(im, bp.NowPlaying.SetImage) diff --git a/ui/browsing/nowplayingpage.go b/ui/browsing/nowplayingpage.go index 252ff09..e785a64 100644 --- a/ui/browsing/nowplayingpage.go +++ b/ui/browsing/nowplayingpage.go @@ -131,24 +131,10 @@ func NewNowPlayingPage( a.queueList = widgets.NewPlayQueueList(a.im, false) a.relatedList = widgets.NewPlayQueueList(a.im, true) a.queueList.Reorderable = true - a.queueList.OnReorderItems = a.doSetNewTrackOrder - a.queueList.OnDownload = contr.ShowDownloadDialog - a.queueList.OnShare = func(tracks []*mediaprovider.Track) { - if len(tracks) > 0 { - a.contr.ShowShareDialog(tracks[0].ID) - } - } - a.queueList.OnAddToPlaylist = contr.DoAddTracksToPlaylistWorkflow - a.queueList.OnPlayItemAt = func(tracknum int) { - _ = a.pm.PlayTrackAt(tracknum) - } - a.queueList.OnShowArtistPage = func(artistID string) { - a.contr.NavigateTo(controller.ArtistRoute(artistID)) - } - a.queueList.OnRemoveFromQueue = func(idxs []int) { - a.queueList.UnselectAll() - a.pm.RemoveTracksFromQueue(idxs) - } + + a.contr.ConnectPlayQueuelistActions(a.queueList) + // override OnSetRating and Favorite so we can also update the + // LargeNowPlayingCard's displayed rating and favorite a.queueList.OnSetRating = func(trackIDs []string, rating int) { contr.SetTrackRatings(trackIDs, rating) if slices.Contains(trackIDs, a.nowPlayingID) { @@ -161,6 +147,7 @@ func NewNowPlayingPage( a.card.SetDisplayedFavorite(fav) } } + a.relatedList.OnDownload = a.queueList.OnDownload a.relatedList.OnShare = a.queueList.OnShare a.relatedList.OnAddToPlaylist = a.queueList.OnAddToPlaylist diff --git a/ui/controller/connectactions.go b/ui/controller/connectactions.go new file mode 100644 index 0000000..815bb84 --- /dev/null +++ b/ui/controller/connectactions.go @@ -0,0 +1,171 @@ +package controller + +import ( + "log" + + "github.com/dweymouth/supersonic/backend" + "github.com/dweymouth/supersonic/backend/mediaprovider" + "github.com/dweymouth/supersonic/backend/player" + "github.com/dweymouth/supersonic/sharedutil" + "github.com/dweymouth/supersonic/ui/widgets" + + "fyne.io/fyne/v2/widget" +) + +func (m *Controller) ConnectTracklistActionsWithReplayGainAlbum(tracklist *widgets.Tracklist) { + m.connectTracklistActionsWithReplayGainMode(tracklist, player.ReplayGainAlbum) +} + +func (m *Controller) ConnectTracklistActions(tracklist *widgets.Tracklist) { + m.connectTracklistActionsWithReplayGainMode(tracklist, player.ReplayGainTrack) +} + +func (m *Controller) connectTracklistActionsWithReplayGainMode(tracklist *widgets.Tracklist, mode player.ReplayGainMode) { + tracklist.OnAddToPlaylist = m.DoAddTracksToPlaylistWorkflow + tracklist.OnPlaySelectionNext = func(tracks []*mediaprovider.Track) { + m.App.PlaybackManager.LoadTracks(tracks, backend.InsertNext, false) + } + tracklist.OnAddToQueue = func(tracks []*mediaprovider.Track) { + m.App.PlaybackManager.LoadTracks(tracks, backend.Append, false) + } + tracklist.OnPlayTrackAt = func(idx int) { + m.App.PlaybackManager.LoadTracks(tracklist.GetTracks(), backend.Replace, false) + if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { + m.App.PlaybackManager.SetReplayGainMode(mode) + } + m.App.PlaybackManager.PlayTrackAt(idx) + } + tracklist.OnPlaySelection = func(tracks []*mediaprovider.Track, shuffle bool) { + m.App.PlaybackManager.LoadTracks(tracks, backend.Replace, shuffle) + if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { + m.App.PlaybackManager.SetReplayGainMode(mode) + } + m.App.PlaybackManager.PlayFromBeginning() + } + tracklist.OnSetFavorite = m.SetTrackFavorites + tracklist.OnSetRating = m.SetTrackRatings + tracklist.OnShowAlbumPage = func(albumID string) { + m.NavigateTo(AlbumRoute(albumID)) + } + tracklist.OnShowArtistPage = func(artistID string) { + m.NavigateTo(ArtistRoute(artistID)) + } + tracklist.OnColumnVisibilityMenuShown = func(pop *widget.PopUp) { + m.ClosePopUpOnEscape(pop) + } + tracklist.OnDownload = m.ShowDownloadDialog + tracklist.OnShare = func(trackID string) { + go m.ShowShareDialog(trackID) + } + tracklist.OnShowTrackInfo = m.ShowTrackInfoDialog + tracklist.OnPlaySongRadio = func(track *mediaprovider.Track) { + go func() { + tracks, err := m.GetSongRadioTracks(track) + if err != nil { + log.Println("Error getting song radio: ", err) + return + } + m.App.PlaybackManager.LoadTracks(tracks, backend.Replace, false) + if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { + m.App.PlaybackManager.SetReplayGainMode(mode) + } + m.App.PlaybackManager.PlayFromBeginning() + }() + } +} + +func (m *Controller) ConnectAlbumGridActions(grid *widgets.GridView) { + grid.OnAddToQueue = func(albumID string) { + go m.App.PlaybackManager.LoadAlbum(albumID, backend.Append, false) + } + grid.OnPlayNext = func(albumID string) { + go m.App.PlaybackManager.LoadAlbum(albumID, backend.InsertNext, false) + } + grid.OnPlay = func(albumID string, shuffle bool) { + go m.App.PlaybackManager.PlayAlbum(albumID, 0, shuffle) + } + grid.OnShowItemPage = func(albumID string) { + m.NavigateTo(AlbumRoute(albumID)) + } + grid.OnShowSecondaryPage = func(artistID string) { + m.NavigateTo(ArtistRoute(artistID)) + } + grid.OnAddToPlaylist = func(albumID string) { + go func() { + album, err := m.App.ServerManager.Server.GetAlbum(albumID) + if err != nil { + log.Printf("error loading bum: %s", err.Error()) + return + } + m.DoAddTracksToPlaylistWorkflow(sharedutil.TracksToIDs(album.Tracks)) + }() + } + grid.OnDownload = func(albumID string) { + go func() { + album, err := m.App.ServerManager.Server.GetAlbum(albumID) + if err != nil { + log.Printf("error loading bum: %s", err.Error()) + return + } + m.ShowDownloadDialog(album.Tracks, album.Name) + }() + } + grid.OnShare = func(albumID string) { + go m.ShowShareDialog(albumID) + } +} + +func (m *Controller) ConnectArtistGridActions(grid *widgets.GridView) { + grid.OnShowItemPage = func(id string) { m.NavigateTo(ArtistRoute(id)) } + grid.OnPlayNext = func(artistID string) { + go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.InsertNext, false) + } + grid.OnPlay = func(artistID string, shuffle bool) { go m.App.PlaybackManager.PlayArtistDiscography(artistID, shuffle) } + grid.OnAddToQueue = func(artistID string) { + go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.Append, false) + } + grid.OnAddToPlaylist = func(artistID string) { + go m.DoAddTracksToPlaylistWorkflow( + sharedutil.TracksToIDs(m.GetArtistTracks(artistID))) + } + grid.OnDownload = func(artistID string) { + go func() { + tracks := m.GetArtistTracks(artistID) + tist, err := m.App.ServerManager.Server.GetArtist(artistID) + if err != nil { + log.Printf("error getting tist: %v", err.Error()) + return + } + m.ShowDownloadDialog(tracks, tist.Name) + }() + } + grid.OnShare = func(artistID string) { + go m.ShowShareDialog(artistID) + } +} + +func (c *Controller) ConnectPlayQueuelistActions(list *widgets.PlayQueueList) { + list.OnReorderItems = func(idxs []int, insertPos int) { + newTracks := sharedutil.ReorderItems(list.Items(), idxs, insertPos) + c.App.PlaybackManager.UpdatePlayQueue(newTracks) + } + list.OnDownload = c.ShowDownloadDialog + list.OnShare = func(tracks []*mediaprovider.Track) { + if len(tracks) > 0 { + c.ShowShareDialog(tracks[0].ID) + } + } + list.OnAddToPlaylist = c.DoAddTracksToPlaylistWorkflow + list.OnPlayItemAt = func(tracknum int) { + _ = c.App.PlaybackManager.PlayTrackAt(tracknum) + } + list.OnShowArtistPage = func(artistID string) { + c.NavigateTo(ArtistRoute(artistID)) + } + list.OnRemoveFromQueue = func(idxs []int) { + list.UnselectAll() + c.App.PlaybackManager.RemoveTracksFromQueue(idxs) + } + list.OnSetRating = c.SetTrackRatings + list.OnSetFavorite = c.SetTrackFavorites +} diff --git a/ui/controller/controller.go b/ui/controller/controller.go index 63e9f64..3b513a8 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -45,11 +45,37 @@ type Controller struct { ReloadFunc func() RefreshPageFunc func() + popUpQueue *widgets.PlayQueueList escapablePopUp *widget.PopUp haveModal bool runOnModalClosed func() } +func New(app *backend.App, appVersion string, mainWindow fyne.Window) *Controller { + c := &Controller{ + AppVersion: appVersion, + MainWindow: mainWindow, + App: app, + } + c.initVisualizations() + c.App.PlaybackManager.OnQueueChange(func() { + if c.popUpQueue != nil { + c.popUpQueue.SetItems(c.App.PlaybackManager.GetPlayQueue()) + } + }) + c.App.PlaybackManager.OnSongChange(func(track mediaprovider.MediaItem, _ *mediaprovider.Track) { + if c.popUpQueue == nil { + return + } + if track == nil { + c.popUpQueue.SetNowPlaying("") + } else { + c.popUpQueue.SetNowPlaying(track.Metadata().ID) + } + }) + return c +} + func (m *Controller) NavigateTo(route Route) { m.NavHandler(route) } @@ -81,6 +107,38 @@ func (m *Controller) HaveModal() bool { return m.haveModal } +func (m *Controller) ShowPopUpPlayQueue() { + if m.popUpQueue == nil { + m.popUpQueue = widgets.NewPlayQueueList(m.App.ImageManager, false) + m.popUpQueue.Reorderable = true + m.popUpQueue.SetItems(m.App.PlaybackManager.GetPlayQueue()) + m.ConnectPlayQueuelistActions(m.popUpQueue) + } + m.popUpQueue.SetNowPlaying(m.App.PlaybackManager.NowPlaying().Metadata().ID) + m.popUpQueue.UnselectAll() + m.popUpQueue.ScrollToNowPlaying() + + title := widget.NewRichTextWithText(lang.L("Play Queue")) + title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter + title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true + container := container.NewBorder(title, nil, nil, nil, + container.NewPadded(m.popUpQueue), + ) + pop := widget.NewPopUp(container, m.MainWindow.Canvas()) + m.ClosePopUpOnEscape(pop) + minSize := fyne.NewSize(300, 400) + maxSize := fyne.NewSize(800, 1000) + canvasSize := m.MainWindow.Canvas().Size() + size := minSize.Max(maxSize.Min( + fyne.NewSize(canvasSize.Width*0.4, canvasSize.Height*0.5), + )) + pop.Resize(size) + pop.ShowAtPosition(fyne.NewPos( + canvasSize.Width-size.Width-10, + canvasSize.Height-size.Height-100, + )) +} + func (m *Controller) ShowPopUpImage(img image.Image) { im := canvas.NewImageFromImage(img) im.FillMode = canvas.ImageFillContain @@ -103,138 +161,6 @@ func (m *Controller) ShowPopUpImage(img image.Image) { )) } -func (m *Controller) ConnectTracklistActionsWithReplayGainAlbum(tracklist *widgets.Tracklist) { - m.connectTracklistActionsWithReplayGainMode(tracklist, player.ReplayGainAlbum) -} - -func (m *Controller) ConnectTracklistActions(tracklist *widgets.Tracklist) { - m.connectTracklistActionsWithReplayGainMode(tracklist, player.ReplayGainTrack) -} - -func (m *Controller) connectTracklistActionsWithReplayGainMode(tracklist *widgets.Tracklist, mode player.ReplayGainMode) { - tracklist.OnAddToPlaylist = m.DoAddTracksToPlaylistWorkflow - tracklist.OnPlaySelectionNext = func(tracks []*mediaprovider.Track) { - m.App.PlaybackManager.LoadTracks(tracks, backend.InsertNext, false) - } - tracklist.OnAddToQueue = func(tracks []*mediaprovider.Track) { - m.App.PlaybackManager.LoadTracks(tracks, backend.Append, false) - } - tracklist.OnPlayTrackAt = func(idx int) { - m.App.PlaybackManager.LoadTracks(tracklist.GetTracks(), backend.Replace, false) - if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { - m.App.PlaybackManager.SetReplayGainMode(mode) - } - m.App.PlaybackManager.PlayTrackAt(idx) - } - tracklist.OnPlaySelection = func(tracks []*mediaprovider.Track, shuffle bool) { - m.App.PlaybackManager.LoadTracks(tracks, backend.Replace, shuffle) - if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { - m.App.PlaybackManager.SetReplayGainMode(mode) - } - m.App.PlaybackManager.PlayFromBeginning() - } - tracklist.OnSetFavorite = m.SetTrackFavorites - tracklist.OnSetRating = m.SetTrackRatings - tracklist.OnShowAlbumPage = func(albumID string) { - m.NavigateTo(AlbumRoute(albumID)) - } - tracklist.OnShowArtistPage = func(artistID string) { - m.NavigateTo(ArtistRoute(artistID)) - } - tracklist.OnColumnVisibilityMenuShown = func(pop *widget.PopUp) { - m.ClosePopUpOnEscape(pop) - } - tracklist.OnDownload = m.ShowDownloadDialog - tracklist.OnShare = func(trackID string) { - go m.ShowShareDialog(trackID) - } - tracklist.OnShowTrackInfo = m.ShowTrackInfoDialog - tracklist.OnPlaySongRadio = func(track *mediaprovider.Track) { - go func() { - tracks, err := m.GetSongRadioTracks(track) - if err != nil { - log.Println("Error getting song radio: ", err) - return - } - m.App.PlaybackManager.LoadTracks(tracks, backend.Replace, false) - if m.App.Config.ReplayGain.Mode == backend.ReplayGainAuto { - m.App.PlaybackManager.SetReplayGainMode(mode) - } - m.App.PlaybackManager.PlayFromBeginning() - }() - } -} - -func (m *Controller) ConnectAlbumGridActions(grid *widgets.GridView) { - grid.OnAddToQueue = func(albumID string) { - go m.App.PlaybackManager.LoadAlbum(albumID, backend.Append, false) - } - grid.OnPlayNext = func(albumID string) { - go m.App.PlaybackManager.LoadAlbum(albumID, backend.InsertNext, false) - } - grid.OnPlay = func(albumID string, shuffle bool) { - go m.App.PlaybackManager.PlayAlbum(albumID, 0, shuffle) - } - grid.OnShowItemPage = func(albumID string) { - m.NavigateTo(AlbumRoute(albumID)) - } - grid.OnShowSecondaryPage = func(artistID string) { - m.NavigateTo(ArtistRoute(artistID)) - } - grid.OnAddToPlaylist = func(albumID string) { - go func() { - album, err := m.App.ServerManager.Server.GetAlbum(albumID) - if err != nil { - log.Printf("error loading album: %s", err.Error()) - return - } - m.DoAddTracksToPlaylistWorkflow(sharedutil.TracksToIDs(album.Tracks)) - }() - } - grid.OnDownload = func(albumID string) { - go func() { - album, err := m.App.ServerManager.Server.GetAlbum(albumID) - if err != nil { - log.Printf("error loading album: %s", err.Error()) - return - } - m.ShowDownloadDialog(album.Tracks, album.Name) - }() - } - grid.OnShare = func(albumID string) { - go m.ShowShareDialog(albumID) - } -} - -func (m *Controller) ConnectArtistGridActions(grid *widgets.GridView) { - grid.OnShowItemPage = func(id string) { m.NavigateTo(ArtistRoute(id)) } - grid.OnPlayNext = func(artistID string) { - go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.InsertNext, false) - } - grid.OnPlay = func(artistID string, shuffle bool) { go m.App.PlaybackManager.PlayArtistDiscography(artistID, shuffle) } - grid.OnAddToQueue = func(artistID string) { - go m.App.PlaybackManager.LoadTracks(m.GetArtistTracks(artistID), backend.Append, false) - } - grid.OnAddToPlaylist = func(artistID string) { - go m.DoAddTracksToPlaylistWorkflow( - sharedutil.TracksToIDs(m.GetArtistTracks(artistID))) - } - grid.OnDownload = func(artistID string) { - go func() { - tracks := m.GetArtistTracks(artistID) - artist, err := m.App.ServerManager.Server.GetArtist(artistID) - if err != nil { - log.Printf("error getting artist: %v", err.Error()) - return - } - m.ShowDownloadDialog(tracks, artist.Name) - }() - } - grid.OnShare = func(artistID string) { - go m.ShowShareDialog(artistID) - } -} - func (m *Controller) GetArtistTracks(artistID string) []*mediaprovider.Track { if mp := m.App.ServerManager.Server; mp != nil { if tr, err := mp.GetArtistTracks(artistID); err != nil { diff --git a/ui/controller/visualizations.go b/ui/controller/visualizations.go index 58b4ed3..7625f06 100644 --- a/ui/controller/visualizations.go +++ b/ui/controller/visualizations.go @@ -18,7 +18,7 @@ type visualizationData struct { visualizationAnim *fyne.Animation } -func (c *Controller) InitVisualizations() { +func (c *Controller) initVisualizations() { c.App.LocalPlayer.OnStopped(c.stopVisualizationAnim) c.App.LocalPlayer.OnPaused(c.stopVisualizationAnim) c.App.LocalPlayer.OnPlaying(func() { diff --git a/ui/mainwindow.go b/ui/mainwindow.go index 7c2aad2..97f5415 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -76,12 +76,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, if app.Config.Application.EnableSystemTray { m.SetupSystemTrayMenu(displayAppName, fyneApp) } - m.Controller = &controller.Controller{ - AppVersion: appVersion, - MainWindow: m.Window, - App: app, - } - m.Controller.InitVisualizations() + m.Controller = controller.New(app, appVersion, m.Window) m.BrowsingPane = browsing.NewBrowsingPane(app, m.Controller, func() { m.Router.NavigateTo(m.StartupPage()) }) m.Router = browsing.NewRouter(app, m.Controller, m.BrowsingPane) // inject controller dependencies diff --git a/ui/theme/theme.go b/ui/theme/theme.go index 3727bb6..1f27372 100644 --- a/ui/theme/theme.go +++ b/ui/theme/theme.go @@ -41,6 +41,7 @@ var ( NowPlayingIcon fyne.Resource = theme.NewThemedResource(res.ResHeadphonesSvg) PlaylistIcon fyne.Resource = theme.NewThemedResource(res.ResPlaylistSvg) PlayNextIcon fyne.Resource = theme.NewThemedResource(res.ResPlaylistAddNextSvg) + PlayQueueIcon fyne.Resource = theme.NewThemedResource(res.ResPlayqueueSvg) ShareIcon fyne.Resource = theme.NewThemedResource(res.ResShareSvg) ShuffleIcon fyne.Resource = theme.NewThemedResource(res.ResShuffleSvg) TracksIcon fyne.Resource = theme.NewThemedResource(res.ResMusicnotesSvg) diff --git a/ui/widgets/auxcontrols.go b/ui/widgets/auxcontrols.go index c23f7bc..16fc38b 100644 --- a/ui/widgets/auxcontrols.go +++ b/ui/widgets/auxcontrols.go @@ -19,6 +19,7 @@ type AuxControls struct { VolumeControl *VolumeControl loop *IconButton + showQueue *IconButton container *fyne.Container } @@ -27,14 +28,18 @@ func NewAuxControls(initialVolume int) *AuxControls { a := &AuxControls{ VolumeControl: NewVolumeControl(initialVolume), loop: NewIconButton(myTheme.RepeatIcon, nil), + showQueue: NewIconButton(myTheme.PlayQueueIcon, nil), } a.loop.IconSize = IconButtonSizeSmaller + a.showQueue.IconSize = IconButtonSizeSmaller a.container = container.NewHBox( layout.NewSpacer(), container.NewVBox( layout.NewSpacer(), a.VolumeControl, - container.NewHBox(layout.NewSpacer(), a.loop, util.NewHSpace(5)), + container.New( + layout.NewCustomPaddedHBoxLayout(theme.Padding()*1.5), + layout.NewSpacer(), a.loop, a.showQueue, util.NewHSpace(5)), layout.NewSpacer(), ), ) @@ -64,6 +69,10 @@ func (a *AuxControls) SetLoopMode(mode backend.LoopMode) { } } +func (a *AuxControls) OnShowPlayQueue(f func()) { + a.showQueue.OnTapped = f +} + type volumeSlider struct { widget.Slider diff --git a/ui/widgets/playqueuelist.go b/ui/widgets/playqueuelist.go index e542171..98b2af0 100644 --- a/ui/widgets/playqueuelist.go +++ b/ui/widgets/playqueuelist.go @@ -2,6 +2,7 @@ package widgets import ( "image" + "slices" "strconv" "sync" @@ -134,6 +135,12 @@ func (p *PlayQueueList) SetItems(items []mediaprovider.MediaItem) { p.Refresh() } +func (p *PlayQueueList) Items() []mediaprovider.MediaItem { + return sharedutil.MapSlice(p.items, func(item *util.TrackListModel) mediaprovider.MediaItem { + return item.Item + }) +} + // Sets the currently playing item ID and updates the list rendering func (p *PlayQueueList) SetNowPlaying(itemID string) { prevNowPlaying := p.nowPlayingID @@ -168,6 +175,15 @@ func (p *PlayQueueList) Scroll(amount float32) { p.list.ScrollToOffset(p.list.GetScrollOffset() + amount) } +func (p *PlayQueueList) ScrollToNowPlaying() { + idx := slices.IndexFunc(p.items, func(item *util.TrackListModel) bool { + return item.Item.Metadata().ID == p.nowPlayingID + }) + if idx > 0 { + p.list.ScrollTo(idx) + } +} + func (p *PlayQueueList) Refresh() { p.list.EnableDragging = p.Reorderable p.BaseWidget.Refresh()