diff --git a/src/app/shared/components/provider-icon/provider-icon.component.ts b/src/app/shared/components/provider-icon/provider-icon.component.ts index 14c7d0e..0eb6114 100644 --- a/src/app/shared/components/provider-icon/provider-icon.component.ts +++ b/src/app/shared/components/provider-icon/provider-icon.component.ts @@ -3,70 +3,77 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; /** Clés courtes du registre fournisseurs (provider-registry.ts). */ export type ProviderIconKey = 'yt' | 'dm' | 'tw' | 'pt' | 'od' | 'ru'; +interface ProviderBrand { + /** Nom affiché, utilisé pour les libellés accessibles. */ + label: string; + /** Couleur de marque officielle. */ + color: string; + /** Tracé 24×24. */ + path: string; +} + /** - * Marque d'une source, dessinée au trait et colorée en `currentColor` : - * - l'icône hérite de la couleur du bouton, donc l'état actif / masqué - * reste lisible sans ajouter une pastille de couleur à côté ; - * - un seul style graphique pour les six sources, cohérent avec les icônes - * d'interface (œil, chevron…) de la même barre. + * Marques officielles des six sources, aux couleurs de marque. * - * Les formes sont volontairement géométriques et sobres : l'identité vient du - * geste (bouton lecture, bulle de discussion, initiale), pas d'un logo coloré - * qui ne serait plus lisible une fois réduit à 18 px. + * Tracés issus de Simple Icons (CC0-1.0) et stockés en local : aucune + * requête vers un CDN au runtime, donc rien à afficher en cas de réseau + * lent ou de politique CSP. Une seule passe de rendu, une seule source de + * vérité pour les logos de sources. + */ +const PROVIDER_BRANDS: Record = { + yt: { + label: 'YouTube', + color: '#FF0000', + path: 'M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z', + }, + tw: { + label: 'Twitch', + color: '#9146FF', + path: 'M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z', + }, + dm: { + label: 'Dailymotion', + // Simple Icons ships #0A0A0A (monochrome-safe) ; on garde le bleu de la + // marque, illisible sur les fonds sombres de l'application. + color: '#0066DC', + path: 'M21.823 7.327a11.928 11.928 0 0 0-2.606-3.814 12.126 12.126 0 0 0-3.866-2.57A12.246 12.246 0 0 0 10.617 0H1.831a.602.602 0 0 0-.609.603v3.764c0 .162.064.312.179.426l4.164 4.123a.612.612 0 0 0 .439.177h4.56c.806 0 1.56.313 2.125.88.557.559.856 1.296.843 2.075-.029 1.571-1.343 2.849-2.931 2.849h-6.74a.613.613 0 0 0-.432.176.619.619 0 0 0-.178.427v3.764c0 .162.063.312.178.427l4.139 4.099a.647.647 0 0 0 .476.21h2.572a12.276 12.276 0 0 0 4.733-.945 12.145 12.145 0 0 0 3.866-2.571 11.959 11.959 0 0 0 2.607-3.813c.633-1.479.956-3.051.956-4.67 0-1.619-.321-3.19-.956-4.669l.001-.005ZM2.441 4.118V1.982l2.945 2.755.001 2.297-2.946-2.916Zm4.975 17.813-2.945-2.917v-2.137l2.945 2.755v2.299Zm-2.004-5.832h5.19c2.248 0 4.107-1.807 4.147-4.03a4.027 4.027 0 0 0-1.192-2.937 4.203 4.203 0 0 0-2.996-1.239H6.606V5.216h3.996c1.831 0 3.553.706 4.849 1.986a6.724 6.724 0 0 1-.152 9.736 6.875 6.875 0 0 1-4.697 1.84H8.275L5.412 16.1v-.001Zm15.289.1a10.753 10.753 0 0 1-2.345 3.431 10.91 10.91 0 0 1-3.48 2.314 11.018 11.018 0 0 1-4.26.847H8.633v-2.814h1.916c2.145 0 4.161-.802 5.675-2.254a7.88 7.88 0 0 0 2.451-5.728c0-2.177-.87-4.21-2.451-5.728-1.514-1.454-3.528-2.254-5.675-2.254h-4.16L3.383 1.202h7.234c1.479 0 2.911.285 4.259.847a10.957 10.957 0 0 1 3.48 2.313 10.769 10.769 0 0 1 2.345 3.432c.571 1.33.86 2.743.86 4.202 0 1.46-.289 2.873-.86 4.203Z', + }, + pt: { + label: 'PeerTube', + color: '#F1680D', + path: 'M12 6.545v10.91L20.727 12M3.273 12v12L12 17.455M3.273 0v12L12 6.545', + }, + od: { + label: 'Odysee', + color: '#EF1970', + path: 'M11.965 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12 12 12 0 0 0-3.209-8.167 7.272 7.272 0 0 1-.799 3.218c-.548.957-2.281 2.77-3.264 3.699a.723.723 0 0 0 .056 1.104c.996.74 2.658 2.151 2.788 3.422.176 1.835 1.6 4.02 1.675 4.159a.67.67 0 0 1-.105.327 12.067 12.067 0 0 1-2.03 1.898 2.435 2.435 0 0 1-.807.126c-1.944-.04-1.526-1.866-1.712-2.905s-.78-3.085-2.716-2.788c0 0 .484 4.243-1.489 5.546s-5.843 2.27-6.55-.408 2.46-2.384 2.684-2.384c.223 0 2.233-.632 1.267-2.53-.967-1.898-2.01-3.5-2.01-3.5a11.37 11.37 0 0 0-2.735 1.285 5.42 5.42 0 0 0-1.061.82c-1.065 1.104-2.19 1.713-2.954 1.358a1.368 1.368 0 0 1-.32-.221A11.926 11.926 0 0 1 .1 13.503c.43-.641 2.082-2.038 3.696-2.906 1.304-.702 2.737-.988 3.118-1.355-.671-2.235-1.882-5.703.832-7.33C9.881.634 12.69-.142 13.77 2.958c1.08 3.1.802 3.796 1.267 3.796.465 0 1.608.223 2.09-1.75.356-1.445.574-2.685 1.379-3.087A12 12 0 0 0 12 0a12 12 0 0 0-.035 0zm-.498 2.125c-.353-.019-.78.05-1.303.224 0 0-1.895.52-1.749 2.53.13 1.777 1.08 2.753 3.053 2.01 1.972-.737 2.31-1.264 1.824-2.753-.364-1.117-.765-1.956-1.825-2.011zm.48.726a.249.249 0 0 1 .183.07 1.58 1.58 0 0 1 .232.346.253.253 0 0 1-.197.37.253.253 0 0 1-.233-.131 1.559 1.559 0 0 0-.148-.232.256.256 0 0 1 0-.353.249.249 0 0 1 .163-.07zm3.529.152a.22.22 0 0 1 .192.103.22.22 0 0 1-.07.305.22.22 0 1 1-.122-.408zM12.609 4.27a.253.253 0 0 1 .227.133 1.5 1.5 0 0 1 .102.982.253.253 0 0 1-.246.205h-.049a.253.253 0 0 1-.2-.295 1.013 1.013 0 0 0-.071-.697.253.253 0 0 1 .237-.328zm-8.035.552a.12.12 0 0 1 .029.003.12.12 0 1 1-.147.091.12.12 0 0 1 .118-.094zm15.77 3.419.273.539.593.12-.539.275-.123.592-.272-.539-.592-.123.538-.272zm-17.767.535a.22.22 0 0 1 .193.104.22.22 0 0 1-.07.304.22.22 0 1 1-.123-.408zm16.004 2.79a.258.258 0 0 1 .062.007.258.258 0 1 1-.31.195.258.258 0 0 1 .248-.202zM4.914 16.115a.17.17 0 0 1 .165.14.17.17 0 0 1-.137.197.17.17 0 1 1-.028-.337zm9.769 4.094a.2.2 0 0 1 .036.004.2.2 0 1 1-.233.15.2.2 0 0 1 .197-.154z', + }, + ru: { + label: 'Rumble', + color: '#85C742', + path: 'M14.4528 13.5458c.8064-.6542.9297-1.8381.2756-2.6445a1.8802 1.8802 0 0 0-.2756-.2756 21.2127 21.2127 0 0 0-4.3121-2.776c-1.066-.51-2.256.2-2.4261 1.414a23.5226 23.5226 0 0 0-.14 5.5021c.116 1.23 1.292 1.964 2.372 1.492a19.6285 19.6285 0 0 0 4.5062-2.704v-.008zm6.9322-5.4002c2.0335 2.228 2.0396 5.637.014 7.8723A26.1487 26.1487 0 0 1 8.2946 23.846c-2.6848.6713-5.4168-.914-6.1662-3.5781-1.524-5.2002-1.3-11.0803.17-16.3045.772-2.744 3.3521-4.4661 6.0102-3.832 4.9242 1.174 9.5443 4.196 13.0764 8.0121v.002z', + }, +}; + +const PROVIDER_ICON_KEYS = Object.keys(PROVIDER_BRANDS) as ProviderIconKey[]; + +/** + * Logo d'une source, aux couleurs de la marque. + * + * L'état actif / masqué n'est plus porté par la couleur de l'icône (elle est + * fixe par marque) mais par l'état du bouton qui la contient : fond plein et + * logo en couleur quand la source est affichée, fond transparent et logo + * désaturé quand elle est masquée. */ @Component({ selector: 'app-provider-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` - @switch (normalized) { - @case ('yt') { - - - } - @case ('tw') { - - - } - @case ('dm') { - - - } - @case ('pt') { - - - } - @case ('od') { - - - } - @case ('ru') { - - - } + @if (brand; as b) { + } ` }) @@ -74,13 +81,13 @@ export class ProviderIconComponent { /** Clé courte du fournisseur. Inconnue => aucun rendu. */ @Input() key: ProviderIconKey | string | null | undefined; /** Taille en px (carré). */ - @Input() size = 18; + @Input() size = 20; - /** Clé normalisée ; seules les six clés connues dessinent quelque chose. */ - get normalized(): ProviderIconKey | null { + /** Marque correspondante, ou null si la clé n'est pas connue. */ + get brand(): ProviderBrand | null { const k = String(this.key || '').toLowerCase(); - return (['yt', 'dm', 'tw', 'pt', 'od', 'ru'] as const).includes(k as ProviderIconKey) - ? (k as ProviderIconKey) + return PROVIDER_ICON_KEYS.includes(k as ProviderIconKey) + ? PROVIDER_BRANDS[k as ProviderIconKey] : null; } } diff --git a/src/components/search/search.component.html b/src/components/search/search.component.html index 9335ae5..702a986 100644 --- a/src/components/search/search.component.html +++ b/src/components/search/search.component.html @@ -68,87 +68,94 @@

{{ 'search.hint' | t }}

} - @if (hasQuery() && railsOpen()) { + @if (hasQuery()) { -
- -
-
- - - - - + + @if (railsOpen()) { +
+ +
+
+ + + + + +
-
-
+
- -
- Sources -
-
+ +
+ Sources +
+
@for (chip of providerChips(); track chip.id) { - } - @if (!allProvidersVisible()) { - - } - @if (!allSourcesActive()) { - } + @if (!allProvidersVisible()) { + + } + @if (!allSourcesActive()) { + + } +
-
+ } @if (filtersOpen()) {