Commit graph

2 commits

Author SHA1 Message Date
f0dec86b19 feat: playlists YouTube (parcourir, ajouter une par une ou d'un coup)
Some checks failed
Publier l'image Docker / test (pull_request) Failing after 4s
Publier l'image Docker / publish (pull_request) Has been skipped
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>
2026-09-19 14:55:38 +02:00
725c5a5a7f feat(client): frontend (formulaire d'ajout + file d'attente)
Interface web complète : formulaire d'ajout (URL directe ou recherche de
chaîne) et panneau de file d'attente avec sondage de la progression.

- views/downloadForm/ : sélecteur de mode (vidéo/audio/miniature) partagé,
  ajout direct par URL, recherche de chaîne (GET /api/channel) avec ajout
  par résultat. Construction DOM via createElement/textContent (jamais
  d'innerHTML avec du texte venant de YouTube), pas juste par prudence :
  ça évite aussi tout risque d'injection depuis un titre de vidéo.
- views/queuePanel/ : sonde GET /api/queue toutes les 1,5s, affiche statut/
  progression/erreur par élément, annulation et lien de téléchargement
  natif (<a download>, pas de fetch+blob).
- api/ : clients fetch typés (channelApi, queueApi), chaque await dans son
  propre try/catch avec message d'erreur adapté (réseau vs HTTP vs JSON).
- QueueItem gagne un champ title optionnel (purement informatif, jamais
  utilisé pour construire la commande yt-dlp) pour un affichage plus
  parlant qu'une URL brute.
- client/tsconfig.json + build.mjs : cible ES2022 (nécessaire pour
  Error.cause, jusque-là ES2020).
- Vitest ajouté côté client (fonctions pures de src/format.ts ; le câblage
  DOM est vérifié manuellement, pas de jsdom pour l'instant).

Deux bugs réels trouvés et corrigés en testant dans un vrai navigateur
(pas seulement en lisant le code) :
- CSS : un attribut `hidden` sur un conteneur `display: flex` se faisait
  écraser par cette règle (même spécificité, la feuille de l'auteur gagne)
  - les deux panneaux d'options restaient visibles en même temps.
- server/src/routes/channel.ts : ne mappait vers 502 que les YtDlpError
  (code de sortie non nul), pas les erreurs brutes de spawn (ex. binaire
  introuvable - ENOENT), qui remontaient donc en 500 générique. Corrigé +
  test de non-régression.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 09:28:49 +02:00