Merge pull request #753 from zacaj/feature/dateAdded-genre-albumArtist-cols

add columns for Date Added, Genre, Album Artist, File Type
This commit is contained in:
Drew Weymouth
2025-11-13 08:22:03 -08:00
committed by GitHub
9 changed files with 216 additions and 95 deletions
@@ -435,6 +435,7 @@ func toTrack(ch *jellyfin.Song) *mediaprovider.Track {
} }
lastPlayed, _ := time.Parse(time.RFC3339Nano, ch.UserData.LastPlayedDate) lastPlayed, _ := time.Parse(time.RFC3339Nano, ch.UserData.LastPlayedDate)
dateAdded, _ := time.Parse(time.RFC3339Nano, ch.DateCreated)
t := &mediaprovider.Track{ t := &mediaprovider.Track{
ID: ch.Id, ID: ch.Id,
@@ -454,6 +455,7 @@ func toTrack(ch *jellyfin.Song) *mediaprovider.Track {
Favorite: ch.UserData.IsFavorite, Favorite: ch.UserData.IsFavorite,
PlayCount: ch.UserData.PlayCount, PlayCount: ch.UserData.PlayCount,
LastPlayed: lastPlayed, LastPlayed: lastPlayed,
DateAdded: dateAdded,
} }
if len(ch.MediaSources) > 0 { if len(ch.MediaSources) > 0 {
t.FilePath = ch.MediaSources[0].Path t.FilePath = ch.MediaSources[0].Path
+33 -29
View File
@@ -123,35 +123,39 @@ type Genre struct {
} }
type Track struct { type Track struct {
ID string ID string
CoverArtID string CoverArtID string
ParentID string ParentID string
Title string Title string
Duration time.Duration Duration time.Duration
TrackNumber int TrackNumber int
DiscNumber int DiscNumber int
Genres []string Genres []string
ArtistIDs []string ArtistIDs []string
ArtistNames []string ArtistNames []string
ComposerIDs []string AlbumArtistIDs []string
ComposerNames []string AlbumArtistNames []string
Album string ComposerIDs []string
AlbumID string ComposerNames []string
Year int Album string
Rating int AlbumID string
Favorite bool Year int
Size int64 Rating int
PlayCount int Favorite bool
LastPlayed time.Time Size int64
FilePath string PlayCount int
BitRate int LastPlayed time.Time
ContentType string FilePath string
Comment string BitRate int
BPM int ContentType string
ReplayGain ReplayGainInfo Comment string
SampleRate int BPM int
BitDepth int ReplayGain ReplayGainInfo
Channels int SampleRate int
BitDepth int
Extension string
Channels int
DateAdded time.Time
} }
type ReplayGainInfo struct { type ReplayGainInfo struct {
@@ -544,6 +544,15 @@ func toTrack(ch *subsonic.Child) *mediaprovider.Track {
artistIDs = append(artistIDs, ch.ArtistID) artistIDs = append(artistIDs, ch.ArtistID)
} }
var albumArtistNames, albumArtistIDs []string
if len(ch.AlbumArtists) > 0 {
// OpenSubsonic extension
for _, a := range ch.AlbumArtists {
albumArtistIDs = append(albumArtistIDs, a.ID)
albumArtistNames = append(albumArtistNames, a.Name)
}
}
var rGain mediaprovider.ReplayGainInfo var rGain mediaprovider.ReplayGainInfo
if rg := ch.ReplayGain; rg != nil { if rg := ch.ReplayGain; rg != nil {
rGain.AlbumGain = rg.AlbumGain rGain.AlbumGain = rg.AlbumGain
@@ -570,35 +579,39 @@ func toTrack(ch *subsonic.Child) *mediaprovider.Track {
} }
return &mediaprovider.Track{ return &mediaprovider.Track{
ID: ch.ID, ID: ch.ID,
CoverArtID: ch.CoverArt, CoverArtID: ch.CoverArt,
ParentID: ch.Parent, ParentID: ch.Parent,
Title: ch.Title, Title: ch.Title,
Duration: time.Duration(ch.Duration) * time.Second, Duration: time.Duration(ch.Duration) * time.Second,
TrackNumber: ch.Track, TrackNumber: ch.Track,
DiscNumber: ch.DiscNumber, DiscNumber: ch.DiscNumber,
Genres: genres, Genres: genres,
ArtistIDs: artistIDs, ArtistIDs: artistIDs,
ArtistNames: artistNames, ArtistNames: artistNames,
ComposerIDs: composerIDs, AlbumArtistIDs: albumArtistIDs,
ComposerNames: composers, AlbumArtistNames: albumArtistNames,
Album: ch.Album, ComposerIDs: composerIDs,
AlbumID: ch.AlbumID, ComposerNames: composers,
Year: ch.Year, Album: ch.Album,
Rating: ch.UserRating, AlbumID: ch.AlbumID,
Favorite: !ch.Starred.IsZero(), Year: ch.Year,
PlayCount: int(ch.PlayCount), Rating: ch.UserRating,
LastPlayed: ch.Played, Favorite: !ch.Starred.IsZero(),
FilePath: ch.Path, PlayCount: int(ch.PlayCount),
Size: ch.Size, LastPlayed: ch.Played,
BitRate: ch.BitRate, DateAdded: ch.Created,
ContentType: ch.ContentType, FilePath: ch.Path,
Comment: ch.Comment, Size: ch.Size,
BPM: ch.BPM, BitRate: ch.BitRate,
ReplayGain: rGain, ContentType: ch.ContentType,
SampleRate: ch.SamplingRate, Extension: ch.Suffix,
BitDepth: ch.BitDepth, Comment: ch.Comment,
Channels: ch.ChannelCount, BPM: ch.BPM,
ReplayGain: rGain,
SampleRate: ch.SamplingRate,
BitDepth: ch.BitDepth,
Channels: ch.ChannelCount,
} }
} }
+4 -2
View File
@@ -6,6 +6,8 @@
"Add to queue": "Add to queue", "Add to queue": "Add to queue",
"Album": "Album", "Album": "Album",
"album": "album", "album": "album",
"Album artist": "Album artist",
"Album artists": "Album artists",
"Album count": "Album count", "Album count": "Album count",
"Album Count": "Album Count", "Album Count": "Album Count",
"Album filters": "Album filters", "Album filters": "Album filters",
@@ -63,6 +65,7 @@
"Content type": "Content type", "Content type": "Content type",
"Could not reach server": "Could not reach server", "Could not reach server": "Could not reach server",
"Create new playlist": "Create new playlist", "Create new playlist": "Create new playlist",
"Date added": "Date added",
"day": "day", "day": "day",
"days": "days", "days": "days",
"Delete Playlist": "Delete Playlist", "Delete Playlist": "Delete Playlist",
@@ -95,6 +98,7 @@
"Field Recording": "Field Recording", "Field Recording": "Field Recording",
"File path": "File path", "File path": "File path",
"File size": "File size", "File size": "File size",
"File type": "File type",
"Filter albums": "Filter albums", "Filter albums": "Filter albums",
"Filter genres": "Filter genres", "Filter genres": "Filter genres",
"Forward": "Forward", "Forward": "Forward",
@@ -294,12 +298,10 @@
"Oct": "Oct", "Oct": "Oct",
"Nov": "Nov", "Nov": "Nov",
"Dec": "Dec", "Dec": "Dec",
"playlist.addedtracks": { "playlist.addedtracks": {
"one": "Added one track to playlist", "one": "Added one track to playlist",
"other": "Added {{.trackCount}} tracks to playlist" "other": "Added {{.trackCount}} tracks to playlist"
}, },
"x_minutes_ago": { "x_minutes_ago": {
"one": "a minute ago", "one": "a minute ago",
"other": "{{.minutes}} minutes ago" "other": "{{.minutes}} minutes ago"
+3
View File
@@ -52,6 +52,9 @@ func (m *Controller) connectTracklistActionsWithReplayGainMode(tracklist *widget
tracklist.OnShowArtistPage = func(artistID string) { tracklist.OnShowArtistPage = func(artistID string) {
m.NavigateTo(ArtistRoute(artistID)) m.NavigateTo(ArtistRoute(artistID))
} }
tracklist.OnShowGenrePage = func(genre string) {
m.NavigateTo(GenreRoute(genre))
}
tracklist.OnColumnVisibilityMenuShown = func(pop *widget.PopUp) { tracklist.OnColumnVisibilityMenuShown = func(pop *widget.PopUp) {
m.ClosePopUpOnEscape(pop) m.ClosePopUpOnEscape(pop)
} }
+18
View File
@@ -58,6 +58,18 @@ func (t *TrackInfoDialog) CreateRenderer() fyne.WidgetRenderer {
} }
c.Add(artists) c.Add(artists)
if len(t.track.AlbumArtistNames) > 0 {
c.Add(newFormText(lang.L("Album artists"), true))
albumArtists := widgets.NewMultiHyperlink()
albumArtists.BuildSegments(t.track.AlbumArtistNames, t.track.AlbumArtistIDs)
albumArtists.OnTapped = func(id string) {
if t.OnNavigateToArtist != nil {
t.OnNavigateToArtist(id)
}
}
c.Add(albumArtists)
}
if len(t.track.ComposerNames) > 0 { if len(t.track.ComposerNames) > 0 {
c.Add(newFormText(lang.L("Composers"), true)) c.Add(newFormText(lang.L("Composers"), true))
composers := widgets.NewMultiHyperlink() composers := widgets.NewMultiHyperlink()
@@ -104,6 +116,7 @@ func (t *TrackInfoDialog) CreateRenderer() fyne.WidgetRenderer {
c.Add(newFormText(t.track.FilePath, false)) c.Add(newFormText(t.track.FilePath, false))
addFormRow(c, lang.L("Content type"), t.track.ContentType) addFormRow(c, lang.L("Content type"), t.track.ContentType)
addFormRow(c, lang.L("File type"), t.track.Extension)
addFormRow(c, lang.L("Bit rate"), fmt.Sprintf("%d kbps", t.track.BitRate)) addFormRow(c, lang.L("Bit rate"), fmt.Sprintf("%d kbps", t.track.BitRate))
if t.track.SampleRate > 0 { if t.track.SampleRate > 0 {
addFormRow(c, lang.L("Sample rate"), fmt.Sprintf("%d Hz", t.track.SampleRate)) addFormRow(c, lang.L("Sample rate"), fmt.Sprintf("%d Hz", t.track.SampleRate))
@@ -115,6 +128,11 @@ func (t *TrackInfoDialog) CreateRenderer() fyne.WidgetRenderer {
addFormRow(c, lang.L("Channels"), strconv.Itoa(t.track.Channels)) addFormRow(c, lang.L("Channels"), strconv.Itoa(t.track.Channels))
} }
addFormRow(c, lang.L("File size"), util.BytesToSizeString(t.track.Size)) addFormRow(c, lang.L("File size"), util.BytesToSizeString(t.track.Size))
if !t.track.DateAdded.IsZero() {
addFormRow(c, lang.L("Date added"), t.track.DateAdded.Format(time.RFC1123))
}
addFormRow(c, lang.L("Play count"), strconv.Itoa(t.track.PlayCount)) addFormRow(c, lang.L("Play count"), strconv.Itoa(t.track.PlayCount))
if !t.track.LastPlayed.IsZero() { if !t.track.LastPlayed.IsZero() {
+19
View File
@@ -100,6 +100,25 @@ func FormatItemDate(date mediaprovider.ItemDate) string {
return sb.String() return sb.String()
} }
func FormatDate(t time.Time) string {
if t.IsZero() {
return ""
}
v := []int{
t.Local().Year(),
int(t.Local().Month()),
t.Local().Day(),
}
id := mediaprovider.ItemDate{
Year: &v[0],
Month: &v[1],
Day: &v[2],
}
return FormatItemDate(id)
}
func LastPlayedDisplayString(t time.Time) string { func LastPlayedDisplayString(t time.Time) string {
if t.IsZero() { if t.IsZero() {
return lang.L("never") return lang.L("never")
+15
View File
@@ -79,6 +79,7 @@ type Tracklist struct {
OnShowArtistPage func(artistID string) OnShowArtistPage func(artistID string)
OnShowAlbumPage func(albumID string) OnShowAlbumPage func(albumID string)
OnShowGenrePage func(genre string)
OnColumnVisibilityMenuShown func(*widget.PopUp) OnColumnVisibilityMenuShown func(*widget.PopUp)
OnVisibleColumnsChanged func([]string) OnVisibleColumnsChanged func([]string)
@@ -432,8 +433,12 @@ func (t *Tracklist) doSortTracks() {
t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Title }) t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Title })
case ColumnArtist: case ColumnArtist:
t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track().ArtistNames, ", ") }) t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track().ArtistNames, ", ") })
case ColumnAlbumArtist:
t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track().AlbumArtistNames, ", ") })
case ColumnAlbum: case ColumnAlbum:
t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Album }) t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Album })
case ColumnGenre:
t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track().Genres, ", ") })
case ColumnPath: case ColumnPath:
t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().FilePath }) t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().FilePath })
case ColumnRating: case ColumnRating:
@@ -450,6 +455,8 @@ func (t *Tracklist) doSortTracks() {
t.intSort(func(tr *util.TrackListModel) int64 { return tr.Track().LastPlayed.Unix() }) t.intSort(func(tr *util.TrackListModel) int64 { return tr.Track().LastPlayed.Unix() })
case ColumnComment: case ColumnComment:
t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Comment }) t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Comment })
case ColumnFileType:
t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Extension })
case ColumnBPM: case ColumnBPM:
t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().BPM) }) t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().BPM) })
case ColumnBitrate: case ColumnBitrate:
@@ -461,6 +468,8 @@ func (t *Tracklist) doSortTracks() {
} }
return 0 return 0
}) })
case ColumnDateAdded:
t.intSort(func(tr *util.TrackListModel) int64 { return tr.Track().DateAdded.Unix() })
} }
} }
@@ -597,6 +606,12 @@ func (t *Tracklist) onAlbumTapped(albumID string) {
} }
} }
func (t *Tracklist) onGenreTapped(genre string) {
if t.OnShowGenrePage != nil {
t.OnShowGenrePage(genre)
}
}
func (t *Tracklist) onDownload(tracks []*mediaprovider.Track, downloadName string) { func (t *Tracklist) onDownload(tracks []*mediaprovider.Track, downloadName string) {
if t.OnDownload != nil { if t.OnDownload != nil {
t.OnDownload(tracks, downloadName) t.OnDownload(tracks, downloadName)
+79 -34
View File
@@ -53,9 +53,11 @@ const (
ColumnNum = "Num" ColumnNum = "Num"
ColumnTitle = "Title" ColumnTitle = "Title"
ColumnArtist = "Artist" ColumnArtist = "Artist"
ColumnAlbumArtist = "AlbumArtist"
ColumnTitleArtist = "Title/Artist" ColumnTitleArtist = "Title/Artist"
ColumnAlbum = "Album" ColumnAlbum = "Album"
ColumnComposer = "Composer" ColumnComposer = "Composer"
ColumnGenre = "Genre"
ColumnTime = "Time" ColumnTime = "Time"
ColumnYear = "Year" ColumnYear = "Year"
ColumnFavorite = "Favorite" ColumnFavorite = "Favorite"
@@ -66,6 +68,8 @@ const (
ColumnBPM = "BPM" ColumnBPM = "BPM"
ColumnBitrate = "Bitrate" ColumnBitrate = "Bitrate"
ColumnSize = "Size" ColumnSize = "Size"
ColumnFileType = "FileType"
ColumnDateAdded = "DateAdded"
ColumnPath = "Path" ColumnPath = "Path"
) )
@@ -82,7 +86,9 @@ var (
title := lang.L("Title") title := lang.L("Title")
artist := lang.L("Artist") artist := lang.L("Artist")
album := lang.L("Album") album := lang.L("Album")
albumArtist := lang.L("Album artist")
composer := lang.L("Composer") composer := lang.L("Composer")
genre := lang.L("Genre")
time := lang.L("Time") time := lang.L("Time")
year := lang.L("Year") year := lang.L("Year")
fav := lang.L("Fav.") fav := lang.L("Fav.")
@@ -93,6 +99,8 @@ var (
bpm := lang.L("BPM") bpm := lang.L("BPM")
bitrate := lang.L("Bit rate") bitrate := lang.L("Bit rate")
size := lang.L("Size") size := lang.L("Size")
fileType := lang.L("File type")
dateAdded := lang.L("Date added")
filepath := lang.L("File path") filepath := lang.L("File path")
CompactTracklistRowColumns = []TracklistColumn{ CompactTracklistRowColumns = []TracklistColumn{
@@ -100,7 +108,9 @@ var (
{Name: ColumnTitle, Col: ListColumn{Text: title, Alignment: fyne.TextAlignLeading, CanToggleVisible: false}}, {Name: ColumnTitle, Col: ListColumn{Text: title, Alignment: fyne.TextAlignLeading, CanToggleVisible: false}},
{Name: ColumnArtist, Col: ListColumn{Text: artist, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnArtist, Col: ListColumn{Text: artist, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnAlbum, Col: ListColumn{Text: album, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnAlbum, Col: ListColumn{Text: album, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnAlbumArtist, Col: ListColumn{Text: albumArtist, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnComposer, Col: ListColumn{Text: composer, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnComposer, Col: ListColumn{Text: composer, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnGenre, Col: ListColumn{Text: genre, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnTime, Col: ListColumn{Text: time, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnTime, Col: ListColumn{Text: time, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnYear, Col: ListColumn{Text: year, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnYear, Col: ListColumn{Text: year, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnFavorite, Col: ListColumn{Text: " " + fav, Alignment: fyne.TextAlignCenter, CanToggleVisible: true}}, {Name: ColumnFavorite, Col: ListColumn{Text: " " + fav, Alignment: fyne.TextAlignCenter, CanToggleVisible: true}},
@@ -111,6 +121,8 @@ var (
{Name: ColumnBPM, Col: ListColumn{Text: bpm, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnBPM, Col: ListColumn{Text: bpm, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnBitrate, Col: ListColumn{Text: bitrate, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnBitrate, Col: ListColumn{Text: bitrate, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnSize, Col: ListColumn{Text: size, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnSize, Col: ListColumn{Text: size, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnFileType, Col: ListColumn{Text: fileType, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnDateAdded, Col: ListColumn{Text: dateAdded, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnPath, Col: ListColumn{Text: filepath, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnPath, Col: ListColumn{Text: filepath, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
} }
@@ -118,7 +130,9 @@ var (
{Name: ColumnNum, Col: ListColumn{Text: "#", Alignment: fyne.TextAlignTrailing, CanToggleVisible: false}}, {Name: ColumnNum, Col: ListColumn{Text: "#", Alignment: fyne.TextAlignTrailing, CanToggleVisible: false}},
{Name: ColumnTitleArtist, Col: ListColumn{Text: title + " / " + artist, Alignment: fyne.TextAlignLeading, CanToggleVisible: false}}, {Name: ColumnTitleArtist, Col: ListColumn{Text: title + " / " + artist, Alignment: fyne.TextAlignLeading, CanToggleVisible: false}},
{Name: ColumnAlbum, Col: ListColumn{Text: album, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnAlbum, Col: ListColumn{Text: album, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnAlbumArtist, Col: ListColumn{Text: albumArtist, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnComposer, Col: ListColumn{Text: composer, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnComposer, Col: ListColumn{Text: composer, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnGenre, Col: ListColumn{Text: genre, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnTime, Col: ListColumn{Text: time, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnTime, Col: ListColumn{Text: time, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnYear, Col: ListColumn{Text: year, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnYear, Col: ListColumn{Text: year, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnFavorite, Col: ListColumn{Text: fav, Alignment: fyne.TextAlignCenter, CanToggleVisible: true}}, {Name: ColumnFavorite, Col: ListColumn{Text: fav, Alignment: fyne.TextAlignCenter, CanToggleVisible: true}},
@@ -129,6 +143,8 @@ var (
{Name: ColumnBPM, Col: ListColumn{Text: bpm, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnBPM, Col: ListColumn{Text: bpm, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnBitrate, Col: ListColumn{Text: bitrate, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnBitrate, Col: ListColumn{Text: bitrate, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnSize, Col: ListColumn{Text: size, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}}, {Name: ColumnSize, Col: ListColumn{Text: size, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnFileType, Col: ListColumn{Text: fileType, Alignment: fyne.TextAlignTrailing, CanToggleVisible: true}},
{Name: ColumnDateAdded, Col: ListColumn{Text: dateAdded, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
{Name: ColumnPath, Col: ListColumn{Text: filepath, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}}, {Name: ColumnPath, Col: ListColumn{Text: filepath, Alignment: fyne.TextAlignLeading, CanToggleVisible: true}},
} }
@@ -152,6 +168,10 @@ var (
widget.NewLabel(lang.LocalizePluralKey("x_minutes_ago", "59 minutes ago", 59, map[string]string{"minutes": "59"})).MinSize().Width, widget.NewLabel(lang.LocalizePluralKey("x_minutes_ago", "59 minutes ago", 59, map[string]string{"minutes": "59"})).MinSize().Width,
widget.NewLabel(lastPlayed).MinSize().Width+sortIconWidth, widget.NewLabel(lastPlayed).MinSize().Width+sortIconWidth,
) )
dateAddedColWidth := fyne.Max(
widget.NewLabel("2006 Jan 30").MinSize().Width,
widget.NewLabel(dateAdded).MinSize().Width+sortIconWidth,
)
bpmColWidth := fyne.Max( bpmColWidth := fyne.Max(
widget.NewLabel(bpm+" ").MinSize().Width, widget.NewLabel(bpm+" ").MinSize().Width,
widget.NewLabel("9999").MinSize().Width) widget.NewLabel("9999").MinSize().Width)
@@ -161,11 +181,14 @@ var (
sizeColWidth := fyne.Max( sizeColWidth := fyne.Max(
widget.NewLabel("99.9 MB").MinSize().Width, widget.NewLabel("99.9 MB").MinSize().Width,
widget.NewLabel(size).MinSize().Width+sortIconWidth) widget.NewLabel(size).MinSize().Width+sortIconWidth)
fileTypeColWidth := fyne.Max(
widget.NewLabel("FLAC").MinSize().Width,
widget.NewLabel(fileType).MinSize().Width+sortIconWidth)
// #, Title, Artist, Album, Composer, Time, Year, Favorite, Rating, Plays, LastPlayed, Comment, BPM, Bitrate, Size, Path // #, Title, Artist, Album, AlbumArtist, Composer, Genre, Time, Year, Favorite, Rating, Plays, LastPlayed, Comment, BPM, Bitrate, Size, FileType, DateAdded, Path
CompactTracklistRowColumnWidths = []float32{numColWidth, -1, -1, -1, -1, timeColWidth, yearColWidth, favColWidth, ratingColWidth, playsColWidth, lastPlayedColWidth, -1, bpmColWidth, bitrateColWidth, sizeColWidth, -1} CompactTracklistRowColumnWidths = []float32{numColWidth, -1, -1, -1, -1, -1, -1, timeColWidth, yearColWidth, favColWidth, ratingColWidth, playsColWidth, lastPlayedColWidth, -1, bpmColWidth, bitrateColWidth, sizeColWidth, fileTypeColWidth, dateAddedColWidth, -1}
// #, Title/Artist, Album, Composer, Time, Year, Favorite, Rating, Plays, LastPlayed, Comment, BPM, Bitrate, Size, Path // #, Title/Artist, Album, AlbumArtist, Composer, Genre, Time, Year, Favorite, Rating, Plays, LastPlayed, Comment, BPM, Bitrate, Size, FileType, DateAdded, Path
ExpandedTracklistRowColumnWidths = []float32{numColWidth, -1, -1, -1, timeColWidth, yearColWidth, favColWidth, ratingColWidth, playsColWidth, lastPlayedColWidth, -1, bpmColWidth, bitrateColWidth, sizeColWidth, -1} ExpandedTracklistRowColumnWidths = []float32{numColWidth, -1, -1, -1, -1, -1, timeColWidth, yearColWidth, favColWidth, ratingColWidth, playsColWidth, lastPlayedColWidth, -1, bpmColWidth, bitrateColWidth, sizeColWidth, fileTypeColWidth, dateAddedColWidth, -1}
}) })
) )
@@ -193,22 +216,26 @@ type tracklistRowBase struct {
nextUpdateModel *util.TrackListModel nextUpdateModel *util.TrackListModel
nextUpdateRowNum int nextUpdateRowNum int
num *widget.Label num *widget.Label
name *ttwidget.RichText name *ttwidget.RichText
artist *MultiHyperlink artist *MultiHyperlink
album *MultiHyperlink // for disabled support, if albumID is "" album *MultiHyperlink // for disabled support, if albumID is ""
composer *MultiHyperlink albumArtist *MultiHyperlink
dur *widget.Label composer *MultiHyperlink
year *widget.Label genre *MultiHyperlink
favorite *fyne.Container dur *widget.Label
rating *StarRating year *widget.Label
bitrate *widget.Label favorite *fyne.Container
plays *widget.Label rating *StarRating
lastPlayed *widget.Label bitrate *widget.Label
comment *ttwidget.Label plays *widget.Label
bpm *widget.Label lastPlayed *widget.Label
size *widget.Label comment *ttwidget.Label
path *ttwidget.Label bpm *widget.Label
size *widget.Label
fileType *widget.Label
dateAdded *widget.Label
path *ttwidget.Label
// must be injected by extending widget // must be injected by extending widget
setColVisibility func(int, bool) bool setColVisibility func(int, bool) bool
@@ -262,7 +289,7 @@ func NewExpandedTracklistRow(tracklist *Tracklist, im *backend.ImageManager, pla
v := makeVerticallyCentered // func alias v := makeVerticallyCentered // func alias
container := container.New(tracklist.colLayout, container := container.New(tracklist.colLayout,
v(t.num), titleArtistImg, v(t.album), v(t.composer), v(t.dur), v(t.year), v(t.favorite), v(t.rating), v(t.plays), v(t.lastPlayed), v(t.comment), v(t.bpm), v(t.bitrate), v(t.size), v(t.path)) v(t.num), titleArtistImg, v(t.album), v(t.albumArtist), v(t.composer), v(t.genre), v(t.dur), v(t.year), v(t.favorite), v(t.rating), v(t.plays), v(t.lastPlayed), v(t.comment), v(t.bpm), v(t.bitrate), v(t.size), v(t.fileType), v(t.dateAdded), v(t.path))
t.Content = container t.Content = container
t.setColVisibility = func(colNum int, vis bool) bool { t.setColVisibility = func(colNum int, vis bool) bool {
c := container.Objects[colNum].(*fyne.Container) c := container.Objects[colNum].(*fyne.Container)
@@ -290,23 +317,27 @@ func NewCompactTracklistRow(tracklist *Tracklist, playingIcon fyne.CanvasObject)
t.playingIcon = playingIcon t.playingIcon = playingIcon
t.Content = container.New(tracklist.colLayout, t.Content = container.New(tracklist.colLayout,
t.num, t.name, t.artist, t.album, t.composer, t.dur, t.year, t.favorite, t.rating, t.plays, t.lastPlayed, t.comment, t.bpm, t.bitrate, t.size, t.path) t.num, t.name, t.artist, t.album, t.albumArtist, t.composer, t.genre, t.dur, t.year, t.favorite, t.rating, t.plays, t.lastPlayed, t.comment, t.bpm, t.bitrate, t.size, t.fileType, t.dateAdded, t.path)
colHiddenPtrMap := map[int]*bool{ colHiddenPtrMap := map[int]*bool{
2: &t.artist.Hidden, 2: &t.artist.Hidden,
3: &t.album.Hidden, 3: &t.album.Hidden,
4: &t.composer.Hidden, 4: &t.albumArtist.Hidden,
5: &t.dur.Hidden, 5: &t.composer.Hidden,
6: &t.year.Hidden, 6: &t.genre.Hidden,
7: &t.favorite.Hidden, 7: &t.dur.Hidden,
8: &t.rating.Hidden, 8: &t.year.Hidden,
9: &t.plays.Hidden, 9: &t.favorite.Hidden,
10: &t.lastPlayed.Hidden, 10: &t.rating.Hidden,
11: &t.comment.Hidden, 11: &t.plays.Hidden,
12: &t.bpm.Hidden, 12: &t.lastPlayed.Hidden,
13: &t.bitrate.Hidden, 13: &t.comment.Hidden,
14: &t.size.Hidden, 14: &t.bpm.Hidden,
15: &t.path.Hidden, 15: &t.bitrate.Hidden,
16: &t.size.Hidden,
17: &t.fileType.Hidden,
18: &t.dateAdded.Hidden,
19: &t.path.Hidden,
} }
t.setColVisibility = func(colNum int, vis bool) bool { t.setColVisibility = func(colNum int, vis bool) bool {
ptr, ok := colHiddenPtrMap[colNum] ptr, ok := colHiddenPtrMap[colNum]
@@ -334,10 +365,18 @@ func (t *tracklistRowBase) create(tracklist *Tracklist) {
t.album.OnTapped = func(id string) { tracklist.onAlbumTapped(id) } t.album.OnTapped = func(id string) { tracklist.onAlbumTapped(id) }
t.album.OnMouseIn = t.MouseIn t.album.OnMouseIn = t.MouseIn
t.album.OnMouseOut = t.MouseOut t.album.OnMouseOut = t.MouseOut
t.albumArtist = NewMultiHyperlink()
t.albumArtist.OnTapped = tracklist.onArtistTapped
t.albumArtist.OnMouseIn = t.MouseIn
t.albumArtist.OnMouseOut = t.MouseOut
t.composer = NewMultiHyperlink() t.composer = NewMultiHyperlink()
t.composer.OnTapped = func(id string) { tracklist.onArtistTapped(id) } t.composer.OnTapped = func(id string) { tracklist.onArtistTapped(id) }
t.composer.OnMouseIn = t.MouseIn t.composer.OnMouseIn = t.MouseIn
t.composer.OnMouseOut = t.MouseOut t.composer.OnMouseOut = t.MouseOut
t.genre = NewMultiHyperlink()
t.genre.OnTapped = func(id string) { tracklist.onGenreTapped(id) }
t.genre.OnMouseIn = t.MouseIn
t.genre.OnMouseOut = t.MouseOut
t.dur = util.NewTrailingAlignLabel() t.dur = util.NewTrailingAlignLabel()
t.year = util.NewTrailingAlignLabel() t.year = util.NewTrailingAlignLabel()
favorite := NewFavoriteIcon() favorite := NewFavoriteIcon()
@@ -355,6 +394,8 @@ func (t *tracklistRowBase) create(tracklist *Tracklist) {
t.bpm = util.NewTrailingAlignLabel() t.bpm = util.NewTrailingAlignLabel()
t.bitrate = util.NewTrailingAlignLabel() t.bitrate = util.NewTrailingAlignLabel()
t.size = util.NewTrailingAlignLabel() t.size = util.NewTrailingAlignLabel()
t.fileType = util.NewTrailingAlignLabel()
t.dateAdded = util.NewTruncatingLabel()
t.path = util.NewTruncatingTooltipLabel() t.path = util.NewTruncatingTooltipLabel()
t.path.OnMouseIn = t.MouseIn t.path.OnMouseIn = t.MouseIn
t.path.OnMouseOut = t.MouseOut t.path.OnMouseOut = t.MouseOut
@@ -412,7 +453,9 @@ func (t *tracklistRowBase) doUpdate(tm *util.TrackListModel, rowNum int) {
t.name.SetToolTip(tr.Title) t.name.SetToolTip(tr.Title)
t.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs) t.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs)
t.album.BuildSegments([]string{tr.Album}, []string{tr.AlbumID}) t.album.BuildSegments([]string{tr.Album}, []string{tr.AlbumID})
t.albumArtist.BuildSegments(tr.AlbumArtistNames, tr.AlbumArtistIDs)
t.composer.BuildSegments(tr.ComposerNames, tr.ComposerIDs) t.composer.BuildSegments(tr.ComposerNames, tr.ComposerIDs)
t.genre.BuildSegments(tr.Genres, tr.Genres)
t.dur.Text = util.SecondsToMMSS(tr.Duration.Seconds()) t.dur.Text = util.SecondsToMMSS(tr.Duration.Seconds())
t.year.Text = strconv.Itoa(tr.Year) t.year.Text = strconv.Itoa(tr.Year)
t.plays.Text = strconv.Itoa(int(tr.PlayCount)) t.plays.Text = strconv.Itoa(int(tr.PlayCount))
@@ -422,6 +465,8 @@ func (t *tracklistRowBase) doUpdate(tm *util.TrackListModel, rowNum int) {
t.bpm.Text = strconv.Itoa(tr.BPM) t.bpm.Text = strconv.Itoa(tr.BPM)
t.bitrate.Text = strconv.Itoa(tr.BitRate) t.bitrate.Text = strconv.Itoa(tr.BitRate)
t.size.Text = util.BytesToSizeString(tr.Size) t.size.Text = util.BytesToSizeString(tr.Size)
t.fileType.Text = tr.Extension
t.dateAdded.Text = util.FormatDate(tr.DateAdded)
t.path.Text = tr.FilePath t.path.Text = tr.FilePath
t.path.SetToolTip(tr.FilePath) t.path.SetToolTip(tr.FilePath)
changed = true changed = true