Fix #286: add "option button" to the right of current track title

This commit is contained in:
Drew Weymouth
2024-06-05 08:26:08 -07:00
parent 9566179649
commit b65bb707a8
3 changed files with 133 additions and 10 deletions
+5
View File
@@ -78,6 +78,11 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr
bp.NowPlaying.OnTrackNameTapped = func() {
contr.NavigateTo(controller.NowPlayingRoute(pm.NowPlaying().Metadata().ID))
}
bp.NowPlaying.OnShare = func() {
if tr, ok := pm.NowPlaying().(*mediaprovider.Track); ok {
contr.ShowShareDialog(tr.ID)
}
}
bp.Controls = widgets.NewPlayerControls()
bp.Controls.OnPlayPause(func() {
pm.PlayPause()
+22 -10
View File
@@ -22,7 +22,7 @@ type NowPlayingCard struct {
DisableRating bool
trackName *widget.Hyperlink
trackName *OptionHyperlink
artistName *MultiHyperlink
albumName *widget.Hyperlink
cover *ImagePlaceholder
@@ -36,28 +36,28 @@ type NowPlayingCard struct {
OnSetRating func(rating int)
OnSetFavorite func(favorite bool)
OnAddToPlaylist func()
OnShare func()
}
func NewNowPlayingCard() *NowPlayingCard {
n := &NowPlayingCard{
trackName: widget.NewHyperlink("", nil),
trackName: NewOptionHyperlink(),
artistName: NewMultiHyperlink(),
albumName: widget.NewHyperlink("", nil),
}
n.ExtendBaseWidget(n)
n.cover = NewImagePlaceholder(myTheme.TracksIcon, 85)
n.cover.OnTapped = n.onShowCoverImage
n.cover.OnTappedSecondary = n.showMenu
n.cover.ScaleMode = canvas.ImageScaleFastest
n.cover.Hidden = true
n.trackName.Hidden = true
n.albumName.Hidden = true
n.albumName.Truncation = fyne.TextTruncateEllipsis
n.trackName.Truncation = fyne.TextTruncateEllipsis
n.trackName.TextStyle.Bold = true
n.trackName.SetTextStyle(fyne.TextStyle{Bold: true})
n.trackName.OnShowMenu = n.showMenu
n.albumName.OnTapped = n.onAlbumNameTapped
n.artistName.OnTapped = n.onArtistNameTapped
n.trackName.OnTapped = n.onTrackNameTapped
n.trackName.SetOnTapped(n.onTrackNameTapped)
return n
}
@@ -109,6 +109,12 @@ func (n *NowPlayingCard) onAddToPlaylist() {
}
}
func (n *NowPlayingCard) onShare() {
if n.OnShare != nil {
n.OnShare()
}
}
func (n *NowPlayingCard) CreateRenderer() fyne.WidgetRenderer {
c := container.New(&layout.CustomPaddedLayout{LeftPadding: -4},
container.NewBorder(nil, nil, n.cover, nil,
@@ -137,7 +143,8 @@ func (n *NowPlayingCard) Update(track mediaprovider.MediaItem) {
n.cover.PlaceholderIcon = myTheme.RadioIcon
}
}
n.trackName.Hidden = n.trackName.Text == ""
n.trackName.Hidden = n.trackName.Text() == ""
n.trackName.SetMenuBtnEnabled(n.cover.PlaceholderIcon != myTheme.RadioIcon)
n.artistName.Hidden = len(n.artistName.Segments) == 0
n.albumName.Hidden = n.albumName.Text == ""
n.Refresh()
@@ -147,7 +154,7 @@ func (n *NowPlayingCard) SetImage(cover image.Image) {
n.cover.SetImage(cover, true)
}
func (n *NowPlayingCard) showMenu(e *fyne.PointEvent) {
func (n *NowPlayingCard) showMenu(btnPos fyne.Position) {
if n.menu == nil {
n.ratingMenu = util.NewRatingSubmenu(n.onSetRating)
favorite := fyne.NewMenuItem("Set favorite", func() { n.onSetFavorite(true) })
@@ -156,10 +163,15 @@ func (n *NowPlayingCard) showMenu(e *fyne.PointEvent) {
unfavorite.Icon = myTheme.NotFavoriteIcon
playlist := fyne.NewMenuItem("Add to playlist...", func() { n.onAddToPlaylist() })
playlist.Icon = myTheme.PlaylistIcon
share := fyne.NewMenuItem("Share...", func() { n.onShare() })
share.Icon = myTheme.ShareIcon
m := fyne.NewMenu("", favorite, unfavorite, n.ratingMenu, playlist)
m := fyne.NewMenu("", favorite, unfavorite, n.ratingMenu, playlist, share)
n.menu = widget.NewPopUpMenu(m, fyne.CurrentApp().Driver().CanvasForObject(n))
}
menuSize := n.menu.MinSize()
n.ratingMenu.Disabled = n.DisableRating
n.menu.ShowAtPosition(e.AbsolutePosition)
btnPos.Y -= (menuSize.Height + theme.Padding()*3)
btnPos.X -= menuSize.Width / 2
n.menu.ShowAtPosition(btnPos)
}
+106
View File
@@ -0,0 +1,106 @@
package widgets
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
// OptionHyperlink is a widget that displays a "vertical dots"/"more" button
// to the right of the text, which can show a menu.
type OptionHyperlink struct {
widget.BaseWidget
h *widget.Hyperlink
b *IconButton
OnShowMenu func(btnPos fyne.Position)
layout optionHyperlinkLayout
}
func NewOptionHyperlink() *OptionHyperlink {
o := &OptionHyperlink{
h: widget.NewHyperlink("", nil),
}
o.h.Truncation = fyne.TextTruncateEllipsis
o.b = NewIconButton(theme.MoreVerticalIcon(), func() {
if o.OnShowMenu != nil {
o.OnShowMenu(fyne.CurrentApp().Driver().AbsolutePositionForObject(o.b))
}
})
o.b.IconSize = IconButtonSizeSmaller
o.ExtendBaseWidget(o)
return o
}
func (o *OptionHyperlink) SetText(text string) {
o.h.SetText(text)
o.updatePreferredWidth()
o.BaseWidget.Refresh()
}
func (o *OptionHyperlink) Text() string {
return o.h.Text
}
func (o *OptionHyperlink) SetTextStyle(style fyne.TextStyle) {
o.h.TextStyle = style
o.updatePreferredWidth()
o.BaseWidget.Refresh()
}
func (o *OptionHyperlink) SetOnTapped(f func()) {
o.h.OnTapped = f
}
func (o *OptionHyperlink) SetMenuBtnEnabled(enabled bool) {
o.b.Hidden = !enabled
}
func (o *OptionHyperlink) updatePreferredWidth() {
var h widget.Hyperlink
h.Text = o.Text()
h.TextStyle = o.h.TextStyle
o.layout.preferredWidth = h.MinSize().Width + theme.Padding()
}
func (o *OptionHyperlink) CreateRenderer() fyne.WidgetRenderer {
return widget.NewSimpleRenderer(
container.New(&o.layout, o.h, o.b),
)
}
var _ fyne.Layout = (*optionHyperlinkLayout)(nil)
type optionHyperlinkLayout struct {
preferredWidth float32
}
func (o *optionHyperlinkLayout) MinSize(objects []fyne.CanvasObject) fyne.Size {
var minSize fyne.Size
for _, obj := range objects {
if !obj.Visible() {
continue
}
ms := obj.MinSize()
minSize.Height = fyne.Max(ms.Height, minSize.Height)
minSize.Width += ms.Width
}
return minSize
}
// only supports the two objects
func (o *optionHyperlinkLayout) Layout(objects []fyne.CanvasObject, size fyne.Size) {
if !objects[1].Visible() {
objects[0].Move(fyne.NewPos(0, 0))
objects[0].Resize(size)
return
}
btnWidth := objects[1].MinSize().Width
hypWidth := fyne.Min(o.preferredWidth, size.Width-btnWidth)
objects[0].Resize(fyne.NewSize(hypWidth, size.Height))
objects[0].Move(fyne.NewPos(0, 0))
objects[1].Resize(fyne.NewSize(btnWidth, size.Height))
objects[1].Move(fyne.NewPos(hypWidth-theme.Padding()*2, 0))
}