fix(shorts): orientation autoritaire, langues YouTube et autoplay fiable
CI / build-and-test (push) Successful in 14m18s
CI / build-and-test (push) Successful in 14m18s
- format: des que largeur/hauteur sont connues, l'orientation fait autorite (horizontale/carree => jamais short, meme <75 s). Repli duree reserve aux providers muets - dimensions mappees: Dailymotion (width,height), PeerTube (aspectRatio), Odysee (value.video.width/height) => validation verticale reelle - YouTube: langue via snippet.defaultAudioLanguage (filtre FR/EN) - autoplay: demarrage muet, suppression du deblocage automatique au scroll/selection (reload d'embed hors geste => ecran noir); son via le bouton dedie - PeerTube embed: muted=1 pour l'autoplay - server/search-filters.mjs: miroir de la regle d'orientation + tests mis a jour
This commit is contained in:
@@ -83,15 +83,14 @@ export class WatchShortComponent implements OnDestroy {
|
||||
frameRef = viewChild<ElementRef<HTMLElement>>('shortsFrame');
|
||||
/**
|
||||
* Son coupé ou non. Démarrer MUET est la seule façon d'obtenir l'autoplay
|
||||
* garanti des iframes (politique navigateur) : c'est aussi ce que fait la
|
||||
* page Watch (mute=1). Le son est rétabli automatiquement à la première
|
||||
* interaction (clic/molette/tactile) via `unlockSound()`, et l'utilisateur
|
||||
* peut couper/réactiver via le bouton. Rebasculer recharge l'embed.
|
||||
* garanti des iframes (politique navigateur) — c'est aussi ce que fait la
|
||||
* page Watch (mute=1). L'utilisateur active le son via le bouton dédié :
|
||||
* un clic sur ce bouton recharge l'embed AVEC son tout en restant dans un
|
||||
* contexte de geste utilisateur (autoplay autorisé). On ne débloque jamais
|
||||
* le son automatiquement : recharger l'embed pendant un scroll relançait un
|
||||
* embed non lisible (écran noir).
|
||||
*/
|
||||
muted = signal(true);
|
||||
/** L'utilisateur a-t-il touché au bouton son ? (sinon on débloque en auto). */
|
||||
private muteTouched = false;
|
||||
private soundUnlocked = false;
|
||||
/**
|
||||
* Embed Rumble autoritaire : id demandé -> vrai id scrapé via
|
||||
* /api/rumble/video/<id> (comme /watch). Les IDs de liste approximatifs
|
||||
@@ -243,7 +242,8 @@ export class WatchShortComponent implements OnDestroy {
|
||||
// : on la dérive de l'URL vidéo, avec repli sur l'instance active.
|
||||
// "Sorry this video does not exist" venait d'un mauvais host.
|
||||
const inst = this.peerTubeHostOf(v) || this.instances.activePeerTubeInstance();
|
||||
const u = `https://${inst}/videos/embed/${encodeURIComponent(v.videoId)}?autoplay=1&api=1`;
|
||||
// `muted=1` est requis pour que l'autoplay ne soit pas bloqué.
|
||||
const u = `https://${inst}/videos/embed/${encodeURIComponent(v.videoId)}?autoplay=1&muted=${this.muted() ? 1 : 0}&api=1`;
|
||||
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
|
||||
}
|
||||
if (p === 'odysee') {
|
||||
@@ -521,21 +521,9 @@ export class WatchShortComponent implements OnDestroy {
|
||||
|
||||
// ---- Actions façon YouTube Shorts ----
|
||||
toggleMute(): void {
|
||||
this.muteTouched = true;
|
||||
this.muted.update(m => !m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Première interaction de l'utilisateur : le navigateur autorise alors un
|
||||
* embed avec son. On débloque le son une seule fois, sauf si l'utilisateur
|
||||
* a déjà choisi explicitement (mute activé manuellement).
|
||||
*/
|
||||
unlockSound(): void {
|
||||
if (this.soundUnlocked || this.muteTouched || !this.muted()) return;
|
||||
this.soundUnlocked = true;
|
||||
this.muted.set(false);
|
||||
}
|
||||
|
||||
toggleFullscreen(): void {
|
||||
try {
|
||||
if (document.fullscreenElement) {
|
||||
|
||||
Reference in New Issue
Block a user