feat(podcasts): queue context source + player order control — item 2.2

Foundation rule R2 (§10): the queue context is the only queue, and
every producer emits the same shape. PodcastSequenceContext gains
source (feed|collection), feed_id, and order; the feed producer sets
them now — the collection producer (2.3) slots into the same shape
without the player ever special-casing beyond showing/hiding controls.

The player header gains the FEED-mode order control next to the
"Ep N/M" counter: a dropdown (native/reverse/oldest/newest) plus a
one-click reverse button. Both PUT the existing per-user feed order
override — the SAME state the feed page writes, so flipping it in the
player updates the feed page's dropdown too. The control renders only
when source=feed: a collection queue's order is curated content
(R1), never a listening preference. Behavior is hx-put +
hx-swap="none" (response discarded) with a module-level
htmx:afterRequest listener in audio.ts reloading the page — the
server re-renders prev/next/index in the new order; templ decides
what it looks like, JS only triggers the round trip (CSP-clean, no
inline handlers).

Pinned by TestPodcastPlayerOrderControl: the config JSON carries
source/feed_id/order/episode_index; the control renders feed-mode;
an order override re-renders with the dropdown reflecting it (data-
json pins must match templ's " attribute escaping).
This commit is contained in:
John O'Keefe committed 2026-10-30 15:52:14 -04:00
1 parent 7bf0b1257d
commit a90e7debfd
6 files changed
+279 -81

No files matched your search

+5
View File
@@ -233,6 +233,11 @@ func buildPodcastSequenceContext(c *echo.Context, cfg *Config, item *database.Me
seq := &templates.PodcastSequenceContext{
FeedURL: "/podcasts/" + uuid.UUID(item.SourceFeedID.Bytes).String(),
FeedTitle: feed.Title,
// R2: this producer is the feed queue. The player's order
// control renders only for this source.
Source: "feed",
FeedID: uuid.UUID(item.SourceFeedID.Bytes).String(),
Order: order,
EpisodeIndex: idx + 1,
IndexTotal: len(ordered),
}