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"),
+}
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()