Files
mal/internal/templates/episodes.templ
Mikkel Elvers a25e8f1655 feat: torrent streaming with hls transcoding (#1)
* feat: add ffmpeg for hls streaming

* feat: torrent streaming with hls transcoding

- add nyaa.si torrent search client
- add streaming service using anacrolix/torrent
- add hls transcoding via ffmpeg for browser playback
- add watch page with episode selection
- add socks5 proxy support via TORRENT_PROXY env
- switch to modernc.org/sqlite (pure go, no cgo conflicts)
- update dockerfile with ffmpeg
2026-04-07 13:23:08 +02:00

73 lines
1.9 KiB
Plaintext

package templates
import "mal/internal/jikan"
import "fmt"
// EpisodesList renders a list of episodes for an anime
templ EpisodesList(animeID int, animeTitle string, episodes []jikan.Episode, totalEpisodes int) {
<section class="episodes-section">
<div class="episodes-header">
<h3>episodes</h3>
if totalEpisodes > 0 {
<span class="episode-count">{ fmt.Sprintf("%d episodes", totalEpisodes) }</span>
}
</div>
if len(episodes) == 0 {
<p class="no-episodes">no episode data available</p>
} else {
<div class="episodes-grid">
for _, ep := range episodes {
@EpisodeCard(animeID, animeTitle, ep)
}
</div>
}
</section>
}
// EpisodeCard renders a single episode card with play button
templ EpisodeCard(animeID int, animeTitle string, ep jikan.Episode) {
<div class="episode-card" data-episode={ fmt.Sprintf("%d", ep.MalID) }>
<div class="episode-number">{ fmt.Sprintf("%d", ep.MalID) }</div>
<div class="episode-info">
<div class="episode-title">
if ep.Title != "" {
{ ep.Title }
} else {
{ fmt.Sprintf("Episode %d", ep.MalID) }
}
</div>
if ep.Filler {
<span class="episode-tag filler">filler</span>
}
if ep.Recap {
<span class="episode-tag recap">recap</span>
}
</div>
<button
class="episode-play"
hx-get={ string(templ.URL(fmt.Sprintf("/watch/%d/%d", animeID, ep.MalID))) }
hx-target="body"
hx-push-url="true"
>
<svg viewBox="0 0 24 24" fill="currentColor" class="play-icon">
<path d="M8 5v14l11-7z"/>
</svg>
</button>
</div>
}
// EpisodesLoading renders a loading state for episodes
templ EpisodesLoading() {
<section class="episodes-section">
<div class="episodes-header">
<h3>episodes</h3>
</div>
<div class="loading-indicator">
<div class="loading-dot"></div>
<div class="loading-dot"></div>
<div class="loading-dot"></div>
<span>loading episodes</span>
</div>
</section>
}