Merge pull request #211 from natilou/album-info

Add UI for viewing the album info returned by Subsonic getAlbumInfo API
This commit is contained in:
Drew Weymouth
2023-06-27 09:32:13 -07:00
committed by GitHub
6 changed files with 163 additions and 1 deletions
+2
View File
@@ -39,6 +39,8 @@ type MediaProvider interface {
GetAlbum(albumID string) (*AlbumWithTracks, error)
GetAlbumInfo(albumID string) (*AlbumInfo, error)
GetArtist(artistID string) (*ArtistWithAlbums, error)
GetArtistInfo(artistID string) (*ArtistInfo, error)
+6
View File
@@ -18,6 +18,12 @@ type AlbumWithTracks struct {
Tracks []*Track
}
type AlbumInfo struct {
Notes string
LastFmUrl string
MusicBrainzID string
}
type Artist struct {
ID string
CoverArtID string
@@ -59,6 +59,19 @@ func (s *subsonicMediaProvider) GetAlbum(albumID string) (*mediaprovider.AlbumWi
return album, nil
}
func (s *subsonicMediaProvider) GetAlbumInfo(albumID string) (*mediaprovider.AlbumInfo, error) {
al, err := s.client.GetAlbumInfo(albumID)
if err != nil {
return nil, err
}
album := &mediaprovider.AlbumInfo{
Notes: al.Notes,
LastFmUrl: al.LastFmUrl,
MusicBrainzID: al.MusicBrainzID,
}
return album, nil
}
func (s *subsonicMediaProvider) GetArtist(artistID string) (*mediaprovider.ArtistWithAlbums, error) {
ar, err := s.client.GetArtist(artistID)
if err != nil {
+3 -1
View File
@@ -203,7 +203,9 @@ func NewAlbumPageHeader(page *AlbumPage) *AlbumPageHeader {
}),
fyne.NewMenuItem("Download...", func() {
a.page.contr.ShowDownloadDialog(a.page.tracks, a.titleLabel.String())
}),
fyne.NewMenuItem("Show Info...", func() {
a.page.contr.ShowAlbumInfoDialog(a.albumID, a.titleLabel.String(), a.cover.Image.Image)
}))
pop = widget.NewPopUpMenu(menu, fyne.CurrentApp().Driver().CanvasForObject(a))
}
+19
View File
@@ -651,3 +651,22 @@ func (c *Controller) sendNotification(title, content string) {
Content: content,
})
}
func (c *Controller) ShowAlbumInfoDialog(albumID, albumName string, albumCover image.Image) {
go func() {
albumInfo, err := c.App.ServerManager.Server.GetAlbumInfo(albumID)
if err != nil {
log.Print("Error getting album info: ", err)
return
}
dlg := dialogs.NewAlbumInfoDialog(albumInfo, albumName, albumCover)
pop := widget.NewModalPopUp(dlg, c.MainWindow.Canvas())
dlg.OnDismiss = func() {
pop.Hide()
c.doModalClosed()
}
c.ClosePopUpOnEscape(pop)
c.haveModal = true
pop.Show()
}()
}
+120
View File
@@ -0,0 +1,120 @@
package dialogs
import (
"fmt"
"image"
"net/url"
"strings"
"github.com/dweymouth/supersonic/backend/mediaprovider"
"github.com/dweymouth/supersonic/ui/layouts"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
const musicBrainzReleaseUrl = "https://musicbrainz.org/release"
type AlbumInfoDialog struct {
widget.BaseWidget
OnDismiss func()
content fyne.CanvasObject
}
func NewAlbumInfoDialog(albumInfo *mediaprovider.AlbumInfo, albumName string, albumCover image.Image) *AlbumInfoDialog {
a := &AlbumInfoDialog{}
a.ExtendBaseWidget(a)
a.content = container.NewVBox(
a.buildMainContainer(albumInfo, albumName, albumCover),
widget.NewSeparator(),
container.NewHBox(
layout.NewSpacer(),
widget.NewButton("Close", func() {
if a.OnDismiss != nil {
a.OnDismiss()
}
}),
),
)
return a
}
func (a *AlbumInfoDialog) MinSize() fyne.Size {
return fyne.NewSize(550, a.BaseWidget.MinSize().Height)
}
func (a *AlbumInfoDialog) buildMainContainer(albumInfo *mediaprovider.AlbumInfo, albumName string, albumCover image.Image) *fyne.Container {
iconImage := canvas.NewImageFromImage(albumCover)
iconImage.FillMode = canvas.ImageFillContain
iconImage.SetMinSize(fyne.NewSize(100, 100))
title := widget.NewRichTextWithText(albumName)
title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true
title.Segments[0].(*widget.TextSegment).Style.SizeName = theme.SizeNameSubHeadingText
title.Segments[0].(*widget.TextSegment).Style.Alignment = fyne.TextAlignCenter
infoContent := widget.NewLabel("Album info not available")
if albumInfo.Notes != "" {
infoContent = a.infoLabel(albumInfo.Notes)
}
urlContainer := a.buildUrlContainer(albumInfo.LastFmUrl, albumInfo.MusicBrainzID)
return container.New(
&layouts.MaxPadLayout{PadLeft: 15, PadRight: 10, PadTop: 15, PadBottom: 10},
container.NewVBox(
iconImage,
title,
infoContent,
urlContainer,
),
)
}
func (a *AlbumInfoDialog) CreateRenderer() fyne.WidgetRenderer {
return widget.NewSimpleRenderer(a.content)
}
func (a *AlbumInfoDialog) infoLabel(info string) *widget.Label {
last := strings.LastIndex(info, "<a href")
infoWithoutLink := strings.TrimSpace(info[:last])
lbl := widget.NewLabel(infoWithoutLink)
lbl.Wrapping = fyne.TextWrapWord
lbl.Alignment = fyne.TextAlignLeading
return lbl
}
func (a *AlbumInfoDialog) buildUrlContainer(lastFm, musicBrainzID string) *fyne.Container {
urls := make([]*widget.Hyperlink, 0)
if lastFm != "" {
if lastFmUrl, err := url.Parse(lastFm); err == nil {
urls = append(urls, widget.NewHyperlink("Last.fm", lastFmUrl))
}
}
if musicBrainzID != "" {
if musicBrainzUrl, err := url.Parse(fmt.Sprintf("%s/%s", musicBrainzReleaseUrl, musicBrainzID)); err == nil {
urls = append(urls, widget.NewHyperlink("MusicBrainz", musicBrainzUrl))
}
}
urlContainer := container.New(&layouts.HboxCustomPadding{DisableThemePad: true, ExtraPad: -10})
for index, url := range urls {
if index > 0 {
urlContainer.Add(widget.NewLabel("·"))
}
urlContainer.Add(url)
}
return container.NewCenter(urlContainer)
}