fix(shorts): flèches aux bords gauche/droite, toujours montées, visibles
CI / build-and-test (push) Successful in 14m55s

Retour utilisateur : les flèches Préc./Suiv. n'étaient toujours pas
visibles et la position attendue est précisée — une à GAUCHE et une à
DROITE de la vidéo, centrées verticalement.

- Flèches remises aux bords gauche/droite du cadre (top-1/2,
  -translate-y-1/2) avec contraste renforcé : ring-2 white/50, fond
  black/55 — lisibles sur toute image.
- Sorties de @if (current()) comme le menu : TOUJOURS montées, donc
  présentes même sur l'état de flux mort (désactivées) — on ne cherche
  plus où naviguer.
- Chaque changement de vidéo réveille les contrôles 2,5 s (poke sous
  matchMedia hover : sur tactile le chrome reste visible en permanence,
  un poke y aurait armé le minuteur et masqué le chrome — régression
  détectée par la recette mobile puis corrigée).
- Recette Playwright desktop+mobile : 17/17 (bords à 6 px, centrage
  vertical ±1 px, fondu repos 0.18, plein au mouvement, mobile plein,
  pas de chevauchement 2D avec la flèche retour, flèches + menu
  présents sur feed mort). Build + test:section + test:shorts-catalog
  verts avant commit.
This commit is contained in:
2026-10-02 12:34:13 -04:00
parent e44b545e01
commit 6b32ede302
2 changed files with 20 additions and 17 deletions
@@ -146,6 +146,21 @@
<span class="pm-item-label">Passer (vidéo illisible)</span>
</button>
</app-player-menu>
<!-- Navigation précédent / suivant : TOUJOURS montés (comme le menu),
aux bords GAUCHE/DROITE de la vidéo, centrés verticalement —
présents même sans vidéo (désactivés). Contraste renforcé pour
rester lisibles sur toute image ; fondu au repos (.shorts-ctrl,
index.css), stopPropagation dans les handlers. -->
<button type="button" (click)="prev(); $event.stopPropagation()" [disabled]="!canPrev()"
class="shorts-ctrl absolute left-1.5 top-1/2 z-20 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/55 text-white ring-2 ring-white/50 backdrop-blur-md transition hover:bg-black/75 disabled:opacity-40"
aria-label="Short précédent">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M15.5 4.5 8 12l7.5 7.5z"/></svg>
</button>
<button type="button" (click)="next(); $event.stopPropagation()" [disabled]="!canNext()"
class="shorts-ctrl absolute right-1.5 top-1/2 z-20 flex h-10 w-10 -translate-y-1/2 items-center justify-center rounded-full bg-black/55 text-white ring-2 ring-white/50 backdrop-blur-md transition hover:bg-black/75 disabled:opacity-40"
aria-label="Short suivant">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8.5 4.5 16 12l-7.5 7.5z"/></svg>
</button>
@if (current(); as v) {
<!-- Capteur tactile (mobile uniquement) : l'iframe mange les
@@ -206,23 +221,6 @@
}
</div>
<!-- Navigation précédent / suivant : MÊME LIGNE que le menu (haut
du cadre, centré pour ne pas chevaucher la flèche retour mobile
ni le FAB) — on les retrouve là où se trouve le menu.
Classe shorts-ctrl : fondu au repos, pleins au mouvement/
survol (index.css). stopPropagation dans les handlers. -->
<div class="absolute left-1/2 top-1.5 z-20 flex -translate-x-1/2 gap-2">
<button type="button" (click)="prev(); $event.stopPropagation()" [disabled]="!canPrev()"
class="shorts-ctrl flex h-10 w-10 items-center justify-center rounded-full bg-black/45 text-white ring-1 ring-white/15 backdrop-blur-md transition hover:bg-black/70 disabled:opacity-40"
aria-label="Short précédent">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M15.5 4.5 8 12l7.5 7.5z"/></svg>
</button>
<button type="button" (click)="next(); $event.stopPropagation()" [disabled]="!canNext()"
class="shorts-ctrl flex h-10 w-10 items-center justify-center rounded-full bg-black/45 text-white ring-1 ring-white/15 backdrop-blur-md transition hover:bg-black/70 disabled:opacity-40"
aria-label="Short suivant">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M8.5 4.5 16 12l-7.5 7.5z"/></svg>
</button>
</div>
}
@if (shareCopied()) {
@@ -684,6 +684,11 @@ export class WatchShortComponent implements OnDestroy {
if (!v) return;
const nx = (i >= 0 && i + 1 < list.length) ? list[i + 1] : null;
this.queueRumbleResolves([v, nx]);
// Chaque nouvelle vidéo réveille les contrôles (flèches + menu) pendant
// 2,5 s : après un swipe, on doit voir où naviguer sans chercher.
// Desktop seulement (hover) : sur tactile le chrome reste visible en
// permanence, un poke y armerait le minuteur et masquerait le chrome.
try { if (matchMedia('(hover: hover)').matches) this.pokeChrome(); } catch {}
// Avatar paresseux via le catalogue (`channelMeta`) : le flux n'affiche
// plus une image cassée quand la recherche ne fournit pas d'avatar.
this.ensureAvatar(v);