fix(collections): the order select re-orders the PAGE — visible order = play order
The detail header's listening-order select persisted fine and the reader chain honored it, but the page's card list never applied chain_order (it kept the composed query's title order) — so flipping the select changed nothing visible, and Play as Sequence launches from the FIRST CARD ON THE PAGE, making the played start (and the perceived order) disagree with the curated setting (2026-11-01 user report on the smart podcast page). - Smart episode collections: the page's match list re-orders through OrderEpisodeMedia (the same OrderEpisodes comparator the sequence producer uses — §10 R2's single source of order truth) before card building. Books-scope matches keep title order. - Static episode playlists: the sequence now honors the curated order too — native keeps the manual position order (SQL), reverse flips it, oldest/newest re-key on publication date with feed position as tiebreak. Previously statics ignored chain_order entirely while the select rendered on their pages. Pins: native page order (feed positions) and the reverse flip re-ordering the SSR cards, asserted in the curated-order subtest alongside the existing reader-chain pins. Podcast/playlist/audiobook/ RLS/dashboard/contract slices green.
This commit is contained in:
1 parent
178b1f30c5
commit
81e54f89b2
4 files changed
+77
No files matched your search
@@ -316,6 +316,13 @@ func (cfg *Config) collectionBooksForScope(c *echo.Context, userUUID uuid.UUID,
|
||||
if evalErr != nil {
|
||||
return nil, isSmart, "books_load_error"
|
||||
}
|
||||
// The visible order IS the play order: the curated listening
|
||||
// order (view_settings.chain_order, §10 R2) re-orders the
|
||||
// episode cards exactly as the sequence producer will play
|
||||
// them, so the select's effect is visible and Play launches
|
||||
// from the card the user sees first (2026-11-01 user report:
|
||||
// the select changed nothing on the page).
|
||||
services.OrderEpisodeMedia(matches, handlers.CollectionChainOrder(collection.ViewSettings))
|
||||
books = handlers.BookCardsFromMediaItems(matches, libTypes)
|
||||
// Episode-awareness for smart matches (item 2.5): episode cards
|
||||
// carry the play affordance (chain via ?queue=collection:).
|
||||
|
||||
@@ -295,6 +295,25 @@ func buildCollectionSequenceContext(c *echo.Context, cfg *Config, item *database
|
||||
if err != nil || len(eps) == 0 {
|
||||
return nil
|
||||
}
|
||||
// The curated listening order applies to static episode playlists
|
||||
// too (§10 R2): native/"" keeps the manual position order (the SQL
|
||||
// order above); reverse flips it; oldest/newest re-key on
|
||||
// publication date with feed position as the tiebreak.
|
||||
switch order := handlers.CollectionChainOrder(coll.ViewSettings); order {
|
||||
case "reverse":
|
||||
for i, j := 0, len(eps)-1; i < j; i, j = i+1, j-1 {
|
||||
eps[i], eps[j] = eps[j], eps[i]
|
||||
}
|
||||
case "oldest", "newest":
|
||||
services.OrderEpisodes(eps, order,
|
||||
func(e database.GetCollectionEpisodesOrderedRow) int32 { return e.FeedPosition.Int32 },
|
||||
func(e database.GetCollectionEpisodesOrderedRow) string {
|
||||
if e.DatePublished.Valid {
|
||||
return e.DatePublished.Time.Format("2006-01-02")
|
||||
}
|
||||
return ""
|
||||
})
|
||||
}
|
||||
|
||||
currentID := uuid.UUID(item.ID.Bytes).String()
|
||||
idx := -1
|
||||
|
||||
Reference in new issue
Block a user