feat(jellyfin): enhance series fetching logic to support independent series retrieval and improve item interleaving

This commit is contained in:
2026-03-12 03:21:16 +01:00
parent f028b1be98
commit 6d1bed2ecb

View File

@@ -91,17 +91,19 @@ impl JellyfinMediaProvider {
params.push(("MaxRunTimeTicks", (max as i64 * TICKS_PER_SEC).to_string())); params.push(("MaxRunTimeTicks", (max as i64 * TICKS_PER_SEC).to_string()));
} }
// Treat the first collection entry as a Jellyfin ParentId (library/folder)
if let Some(parent_id) = filter.collections.first() {
params.push(("ParentId", parent_id.clone()));
}
if let Some(name) = series_name { if let Some(name) = series_name {
// Series-level targeting: skip ParentId so the show is found regardless
// of which library it lives in. SeriesName is already precise enough.
params.push(("SeriesName", name.to_string())); params.push(("SeriesName", name.to_string()));
// Return episodes in chronological order when a specific series is // Return episodes in chronological order when a specific series is
// requested — season first, then episode within the season. // requested — season first, then episode within the season.
params.push(("SortBy", "ParentIndexNumber,IndexNumber".into())); params.push(("SortBy", "ParentIndexNumber,IndexNumber".into()));
params.push(("SortOrder", "Ascending".into())); params.push(("SortOrder", "Ascending".into()));
} else {
// No series filter — scope to the collection (library) if one is set.
if let Some(parent_id) = filter.collections.first() {
params.push(("ParentId", parent_id.clone()));
}
} }
if let Some(q) = &filter.search_term { if let Some(q) = &filter.search_term {
@@ -166,12 +168,27 @@ impl IMediaProvider for JellyfinMediaProvider {
self.fetch_items_for_series(filter, series).await self.fetch_items_for_series(filter, series).await
} }
_ => { _ => {
let mut all = Vec::new(); // Fetch each series independently, then interleave round-robin.
// Round-robin ensures every show gets fair representation when a
// downstream limit is applied (preview, block fill) even if one
// series has far more episodes than another.
let mut per_series: Vec<Vec<MediaItem>> = Vec::new();
for series_name in &filter.series_names { for series_name in &filter.series_names {
let items = self let items = self
.fetch_items_for_series(filter, Some(series_name.as_str())) .fetch_items_for_series(filter, Some(series_name.as_str()))
.await?; .await?;
all.extend(items); if !items.is_empty() {
per_series.push(items);
}
}
let max_len = per_series.iter().map(|s| s.len()).max().unwrap_or(0);
let mut all = Vec::with_capacity(per_series.iter().map(|s| s.len()).sum());
for i in 0..max_len {
for s in &per_series {
if let Some(item) = s.get(i) {
all.push(item.clone());
}
}
} }
Ok(all) Ok(all)
} }