feat(library): liste « À regarder plus tard » (watch later)
CI / build-and-test (push) Successful in 14m55s
CI / build-and-test (push) Successful in 14m55s
Nouvelle liste dans la section Vous de la barre latérale, avec un bouton horloge a cote du coeur sur toutes les cartes (accueil, themes, provider- themes, recherche). - db : les 4 fonctions de listes (like/unlike/isLiked/list) prennent un paramètre `tag` — la table `tags` sert déjà de mot-clés génériques, donc zéro migration. - api : les 4 routes likes sont générées par registerVideoTagRoutes(prefix, tagName) ; /api/user/watch-later = même fabrique, même enrichissement yt-dlp, même middleware cookie-aware. Entrée OpenAPI ajoutée. - front : LikesService prend un VideoTag, like-button un @Input() list (icône horloge, ambre quand enregistré, libellés a11y dédiés) — un seul composant pour les deux boutons, pas de copie. - cartes de recherche : la grille partagée n'avait AUCUN bouton ; cœur + horloge ajoutés, masqués sur les lives et cartes chaîne (coin bas-gauche déjà occupé par le compteur de spectateurs / pas des vidéos). - route /library/watch-later = LikedComponent via data.list (titre, icône, placeholder et état vide pilotés par la route), clés nav.watchLater FR/EN. Tests : npm run test:api 41/41 (nouveau test watch-later : ajout, statut, indépendance vis-à-vis des likes, liste, retrait, 400, 401) + 21 autres suites vertes. Build OK, instance locale 4200 rebuildée. Sondage Playwright desktop+mobile : 12/14 (2 faux positifs du sondage : accordéon replié sur une route hors /library, 3×401 console pendant la phase déconnectée).
This commit is contained in:
@@ -42,6 +42,13 @@
|
||||
<span *ngIf="showClipBadge" class="rounded bg-orange-600 px-1.5 py-0.5 text-[11px] font-bold text-white">CLIP</span>
|
||||
<span *ngIf="showChannelBadge" class="rounded bg-slate-700/90 px-1.5 py-0.5 text-[11px] font-bold text-slate-200 ring-1 ring-slate-500/50">CHAÎNE</span>
|
||||
</div>
|
||||
<!-- Like + « à regarder plus tard », sur la miniature comme sur les
|
||||
cartes de thème. Masqués pour un live (badge LIVE en haut à gauche)
|
||||
et une carte chaîne : ce ne sont pas des vidéos. -->
|
||||
<div *ngIf="!showChannelBadge && !showLiveBadge" class="absolute bottom-1 left-1 flex items-center gap-1">
|
||||
<app-like-button [videoId]="video.id" [provider]="video.provider" [title]="video.title" [thumbnail]="video.thumbnailUrl"></app-like-button>
|
||||
<app-like-button [list]="'watch-later'" [videoId]="video.id" [provider]="video.provider" [title]="video.title" [thumbnail]="video.thumbnailUrl"></app-like-button>
|
||||
</div>
|
||||
<span *ngIf="showDuration" class="absolute bottom-1 right-1 rounded bg-black/80 px-1.5 py-0.5 text-xs text-white">
|
||||
{{ video.durationSec | duration }}
|
||||
</span>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { DurationPipe } from '../../pipes/duration.pipe';
|
||||
import { ProviderBadgeComponent } from '../provider-badge/provider-badge.component';
|
||||
import { SubscribeButtonComponent } from '../subscribe-button/subscribe-button.component';
|
||||
import { ChannelIdentityComponent } from '../channel-identity/channel-identity.component';
|
||||
import { LikeButtonComponent } from '../../../../components/shared/components/like-button/like-button.component';
|
||||
import type { ChannelMeta, ProviderId } from '../../models/channel.model';
|
||||
import { toShortProviderId } from '../../providers/provider-ids';
|
||||
import { isLiveVideoItem, isShortVideoItem, isVerticalVideoItem, videoAspectRatio, verticalFrameWidthPercent } from '../../utils/video-kind';
|
||||
@@ -16,7 +17,7 @@ import { capturedAgoLabel, sourceLabel } from '../../../search/adapters/provenan
|
||||
templateUrl: './video-card.component.html',
|
||||
styleUrls: ['./video-card.component.scss'],
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink, DurationPipe, ProviderBadgeComponent, SubscribeButtonComponent, ChannelIdentityComponent],
|
||||
imports: [CommonModule, RouterLink, DurationPipe, ProviderBadgeComponent, SubscribeButtonComponent, ChannelIdentityComponent, LikeButtonComponent],
|
||||
})
|
||||
export class VideoCardComponent implements OnChanges {
|
||||
@Input() video!: VideoItem;
|
||||
|
||||
Reference in New Issue
Block a user