fix(library): podcasts list newest episode first

A Jellypod podcast listed its episodes alphabetically. The store pinned
SortBy=SortName onto every drill-down, which overrode the order the
channel plugin returns — and since Jellypod prefixes played episodes with
"[Played]", the name sort also clumped every heard episode at the top.

Which order a container's children take is domain knowledge, so it moves
to Rust: the caller names the container (GetItemsOptions.parentKind) and
default_listing_sort answers with the sort. A channel folder is
PremiereDate descending, every other container keeps SortName ascending,
and a caller naming no container still gets no SortBy, so the paths that
rely on the server's own order keep it. An explicit sort always wins.

ChannelFolderItem with is_folder now maps to MediaKind::ChannelFolder
instead of collapsing into Folder — while both were Folder there was
nothing to key the rule on. The offline leg of the cache/server race
applies the same order, so the cached list no longer flashes in name
order before the server's arrives.

TRACES: UR-007 | DR-257 | UT-229, UT-230, UT-231
This commit is contained in:
2026-08-23 18:38:24 +02:00
parent 2ff07bfa49
commit 231ffae626
15 changed files with 285 additions and 16 deletions
+20 -1
View File
@@ -2305,7 +2305,16 @@ export type GetItemsOptions = { startIndex?: number | null; limit?: number | nul
*
* TRACES: UR-067 | DR-116 | UT-104
*/
favoritesOnly?: boolean | null }
favoritesOnly?: boolean | null;
/**
* What the container being listed *is*, so the repository can pick the
* order its children belong in when the caller names none. The frontend
* sends the neutral kind it already holds; what that kind implies about
* ordering is decided here, the same division as `SearchScope`.
*
* TRACES: UR-007 | DR-257
*/
parentKind?: MediaKind | null }
/**
* Image options
*/
@@ -2463,6 +2472,16 @@ export type MediaKind = "track" | "album" | "artist" | "playlist" | "movie" | "s
* and from `Other` so the UI can route it to playback.
*/
"channelItem" |
/**
* A *container* inside a channel — a Jellyfin `ChannelFolderItem` that is
* itself a folder, e.g. one podcast within a podcast channel. Distinct
* from `Folder` because its children are plugin content with an order of
* their own (newest episode first), which a folder's name order silently
* overrode.
*
* TRACES: UR-007 | DR-257
*/
"channelFolder" |
/**
* A kind we do not model explicitly. Reached only for provider item types
* that map to nothing meaningful; consumers treat it like an opaque