# Étape 18.4 - Chaînes personnelles + chargement vidéos + SponsorBlock Cette étape corrige les trois points remontés après la capture du menu Chaînes. ## 1. Les vidéos d'une chaîne se chargent réellement La page chaîne essaie maintenant en priorité le chemin officiel déjà présent dans l'application : ```text Google OAuth youtube.readonly ↓ channels.list -> playlist uploads ↓ playlistItems.list (pagination de 50) ↓ videos.list (durée + vues + date) ↓ affichage progressif ``` Elle ne s'arrête plus aux 30 vidéos de l'ancienne version et suit `nextPageToken` jusqu'à la fin de la playlist d'uploads. Si le compte Google n'est pas disponible, elle bascule sur le chemin public `youtube_explode_dart.getUploadsFromPage()`. ## 2. Le classement Chaînes utilise MES vues Le classement précédent utilisait les vues publiques YouTube. C'était une mauvaise interprétation de la demande. Nouveau classement : ```text #1 chaîne avec le plus de lectures dans YouTube Personal #2 ... #3 ... ``` Chaque ouverture réelle d'une vidéo incrémente un compteur local : ```text youtube_personal.watch_counts.v1 ``` Un changement 1080p -> 4K ne compte PAS comme une nouvelle vue. Les anciennes entrées de l'historique sont migrées avec au moins 1 vue par vidéo, car l'application ne peut pas reconstruire les répétitions passées qu'elle n'enregistrait pas encore. Carte exemple : ```text 12 de mes vues • 4 vidéos différentes La plus regardée par moi (5×) : ... ``` ## 3. Une chaîne ne m'intéresse pas Menu `...` d'une chaîne : ```text Cette chaîne ne m'intéresse pas ``` La chaîne est alors : ```text - retirée du menu Chaînes - exclue des prochaines recommandations Radar - mémorisée localement ``` Un bouton ANNULER apparaît immédiatement après le masquage. La page complète de la chaîne possède aussi : ```text Ne plus me proposer cette chaîne ``` L'historique existant n'est pas détruit. ## 4. Sponsors intégrés aux vidéos Ajout de SponsorBlock, catégorie `sponsor` uniquement. YouTube Personal récupère les segments connus et, lorsque la lecture entre dans l'un d'eux : ```text lecture normale ↓ début sponsor détecté ↓ seek automatique à la fin du sponsor ↓ lecture continue ``` Notification courte : ```text Sponsor ignoré automatiquement • 34s ``` Le mécanisme fonctionne dans le lecteur Windows/Android et aussi dans le Player audio Android lorsque l'écran est verrouillé. ### Vie privée SponsorBlock Le client utilise l'endpoint k-anonymity : il calcule SHA-256(videoId) et n'envoie au serveur que les 4 premiers caractères du hash. Il filtre ensuite localement la réponse pour retrouver la vidéo exacte. Seule la catégorie `sponsor` est ignorée. Les intros, outros, rappels de s'abonner et autres catégories ne sont pas sautés. ## Test Extraire le ZIP à la racine puis : Windows : ```powershell cd "D:\07-Logiciels\23-youtube_personal" flutter run -d windows ``` Android : ```powershell cd "D:\07-Logiciels\23-youtube_personal" flutter run -d f10778d8 ``` Pas besoin de `flutter clean`. ### Vérifications 1. Menu Chaînes : le texte doit afficher `mes vues`, plus les millions de vues publiques. 2. Ouvrir deux fois une vidéo, revenir dans Chaînes : le compteur augmente. 3. Changer seulement la qualité : le compteur ne doit pas augmenter. 4. Cliquer une chaîne : les vidéos doivent commencer à apparaître. 5. Tester `Plus vues sur YouTube` dans la page de la chaîne. 6. Masquer une chaîne puis vérifier qu'elle disparaît du Radar. 7. Sur une vidéo connue de SponsorBlock, chercher le log : ```text [SPONSORBLOCK] ... segment(s) sponsor trouvé(s) [SPONSORBLOCK] skip ... ```