fix(shorts): anti-Forbidden Dailymotion + selecteur icon-only
CI / build-and-test (push) Successful in 14m55s

- DM: embed mute par defaut (comme /watch) + son sur action explicite
- helmet: Referrer-Policy strict-origin-when-cross-origin (Dailymotion exige un Referer)
- searchVideosPage DM: champs allow_embed/width/height/language/owner.id
- iframes shorts/watch: allow fullscreen (conforme embed officiel DM)
- selecteur shorts icon-only (pastilles + globe cyclique)
This commit is contained in:
2026-09-30 19:55:23 -04:00
parent 49859f4e81
commit 6b20b1ce79
6 changed files with 61 additions and 32 deletions
+22 -3
View File
@@ -1,6 +1,5 @@
import { ChangeDetectionStrategy, Component, computed, effect, ElementRef, inject, signal, viewChild, HostListener, OnDestroy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterLink } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
@@ -24,6 +23,7 @@ import {
formatCapturedAgo,
normalizeShortsLangMode,
resolveShortsLangs,
SHORTS_LANG_MODES,
type ShortsLangMode,
SHORTS_CATALOG_PAGE_SIZE,
SHORTS_CATALOG_MIN_ITEMS,
@@ -86,7 +86,7 @@ const SHORTS_QUERIES: Record<string, string[]> = {
selector: 'app-watch-short',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule, FormsModule, RouterLink],
imports: [CommonModule, RouterLink],
templateUrl: './watch-short.component.html'
})
export class WatchShortComponent implements OnDestroy {
@@ -244,6 +244,17 @@ export class WatchShortComponent implements OnDestroy {
try { this.loadFeed(); } catch {}
}
/**
* Globe cyclique (bouton icon-only) : Profil → Français → Anglais →
* FR+EN → Toutes → Profil… Le filtre actif se lit dans le tooltip et
* l'anneau ambré ; aucun texte affiché.
*/
cycleLangFilter(): void {
const order = [...SHORTS_LANG_MODES];
const at = order.indexOf(this.langFilter());
this.setLangFilter(order[(at + 1) % order.length]);
}
/** Langues effectives : `[]` = aucune restriction (tout passe). */
private effectiveShortsLangs(): string[] {
try {
@@ -367,7 +378,15 @@ export class WatchShortComponent implements OnDestroy {
// Nouveau player obligatoire depuis fév. 2026 (l'ancien /embed est
// coupé et répond "Forbidden"). Seuls mute/startTime/loop passent
// en query sans Player ID ; autoplay est tenté au mieux.
const u = `https://geo.dailymotion.com/player.html?video=${encodeURIComponent(v.videoId)}&mute=${this.muted() ? 1 : 0}&autoplay=1`;
// Correctif bug "Forbidden" systématique en Shorts alors que /watch
// (toujours muet) joue la même vidéo : on démarre MUET comme /watch
// (même URL, mute=1) et on ne passe au son QUE sur action explicite
// du bouton Son — le clic EST le geste qui autorise le son (même
// motif que le player Odysee, cf. soundTouched). L'autoplay sonore
// sans geste préalable est bloqué et le player par défaut l'affiche
// comme "Forbidden".
const withSound = !this.muted() && this.soundTouched();
const u = `https://geo.dailymotion.com/player.html?video=${encodeURIComponent(v.videoId)}&mute=${withSound ? 0 : 1}&autoplay=1`;
return this.sanitizer.bypassSecurityTrustResourceUrl(u);
}
if (p === 'twitch' && v.videoId) {