package dialogs import ( "fmt" "strconv" "time" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/lang" "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/util" "github.com/dweymouth/supersonic/ui/widgets" ) type TrackInfoDialog struct { widget.BaseWidget OnDismiss func() OnNavigateToArtist func(artistID string) OnNavigateToAlbum func(albumID string) OnNavigateToGenre func(genre string) OnCopyFilePath func() 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()) addFormRow(c, lang.L("Title"), t.track.Title) c.Add(newFormText(lang.L("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(lang.L("Artists"), 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) if len(t.track.ComposerNames) > 0 { c.Add(newFormText(lang.L("Composers"), true)) composers := widgets.NewMultiHyperlink() composers.BuildSegments(t.track.ComposerNames, t.track.ComposerIDs) artists.OnTapped = func(id string) { if t.OnNavigateToArtist != nil { t.OnNavigateToArtist(id) } } c.Add(composers) } if len(t.track.Genres) > 0 { c.Add(newFormText(lang.L("Genres"), true)) genres := widgets.NewMultiHyperlink() genres.BuildSegments(t.track.Genres, t.track.Genres) genres.OnTapped = func(g string) { if t.OnNavigateToGenre != nil { t.OnNavigateToGenre(g) } } c.Add(genres) } addFormRow(c, lang.L("Duration"), util.SecondsToTimeString(t.track.Duration.Seconds())) addFormRow(c, lang.L("Comment"), t.track.Comment) addFormRow(c, lang.L("Year"), strconv.Itoa(t.track.Year)) addFormRow(c, lang.L("Track number"), strconv.Itoa(t.track.TrackNumber)) addFormRow(c, lang.L("Disc number"), strconv.Itoa(t.track.DiscNumber)) if t.track.BPM > 0 { addFormRow(c, lang.L("BPM"), strconv.Itoa(t.track.BPM)) } copyBtn := widgets.NewIconButton(theme.ContentCopyIcon(), func() { if t.OnCopyFilePath != nil { t.OnCopyFilePath() } }) copyBtn.IconSize = widgets.IconButtonSizeSmaller btnCtr := container.New(layout.NewCustomPaddedLayout(8, 0, 10, 0), container.NewVBox(copyBtn, layout.NewSpacer())) c.Add(container.NewHBox(layout.NewSpacer(), btnCtr, newFormText(lang.L("File path"), true))) c.Add(newFormText(t.track.FilePath, false)) addFormRow(c, lang.L("Content type"), t.track.ContentType) addFormRow(c, lang.L("Bit rate"), fmt.Sprintf("%d kbps", t.track.BitRate)) addFormRow(c, lang.L("File size"), util.BytesToSizeString(t.track.Size)) addFormRow(c, lang.L("Play count"), strconv.Itoa(t.track.PlayCount)) if !t.track.LastPlayed.IsZero() { addFormRow(c, lang.L("Last played"), t.track.LastPlayed.Format(time.RFC1123)) } if t.track.ReplayGain.TrackPeak > 0 { addFormRow(c, lang.L("Track gain"), fmt.Sprintf("%0.2f dB", t.track.ReplayGain.TrackGain)) addFormRow(c, lang.L("Track peak"), fmt.Sprintf("%0.6f", t.track.ReplayGain.TrackPeak)) } if t.track.ReplayGain.AlbumPeak > 0 { addFormRow(c, lang.L("Album gain"), fmt.Sprintf("%0.2f dB", t.track.ReplayGain.AlbumGain)) addFormRow(c, lang.L("Album peak"), fmt.Sprintf("%0.6f", t.track.ReplayGain.AlbumPeak)) } title := widget.NewRichTextWithText(lang.L("Track Info")) title.Segments[0].(*widget.TextSegment).Style.TextStyle.Bold = true dismissBtn := widget.NewButton(lang.L("Close"), func() { if t.OnDismiss != nil { t.OnDismiss() } }) return widget.NewSimpleRenderer( container.NewBorder( /*top*/ container.NewHBox(layout.NewSpacer(), title, layout.NewSpacer()), /*bottom*/ container.NewVBox( widget.NewSeparator(), container.NewHBox(layout.NewSpacer(), dismissBtn), ), /*left/right*/ nil, nil, /*center*/ container.New(layout.NewCustomPaddedLayout(10, 10, 15, 15), container.NewScroll(c)), ), ) } func addFormRow(c *fyne.Container, left, right string) { if right == "" { return } c.Add(newFormText(left, true)) c.Add(newFormText(right, false)) } func newFormText(text string, leftCol bool) *widget.RichText { alignment := fyne.TextAlignLeading if leftCol { alignment = fyne.TextAlignTrailing } rt := widget.NewRichText( &widget.TextSegment{ Text: text, Style: widget.RichTextStyle{ TextStyle: fyne.TextStyle{Bold: leftCol}, Alignment: alignment, }, }, ) if !leftCol { rt.Wrapping = fyne.TextWrapWord } return rt }