package templates
// Feed detail page (plan task 1.9, D5/D7/D8/D19): hero (artwork,
// metadata, admin cluster), action row (Download All, Refresh, order
// override, subscription policy, admin delete), and the episode list
// with the download lifecycle inline. The episode list is a self-
// refreshing htmx partial: it re-fetches on the podcast:changed event
// AND polls every 4s ONLY while downloads are active (server decides —
// the polling attributes render only then).
templ PodcastDetailPage(user User, data PodcastDetailData) {
{ podcastInt(data.Feed.DownloadedN) + " of " + podcastInt(data.Feed.EpisodeTotal) + " episodes downloaded" }
if data.Feed.LastFetched != "" {
{ " · last checked " + data.Feed.LastFetched }
}
if data.IsSerial && data.Order == "native" {
}
if data.Feed.AutoDownload == "newest" {
}
if data.IsAdmin {
}
if data.GapCount > 0 {
@Icon("circle", "h-5 w-5")
{ podcastInt(data.GapCount) + " episode(s) not downloaded in the middle of this feed" }
Playback skips them and keeps going — use Download All to fill the gaps.
}
@PodcastEpisodeList(data)
}
// PodcastEpisodeList is the refresh unit: re-fetched on the
// podcast:changed event (download/refresh/order endpoints fire it) and
// polled every 4s only while the server says downloads are active.
templ PodcastEpisodeList(data PodcastDetailData) {
Episodes
if len(data.Episodes) == 0 {
No episodes yet — hit Refresh to check the feed.
} else {
for _, ep := range data.Episodes {
@PodcastEpisodeRowView(ep)
}
}
}
// PodcastEpisodeListPolling renders the poll-active variant of the list
// container (same content; the hx-trigger adds the 4s poll + load). The
// SSR episode route picks one of the two by download activity.
templ PodcastEpisodeListPolling(data PodcastDetailData) {
Episodes
for _, ep := range data.Episodes {
@PodcastEpisodeRowView(ep)
}