feat(shorts): vraie variété du flux a chaque chargement
CI / build-and-test (push) Successful in 15m2s

Trois causes du « toujours les mêmes vidéos » (peu importe le fournisseur) :

- watch-short : queryIndex repartait à 0 a chaque loadFeed() -> toujours la
  même requête (« shorts ») et donc les mêmes résultats du fournisseur.
  Départ désormais aléatoire dans SHORTS_QUERIES (la rotation par page reste).
- watch-short : dedup() ne triait rien -> le 1er lot arrivait toujours dans
  l'ordre du fournisseur. Le lot neuf est maintenant mélangé (Fisher-Yates),
  comme le chemin « Pour toi » le fait déjà. Un seul point de passage, donc
  catalogue, historique, repli trending et Twitch sont couverts.
- youtube-api : la rotation des top games Twitch démarrait à l'index 0 ->
  mêmes clips à chaque session. Départ aléatoire, rotation conservée.

Le cache serveur (5 min / 30 min YT) n'est pas en cause.

Vérif instance locale : YouTube 3/3 premières vidéos distinctes sur 3
rechargements, Twitch 2 distinctes sur 3. tests verts.
This commit is contained in:
2026-10-01 12:58:47 -04:00
parent f3fd57014a
commit 88a2d21133
2 changed files with 18 additions and 4 deletions
+15 -3
View File
@@ -1471,8 +1471,11 @@ export class WatchShortComponent implements OnDestroy {
this.index.set(0);
this.nextCursor.set(null);
this.seenIds = new Set<string>();
this.queryIndex = 0;
this.exhaustedQueries = new Set<string>();
// Requête de départ ALÉATOIRE : sinon chaque rechargement repart de la
// même recherche (« shorts ») et le fournisseur renvoie les mêmes vidéos
// jour après jour.
this.queryIndex = Math.floor(Math.random() * this.queriesFor(this.provider()).length);
this.exhaustedQueries = new Set();
this.catalogActive = false;
this.catalogError.set(null);
const ready = this.instances.getProviderReadiness(this.provider());
@@ -1772,7 +1775,12 @@ export class WatchShortComponent implements OnDestroy {
);
}
/** Dedup inter-pages (clé videoId + provider). */
/**
* Dedup inter-pages (clé videoId + provider) + mélange du lot neuf.
* Le mélange est volontaire : un rechargement du flux Shorts ne doit pas
* présenter les mêmes vidéos dans le même ordre (même chemin Pour toi,
* qui mélange déjà ses lots par sujet).
*/
private dedup(list: Video[]): Video[] {
const out: Video[] = [];
for (const v of list) {
@@ -1781,6 +1789,10 @@ export class WatchShortComponent implements OnDestroy {
this.seenIds.add(key);
out.push(v);
}
for (let i = out.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[out[i], out[j]] = [out[j], out[i]];
}
return out;
}
+3 -1
View File
@@ -1765,7 +1765,9 @@ export class YoutubeApiService {
// tourne sur les top games, ce qui donne toujours des clips récents.
// Curseur opaque : "<gameId>::<paginationCursor>" (pagination vide = page 1).
private twitchTopGameIds: string[] | null = null;
private twitchGameIdx = 0;
// Index de départ ALÉATOIRE : un rechargement ne repart pas toujours du
// même jeu (sinon mêmes clips jour après jour). `++` garde la rotation.
private twitchGameIdx = Math.floor(Math.random() * 1000);
private twitchClipsSinceDays = 30;
private getTwitchTopGameIds(): Observable<string[]> {