From bb91a0c6b4242f11976032d9de99b77326aaa7c9 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 14 Jul 2024 16:46:07 -0700 Subject: [PATCH] WIP: add track info dialog --- ui/controller/controller.go | 18 +++++++ ui/dialogs/trackinfodialog.go | 94 +++++++++++++++++++++++++++++++++++ ui/widgets/tracklist.go | 11 +++- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 ui/dialogs/trackinfodialog.go diff --git a/ui/controller/controller.go b/ui/controller/controller.go index 08f30e7..41affdc 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -146,6 +146,7 @@ func (m *Controller) connectTracklistActionsWithReplayGainMode(tracklist *widget tracklist.OnShare = func(trackID string) { go m.ShowShareDialog(trackID) } + tracklist.OnShowTrackInfo = m.ShowTrackInfoDialog tracklist.OnPlaySongRadio = func(track *mediaprovider.Track) { go func() { tracks, err := m.GetSongRadioTracks(track) @@ -858,6 +859,23 @@ func (c *Controller) ShowAlbumInfoDialog(albumID, albumName string, albumCover i }() } +func (c *Controller) ShowTrackInfoDialog(track *mediaprovider.Track) { + info := dialogs.NewTrackInfoDialog(track) + pop := widget.NewModalPopUp(info, c.MainWindow.Canvas()) + info.OnDismiss = func() { + pop.Hide() + c.doModalClosed() + } + c.ClosePopUpOnEscape(pop) + winSize := c.MainWindow.Canvas().Size() + popMin := pop.MinSize() + width := fyne.Max(700, fyne.Max(popMin.Width, winSize.Width*0.6)) + height := fyne.Max(500, fyne.Max(popMin.Height, winSize.Height*0.7)) + pop.Resize(fyne.NewSize(width, height)) + c.haveModal = true + pop.Show() +} + func (c *Controller) GetSongRadioTracks(sourceTrack *mediaprovider.Track) ([]*mediaprovider.Track, error) { radioTracks, err := c.App.ServerManager.Server.GetSongRadio(sourceTrack.ID, 100) if err != nil { diff --git a/ui/dialogs/trackinfodialog.go b/ui/dialogs/trackinfodialog.go new file mode 100644 index 0000000..e634841 --- /dev/null +++ b/ui/dialogs/trackinfodialog.go @@ -0,0 +1,94 @@ +package dialogs + +import ( + "strconv" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/layout" + "fyne.io/fyne/v2/widget" + "github.com/dweymouth/supersonic/backend/mediaprovider" + "github.com/dweymouth/supersonic/ui/util" + "github.com/dweymouth/supersonic/ui/widgets" +) + +type TrackInfoDialog struct { + widget.BaseWidget + + OnDismiss func() + OnNavigateToArtist func(artistID string) + OnNavigateToAlbum func(albumID string) + + track *mediaprovider.Track +} + +func NewTrackInfoDialog(track *mediaprovider.Track) *TrackInfoDialog { + t := &TrackInfoDialog{track: track} + t.ExtendBaseWidget(t) + return t +} + +func (t *TrackInfoDialog) CreateRenderer() fyne.WidgetRenderer { + c := container.New(layout.NewFormLayout()) + c.Add(newFormText("Title", true)) + c.Add(newFormText(t.track.Title, false)) + + c.Add(newFormText("Artist", true)) + artists := widgets.NewMultiHyperlink() + artists.BuildSegments(t.track.ArtistNames, t.track.ArtistIDs) + artists.OnTapped = func(id string) { + if t.OnNavigateToArtist != nil { + t.OnNavigateToArtist(id) + } + } + c.Add(artists) + + c.Add(newFormText("Album", true)) + album := widget.NewHyperlink(t.track.Album, nil) + album.OnTapped = func() { + if t.OnNavigateToAlbum != nil { + t.OnNavigateToAlbum(t.track.AlbumID) + } + } + c.Add(album) + + c.Add(newFormText("File Path", true)) + path := widgets.NewMaxRowsLabel(2, t.track.FilePath) + //path.Segments[0].(*widget.TextSegment).Style.SizeName = myTheme.SizeNameSubText + path.Wrapping = fyne.TextWrapWord + path.Truncation = fyne.TextTruncateEllipsis + c.Add(path) + + c.Add(newFormText("Comment", true)) + c.Add(newFormText(t.track.Comment, false)) + + c.Add(newFormText("Year", true)) + c.Add(newFormText(strconv.Itoa(t.track.Year), false)) + + c.Add(newFormText("Bit Rate", true)) + c.Add(newFormText(strconv.Itoa(t.track.BitRate)+"kbps", false)) + + c.Add(newFormText("File Size", true)) + c.Add(newFormText(util.BytesToSizeString(t.track.Size), false)) + + c.Add(newFormText("Play Count", true)) + c.Add(newFormText(strconv.Itoa(t.track.PlayCount), false)) + + return widget.NewSimpleRenderer(c) +} + +func newFormText(text string, leftCol bool) *widget.RichText { + alignment := fyne.TextAlignLeading + if leftCol { + alignment = fyne.TextAlignTrailing + } + return widget.NewRichText( + &widget.TextSegment{ + Text: text, + Style: widget.RichTextStyle{ + TextStyle: fyne.TextStyle{Bold: leftCol}, + Alignment: alignment, + }, + }, + ) +} diff --git a/ui/widgets/tracklist.go b/ui/widgets/tracklist.go index 6cd9c55..3c703b6 100644 --- a/ui/widgets/tracklist.go +++ b/ui/widgets/tracklist.go @@ -78,6 +78,7 @@ type Tracklist struct { OnShare func(trackID string) OnPlaySongRadio func(track *mediaprovider.Track) OnReorderTracks func(trackIDs []string, insertPos int) + OnShowTrackInfo func(track *mediaprovider.Track) OnShowArtistPage func(artistID string) OnShowAlbumPage func(albumID string) @@ -101,6 +102,7 @@ type Tracklist struct { ratingSubmenu *fyne.MenuItem shareMenuItem *fyne.MenuItem songRadioMenuItem *fyne.MenuItem + infoMenuItem *fyne.MenuItem container *fyne.Container } @@ -559,6 +561,12 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { t.onDownload(t.selectedTracks(), "Selected tracks") }) download.Icon = theme.DownloadIcon() + t.infoMenuItem = fyne.NewMenuItem("Show info...", func() { + if t.OnShowTrackInfo != nil { + t.OnShowTrackInfo(t.selectedTracks()[0]) + } + }) + t.infoMenuItem.Icon = theme.InfoIcon() favorite := fyne.NewMenuItem("Set favorite", func() { t.onSetFavorites(t.selectedTracks(), true, true) }) @@ -568,7 +576,7 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { }) unfavorite.Icon = myTheme.NotFavoriteIcon t.ctxMenu.Items = append(t.ctxMenu.Items, fyne.NewMenuItemSeparator(), - playlist, download) + playlist, download, t.infoMenuItem) t.shareMenuItem = fyne.NewMenuItem("Share...", func() { t.onShare(t.selectedTracks()) }) @@ -587,6 +595,7 @@ func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { } t.ratingSubmenu.Disabled = t.Options.DisableRating t.shareMenuItem.Disabled = t.Options.DisableSharing || len(t.selectedTracks()) != 1 + t.infoMenuItem.Disabled = len(t.selectedTracks()) != 1 widget.ShowPopUpMenuAtPosition(t.ctxMenu, fyne.CurrentApp().Driver().CanvasForObject(t), e.AbsolutePosition) }