Coller un lien de playlist (youtube.com/playlist?list=...) dans le champ URL affiche toutes ses videos dans la meme zone de resultats que la recherche de chaine ; chaque ligne a son bouton "Ajouter", et un bouton "Tout ajouter a la file" ajoute le reste d'un coup. Serveur : - GET /api/playlist (PlaylistDiscoveryService) : yt-dlp --flat-playlist -J. -J plutot que -j : le titre de la playlist n'existe qu'a la racine, et une playlist vide reste un resultat valide. - playlistUrl.ts : n'accepte que les liens youtube.com/playlist?list=<id> et reconstruit l'URL canonique depuis le seul identifiant valide (rien d'autre de l'entree n'atteint yt-dlp). Un lien watch?v=...&list=... reste une video (--no-playlist etait deja passe au telechargement). - videoSummary.ts : conversion d'une entree --flat-playlist en resume de video, extraite de ChannelDiscoveryService pour etre partagee (chaine et playlist parsent desormais identiquement). ChannelVideoSummary devient VideoSummary (et ChannelVideoDto -> VideoDto cote client). Client : - Le champ URL accepte video ou playlist (isPlaylistUrl aiguille) ; zone de resultats partagee (createResultsView). - "Tout ajouter" : POST /api/queue sequentiels (ordre conserve, pas de doublon avec les lignes deja ajoutees). Un echec n'interrompt pas le lot : nombre d'echecs + premier message affiches, seules les lignes en echec redeviennent ajoutables. Le mode est lu une seule fois pour tout le lot. - Miniatures de resultats en loading="lazy" (une playlist peut compter des centaines de videos). Verifie contre le vrai yt-dlp (2026.07.04) : forme reelle de -J relevee (fixtures de test calquees dessus), playlist de 1607 videos listee en ~11 s (delai fixe a 120 s). Teste dans le navigateur reel : playlist de 13 videos, ajout unitaire, "tout ajouter" (13 elements, aucun doublon), echec partiel simule + reprise, playlist inexistante, lien video avec list=, recherche de chaine (non-regression). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
64 lines
2.3 KiB
HTML
64 lines
2.3 KiB
HTML
<div class="download-form">
|
|
<h2>Ajouter des vidéos</h2>
|
|
|
|
<fieldset class="download-form__mode">
|
|
<legend>Mode</legend>
|
|
<label><input type="radio" name="mode" value="video" checked /> Vidéo</label>
|
|
<label><input type="radio" name="mode" value="audio" /> Audio</label>
|
|
<label><input type="radio" name="mode" value="thumbnail" /> Miniature seule</label>
|
|
</fieldset>
|
|
|
|
<div class="download-form__options" data-mode-options="video">
|
|
<label><input type="checkbox" data-field="subtitles" /> Sous-titres (fr/en)</label>
|
|
<label><input type="checkbox" data-field="embedThumbnail" /> Miniature embarquée</label>
|
|
</div>
|
|
<div class="download-form__options" data-mode-options="audio" hidden>
|
|
<label>
|
|
Format
|
|
<select data-field="audioFormat">
|
|
<option value="mp3">MP3</option>
|
|
<option value="m4a">M4A</option>
|
|
<option value="opus">Opus</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
|
|
<form class="download-form__form" data-form="url">
|
|
<label class="download-form__field">
|
|
URL (vidéo ou playlist)
|
|
<input type="url" name="url" placeholder="https://www.youtube.com/..." required />
|
|
</label>
|
|
<button type="submit">Ajouter</button>
|
|
</form>
|
|
<p class="download-form__error" data-role="url-error" hidden></p>
|
|
|
|
<hr />
|
|
|
|
<form class="download-form__form" data-form="channel">
|
|
<label class="download-form__field">
|
|
Chaîne (@handle ou URL)
|
|
<input type="text" name="channel" placeholder="@nomdelachaine" required />
|
|
</label>
|
|
<label class="download-form__field">
|
|
Section
|
|
<select name="section">
|
|
<option value="videos">Vidéos</option>
|
|
<option value="streams">Streams</option>
|
|
</select>
|
|
</label>
|
|
<label class="download-form__field">
|
|
Mots-clés (optionnel, séparés par des virgules)
|
|
<input type="text" name="keywords" placeholder="mot-clé1, mot-clé2" />
|
|
</label>
|
|
<button type="submit">Rechercher</button>
|
|
</form>
|
|
<p class="download-form__error" data-role="channel-error" hidden></p>
|
|
|
|
<div class="download-form__results-header" data-role="results-header" hidden>
|
|
<p class="download-form__status" data-role="results-status"></p>
|
|
<button type="button" class="secondary" data-role="add-all" hidden>Tout ajouter à la file</button>
|
|
<p class="download-form__error" data-role="results-error" hidden></p>
|
|
</div>
|
|
|
|
<ul class="download-form__results" data-role="results"></ul>
|
|
</div>
|