mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 11:16:37 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f196e5621f |
@@ -195,7 +195,8 @@ func listLibrarySeriesEpisodesHandler(svc *service.Container) gin.HandlerFunc {
|
||||
writeInternalOrCanceled(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": len(items)})
|
||||
grouped := service.GroupEpisodeVersionsForDisplay(items)
|
||||
c.JSON(http.StatusOK, gin.H{"items": grouped, "total": len(grouped)})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +236,7 @@ func listMediaEpisodesHandler(svc *service.Container) gin.HandlerFunc {
|
||||
writeInternalOrCanceled(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "total": len(items)})
|
||||
grouped := service.GroupEpisodeVersionsForDisplay(items)
|
||||
c.JSON(http.StatusOK, gin.H{"items": grouped, "total": len(grouped)})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,25 @@ func GroupMediaVersions(items []model.Media) []MediaItem {
|
||||
return groupMediaVersions(items)
|
||||
}
|
||||
|
||||
// GroupEpisodeVersionsForDisplay folds encoding/container variants into one
|
||||
// episode while preserving season/episode ordering for episode-list APIs.
|
||||
func GroupEpisodeVersionsForDisplay(items []model.Media) []MediaItem {
|
||||
grouped := groupMediaVersions(items)
|
||||
if grouped == nil {
|
||||
return []MediaItem{}
|
||||
}
|
||||
sort.SliceStable(grouped, func(i, j int) bool {
|
||||
if grouped[i].SeasonNum != grouped[j].SeasonNum {
|
||||
return grouped[i].SeasonNum < grouped[j].SeasonNum
|
||||
}
|
||||
if grouped[i].EpisodeNum != grouped[j].EpisodeNum {
|
||||
return grouped[i].EpisodeNum < grouped[j].EpisodeNum
|
||||
}
|
||||
return grouped[i].CreatedAt.Before(grouped[j].CreatedAt)
|
||||
})
|
||||
return grouped
|
||||
}
|
||||
|
||||
func mediaVersionGroupKey(m model.Media) string {
|
||||
// 远程 Emby 挂载条目保持独立,不与其它远程条目或本地条目折叠合并。
|
||||
if IsEmbyRemoteID(m.ID) {
|
||||
|
||||
@@ -49,6 +49,28 @@ func TestGroupMediaVersionsMergesEpisodeByExternalIDAcrossLibraries(t *testing.T
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupEpisodeVersionsForDisplayMergesAndKeepsEpisodeOrder(t *testing.T) {
|
||||
rows := []model.Media{
|
||||
{Base: model.Base{ID: "ep2"}, LibraryID: "tv", Title: "Show", SeasonNum: 1, EpisodeNum: 2, TMDbID: 99, Path: "/show/s01e02.mkv"},
|
||||
{Base: model.Base{ID: "ep1-small"}, LibraryID: "tv", Title: "Show", SeasonNum: 1, EpisodeNum: 1, TMDbID: 99, Path: "/show/s01e01.mp4", SizeBytes: 100},
|
||||
{Base: model.Base{ID: "ep1-large"}, LibraryID: "tv", Title: "Show", SeasonNum: 1, EpisodeNum: 1, TMDbID: 99, Path: "/show/s01e01.mkv", SizeBytes: 200},
|
||||
}
|
||||
|
||||
grouped := GroupEpisodeVersionsForDisplay(rows)
|
||||
if len(grouped) != 2 {
|
||||
t.Fatalf("grouped len = %d, want 2: %#v", len(grouped), grouped)
|
||||
}
|
||||
if grouped[0].EpisodeNum != 1 || len(grouped[0].Versions) != 2 {
|
||||
t.Fatalf("episode 1 was not merged first: %#v", grouped)
|
||||
}
|
||||
if grouped[0].ID != "ep1-large" {
|
||||
t.Fatalf("primary version = %q, want ep1-large", grouped[0].ID)
|
||||
}
|
||||
if grouped[1].EpisodeNum != 2 {
|
||||
t.Fatalf("second item episode = %d, want 2", grouped[1].EpisodeNum)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupMediaVersionsMergesMovieEncodingVariants(t *testing.T) {
|
||||
hd := model.Media{
|
||||
LibraryID: "movies",
|
||||
|
||||
@@ -65,6 +65,7 @@ export function LibrarySeriesEpisodes({
|
||||
<div className="grid grid-cols-1 gap-2.5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
|
||||
{visibleEpisodes.map((ep) => {
|
||||
const displayTitle = episodeDisplayTitle(ep, visibleEpisodes)
|
||||
const versionCount = ep.versions?.length ?? 1
|
||||
return (
|
||||
<div
|
||||
key={ep.id}
|
||||
@@ -102,6 +103,7 @@ export function LibrarySeriesEpisodes({
|
||||
{ep.duration_sec > 0
|
||||
? `${Math.floor(ep.duration_sec / 60)} 分钟`
|
||||
: formatSize(ep.size_bytes)}
|
||||
{versionCount > 1 ? ` · ${versionCount} 版本` : ''}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
Reference in New Issue
Block a user