From ff3b1addf831ec51ab9106090cff64dd8cb63acf Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 23 Dec 2024 17:23:26 -0800 Subject: [PATCH 1/3] show full OpenSubsonic date where available --- .../jellyfin/jellyfinmediaprovider.go | 2 +- backend/mediaprovider/mediaprovider.go | 2 +- backend/mediaprovider/model.go | 17 ++++- .../subsonic/subsonicmediaprovider.go | 23 ++++--- ui/browsing/albumpage.go | 7 +- ui/browsing/artistpage.go | 6 +- ui/util/util.go | 69 +++++++++++++++++++ ui/widgets/gridview.go | 4 +- 8 files changed, 109 insertions(+), 21 deletions(-) diff --git a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go index ea5586de..2315c429 100644 --- a/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go +++ b/backend/mediaprovider/jellyfin/jellyfinmediaprovider.go @@ -458,7 +458,7 @@ func fillAlbum(a *jellyfin.Album, album *mediaprovider.Album) { album.Duration = int(a.RunTimeTicks / runTimeTicksPerSecond) album.ArtistIDs = artistIDs album.ArtistNames = artistNames - album.Year = a.Year + album.Date.Year = &a.Year album.TrackCount = a.ChildCount album.Genres = a.Genres album.Favorite = a.UserData.IsFavorite diff --git a/backend/mediaprovider/mediaprovider.go b/backend/mediaprovider/mediaprovider.go index 9fb19517..a40db186 100644 --- a/backend/mediaprovider/mediaprovider.go +++ b/backend/mediaprovider/mediaprovider.go @@ -106,7 +106,7 @@ func (f albumFilter) Matches(album *Album) bool { if f.options.ExcludeUnfavorited && !album.Favorite { return false } - if y := album.Year; y < f.options.MinYear || (f.options.MaxYear > 0 && y > f.options.MaxYear) { + if y := album.YearOrZero(); y < f.options.MinYear || (f.options.MaxYear > 0 && y > f.options.MaxYear) { return false } if len(f.options.Genres) == 0 { diff --git a/backend/mediaprovider/model.go b/backend/mediaprovider/model.go index e83264ba..b2ec9d7e 100644 --- a/backend/mediaprovider/model.go +++ b/backend/mediaprovider/model.go @@ -32,6 +32,12 @@ const ( ReleaseTypeSpokenWord ReleaseType = 0x8000 ) +type ItemDate struct { + Year *int + Month *int + Day *int +} + type Album struct { ID string CoverArtID string @@ -39,14 +45,21 @@ type Album struct { Duration int ArtistIDs []string ArtistNames []string - Year int - ReissueYear int + Date ItemDate + ReissueDate ItemDate Genres []string TrackCount int Favorite bool ReleaseTypes ReleaseTypes } +func (a *Album) YearOrZero() int { + if a.Date.Year != nil { + return *a.Date.Year + } + return 0 +} + type AlbumWithTracks struct { Album Tracks []*Track diff --git a/backend/mediaprovider/subsonic/subsonicmediaprovider.go b/backend/mediaprovider/subsonic/subsonicmediaprovider.go index 9dc7df59..7c736615 100644 --- a/backend/mediaprovider/subsonic/subsonicmediaprovider.go +++ b/backend/mediaprovider/subsonic/subsonicmediaprovider.go @@ -581,14 +581,21 @@ func fillAlbum(subAlbum *subsonic.AlbumID3, album *mediaprovider.Album) { genres = append(genres, subAlbum.Genre) } - album.Year = subAlbum.Year - if subAlbum.OriginalReleaseDate != nil && - subAlbum.OriginalReleaseDate.Year != nil && - *subAlbum.OriginalReleaseDate.Year < subAlbum.Year { - album.Year = *subAlbum.OriginalReleaseDate.Year - } - if subAlbum.ReleaseDate != nil && subAlbum.ReleaseDate.Year != nil { - album.ReissueYear = *subAlbum.ReleaseDate.Year + if ord := subAlbum.OriginalReleaseDate; ord != nil && ord.Year != nil { + album.Date = mediaprovider.ItemDate{ + Year: ord.Year, + Month: ord.Month, + Day: ord.Date, + } + } else { + album.Date.Year = &subAlbum.Year + } + if rd := subAlbum.ReleaseDate; rd != nil && rd.Year != nil { + album.ReissueDate = mediaprovider.ItemDate{ + Year: rd.Year, + Month: rd.Month, + Day: rd.Date, + } } album.ID = subAlbum.ID diff --git a/ui/browsing/albumpage.go b/ui/browsing/albumpage.go index c8cd55e9..c2bb5534 100644 --- a/ui/browsing/albumpage.go +++ b/ui/browsing/albumpage.go @@ -3,7 +3,6 @@ package browsing import ( "fmt" "log" - "strconv" "github.com/dweymouth/supersonic/backend" "github.com/dweymouth/supersonic/backend/mediaprovider" @@ -370,9 +369,9 @@ func formatMiscLabelStr(a *mediaprovider.AlbumWithTracks) string { if a.TrackCount == 1 { tracks = lang.L("track") } - yearStr := strconv.Itoa(a.Year) - if a.ReissueYear > a.Year { - yearStr += fmt.Sprintf(" (%s %d)", lang.L("reissued"), a.ReissueYear) + yearStr := util.FormatItemDate(a.Date) + if y := a.ReissueDate.Year; y != nil && *y > a.YearOrZero() { + yearStr += fmt.Sprintf(" (%s %d)", lang.L("reissued"), util.FormatItemDate(a.ReissueDate)) } return fmt.Sprintf("%s · %d %s · %s%s", yearStr, a.TrackCount, tracks, discs, util.SecondsToTimeString(float64(a.Duration))) } diff --git a/ui/browsing/artistpage.go b/ui/browsing/artistpage.go index 42390d59..34d8c3b6 100644 --- a/ui/browsing/artistpage.go +++ b/ui/browsing/artistpage.go @@ -203,12 +203,12 @@ func (a *ArtistPage) getGridViewAlbumsModel() []widgets.GridViewItemModel { return nil } sortFunc := func(x, y int) bool { - return a.artistInfo.Albums[x].Year < a.artistInfo.Albums[y].Year + return a.artistInfo.Albums[x].YearOrZero() < a.artistInfo.Albums[y].YearOrZero() } switch a.cfg.DiscographySort { case discographySorts[1]: /*year descending*/ sortFunc = func(x, y int) bool { - return a.artistInfo.Albums[x].Year > a.artistInfo.Albums[y].Year + return a.artistInfo.Albums[x].YearOrZero() > a.artistInfo.Albums[y].YearOrZero() } case discographySorts[2]: /*name*/ sortFunc = func(x, y int) bool { @@ -222,7 +222,7 @@ func (a *ArtistPage) getGridViewAlbumsModel() []widgets.GridViewItemModel { Name: al.Name, ID: al.ID, CoverArtID: al.CoverArtID, - Secondary: []string{strconv.Itoa(al.Year)}, + Secondary: []string{strconv.Itoa(al.YearOrZero())}, } }) } diff --git a/ui/util/util.go b/ui/util/util.go index 8b2c964b..8bf0ad2c 100644 --- a/ui/util/util.go +++ b/ui/util/util.go @@ -25,6 +25,75 @@ import ( "golang.org/x/net/html" ) +type DateFormat int + +const ( + DateFormatDMY DateFormat = iota + DateFormatMDY + DateFormatYMD +) + +func dateFormatForLocale(locale string) DateFormat { + var region string + if i := strings.Index(locale, "-"); i > 0 { + region = locale[i+1:] + } + switch strings.ToUpper(region) { + case "US": + return DateFormatMDY + case "CN", "JP", "KR", "HU", "MN", "LT": + return DateFormatYMD + default: + return DateFormatDMY + } +} + +func shortMonthName(month int) string { + var months = [12]string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"} + if month >= 1 && month <= 12 { + return lang.L(months[month-1]) + } + return "" +} + +func FormatItemDate(date mediaprovider.ItemDate) string { + var sb strings.Builder + df := dateFormatForLocale(fyne.CurrentDevice().Locale().String()) + switch df { + case DateFormatDMY: + if d := date.Day; d != nil { + sb.WriteString(fmt.Sprintf("%d ", *d)) + } + if m := date.Month; m != nil { + sb.WriteString(shortMonthName(*m) + " ") + } + if y := date.Year; y != nil { + sb.WriteString(fmt.Sprintf("%d", *y)) + } + case DateFormatMDY: + if m := date.Month; m != nil { + sb.WriteString(shortMonthName(*m) + " ") + } + if d := date.Day; d != nil { + sb.WriteString(fmt.Sprintf("%d, ", *d)) + } + if y := date.Year; y != nil { + sb.WriteString(fmt.Sprintf("%d", *y)) + } + case DateFormatYMD: + if y := date.Year; y != nil { + sb.WriteString(fmt.Sprintf("%d ", *y)) + } + if m := date.Month; m != nil { + sb.WriteString(shortMonthName(*m) + " ") + } + if d := date.Day; d != nil { + sb.WriteString(fmt.Sprintf("%d", *d)) + } + } + return sb.String() +} + var BoldRichTextStyle = widget.RichTextStyle{TextStyle: fyne.TextStyle{Bold: true}, Inline: true} func MakeOpaque(c color.Color) color.Color { diff --git a/ui/widgets/gridview.go b/ui/widgets/gridview.go index f81a10da..a438ee60 100644 --- a/ui/widgets/gridview.go +++ b/ui/widgets/gridview.go @@ -61,8 +61,8 @@ func (g gridViewAlbumIterator) NextN(n int) []GridViewItemModel { Secondary: al.ArtistNames, SecondaryIDs: al.ArtistIDs, } - if al.Year > 0 { - model.Suffix = strconv.Itoa(al.Year) + if y := al.Date.Year; y != nil { + model.Suffix = strconv.Itoa(*al.Date.Year) } return model }) From 774bd996fc2eaf3059541893d1681a0031f1b1f5 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 23 Dec 2024 17:39:57 -0800 Subject: [PATCH 2/3] fix opensubsonic date, and locale detection --- backend/mediaprovider/subsonic/subsonicmediaprovider.go | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- ui/util/util.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/mediaprovider/subsonic/subsonicmediaprovider.go b/backend/mediaprovider/subsonic/subsonicmediaprovider.go index 7c736615..5b0b4cca 100644 --- a/backend/mediaprovider/subsonic/subsonicmediaprovider.go +++ b/backend/mediaprovider/subsonic/subsonicmediaprovider.go @@ -585,7 +585,7 @@ func fillAlbum(subAlbum *subsonic.AlbumID3, album *mediaprovider.Album) { album.Date = mediaprovider.ItemDate{ Year: ord.Year, Month: ord.Month, - Day: ord.Date, + Day: ord.Day, } } else { album.Date.Year = &subAlbum.Year @@ -594,7 +594,7 @@ func fillAlbum(subAlbum *subsonic.AlbumID3, album *mediaprovider.Album) { album.ReissueDate = mediaprovider.ItemDate{ Year: rd.Year, Month: rd.Month, - Day: rd.Date, + Day: rd.Day, } } diff --git a/go.mod b/go.mod index 9c6c67ed..e20b4539 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.8 github.com/quarckster/go-mpris-server v1.0.3 github.com/supersonic-app/go-mpv v0.1.0 - github.com/supersonic-app/go-subsonic v0.0.0-20241017150725-a5686988ef9c + github.com/supersonic-app/go-subsonic v0.0.0-20241224013245-9b2841f3711d github.com/zalando/go-keyring v0.2.1 golang.org/x/net v0.25.0 golang.org/x/text v0.16.0 diff --git a/go.sum b/go.sum index 796f7138..76a574ad 100644 --- a/go.sum +++ b/go.sum @@ -311,8 +311,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/supersonic-app/go-mpv v0.1.0 h1:U+cCnLQxmpqx5mY6nMlC0J4uIdCCXUbAjpjS04XkFu8= github.com/supersonic-app/go-mpv v0.1.0/go.mod h1:1bQz6kBQumJopXEbkiqoLxIXLy7F7yWFBvknvpAtIC0= -github.com/supersonic-app/go-subsonic v0.0.0-20241017150725-a5686988ef9c h1:UsXe5/TXViPgw21zO2Fgh0F/hSl0TXox0yjRc+vT6XQ= -github.com/supersonic-app/go-subsonic v0.0.0-20241017150725-a5686988ef9c/go.mod h1:D+OWPXeD9owcdcoXATv5YPBGWxxVvn5k98rt5B4wMc4= +github.com/supersonic-app/go-subsonic v0.0.0-20241224013245-9b2841f3711d h1:70+Nn7yh+cfeKqqXVTdpneFqXuvrBLyP7U6GVUsjTU4= +github.com/supersonic-app/go-subsonic v0.0.0-20241224013245-9b2841f3711d/go.mod h1:D+OWPXeD9owcdcoXATv5YPBGWxxVvn5k98rt5B4wMc4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/ui/util/util.go b/ui/util/util.go index 8bf0ad2c..25fb1901 100644 --- a/ui/util/util.go +++ b/ui/util/util.go @@ -35,8 +35,8 @@ const ( func dateFormatForLocale(locale string) DateFormat { var region string - if i := strings.Index(locale, "-"); i > 0 { - region = locale[i+1:] + if i := strings.Index(locale, "-"); i > 0 && len(locale) >= 5 { + region = locale[i+1 : i+3] } switch strings.ToUpper(region) { case "US": From 4a1b04dd68c9f96dc195dbaf038249afce8f38de Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Mon, 23 Dec 2024 17:54:31 -0800 Subject: [PATCH 3/3] add some translations for the months --- res/translations/de.json | 16 ++++++++++++++-- res/translations/en.json | 16 ++++++++++++++-- res/translations/es.json | 14 +++++++++++++- res/translations/fr.json | 14 +++++++++++++- res/translations/it.json | 14 +++++++++++++- res/translations/ro.json | 14 +++++++++++++- 6 files changed, 80 insertions(+), 8 deletions(-) diff --git a/res/translations/de.json b/res/translations/de.json index 962fb68a..6c9c9ed2 100644 --- a/res/translations/de.json +++ b/res/translations/de.json @@ -226,6 +226,18 @@ "Unset favorite": "Von Favoriten entfernen", "Remove from queue": "Aus Wiedergabeliste entfernen", "Play song radio": "Liedradio abspielen", - "to":"bis", - "by":"von" + "to": "bis", + "by": "von", + "Jan": "Jan", + "Feb": "Feb", + "Mar": "März", + "Apr": "Apr", + "May": "Mai", + "Jun": "Jun", + "Jul": "Jul", + "Aug": "Aug", + "Sept": "Sept", + "Oct": "Okt", + "Nov": "Nov", + "Dec": "Dec" } diff --git a/res/translations/en.json b/res/translations/en.json index 528bbfda..7a4fd466 100644 --- a/res/translations/en.json +++ b/res/translations/en.json @@ -228,6 +228,18 @@ "Unset favorite": "Unset favorite", "Remove from queue": "Remove from queue", "Play song radio": "Play song radio", - "to":"to", - "by":"by" + "to": "to", + "by": "by", + "Jan": "Jan", + "Feb": "Feb", + "Mar": "Mar", + "Apr": "Apr", + "May": "May", + "Jun": "Jun", + "Jul": "Jul", + "Aug": "Aug", + "Sept": "Sept", + "Oct": "Oct", + "Nov": "Nov", + "Dec": "Dec" } diff --git a/res/translations/es.json b/res/translations/es.json index 826b5381..7830ff53 100644 --- a/res/translations/es.json +++ b/res/translations/es.json @@ -229,5 +229,17 @@ "Remove from queue": "Remover de la cola", "Play song radio": "Reproducir canciones similares", "to": "a", - "by": "por" + "by": "por", + "Jan": "Ene", + "Feb": "Feb", + "Mar": "Mar", + "Apr": "Abr", + "May": "May", + "Jun": "Jun", + "Jul": "Jul", + "Aug": "Ago", + "Sept": "Set", + "Oct": "Oct", + "Nov": "Nov", + "Dec": "Dic" } diff --git a/res/translations/fr.json b/res/translations/fr.json index 6da71faf..e5729444 100644 --- a/res/translations/fr.json +++ b/res/translations/fr.json @@ -228,5 +228,17 @@ "Remove from queue": "Retirer de la file d'attente", "Play song radio": "Lire une radio basée sur la piste", "to": "à", - "by": "par" + "by": "par", + "Jan": "Janv", + "Feb": "Févr", + "Mar": "Mars", + "Apr": "Avr", + "May": "Mai", + "Jun": "Juin", + "Jul": "Juil", + "Aug": "Août", + "Sept": "Sept", + "Oct": "Oct", + "Nov": "Nov", + "Dec": "Déc" } diff --git a/res/translations/it.json b/res/translations/it.json index 3a8beb8d..2d657f1a 100644 --- a/res/translations/it.json +++ b/res/translations/it.json @@ -226,5 +226,17 @@ "Remove from queue": "Rimuovi dalla coda", "Play song radio": "Avvia radio mix", "to": "al", - "by": "by" + "by": "by", + "Jan": "Gen", + "Feb": "Feb", + "Mar": "Mar", + "Apr": "Apr", + "May": "Mag", + "Jun": "Giu", + "Jul": "Lug", + "Aug": "Ago", + "Sept": "Set", + "Oct": "Ott", + "Nov": "Nov", + "Dec": "Dic" } diff --git a/res/translations/ro.json b/res/translations/ro.json index 463acaa1..cd0b9d79 100644 --- a/res/translations/ro.json +++ b/res/translations/ro.json @@ -218,5 +218,17 @@ "Remove from queue": "Șterge din lista de redare", "Play song radio": "Redă melodie radio", "to": "la", - "by": "de" + "by": "de", + "Jan": "Ian", + "Feb": "Feb", + "Mar": "Mar", + "Apr": "Apr", + "May": "Mai", + "Jun": "Iunie", + "Jul": "Iulie", + "Aug": "Aug", + "Sept": "Sept", + "Oct": "Oct", + "Nov": "Noiem", + "Dec": "Dec" }