Fix #774: Make headers for Album, Artist, Playlist page collapsible / compact
This commit is contained in:
@@ -70,6 +70,7 @@ type AppConfig struct {
|
|||||||
|
|
||||||
type AlbumPageConfig struct {
|
type AlbumPageConfig struct {
|
||||||
TracklistColumns []string
|
TracklistColumns []string
|
||||||
|
CompactHeader bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// shared between Albums and Genre pages
|
// shared between Albums and Genre pages
|
||||||
@@ -84,6 +85,7 @@ type ArtistPageConfig struct {
|
|||||||
InitialView string
|
InitialView string
|
||||||
DiscographySort string
|
DiscographySort string
|
||||||
TracklistColumns []string
|
TracklistColumns []string
|
||||||
|
CompactHeader bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArtistsPageConfig struct {
|
type ArtistsPageConfig struct {
|
||||||
@@ -102,6 +104,7 @@ type GridViewConfig struct {
|
|||||||
|
|
||||||
type PlaylistPageConfig struct {
|
type PlaylistPageConfig struct {
|
||||||
TracklistColumns []string
|
TracklistColumns []string
|
||||||
|
CompactHeader bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlaylistsPageConfig struct {
|
type PlaylistsPageConfig struct {
|
||||||
|
|||||||
+63
-19
@@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
"fyne.io/fyne/v2/lang"
|
"fyne.io/fyne/v2/lang"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
@@ -85,12 +86,12 @@ func newAlbumPage(
|
|||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
if h := pool.Obtain(util.WidgetTypeAlbumPageHeader); h != nil {
|
if h := pool.Obtain(util.WidgetTypeAlbumPageHeader); h != nil {
|
||||||
a.header = h.(*AlbumPageHeader)
|
a.header = h.(*AlbumPageHeader)
|
||||||
a.header.page = a
|
|
||||||
a.header.Clear()
|
a.header.Clear()
|
||||||
} else {
|
} else {
|
||||||
a.header = NewAlbumPageHeader(a)
|
a.header = NewAlbumPageHeader(a)
|
||||||
}
|
}
|
||||||
a.header.page = a
|
a.header.page = a
|
||||||
|
a.header.Compact = a.cfg.CompactHeader
|
||||||
if t := a.pool.Obtain(util.WidgetTypeCompactTracklist); t != nil {
|
if t := a.pool.Obtain(util.WidgetTypeCompactTracklist); t != nil {
|
||||||
a.tracklist = t.(*widgets.Tracklist)
|
a.tracklist = t.(*widgets.Tracklist)
|
||||||
a.tracklist.Reset()
|
a.tracklist.Reset()
|
||||||
@@ -203,19 +204,23 @@ func (a *AlbumPage) load() {
|
|||||||
type AlbumPageHeader struct {
|
type AlbumPageHeader struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
|
Compact bool
|
||||||
|
|
||||||
albumID string
|
albumID string
|
||||||
coverID string
|
coverID string
|
||||||
|
|
||||||
page *AlbumPage
|
page *AlbumPage
|
||||||
|
|
||||||
cover *widgets.ImagePlaceholder
|
cover *widgets.ImagePlaceholder
|
||||||
titleLabel *widget.RichText
|
titleLabel *widget.RichText
|
||||||
releaseTypeLabel *widget.RichText
|
releaseTypeLabel *widget.RichText
|
||||||
artistLabel *widgets.MultiHyperlink
|
artistLabel *widgets.MultiHyperlink
|
||||||
artistLabelSpace *util.Space // TODO: remove when no longer needed
|
artistLabelSpace *util.Space // TODO: remove when no longer needed
|
||||||
genreLabel *widgets.MultiHyperlink
|
genreLabel *widgets.MultiHyperlink
|
||||||
miscLabel *widget.Label
|
miscLabel *widget.Label
|
||||||
shareMenuItem *fyne.MenuItem
|
shareMenuItem *fyne.MenuItem
|
||||||
|
collapseBtn *widgets.HeaderCollapseButton
|
||||||
|
artistReleaseTypeLine *fyne.Container
|
||||||
|
|
||||||
toggleFavButton *widgets.FavoriteButton
|
toggleFavButton *widgets.FavoriteButton
|
||||||
|
|
||||||
@@ -229,7 +234,7 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
|||||||
// be directly captured in a closure throughout this function!
|
// be directly captured in a closure throughout this function!
|
||||||
a := &AlbumPageHeader{page: page}
|
a := &AlbumPageHeader{page: page}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.cover = widgets.NewImagePlaceholder(myTheme.AlbumIcon, 225)
|
a.cover = widgets.NewImagePlaceholder(myTheme.AlbumIcon, myTheme.HeaderImageSize)
|
||||||
a.cover.OnTapped = func(*fyne.PointEvent) { go a.showPopUpCover() }
|
a.cover.OnTapped = func(*fyne.PointEvent) { go a.showPopUpCover() }
|
||||||
|
|
||||||
a.titleLabel = widget.NewRichTextWithText("")
|
a.titleLabel = widget.NewRichTextWithText("")
|
||||||
@@ -297,28 +302,39 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
|
|||||||
}
|
}
|
||||||
a.toggleFavButton = widgets.NewFavoriteButton(func() { go a.toggleFavorited() })
|
a.toggleFavButton = widgets.NewFavoriteButton(func() { go a.toggleFavorited() })
|
||||||
|
|
||||||
|
a.collapseBtn = widgets.NewHeaderCollapseButton(func() {
|
||||||
|
a.Compact = !a.Compact
|
||||||
|
a.page.cfg.CompactHeader = a.Compact
|
||||||
|
a.page.Refresh()
|
||||||
|
})
|
||||||
|
a.collapseBtn.Hidden = true
|
||||||
|
|
||||||
// TODO: Create a nicer custom layout to set this up properly
|
// TODO: Create a nicer custom layout to set this up properly
|
||||||
// OR once TODO in MultiHyperlink to use RichText as a provider is solved,
|
// OR once TODO in MultiHyperlink to use RichText as a provider is solved,
|
||||||
// extend MultiHyperlink to support prepending rich text segments and
|
// extend MultiHyperlink to support prepending rich text segments and
|
||||||
// don't use two separate widgets here at all.
|
// don't use two separate widgets here at all.
|
||||||
// n.b. cannot place MultiHyperlink in a HBox or it collapses in width
|
// n.b. cannot place MultiHyperlink in a HBox or it collapses in width
|
||||||
artistReleaseTypeLine := container.NewStack(
|
a.artistReleaseTypeLine = container.NewStack(
|
||||||
a.releaseTypeLabel,
|
a.releaseTypeLabel,
|
||||||
container.NewBorder(nil, nil, a.artistLabelSpace, nil, a.artistLabel))
|
container.NewBorder(nil, nil, a.artistLabelSpace, nil, a.artistLabel))
|
||||||
// TODO: there's got to be a way to make this less convoluted. Custom layout?
|
// TODO: there's got to be a way to make this less convoluted. Custom layout?
|
||||||
a.container = util.AddHeaderBackground(
|
a.container = util.AddHeaderBackground(
|
||||||
container.NewBorder(nil, nil, a.cover, nil,
|
container.NewStack(
|
||||||
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
container.NewBorder(nil, nil, a.cover, nil,
|
||||||
a.titleLabel,
|
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
||||||
container.NewVBox(
|
a.titleLabel,
|
||||||
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-12), artistReleaseTypeLine, a.genreLabel, a.miscLabel),
|
|
||||||
container.NewVBox(
|
container.NewVBox(
|
||||||
container.NewHBox(util.NewHSpace(2), playButton, shuffleBtn, menuBtn),
|
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-12), a.artistReleaseTypeLine, a.genreLabel, a.miscLabel),
|
||||||
container.NewHBox(util.NewHSpace(2), a.toggleFavButton),
|
container.NewVBox(
|
||||||
|
container.NewHBox(util.NewHSpace(2), playButton, shuffleBtn, menuBtn),
|
||||||
|
container.NewHBox(util.NewHSpace(2), a.toggleFavButton),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
))
|
container.NewVBox(container.NewHBox(layout.NewSpacer(), a.collapseBtn)),
|
||||||
|
),
|
||||||
|
)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,6 +385,34 @@ func (a *AlbumPageHeader) toggleFavorited() {
|
|||||||
a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited)
|
a.page.mp.SetFavorite(params, a.toggleFavButton.IsFavorited)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ desktop.Hoverable = (*AlbumPageHeader)(nil)
|
||||||
|
|
||||||
|
func (a *AlbumPageHeader) MouseIn(e *desktop.MouseEvent) {
|
||||||
|
a.collapseBtn.Show()
|
||||||
|
a.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlbumPageHeader) MouseOut() {
|
||||||
|
a.collapseBtn.HideIfNotMousedIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlbumPageHeader) MouseMoved(*desktop.MouseEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlbumPageHeader) Refresh() {
|
||||||
|
a.artistReleaseTypeLine.Hidden = a.Compact
|
||||||
|
a.genreLabel.Hidden = a.Compact
|
||||||
|
a.miscLabel.Hidden = a.Compact
|
||||||
|
a.toggleFavButton.Hidden = a.Compact
|
||||||
|
a.collapseBtn.Collapsed = a.Compact
|
||||||
|
if a.Compact {
|
||||||
|
a.cover.SetMinSize(fyne.NewSquareSize(myTheme.CompactHeaderImageSize))
|
||||||
|
} else {
|
||||||
|
a.cover.SetMinSize(fyne.NewSquareSize(myTheme.HeaderImageSize))
|
||||||
|
}
|
||||||
|
a.BaseWidget.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
// should be called asynchronously
|
// should be called asynchronously
|
||||||
func (a *AlbumPageHeader) showPopUpCover() {
|
func (a *AlbumPageHeader) showPopUpCover() {
|
||||||
if a.fullSizeCoverFetching {
|
if a.fullSizeCoverFetching {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
"fyne.io/fyne/v2/lang"
|
"fyne.io/fyne/v2/lang"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
@@ -97,6 +98,7 @@ func newArtistPage(state artistPageState) *ArtistPage {
|
|||||||
a.header = NewArtistPageHeader(a)
|
a.header = NewArtistPageHeader(a)
|
||||||
}
|
}
|
||||||
a.header.artistPage = a
|
a.header.artistPage = a
|
||||||
|
a.header.Compact = a.cfg.CompactHeader
|
||||||
if img, ok := state.im.GetCachedArtistImage(state.artistID); ok {
|
if img, ok := state.im.GetCachedArtistImage(state.artistID); ok {
|
||||||
a.header.artistImage.SetImage(img, true /*tappable*/)
|
a.header.artistImage.SetImage(img, true /*tappable*/)
|
||||||
}
|
}
|
||||||
@@ -473,6 +475,8 @@ const artistBioNotAvailableKey = "Artist biography not available."
|
|||||||
type ArtistPageHeader struct {
|
type ArtistPageHeader struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
|
Compact bool
|
||||||
|
|
||||||
artistID string
|
artistID string
|
||||||
artistPage *ArtistPage
|
artistPage *ArtistPage
|
||||||
artistImage *widgets.ImagePlaceholder
|
artistImage *widgets.ImagePlaceholder
|
||||||
@@ -485,6 +489,7 @@ type ArtistPageHeader struct {
|
|||||||
playRadioBtn *widget.Button
|
playRadioBtn *widget.Button
|
||||||
menuBtn *widget.Button
|
menuBtn *widget.Button
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
|
collapseBtn *widgets.HeaderCollapseButton
|
||||||
fullSizeCoverFetching bool
|
fullSizeCoverFetching bool
|
||||||
// shareMenuItem *fyne.MenuItem
|
// shareMenuItem *fyne.MenuItem
|
||||||
}
|
}
|
||||||
@@ -501,7 +506,7 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader {
|
|||||||
a.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
a.titleDisp.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
||||||
SizeName: theme.SizeNameHeadingText,
|
SizeName: theme.SizeNameHeadingText,
|
||||||
}
|
}
|
||||||
a.artistImage = widgets.NewImagePlaceholder(myTheme.ArtistIcon, 225)
|
a.artistImage = widgets.NewImagePlaceholder(myTheme.ArtistIcon, myTheme.HeaderImageSize)
|
||||||
a.artistImage.OnTapped = func(*fyne.PointEvent) { a.showPopUpCover() }
|
a.artistImage.OnTapped = func(*fyne.PointEvent) { a.showPopUpCover() }
|
||||||
a.favoriteBtn = widgets.NewFavoriteButton(func() { go a.toggleFavorited() })
|
a.favoriteBtn = widgets.NewFavoriteButton(func() { go a.toggleFavorited() })
|
||||||
a.playBtn = widget.NewButtonWithIcon(lang.L("Play Discography"), theme.MediaPlayIcon(), func() {
|
a.playBtn = widget.NewButtonWithIcon(lang.L("Play Discography"), theme.MediaPlayIcon(), func() {
|
||||||
@@ -546,6 +551,12 @@ func NewArtistPageHeader(page *ArtistPage) *ArtistPageHeader {
|
|||||||
|
|
||||||
a.biographyDisp.Wrapping = fyne.TextWrapWord
|
a.biographyDisp.Wrapping = fyne.TextWrapWord
|
||||||
a.biographyDisp.Truncation = fyne.TextTruncateEllipsis
|
a.biographyDisp.Truncation = fyne.TextTruncateEllipsis
|
||||||
|
a.collapseBtn = widgets.NewHeaderCollapseButton(func() {
|
||||||
|
a.Compact = !a.Compact
|
||||||
|
a.artistPage.cfg.CompactHeader = a.Compact
|
||||||
|
a.artistPage.Refresh()
|
||||||
|
})
|
||||||
|
a.collapseBtn.Hidden = true
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
a.createContainer()
|
a.createContainer()
|
||||||
return a
|
return a
|
||||||
@@ -636,6 +647,32 @@ func (a *ArtistPageHeader) UpdateInfo(info *mediaprovider.ArtistInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ desktop.Hoverable = (*ArtistPageHeader)(nil)
|
||||||
|
|
||||||
|
func (a *ArtistPageHeader) MouseIn(*desktop.MouseEvent) {
|
||||||
|
a.collapseBtn.Show()
|
||||||
|
a.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPageHeader) MouseOut() {
|
||||||
|
a.collapseBtn.HideIfNotMousedIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPageHeader) MouseMoved(*desktop.MouseEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ArtistPageHeader) Refresh() {
|
||||||
|
a.biographyDisp.Hidden = a.Compact
|
||||||
|
a.similarArtists.Hidden = a.Compact
|
||||||
|
a.collapseBtn.Collapsed = a.Compact
|
||||||
|
if a.Compact {
|
||||||
|
a.artistImage.SetMinSize(fyne.NewSquareSize(myTheme.CompactHeaderImageSize))
|
||||||
|
} else {
|
||||||
|
a.artistImage.SetMinSize(fyne.NewSquareSize(myTheme.HeaderImageSize))
|
||||||
|
}
|
||||||
|
a.BaseWidget.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
// should NOT be called asynchronously
|
// should NOT be called asynchronously
|
||||||
func (a *ArtistPageHeader) showPopUpCover() {
|
func (a *ArtistPageHeader) showPopUpCover() {
|
||||||
if a.artistImageID == "" {
|
if a.artistImageID == "" {
|
||||||
@@ -670,12 +707,16 @@ func (a *ArtistPageHeader) createContainer() {
|
|||||||
btnContainer := container.NewHBox(util.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn, a.menuBtn)
|
btnContainer := container.NewHBox(util.NewHSpace(2), a.favoriteBtn, a.playBtn, a.playRadioBtn, a.menuBtn)
|
||||||
|
|
||||||
a.container = util.AddHeaderBackground(
|
a.container = util.AddHeaderBackground(
|
||||||
container.NewBorder(nil, nil, a.artistImage, nil,
|
container.NewStack(
|
||||||
container.NewVBox(
|
container.NewBorder(nil, nil, a.artistImage, nil,
|
||||||
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
container.NewVBox(
|
||||||
a.titleDisp, a.biographyDisp, a.similarArtists),
|
container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
||||||
btnContainer),
|
a.titleDisp, a.biographyDisp, a.similarArtists),
|
||||||
))
|
btnContainer),
|
||||||
|
),
|
||||||
|
container.NewVBox(container.NewHBox(layout.NewSpacer(), a.collapseBtn)),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ArtistPageHeader) CreateRenderer() fyne.WidgetRenderer {
|
func (a *ArtistPageHeader) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
"fyne.io/fyne/v2/container"
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
"fyne.io/fyne/v2/lang"
|
"fyne.io/fyne/v2/lang"
|
||||||
"fyne.io/fyne/v2/layout"
|
"fyne.io/fyne/v2/layout"
|
||||||
"fyne.io/fyne/v2/theme"
|
"fyne.io/fyne/v2/theme"
|
||||||
@@ -76,12 +77,12 @@ func newPlaylistPage(
|
|||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
if h := a.widgetPool.Obtain(util.WidgetTypePlaylistPageHeader); h != nil {
|
if h := a.widgetPool.Obtain(util.WidgetTypePlaylistPageHeader); h != nil {
|
||||||
a.header = h.(*PlaylistPageHeader)
|
a.header = h.(*PlaylistPageHeader)
|
||||||
a.header.page = a
|
|
||||||
a.header.Clear()
|
a.header.Clear()
|
||||||
} else {
|
} else {
|
||||||
a.header = NewPlaylistPageHeader(a)
|
a.header = NewPlaylistPageHeader(a)
|
||||||
}
|
}
|
||||||
a.header.page = a
|
a.header.page = a
|
||||||
|
a.header.Compact = a.conf.CompactHeader
|
||||||
if tl := a.widgetPool.Obtain(util.WidgetTypeTracklist); tl != nil {
|
if tl := a.widgetPool.Obtain(util.WidgetTypeTracklist); tl != nil {
|
||||||
a.tracklist = tl.(*widgets.Tracklist)
|
a.tracklist = tl.(*widgets.Tracklist)
|
||||||
a.tracklist.Reset()
|
a.tracklist.Reset()
|
||||||
@@ -304,6 +305,8 @@ func (a *PlaylistPage) onSearched(query string) {
|
|||||||
type PlaylistPageHeader struct {
|
type PlaylistPageHeader struct {
|
||||||
widget.BaseWidget
|
widget.BaseWidget
|
||||||
|
|
||||||
|
Compact bool
|
||||||
|
|
||||||
page *PlaylistPage
|
page *PlaylistPage
|
||||||
playlistInfo *mediaprovider.PlaylistWithTracks
|
playlistInfo *mediaprovider.PlaylistWithTracks
|
||||||
image *widgets.ImagePlaceholder
|
image *widgets.ImagePlaceholder
|
||||||
@@ -314,6 +317,7 @@ type PlaylistPageHeader struct {
|
|||||||
createdAtLabel *widget.Label
|
createdAtLabel *widget.Label
|
||||||
ownerLabel *widget.Label
|
ownerLabel *widget.Label
|
||||||
trackTimeLabel *widget.Label
|
trackTimeLabel *widget.Label
|
||||||
|
collapseBtn *widgets.HeaderCollapseButton
|
||||||
|
|
||||||
fullSizeCoverFetching bool
|
fullSizeCoverFetching bool
|
||||||
|
|
||||||
@@ -326,7 +330,7 @@ func NewPlaylistPageHeader(page *PlaylistPage) *PlaylistPageHeader {
|
|||||||
a := &PlaylistPageHeader{page: page}
|
a := &PlaylistPageHeader{page: page}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
|
|
||||||
a.image = widgets.NewImagePlaceholder(myTheme.PlaylistIcon, 225)
|
a.image = widgets.NewImagePlaceholder(myTheme.PlaylistIcon, myTheme.HeaderImageSize)
|
||||||
a.image.OnTapped = func(*fyne.PointEvent) { go a.showPopUpCover() }
|
a.image.OnTapped = func(*fyne.PointEvent) { go a.showPopUpCover() }
|
||||||
a.titleLabel = util.NewTruncatingRichText()
|
a.titleLabel = util.NewTruncatingRichText()
|
||||||
a.titleLabel.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
a.titleLabel.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{
|
||||||
@@ -433,14 +437,25 @@ func NewPlaylistPageHeader(page *PlaylistPage) *PlaylistPageHeader {
|
|||||||
|
|
||||||
buttonRow = container.NewHBox(a.editButton, playButton, shuffleBtn, searchBtn, menuBtn)
|
buttonRow = container.NewHBox(a.editButton, playButton, shuffleBtn, searchBtn, menuBtn)
|
||||||
|
|
||||||
|
a.collapseBtn = widgets.NewHeaderCollapseButton(func() {
|
||||||
|
a.Compact = !a.Compact
|
||||||
|
a.page.conf.CompactHeader = a.Compact
|
||||||
|
a.page.Refresh()
|
||||||
|
})
|
||||||
|
a.collapseBtn.Hidden = true
|
||||||
|
|
||||||
a.container = util.AddHeaderBackground(
|
a.container = util.AddHeaderBackground(
|
||||||
container.NewBorder(nil, nil, a.image, nil,
|
container.NewStack(
|
||||||
container.NewVBox(a.titleLabel, container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
container.NewBorder(nil, nil, a.image, nil,
|
||||||
a.descriptionLabel,
|
container.NewVBox(a.titleLabel, container.New(layout.NewCustomPaddedVBoxLayout(theme.Padding()-10),
|
||||||
a.ownerLabel,
|
a.descriptionLabel,
|
||||||
a.trackTimeLabel),
|
a.ownerLabel,
|
||||||
buttonRow,
|
a.trackTimeLabel),
|
||||||
)))
|
buttonRow,
|
||||||
|
)),
|
||||||
|
container.NewVBox(container.NewHBox(layout.NewSpacer(), a.collapseBtn)),
|
||||||
|
),
|
||||||
|
)
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,6 +494,33 @@ func (a *PlaylistPageHeader) Update(playlist *mediaprovider.PlaylistWithTracks)
|
|||||||
a.Refresh()
|
a.Refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ desktop.Hoverable = (*PlaylistPageHeader)(nil)
|
||||||
|
|
||||||
|
func (a *PlaylistPageHeader) MouseIn(*desktop.MouseEvent) {
|
||||||
|
a.collapseBtn.Show()
|
||||||
|
a.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *PlaylistPageHeader) MouseOut() {
|
||||||
|
a.collapseBtn.HideIfNotMousedIn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *PlaylistPageHeader) MouseMoved(*desktop.MouseEvent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *PlaylistPageHeader) Refresh() {
|
||||||
|
a.descriptionLabel.Hidden = a.Compact
|
||||||
|
a.ownerLabel.Hidden = a.Compact
|
||||||
|
a.trackTimeLabel.Hidden = a.Compact
|
||||||
|
a.collapseBtn.Collapsed = a.Compact
|
||||||
|
if a.Compact {
|
||||||
|
a.image.SetMinSize(fyne.NewSquareSize(myTheme.CompactHeaderImageSize))
|
||||||
|
} else {
|
||||||
|
a.image.SetMinSize(fyne.NewSquareSize(myTheme.HeaderImageSize))
|
||||||
|
}
|
||||||
|
a.BaseWidget.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
// should be called asynchronously
|
// should be called asynchronously
|
||||||
func (a *PlaylistPageHeader) showPopUpCover() {
|
func (a *PlaylistPageHeader) showPopUpCover() {
|
||||||
if a.fullSizeCoverFetching || a.playlistInfo == nil {
|
if a.fullSizeCoverFetching || a.playlistInfo == nil {
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ const (
|
|||||||
AnimationDurationShort = canvas.DurationShort
|
AnimationDurationShort = canvas.DurationShort
|
||||||
AnimationDurationMedium = 225 * time.Millisecond
|
AnimationDurationMedium = 225 * time.Millisecond
|
||||||
AnimationDurationLong = canvas.DurationStandard
|
AnimationDurationLong = canvas.DurationStandard
|
||||||
|
|
||||||
|
HeaderImageSize = 225
|
||||||
|
CompactHeaderImageSize = 95
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/driver/desktop"
|
||||||
|
"fyne.io/fyne/v2/theme"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HeaderCollapseButton struct {
|
||||||
|
widget.Button
|
||||||
|
|
||||||
|
Collapsed bool
|
||||||
|
|
||||||
|
shouldHide bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHeaderCollapseButton(onTapped func()) *HeaderCollapseButton {
|
||||||
|
b := &HeaderCollapseButton{
|
||||||
|
Button: widget.Button{
|
||||||
|
Icon: theme.ContentRemoveIcon(),
|
||||||
|
Importance: widget.LowImportance,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
b.OnTapped = func() {
|
||||||
|
b.Collapsed = !b.Collapsed
|
||||||
|
onTapped()
|
||||||
|
}
|
||||||
|
b.ExtendBaseWidget(b)
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
// HideIfNotMousedIn hides the button after a short delay
|
||||||
|
// if the mouse is not hovering over it.
|
||||||
|
func (b *HeaderCollapseButton) HideIfNotMousedIn() {
|
||||||
|
b.shouldHide = true
|
||||||
|
fyne.Do(func() {
|
||||||
|
if b.shouldHide {
|
||||||
|
b.Hide()
|
||||||
|
b.shouldHide = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *HeaderCollapseButton) MouseIn(e *desktop.MouseEvent) {
|
||||||
|
b.shouldHide = false
|
||||||
|
b.Button.MouseIn(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *HeaderCollapseButton) MinSize() fyne.Size {
|
||||||
|
return fyne.NewSize(24, 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *HeaderCollapseButton) Refresh() {
|
||||||
|
if b.Collapsed {
|
||||||
|
b.Icon = theme.ContentAddIcon()
|
||||||
|
} else {
|
||||||
|
b.Icon = theme.ContentRemoveIcon()
|
||||||
|
}
|
||||||
|
b.Button.Refresh()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user