From cb4329cf0849e4f08388877b4a4012374e82a5a3 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 16 Dec 2023 15:03:22 -0800 Subject: [PATCH] Display release types in album page --- ui/browsing/albumpage.go | 32 +++++++++++++++++------ ui/dialogs/quicksearch.go | 2 +- ui/dialogs/settingsdialog.go | 10 +++----- ui/util/util.go | 49 ++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/ui/browsing/albumpage.go b/ui/browsing/albumpage.go index f27e1a3..b6f7c39 100644 --- a/ui/browsing/albumpage.go +++ b/ui/browsing/albumpage.go @@ -170,11 +170,13 @@ type AlbumPageHeader struct { page *AlbumPage - cover *widgets.ImagePlaceholder - titleLabel *widget.RichText - artistLabel *widgets.MultiHyperlink - genreLabel *widgets.MultiHyperlink - miscLabel *widget.Label + cover *widgets.ImagePlaceholder + titleLabel *widget.RichText + releaseTypeLabel *widget.RichText + artistLabel *widgets.MultiHyperlink + artistLabelSpace *util.HSpace // TODO: remove when no longer needed + genreLabel *widgets.MultiHyperlink + miscLabel *widget.Label toggleFavButton *widgets.FavoriteButton @@ -196,10 +198,15 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader { a.titleLabel.Segments[0].(*widget.TextSegment).Style = widget.RichTextStyle{ SizeName: theme.SizeNameHeadingText, } + a.releaseTypeLabel = widget.NewRichText( + &widget.TextSegment{Text: "Album", Style: util.BoldRichTextStyle}, + &widget.TextSegment{Text: " by", Style: widget.RichTextStyle{Inline: true}}, + ) a.artistLabel = widgets.NewMultiHyperlink() a.artistLabel.OnTapped = func(id string) { a.page.contr.NavigateTo(controller.ArtistRoute(id)) } + a.artistLabelSpace = util.NewHSpace(0) // updated in Update a.genreLabel = widgets.NewMultiHyperlink() a.genreLabel.OnTapped = func(genre string) { a.page.contr.NavigateTo(controller.GenreRoute(genre)) @@ -237,13 +244,21 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader { } a.toggleFavButton = widgets.NewFavoriteButton(func() { go a.toggleFavorited() }) - // Todo: there's got to be a way to make this less convoluted. Custom layout? + // TODO: Create a nicer custom layout to set this up properly + // OR once TODO in MultiHyperlink to use RichText as a provider is solved, + // extend MultiHyperlink to support prepending rich text segments and + // don't use two separate widgets here at all. + // n.b. cannot place MultiHyperlink in a HBox or it collapses in width + artistReleaseTypeLine := container.NewStack( + a.releaseTypeLabel, + container.NewBorder(nil, nil, a.artistLabelSpace, nil, a.artistLabel)) + // TODO: there's got to be a way to make this less convoluted. Custom layout? a.container = util.AddHeaderBackground( container.NewBorder(nil, nil, a.cover, nil, container.New(&layouts.VboxCustomPadding{ExtraPad: -10}, a.titleLabel, container.NewVBox( - container.New(&layouts.VboxCustomPadding{ExtraPad: -12}, a.artistLabel, a.genreLabel, a.miscLabel), + container.New(&layouts.VboxCustomPadding{ExtraPad: -12}, artistReleaseTypeLine, a.genreLabel, a.miscLabel), container.NewVBox( container.NewHBox(util.NewHSpace(2), playButton, shuffleBtn, menuBtn), container.NewHBox(util.NewHSpace(2), a.toggleFavButton), @@ -262,6 +277,9 @@ func (a *AlbumPageHeader) Update(album *mediaprovider.AlbumWithTracks, im *backe a.albumID = album.ID a.coverID = album.CoverArtID a.titleLabel.Segments[0].(*widget.TextSegment).Text = album.Name + a.releaseTypeLabel.Segments[0].(*widget.TextSegment).Text = util.DisplayReleaseType(album.ReleaseTypes) + a.releaseTypeLabel.Refresh() // needed so MinSize returns correct width below + a.artistLabelSpace.Width = a.releaseTypeLabel.MinSize().Width - 16 a.artistLabel.BuildSegments(album.ArtistNames, album.ArtistIDs) a.genreLabel.BuildSegments(album.Genres, album.Genres) a.miscLabel.SetText(formatMiscLabelStr(album)) diff --git a/ui/dialogs/quicksearch.go b/ui/dialogs/quicksearch.go index 9dccd74..0a33bab 100644 --- a/ui/dialogs/quicksearch.go +++ b/ui/dialogs/quicksearch.go @@ -74,7 +74,7 @@ func NewQuickSearch(mp mediaprovider.MediaProvider, im util.ImageFetcher) *Quick ) dismissBtn := widget.NewButton("Close", q.onDismiss) - title := widget.NewRichText(&widget.TextSegment{Text: "Quick Search", Style: boldStyle}) + title := widget.NewRichText(&widget.TextSegment{Text: "Quick Search", Style: util.BoldRichTextStyle}) title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter q.content = container.NewBorder( container.NewVBox(title, se), diff --git a/ui/dialogs/settingsdialog.go b/ui/dialogs/settingsdialog.go index ada8961..91477e9 100644 --- a/ui/dialogs/settingsdialog.go +++ b/ui/dialogs/settingsdialog.go @@ -26,8 +26,6 @@ import ( "fyne.io/fyne/v2/widget" ) -var boldStyle = widget.RichTextStyle{TextStyle: fyne.TextStyle{Bold: true}} - type SettingsDialog struct { widget.BaseWidget @@ -236,7 +234,7 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { container.NewHBox(systemTrayEnable, closeToTray), s.newSectionSeparator(), - widget.NewRichText(&widget.TextSegment{Text: "Scrobbling", Style: boldStyle}), + widget.NewRichText(&widget.TextSegment{Text: "Scrobbling", Style: util.BoldRichTextStyle}), scrobbleEnabled, container.NewHBox( widget.NewLabel("Scrobble when"), @@ -339,7 +337,7 @@ func (s *SettingsDialog) createPlaybackTab() *container.TabItem { )), s.newSectionSeparator(), - widget.NewRichText(&widget.TextSegment{Text: "ReplayGain", Style: boldStyle}), + widget.NewRichText(&widget.TextSegment{Text: "ReplayGain", Style: util.BoldRichTextStyle}), container.New(layout.NewFormLayout(), widget.NewLabel("ReplayGain mode"), container.NewGridWithColumns(2, replayGainSelect), widget.NewLabel("ReplayGain preamp"), container.NewHBox(preampGain, widget.NewLabel("dB")), @@ -423,10 +421,10 @@ func (s *SettingsDialog) createExperimentalTab(window fyne.Window) *container.Ta return container.NewTabItem("Experimental", container.NewVBox( warningLabel, s.newSectionSeparator(), - widget.NewRichText(&widget.TextSegment{Text: "UI Scaling", Style: boldStyle}), + widget.NewRichText(&widget.TextSegment{Text: "UI Scaling", Style: util.BoldRichTextStyle}), uiScaleRadio, s.newSectionSeparator(), - widget.NewRichText(&widget.TextSegment{Text: "Application Font", Style: boldStyle}), + widget.NewRichText(&widget.TextSegment{Text: "Application Font", Style: util.BoldRichTextStyle}), container.New(layout.NewFormLayout(), widget.NewLabel("Normal font"), container.NewBorder(nil, nil, nil, normalFontBrowse, normalFontEntry), widget.NewLabel("Bold font"), container.NewBorder(nil, nil, nil, boldFontBrowse, boldFontEntry), diff --git a/ui/util/util.go b/ui/util/util.go index 35c3510..643c02e 100644 --- a/ui/util/util.go +++ b/ui/util/util.go @@ -14,11 +14,14 @@ import ( "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" + "github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/ui/layouts" myTheme "github.com/dweymouth/supersonic/ui/theme" "golang.org/x/net/html" ) +var BoldRichTextStyle = widget.RichTextStyle{TextStyle: fyne.TextStyle{Bold: true}, Inline: true} + func SecondsToTimeString(s float64) string { if s < 0 { s = 0 @@ -109,6 +112,52 @@ func PlaintextFromHTMLString(s string) string { return text } +func DisplayReleaseType(releaseTypes mediaprovider.ReleaseTypes) string { + baseType := "Album" + switch { + case releaseTypes&mediaprovider.ReleaseTypeAudiobook > 0: + baseType = "Audiobook" + case releaseTypes&mediaprovider.ReleaseTypeAudioDrama > 0: + baseType = "Audio Drama" + case releaseTypes&mediaprovider.ReleaseTypeBroadcast > 0: + baseType = "Broadcast" + case releaseTypes&mediaprovider.ReleaseTypeDJMix > 0: + baseType = "DJ-Mix" + case releaseTypes&mediaprovider.ReleaseTypeEP > 0: + baseType = "EP" + case releaseTypes&mediaprovider.ReleaseTypeFieldRecording > 0: + baseType = "Field Recording" + case releaseTypes&mediaprovider.ReleaseTypeInterview > 0: + baseType = "Interview" + case releaseTypes&mediaprovider.ReleaseTypeMixtape > 0: + baseType = "Mixtape" + case releaseTypes&mediaprovider.ReleaseTypeSingle > 0: + baseType = "Single" + case releaseTypes&mediaprovider.ReleaseTypeSoundtrack > 0: + baseType = "Soundtrack" + } + + var modifiers []string + if releaseTypes&mediaprovider.ReleaseTypeLive > 0 { + modifiers = append(modifiers, "Live") + } + if releaseTypes&mediaprovider.ReleaseTypeDemo > 0 { + modifiers = append(modifiers, "Demo") + } + if releaseTypes&mediaprovider.ReleaseTypeRemix > 0 { + modifiers = append(modifiers, "Remix") + } + if releaseTypes&mediaprovider.ReleaseTypeSpokenWord > 0 { + modifiers = append(modifiers, "Spoken Word") + } + if releaseTypes&mediaprovider.ReleaseTypeCompilation > 0 { + modifiers = append(modifiers, "Compilation") + } + + modifiers = append(modifiers, baseType) + return strings.Join(modifiers, " ") +} + func NewRatingSubmenu(onSetRating func(int)) *fyne.MenuItem { newRatingMenuItem := func(rating int) *fyne.MenuItem { label := "(none)"