Choix de la langue VF/VOSTFR sur la fiche titre
- Episode : nouveau champ version (vf/vostfr) - French-Manga : épisodes listés pour chaque langue disponible (VOSTFR puis VF) au lieu d'un choix automatique, fragment #ep=<version>-<num> déjà résolu par extract_embed_links - Vostfree : langue déduite du titre h1 ou du slug de la fiche - UI : filtre VOSTFR/VF/Tout (défaut VOSTFR), badge par épisode, téléchargement de saison limité à la langue filtrée, compteur d'épisodes unique, version incluse dans le nom de fichier
This commit is contained in:
@@ -28,7 +28,7 @@
|
||||
<div class="title-stats">
|
||||
<span x-show="details.rating"><span class="rating-star">★</span> <strong x-text="details.rating"></strong>/10</span>
|
||||
<span x-show="details.year">Année : <strong x-text="details.year"></strong></span>
|
||||
<span><strong x-text="details.episodes.length"></strong> épisode(s)</span>
|
||||
<span><strong x-text="uniqueEpisodeCount"></strong> épisode(s)</span>
|
||||
</div>
|
||||
<div class="title-actions">
|
||||
<button class="btn" @click="downloadSeason" :disabled="seasonJob.running">
|
||||
@@ -43,11 +43,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="section-title">Épisodes</h2>
|
||||
<h2 class="section-title">Épisodes
|
||||
<span class="version-filter" x-show="epVersions.length" x-cloak>
|
||||
<template x-for="v in epVersions" :key="v">
|
||||
<button class="version-tab" :class="{ active: versionFilter === v }"
|
||||
@click="versionFilter = v" x-text="v.toUpperCase()"></button>
|
||||
</template>
|
||||
<button class="version-tab" :class="{ active: versionFilter === 'all' }"
|
||||
@click="versionFilter = 'all'">Tout</button>
|
||||
</span>
|
||||
</h2>
|
||||
<div class="episode-list">
|
||||
<template x-for="ep in details.episodes" :key="ep.number">
|
||||
<template x-for="ep in filteredEpisodes" :key="ep.number + '-' + (ep.version || '')">
|
||||
<div class="episode-row">
|
||||
<span class="episode-num" x-text="'E' + ep.number"></span>
|
||||
<span class="badge badge-version" x-show="ep.version" x-text="ep.version.toUpperCase()"></span>
|
||||
<span class="episode-name" x-text="ep.title || `Épisode ${ep.number}`"></span>
|
||||
<button class="btn btn-sm btn-ghost" @click="streamEpisode(ep)" :disabled="ep._busy">▶ Stream</button>
|
||||
<button class="btn btn-sm" @click="downloadEpisode(ep)" :disabled="ep._busy">⬇</button>
|
||||
@@ -76,6 +86,23 @@ function titlePage() {
|
||||
details: null, loading: true, error: null, favorite: false,
|
||||
player: { active: false, hls: null },
|
||||
seasonJob: { running: false, done: 0, total: 0 },
|
||||
versionFilter: 'all',
|
||||
|
||||
get epVersions() {
|
||||
if (!this.details) return [];
|
||||
return [...new Set(this.details.episodes.map(e => e.version).filter(Boolean))];
|
||||
},
|
||||
|
||||
get filteredEpisodes() {
|
||||
if (!this.details) return [];
|
||||
if (this.versionFilter === 'all') return this.details.episodes;
|
||||
return this.details.episodes.filter(e => e.version === this.versionFilter);
|
||||
},
|
||||
|
||||
get uniqueEpisodeCount() {
|
||||
if (!this.details) return 0;
|
||||
return new Set(this.details.episodes.map(e => e.number)).size;
|
||||
},
|
||||
|
||||
async load(source, sourceId) {
|
||||
this.source = source; this.sourceId = sourceId;
|
||||
@@ -84,6 +111,7 @@ function titlePage() {
|
||||
if (!res.ok) throw new Error((await res.json()).detail || 'Erreur ' + res.status);
|
||||
this.details = await res.json();
|
||||
this.details.episodes.forEach(e => e._busy = false);
|
||||
this.versionFilter = this.epVersions.includes('vostfr') ? 'vostfr' : 'all';
|
||||
document.title = this.details.title + ' — Ohm Stream';
|
||||
} catch (e) { this.error = e.message; }
|
||||
finally { this.loading = false; }
|
||||
@@ -98,7 +126,10 @@ function titlePage() {
|
||||
return data.links[0];
|
||||
},
|
||||
|
||||
epLabel(ep) { return `${this.details.title} - E${ep.number}`; },
|
||||
epLabel(ep) {
|
||||
const version = ep.version ? ` (${ep.version.toUpperCase()})` : '';
|
||||
return `${this.details.title} - E${ep.number}${version}`;
|
||||
},
|
||||
|
||||
// Lecture via le proxy serveur (tokens liés à l'IP, Referer obligatoire)
|
||||
openPlayer(link) {
|
||||
@@ -148,8 +179,8 @@ function titlePage() {
|
||||
},
|
||||
|
||||
async downloadSeason() {
|
||||
this.seasonJob = { running: true, done: 0, total: this.details.episodes.length };
|
||||
for (const ep of this.details.episodes) {
|
||||
this.seasonJob = { running: true, done: 0, total: this.filteredEpisodes.length };
|
||||
for (const ep of this.filteredEpisodes) {
|
||||
await this.downloadEpisode(ep);
|
||||
this.seasonJob.done++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user