@using MaBibli.Client.Services
@inject CacheHorsLigne Cache
@inject EtatReseau Reseau
@implements IAsyncDisposable
@*
Couverture d'un livre, avec substitut.
Les URL de couverture OpenLibrary renvoient des 502 intermittents (mesuré en phase 2 :
200, 200, puis 502 sur le même ISBN). On ne valide donc JAMAIS l'URL par un appel préalable :
on l'affiche, et si l'image casse, l'attribut onerror la masque et laisse apparaître le
substitut qui se trouve déjà dessous. Aucun aller-retour serveur, aucun état C# à gérer.
@key sur l'img : si l'URL change, Blazor recrée l'élément au lieu de réutiliser celui que
le onerror a marqué comme cassé.
Agrandissement (IDEES.md) : seulement quand il y a une URL. Sans couverture, il n'y a rien
à agrandir - le substitut à initiale reste un simple décor, jamais un bouton.
⚠️ Image cassée après coup (404/502 intermittent d'OpenLibrary) : le onerror désactive aussi
le bouton déclencheur (this.closest('.couverture-declencheur').disabled = true), pas
seulement l'image. Sans ça, cliquer une vignette cassée agrandissait quand même une image
cassée (A4, IDEES.md).
Cache des couvertures : le cache IndexedDB est consulté D'ABORD, en ligne comme hors ligne.
Une image déjà rangée sur l'appareil s'affiche sans aucune requête réseau — c'est ce qui rend
un rechargement instantané sur téléphone, là où covers.openlibrary.org impose deux
redirections avant d'aboutir sur archive.org. Le réseau n'est sollicité QUE si rien n'est en
cache, et la mise en cache démarre alors en tâche de fond.
⚠️ Ceci REMPLACE la règle d'origine (A5) « en ligne, rien ne doit ralentir la voie rapide »,
qui réservait le cache au hors-ligne. La lecture IndexedDB précède désormais l'affichage :
elle est locale et sans réseau, donc largement plus rapide que ce qu'elle remplace.
⚠️ Corollaire : l'URL d'objet doit être LIBÉRÉE quand le composant disparaît ou change
d'image (Dispose / changement d'URL). Un blob: retient son Blob en mémoire jusque-là, et il y
a maintenant une vignette par carte sur tous les écrans.
⚠️ L'allègement (redimensionner, convertir en WebP) n'est PAS fait ici : à mesurer avant
de s'y engager, comme pour l'AOT — voir IDEES.md.
*@
@Initiale
@if (ADesPixels)
{
@if (Agrandissable)
{
@* Un vrai