add context menu to cover thumbnail in bottom panel
This commit is contained in:
@@ -56,6 +56,15 @@ func NewBottomPanel(p *player.Player, contr *controller.Controller) *BottomPanel
|
|||||||
contr.ShowPopUpImage(im)
|
contr.ShowPopUpImage(im)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bp.NowPlaying.OnSetFavorite = func(fav bool) {
|
||||||
|
contr.SetTrackFavorites([]string{bp.playbackManager.NowPlaying().ID}, fav)
|
||||||
|
}
|
||||||
|
bp.NowPlaying.OnSetRating = func(rating int) {
|
||||||
|
contr.SetTrackRatings([]string{bp.playbackManager.NowPlaying().ID}, rating)
|
||||||
|
}
|
||||||
|
bp.NowPlaying.OnAddToPlaylist = func() {
|
||||||
|
contr.DoAddTracksToPlaylistWorkflow([]string{bp.playbackManager.NowPlaying().ID})
|
||||||
|
}
|
||||||
bp.NowPlaying.OnAlbumNameTapped(func() {
|
bp.NowPlaying.OnAlbumNameTapped(func() {
|
||||||
contr.NavigateTo(controller.AlbumRoute(bp.playbackManager.NowPlaying().AlbumID))
|
contr.NavigateTo(controller.AlbumRoute(bp.playbackManager.NowPlaying().AlbumID))
|
||||||
})
|
})
|
||||||
|
|||||||
+15
-13
@@ -105,18 +105,8 @@ func (m *Controller) ConnectTracklistActions(tracklist *widgets.Tracklist) {
|
|||||||
m.App.PlaybackManager.LoadTracks(tracks, false, false)
|
m.App.PlaybackManager.LoadTracks(tracks, false, false)
|
||||||
m.App.PlaybackManager.PlayFromBeginning()
|
m.App.PlaybackManager.PlayFromBeginning()
|
||||||
}
|
}
|
||||||
tracklist.OnSetFavorite = func(trackIDs []string, fav bool) {
|
tracklist.OnSetFavorite = m.SetTrackFavorites
|
||||||
s := m.App.ServerManager.Server
|
tracklist.OnSetRating = m.SetTrackRatings
|
||||||
if fav {
|
|
||||||
go s.Star(subsonic.StarParameters{SongIDs: trackIDs})
|
|
||||||
} else {
|
|
||||||
go s.Unstar(subsonic.StarParameters{SongIDs: trackIDs})
|
|
||||||
}
|
|
||||||
for _, id := range trackIDs {
|
|
||||||
m.App.PlaybackManager.OnTrackFavoriteStatusChanged(id, fav)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tracklist.OnSetRating = m.setTrackRatings
|
|
||||||
tracklist.OnShowAlbumPage = func(albumID string) {
|
tracklist.OnShowAlbumPage = func(albumID string) {
|
||||||
m.NavigateTo(AlbumRoute(albumID))
|
m.NavigateTo(AlbumRoute(albumID))
|
||||||
}
|
}
|
||||||
@@ -417,7 +407,19 @@ func (c *Controller) doModalClosed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) setTrackRatings(trackIDs []string, rating int) {
|
func (c *Controller) SetTrackFavorites(trackIDs []string, favorite bool) {
|
||||||
|
s := c.App.ServerManager.Server
|
||||||
|
if favorite {
|
||||||
|
go s.Star(subsonic.StarParameters{SongIDs: trackIDs})
|
||||||
|
} else {
|
||||||
|
go s.Unstar(subsonic.StarParameters{SongIDs: trackIDs})
|
||||||
|
}
|
||||||
|
for _, id := range trackIDs {
|
||||||
|
c.App.PlaybackManager.OnTrackFavoriteStatusChanged(id, favorite)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) SetTrackRatings(trackIDs []string, rating int) {
|
||||||
// Subsonic doesn't allow bulk setting ratings.
|
// Subsonic doesn't allow bulk setting ratings.
|
||||||
// To not overwhelm the server with requests, set rating for
|
// To not overwhelm the server with requests, set rating for
|
||||||
// only 5 tracks at a time concurrently
|
// only 5 tracks at a time concurrently
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
@@ -87,6 +88,28 @@ func RichTextSegsFromHTMLString(s string) []widget.RichTextSegment {
|
|||||||
return segs
|
return segs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRatingSubmenu(onSetRating func(int)) *fyne.MenuItem {
|
||||||
|
newRatingMenuItem := func(rating int) *fyne.MenuItem {
|
||||||
|
label := "(none)"
|
||||||
|
if rating > 0 {
|
||||||
|
label = strconv.Itoa(rating)
|
||||||
|
}
|
||||||
|
return fyne.NewMenuItem(label, func() {
|
||||||
|
onSetRating(rating)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ratingMenu := fyne.NewMenuItem("Set rating", nil)
|
||||||
|
ratingMenu.ChildMenu = fyne.NewMenu("", []*fyne.MenuItem{
|
||||||
|
newRatingMenuItem(0),
|
||||||
|
newRatingMenuItem(1),
|
||||||
|
newRatingMenuItem(2),
|
||||||
|
newRatingMenuItem(3),
|
||||||
|
newRatingMenuItem(4),
|
||||||
|
newRatingMenuItem(5),
|
||||||
|
}...)
|
||||||
|
return ratingMenu
|
||||||
|
}
|
||||||
|
|
||||||
type HSpace struct {
|
type HSpace struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
|
|
||||||
"github.com/dweymouth/supersonic/ui/layouts"
|
"github.com/dweymouth/supersonic/ui/layouts"
|
||||||
|
"github.com/dweymouth/supersonic/ui/util"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/canvas"
|
"fyne.io/fyne/v2/canvas"
|
||||||
@@ -20,8 +21,12 @@ type NowPlayingCard struct {
|
|||||||
artistName *CustomHyperlink
|
artistName *CustomHyperlink
|
||||||
albumName *CustomHyperlink
|
albumName *CustomHyperlink
|
||||||
cover *TappableImage
|
cover *TappableImage
|
||||||
|
menu *widget.PopUpMenu
|
||||||
|
|
||||||
OnShowCoverImage func()
|
OnShowCoverImage func()
|
||||||
|
OnSetRating func(rating int)
|
||||||
|
OnSetFavorite func(favorite bool)
|
||||||
|
OnAddToPlaylist func()
|
||||||
|
|
||||||
c fyne.CanvasObject
|
c fyne.CanvasObject
|
||||||
}
|
}
|
||||||
@@ -34,6 +39,7 @@ func NewNowPlayingCard() *NowPlayingCard {
|
|||||||
}
|
}
|
||||||
n.ExtendBaseWidget(n)
|
n.ExtendBaseWidget(n)
|
||||||
n.cover = NewTappableImage(n.onShowCoverImage)
|
n.cover = NewTappableImage(n.onShowCoverImage)
|
||||||
|
n.cover.OnTappedSecondary = n.showMenu
|
||||||
n.trackName.Hidden = true
|
n.trackName.Hidden = true
|
||||||
n.artistName.Hidden = true
|
n.artistName.Hidden = true
|
||||||
n.albumName.Hidden = true
|
n.albumName.Hidden = true
|
||||||
@@ -55,6 +61,24 @@ func (n *NowPlayingCard) onShowCoverImage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NowPlayingCard) onSetFavorite(fav bool) {
|
||||||
|
if n.OnSetFavorite != nil {
|
||||||
|
n.OnSetFavorite(fav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NowPlayingCard) onSetRating(rating int) {
|
||||||
|
if n.OnSetRating != nil {
|
||||||
|
n.OnSetRating(rating)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *NowPlayingCard) onAddToPlaylist() {
|
||||||
|
if n.OnAddToPlaylist != nil {
|
||||||
|
n.OnAddToPlaylist()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NowPlayingCard) CreateRenderer() fyne.WidgetRenderer {
|
func (n *NowPlayingCard) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(n.c)
|
return widget.NewSimpleRenderer(n.c)
|
||||||
}
|
}
|
||||||
@@ -82,3 +106,16 @@ func (n *NowPlayingCard) OnAlbumNameTapped(f func()) {
|
|||||||
func (n *NowPlayingCard) OnTrackNameTapped(f func()) {
|
func (n *NowPlayingCard) OnTrackNameTapped(f func()) {
|
||||||
n.trackName.OnTapped = f
|
n.trackName.OnTapped = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *NowPlayingCard) showMenu(pos fyne.Position) {
|
||||||
|
if n.menu == nil {
|
||||||
|
ratingMenu := util.NewRatingSubmenu(n.onSetRating)
|
||||||
|
m := fyne.NewMenu("",
|
||||||
|
fyne.NewMenuItem("Set favorite", func() { n.onSetFavorite(true) }),
|
||||||
|
fyne.NewMenuItem("Unset favorite", func() { n.onSetFavorite(false) }),
|
||||||
|
ratingMenu,
|
||||||
|
fyne.NewMenuItem("Add to playlist...", func() { n.onAddToPlaylist() }))
|
||||||
|
n.menu = widget.NewPopUpMenu(m, fyne.CurrentApp().Driver().CanvasForObject(n))
|
||||||
|
}
|
||||||
|
n.menu.ShowAtPosition(pos)
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ type TappableImage struct {
|
|||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
canvas.Image
|
canvas.Image
|
||||||
|
|
||||||
OnTapped func()
|
OnTapped func()
|
||||||
|
OnTappedSecondary func(pos fyne.Position)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTappableImage(onTapped func()) *TappableImage {
|
func NewTappableImage(onTapped func()) *TappableImage {
|
||||||
@@ -86,12 +87,18 @@ func (t *TappableImage) Cursor() desktop.Cursor {
|
|||||||
return desktop.DefaultCursor
|
return desktop.DefaultCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TappableImage) Tapped(e *fyne.PointEvent) {
|
func (t *TappableImage) Tapped(_ *fyne.PointEvent) {
|
||||||
if t.haveImage() && t.OnTapped != nil {
|
if t.haveImage() && t.OnTapped != nil {
|
||||||
t.OnTapped()
|
t.OnTapped()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TappableImage) TappedSecondary(e *fyne.PointEvent) {
|
||||||
|
if t.haveImage() && t.OnTappedSecondary != nil {
|
||||||
|
t.OnTappedSecondary(e.AbsolutePosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TappableImage) CreateRenderer() fyne.WidgetRenderer {
|
func (t *TappableImage) CreateRenderer() fyne.WidgetRenderer {
|
||||||
return widget.NewSimpleRenderer(&t.Image)
|
return widget.NewSimpleRenderer(&t.Image)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-19
@@ -308,15 +308,9 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) {
|
|||||||
fyne.NewMenuItem("Unset favorite", func() {
|
fyne.NewMenuItem("Unset favorite", func() {
|
||||||
t.onSetFavorites(t.selectedTracks(), false, true)
|
t.onSetFavorites(t.selectedTracks(), false, true)
|
||||||
}))
|
}))
|
||||||
ratingMenu := fyne.NewMenuItem("Set rating", nil)
|
ratingMenu := util.NewRatingSubmenu(func(rating int) {
|
||||||
ratingMenu.ChildMenu = fyne.NewMenu("", []*fyne.MenuItem{
|
t.onSetRatings(t.selectedTracks(), rating, true)
|
||||||
t.newRatingMenuItem(0),
|
})
|
||||||
t.newRatingMenuItem(1),
|
|
||||||
t.newRatingMenuItem(2),
|
|
||||||
t.newRatingMenuItem(3),
|
|
||||||
t.newRatingMenuItem(4),
|
|
||||||
t.newRatingMenuItem(5),
|
|
||||||
}...)
|
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items, ratingMenu)
|
t.ctxMenu.Items = append(t.ctxMenu.Items, ratingMenu)
|
||||||
if len(t.AuxiliaryMenuItems) > 0 {
|
if len(t.AuxiliaryMenuItems) > 0 {
|
||||||
t.ctxMenu.Items = append(t.ctxMenu.Items, fyne.NewMenuItemSeparator())
|
t.ctxMenu.Items = append(t.ctxMenu.Items, fyne.NewMenuItemSeparator())
|
||||||
@@ -326,16 +320,6 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) {
|
|||||||
widget.ShowPopUpMenuAtPosition(t.ctxMenu, fyne.CurrentApp().Driver().CanvasForObject(t), e.AbsolutePosition)
|
widget.ShowPopUpMenuAtPosition(t.ctxMenu, fyne.CurrentApp().Driver().CanvasForObject(t), e.AbsolutePosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tracklist) newRatingMenuItem(rating int) *fyne.MenuItem {
|
|
||||||
label := "(none)"
|
|
||||||
if rating > 0 {
|
|
||||||
label = strconv.Itoa(rating)
|
|
||||||
}
|
|
||||||
return fyne.NewMenuItem(label, func() {
|
|
||||||
t.onSetRatings(t.selectedTracks(), rating, true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Tracklist) onSetFavorite(trackID string, fav bool) {
|
func (t *Tracklist) onSetFavorite(trackID string, fav bool) {
|
||||||
t.tracksMutex.RLock()
|
t.tracksMutex.RLock()
|
||||||
tr := sharedutil.FindTrackByID(trackID, t.Tracks)
|
tr := sharedutil.FindTrackByID(trackID, t.Tracks)
|
||||||
|
|||||||
Reference in New Issue
Block a user