Commit Graph
15 Commits
Author SHA1 Message Date
bruno d1acd1b5b5 style(ui): harmonisation des couleurs par thème + contour fournisseur 1 px
CI / build-and-test (push) Successful in 15m1s
Balayage de la couche d'overrides de index.css : les 75 jetons neutres
slate/zinc/gray qui n'étaient pas couverts (36 fichiers) sont mappés sur les
variables du thème — fonds, textes, bordures, anneaux, divide, placeholders,
dégradés + variants hover/focus/focus-within/disabled/group-hover, alpha via
color-mix. Barre de recherche, menus, panneaux, cartes et résultats de
recherche suivent donc le thème appliqué (dark/light/blue/black) au lieu de la
palette slate figée. Volontairement exclus : bg-white/text-black (boutons
inversés), pastilles « inversées » conditionnelles au thème clair, chrome
au-dessus des vidéos, rouges sémantiques.

Panneau d'informations ⓘ des Shorts re-colorié dans son propre scope
(fond/bordures/textes/pastilles d'action → panel/text/muted), les mêmes tokens
restant blancs ailleurs (rail, méta). Marqueur border-l-4 des titres de page
sur --accent.

Cartes vidéo harmonisées : titre text-sm font-semibold leading-snug
(résultats de recherche, chaîne, thèmes), méta text-xs, rayon rounded-lg sur les
cadres, pastille de durée sans font-mono, titre « Abonnements » avec le
marqueur d'accent.

Contour fournisseur 1 px autour de chaque cadre vidéo, à la couleur du premier
stop du dégradé de la pastille (table unique en CSS, ids longs + courts) :
résultats de recherche, grille chaîne, pages thèmes, watch (lecteur + « à
suivre »), shorts, historique, aimés/à regarder plus tard, détail de playlist.

Tests verts (search, filters, kind, section, highlight, shorts-catalog,
api 41/41) ; vérif UI Playwright desktop 1280x900 + mobile 390x844 sur 4
thèmes : 250 assertions + 13 couleurs de contour au vert.
2026-10-02 16:30:28 -04:00
bruno 99e01c0679 feat(shorts): UI/UX — rail d'actions à droite (flèches ↑/↓), panneau d'infos, glissement magnétique
CI / build-and-test (push) Canceled after 8s
- Supprime les flèches Préc./Suiv. aux bords gauche/droite (troubles
  d'affichage récurrents) : la navigation passe au rail vertical ancré au
  bord DROIT de la vidéo, centré au bureau et ancré au-dessus de la méta
  sur mobile, avec des flèches ↑/↓ plus grosses (44 px).
- Même rail : informations, j'aime, s'abonner (pastille = avatar), commentaires,
  partager, lecture auto. Toujours monté (comme le FAB), désactivé sans vidéo.
- Bouton ⓘ : panneau d'informations (titre, vues, engagement, chaîne,
  description, commentaires → Watch). Colonne à droite au bureau (la vidéo
  rétrécit, jamais masquée : --shorts-panel-w retiré du calcul de taille),
  tiroir plein écran sur mobile. Échap ferme.
- Transition de short : le doigt fait glisser le cadre (chrome solidaire),
  résistance aux extrémités, seuil de bascule 25 % de la hauteur, ressort
  sous le seuil, éjection + emboîtement au-delà (Web Animations, respecte
  prefers-reduced-motion). Aucun état de lecture modifié.
- Lecture auto : interrupteur réel (rail + menu), persisté, respecté par le
  minuteur et par la fin de vidéo YouTube.
- Tap sur un contrôle du rail = plus de play/pause parasite (garde
  isChromeTarget dans onTouchStart/onTouchEnd).
- FAB menu conservé (haut droit, déplaçable) ; son touchmove ne déplace plus
  le cadre en même temps.
2026-10-02 13:37:50 -04:00
bruno e44b545e01 feat(shorts): flèches en ligne avec le menu + fondu des contrôles au repos
CI / build-and-test (push) Successful in 14m54s
Demandes (page /shorts) : retrouver les flèches Préc./Suiv. là où se
trouve le menu, et des contrôles presque invisibles au repos pour
laisser la vidéo respirer (ton pro).

- Flèches déplacées du milieu des côtés vers la rangée HAUTE du cadre,
  centrées : même niveau que le FAB menu, sans chevaucher la flèche
  retour mobile (gauche) ni le FAB (droite). Le toast « Lien copié »
  passe en z-30 pour rester lisible sous la rangée.
- Fondu au repos : nouvelles règles index.css — flèches (.shorts-ctrl)
  et FAB à 0.18 d'opacité quand le chrome est au repos (2,5 s sans
  souris), pleins au moindre mouvement (chromeVisible) ou au survol
  direct (:hover), jamais atténués quand le panneau est ouvert
  (pm-fab-open). Sur tactile, le chrome ne se masque jamais (pas de
  mousemove : comportement voulu, mobile inchangé).
- Le minuteur d'immobilité est armé au chargement (pokeChrome sous
  matchMedia('(hover: hover)')) : sans un premier mousemove,
  chromeVisible restait true et le fondu ne s'armait jamais.
- mouseenter sur l'iframe : en entrant sur la vidéo, le document
  parent ne reçoit pas les mouvements internes à l'iframe — l'entrée
  réveille les contrôles.

Recette Playwright desktop+mobile, 14/14 : position haute centrée,
absence de chevauchements, repos 0.18 (flèches + FAB), retour plein
après mouvement réel, mobile plein en permanence. Build + test:section
verts avant commit.
2026-10-02 11:28:03 -04:00
bruno 4d1d44f4ee feat(shorts): flèches Préc./Suivant SUR la vidéo + embed Rumble en 16:9
CI / build-and-test (push) Canceled after 0s
- Flèches : elles vivaient EN DEHORS du cadre (et se fadaient avec le
  chrome auto-hide). Elles sont désormais posées dans le cadre, à mi-hauteur
  sur les bords, toujours visibles (classe `shorts-chrome` retirée), sur
  mobile comme sur bureau, et le stopPropagation protège le geste tactile.
- Rumble : la plateforme est16:9 mais n'expose ni largeur ni hauteur →
  l'embed tombait dans un cadre 9:16 (étiré / réduit). `isWideEmbed()`
  (pur + testé) décide de la boîte : dimensions connues => orientation
  réelle, sinon repli « rumble = paysage » ; la CSS `.embed-wide` rend une
  iframe 16:9 centrée (434x244 dans un cadre 434x771, mesuré). Les vidéos
  verticales (dimensions connues) gardent le cadre pleine hauteur.
- État vide : un fournisseur sans résultat laissait un cadre NOIR muet
  (ni squelette, ni message) — il affiche désormais « Aucun short à afficher
  pour ce fournisseur » + Réessayer.

Tests : test:shorts-catalog (3 cas isWideEmbed), test:kind, test:section,
test:search verts ; build ng OK ; sondage Playwright local : flèches dans
le cadre + navigation suivant/précédent réelle, boîte embed-wide 16:9
centrée, short vertical inchangé (iframe pleine hauteur), état vide affiché.
2026-10-01 23:37:10 -04:00
bruno 474de0570c fix(shorts): embed PeerTube sur l'instance d'origine + FAB glissable + layout bureau
CI / build-and-test (push) Canceled after 0s
- PeerTube : l'adaptateur pt.ts reconstruisait l'item SANS `url` et le pont
  catalogue ne conservait l'URL que pour Odysee → /shorts reconstruisait
  l'embed sur l'instance ACTIVE → « Sorry this video does not exist » sur
  toute vidéo fédérée. `url` est désormais miroitée dans VideoItem (contrat
  v2), propagée par PtAdapter et gardée par catalogShortToVideo :
  peerTubeHostOf() dérive enfin le host d'origine. Vérifié de bout en bout :
  embed tube.blueben.net → 200 + vrai titre, cas de test dédié dans
  shorts-catalog.spec.
- FAB du menu : déplaçable au pointeur (seuil 6 px, position en % du cadre,
  persistée en localStorage). Le clic qui suit un glissement n'ouvre pas le
  menu, et le panneau s'ouvre TOUJOURS vers l'intérieur du cadre (classes
  pm-opens-left / pm-opens-right / pm-opens-up posées par applyAnchor) :
  sinon overflow:hidden le rognait dès qu'on déplaçait le bouton.
- Bureau : --shorts-chrome 9rem → 4rem (la vidéo passe de 691 à 771 px de
  haut en 1280x900, 389 → 434 de large) et menu compact au-delà de 768 px
  (FAB 36 → 30 px, panneau 233 → 202 px). Mobile inchangé (36 / 636 px).

Tests : test:shorts-catalog (nouveau cas PeerTube), test:kind,
test:section, test:search verts ; build ng OK ; sondage Playwright 19/19
sur l'instance locale (layout, glissement + restauration, embed PeerTube
200 sans erreur).
2026-10-01 23:09:28 -04:00
bruno 82d0a8fb3b fix(menu-fab): navigation du menu correcte sur /shorts + FAB plus compact
CI / build-and-test (push) Canceled after 31s
- app-player-menu : stopPropagation wheel/touchstart/touchend sur le host —
  les handlers window:wheel et window:touch* de /shorts ne volaient plus les
  gestes sur le panneau (impossible de scroller jusqu'en bas du menu, tap =
  play/pause, swipe = changement de short)
- /shorts : ArrowUp/Down ignore quand le menu est ouvert
- /shorts : le FAB passe en haut a DROITE du cadre (la fleche retour mobile
  z-20 passait par-dessus le FAB piege dans la scene z-10)
- Look/taille : FAB 40->36px, panneau 288->240px, items compacts,
  max-height 70vh/480 -> 65vh/430 (plus de rognage par overflow:hidden),
  pastille en degrade + relief, panneau rounded-xl + highlight interne
2026-10-01 08:26:41 -04:00
bruno 7ceec59841 feat(menu-lecteur): refonte UI/UX professionnelle du menu FAB
CI / build-and-test (push) Successful in 14m57s
- FAB : pastille verre depoli 40px + icone sliders (standard options)
- Panneau : en-tete (titre + fermer), verre depoli, ombre profonde, coins arrondis
- Animations ouverture/fermeture (fondu + slide + scale), fermeture Echap + clic exterieur
- Items : hover/active/focus, icones teintees, sections + separateurs raffinés
- Playlist : modale rendue HORS du panneau (backdrop-filter piegeait position:fixed)
2026-10-01 07:20:26 -04:00
bruno 01e0671de9 feat(lecteur): menu FAB partage /watch et /shorts
CI / build-and-test (push) Successful in 14m48s
- PlayerMenuComponent : FAB circulaire translucide (haut-gauche) + panneau
  deroulant, commun aux deux pages (position, style, open/close, clic exterieur)
- /shorts : consolidation de tous les boutons (fournisseurs, langue, actions)
  dans le menu FAB ; suppression du rail a droite et de la rangee du haut
- /watch : actions (cinema, qualite, j'aime, playlist, transcription,
  telechargement, partage, ouvrir) deplacees dans le menu FAB
- AddToPlaylistComponent : variante menuItem pour s'integrer au menu
- styles .pm-item/.pm-sep/.pm-section-label dans index.css
2026-09-30 22:50:46 -04:00
bruno 3e1980283a fix(shorts): hover-chrome, swipe mobile garanti, avance auto fiabilisee
CI / build-and-test (push) Successful in 15m2s
Chrome auto-hide au hover desktop (2,5 s). Capteur tactile mobile : swipe garanti (l'iframe mangeait les touchers), tap = play/pause YT ou 6 s d'acces direct au lecteur sinon. Fleche retour accueil mobile, cadre quasi plein ecran. Avance auto : handshake YT listening (les evenements player n'arrivaient jamais), onStateChange canonique, retry borne anti-prefetch. Docs 9.9.
2026-09-30 12:21:15 -04:00
bruno 8e087daf93 feat(shorts): page /shorts alimentee par le catalogue + refonte pro/mobile
CI / build-and-test (push) Successful in 14m45s
SearchService.fetchCatalogShorts (type shorts via /api/search : cache, provenance, FF) + pont pur shorts-catalog.ts (mapping, meta, fraicheur, spec 27 assertions). WatchShortComponent : catalogue d'abord (feed, pagination, Pour toi), repli legacy, Twitch clips inchanges, avatars paresseux via channelMeta. UI facon YouTube : plein ecran 100dvh, fond d'ambiance, rail overlay 48px, meta/fraicheur/pastille provider, safe-area.
2026-09-30 09:16:56 -04:00
bruno f1f673040e feat(search): panneau de filtres unifié, clavier/focus du typeahead
CI / build-and-test (push) Successful in 14m10s
Barre de recherche
- Panneau de filtres unifié (remplace le ProviderPicker) : sources, type
  (vidéos/shorts/direct/chaînes), période (heure/jour/semaine/mois/année),
  durée (<4 / 4-20 / >20 min) et tri. Pastilles + roving tabindex
  (←/→ dans un groupe, ↑/↓ entre groupes), focus trap, Échap, Ctrl/⌘+Maj+F,
  recherches récentes, « mémoriser par défaut », « Réinitialiser ».
- Pastilles des filtres actifs sous la barre (retrait en un clic) + compteur.
- Typeahead : un seul keydown (fin du double Enter), ↑/↓ bouclants,
  Home/End, PageUp/PageDown, Entrée valide la ligne surlignée (sinon
  recherche brute), Tab complète sans chercher, Échap ferme puis vide,
  ligne « Rechercher <q> », défilement de l'option active, aria à jour.
- Focus : le panneau se referme dès que le focus quitte la barre
  (focusout + relatedTarget + activeElement), pointerdown neutralisé sur les
  lignes pour garder le focus dans l'input (plus de scintillement).
- Opérateurs en clair : `linux live:`, `tuto today: long:` deviennent des
  filtres et sont retirés de la requête (autocomplétion après le `:`).

Filtres côté serveur
- Modèle partagé : src/app/search/filters.ts + server/search-filters.mjs.
- /api/search?type=&duration=&period=&sort= : InnerTube (upload_date, type,
  duration, features), Data API v3 (type, videoDuration, publishedAfter),
  yt-dlp --dateafter ; post-filtrage pour les providers sans filtre natif.
  Un champ manquant ne fait jamais disparaître un résultat.
- Filtres dans l'URL (partageables) + adapters + SearchService (clé de cache).
- Correction : la recherche Shorts renvoyait 0 (ShortsLockupView/GridShelfView
  non mappés, id/titre dans l'endpoint) -> mappage + shelf + vignette/vues.

Tests / docs
- 23 tests unitaires (clavier, focus, opérateurs, panneau de filtres),
  server/tests/search-filters.test.mjs (npm run test:filters) + CI,
  scénarios e2e des filtres, README/api/README/todo/MCP à jour.
2026-09-28 17:42:19 -04:00
bruno 9fb0ce7549 fix(mobile): barre de thèmes masquée, modale @ hors écran, pastille d'avatar
CI / build-and-test (push) Successful in 14m14s
Cinq correctifs signalés sur le mode mobile et le mode desktop.

1. La modale « @ » était confinée dans le header (desktop + mobile)
   <header> portait `backdrop-blur-sm`, et `backdrop-filter` fait de l'élément
   le containing block de ses descendants en position:fixed. Les overlays du
   provider-picker (et du menu Ctrl+K) se résolvaient donc contre le header :
   mesuré 1440x64 au lieu de 1440x900, dialogue réduit à 32px de haut pour 466px
   de contenu, haut de la fenêtre inatteignable.
   Le flou passe sur une couche enfant (`-z-10`) qui n'est pas un ancêtre des
   overlays : `fixed` redevient relatif au viewport.
   Desktop : dialogue 512x468 centré. Mobile : 358x686, entièrement visible.

2. La barre de thèmes disparaissait sous le header (desktop + mobile)
   `--header-offset` vaut 56/64px, mais le header mesure 57/65px (bordure) et
   118px quand la feuille de recherche mobile est ouverte. La barre était donc
   déjà glissée dessous, et totalement invisible dans ce dernier cas
   (hauteur visible mesurée : 0px).
   HeaderComponent publie maintenant sa hauteur réelle dans `--header-measured`
   via ResizeObserver ; `--header-offset` l'utilise quand elle existe et garde
   la valeur statique en repli. Barre visible dans tous les cas, y compris
   feuille de recherche ouverte.

3. Barre de thèmes : icônes seules sur mobile
   Les libellés sont masqués sous md (`aria-label` conservé pour
   l'accessibilité). 7 pastilles visibles au lieu de 3, sans scroll.

4. Avatar en pastille
   `.avatar-circle` est renforcé : `rounded-full` dans le markup plus
   `border-radius: 9999px !important`, `aspect-ratio: 1/1`, min-width/min-height
   et `line-height: 1`, pour qu'aucun style de thème ne puisse le dégrader en
   rectangle.

Vérifié : audit navigateur sur 17 routes x 320/390/768/1440 px — aucun
débordement horizontal, barre de thèmes visible partout ; tests du dépôt verts ;
build production OK.
2026-09-28 16:25:55 -04:00
bruno 66f1da1d72 feat(mobile): refonte responsive complète (header, drawer, dvh, cibles tactiles)
Le header était en grid-cols-[auto_1fr_auto] avec une barre de recherche
non-wrappable (7 chips + input + 2 boutons, aucun min-w-0) : ~1000px de
largeur intrinsèque dans un viewport de 375px. Toutes les routes
débordaient horizontalement et les boutons Connexion/Inscription partaient
hors écran.

Socle
- --header-h / --header-offset / --app-vh centralisent la métrique du
  header : supprime les top-16 codés en dur (channel-tabs était en top-0 et
  glissait sous le header au scroll).
- Safe-area iOS, viewport-fit=cover, color-scheme/theme-color.
- dvh partout (100vh > hauteur visible sur iOS), overflow-x: clip au lieu de
  hidden (hidden cassait silencieusement tous les sticky).
- Cible tactile 44px sur pointeur grossier, skip link, focus-ring clavier,
  scroll-rail pour les tab strips.

Header
- Barre mobile (burger, logo, recherche, menu ⋮) + barre desktop inchangée.
- Le menu ⋮ expose ce qui disparaissait : bande des thèmes, préférences,
  historique, favoris, téléchargements, thème, connexion/inscription.
- Recherche en feuille sous le header avec focus automatique.
- Échap / clic extérieur / navigation ferment les panneaux transitoires.

Drawer
- Partait à inset-y-0 : les 56 premiers px du menu étaient derrière le
  header. Descend sous le header, bouton fermer intégré, verrouille le
  scroll, se ferme à Échap.

Barre de recherche
- Chips masquées sous lg, remplacées par un bouton résumé qui ouvre le
  sélecteur de fournisseurs. Suggestions en dvh, menu Ctrl+K plein écran
  sur mobile.

Pages
- Shorts : cadre 9:16 contraint par dvh ET vw (il débordait en paysage),
  Préc./Suiv. qui étaient hors du conteneur height-capped.
- Watch : barre d'actions qui wrappe, mode cinéma en opacity-0 group-hover
  donc invisible au doigt, thumbnails fluides, playsinline sur les iframes.
- Historique, thèmes, chaîne, playlists, préférences, sessions : rails
  swipables, min-w-0, truncate, en-têtes qui wrappent.

Vérifié : audit navigateur (CDP) sur 17 routes x 7 largeurs (320→1440),
zéro débordement horizontal ; 19 tests d'interaction mobile ; suites de
tests du dépôt vertes (api 40/40, transcript 27/27, search, suggest,
playlists, preferences, subscriptions, highlight, telemetry).
2026-09-28 14:38:31 -04:00
bruno 1b0a7eb3ce feat(sidebar): accordeon unique strict, Plus/Moins, scroll au survol
CI / build-and-test (push) Failing after 8m17s
2026-09-26 11:20:54 -04:00
bruno 2866d74b32 first commit 2025-09-14 23:05:30 -04:00