- A1 : forcer la revalidation HTTP (Cache-Control: no-cache) sur les fichiers statiques, pour empêcher un navigateur de garder indéfiniment un CSS/JS périmé quand le service worker ne s'active pas. - A2 : le filtre du catalogue (statut, type de document) reprend les mêmes pastilles colorées que les cartes (Libelles.ClasseStatut / nouvelle Libelles.ClasseTypeDocument). - A3 : remplacement du logo par défaut de Blazor par un pictogramme de livre ouvert (favicon, icônes PWA, logo du bandeau, logo mabibli_ynh). - A4 : une couverture cassée désactive aussi son bouton d'agrandissement. - A5 : cache IndexedDB des couvertures pour la consultation hors-ligne, sans ralentir l'affichage en ligne (mise en cache en tâche de fond). L'allègement (redimensionnement, WebP) reste hors scope, à mesurer avant de s'y engager. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
153 lines
5.3 KiB
Plaintext
153 lines
5.3 KiB
Plaintext
@inherits LayoutComponentBase
|
|
@implements IDisposable
|
|
@inject ServiceLivresApi Api
|
|
@inject EtatReseau Reseau
|
|
|
|
@* Mise en page pensée mobile d'abord : un bandeau, une colonne, rien à gauche.
|
|
Le PC hérite de la même colonne, simplement centrée et limitée en largeur. *@
|
|
<header class="bandeau">
|
|
<a class="marque" href="">
|
|
<img src="logo-bandeau.svg" alt="" class="marque-logo" />
|
|
MaBibli
|
|
</a>
|
|
|
|
@if (!Reseau.EnLigne)
|
|
{
|
|
@* Une pastille dans le bandeau, visible sur tous les écrans : l'état du réseau change
|
|
l'usage de l'application, il ne doit pas se découvrir au premier clic qui échoue. *@
|
|
<span class="pastille-hors-ligne" title="@EtatReseau.MotifHorsLigne">Hors ligne</span>
|
|
}
|
|
|
|
@if (_utilisateur?.Identifiant is not null)
|
|
{
|
|
<span class="utilisateur" title="@(_utilisateur.Simule ? "Utilisateur simulé (développement)" : "Connecté via le portail YunoHost")">
|
|
@_utilisateur.Affichage@(_utilisateur.Simule ? " (dev)" : "")
|
|
</span>
|
|
}
|
|
</header>
|
|
|
|
@if (!Reseau.EnLigne)
|
|
{
|
|
@*
|
|
Dire d'où viennent les données et de quand elles datent. Sans cette phrase, une
|
|
bibliothèque affichée hors-ligne est indiscernable d'une bibliothèque à jour — et un
|
|
livre ajouté depuis un autre appareil manquerait sans explication.
|
|
*@
|
|
<p class="bandeau-reseau" role="status">
|
|
<strong>Hors ligne.</strong>
|
|
@(Reseau.DerniereSynchro is { } synchro
|
|
? $" Données enregistrées {Quand(synchro)}. "
|
|
: " Aucune donnée n'a encore pu être enregistrée sur cet appareil. ")
|
|
Consultation et recherche fonctionnent ; les modifications sont impossibles.
|
|
</p>
|
|
}
|
|
|
|
<main class="contenu">
|
|
@Body
|
|
</main>
|
|
|
|
@*
|
|
Navigation permanente, en bas de l'écran : six onglets, toujours au même endroit.
|
|
Elle remplace les listes de liens que chaque page portait dans sa barre d'actions — cinq
|
|
boutons y passaient sur deux ou trois lignes sur un téléphone, et l'entrée « Envies » ne
|
|
figurait pas partout. Les barres d'actions restantes ne portent plus que des ACTIONS.
|
|
|
|
⚠️ Le pouce atteint le bas de l'écran, pas le haut : c'est ce qui justifie le bas plutôt
|
|
qu'un rang d'onglets sous le bandeau. Les actions de page se placent juste au-dessus
|
|
(variable --mb-onglets-hauteur, partagée avec .actions-flottantes).
|
|
|
|
Les onglets restent actifs hors-ligne : les six écrans se consultent depuis leurs
|
|
instantanés. Ce sont les écritures qui se désactivent, pas la navigation.
|
|
*@
|
|
<nav class="onglets" aria-label="Navigation principale">
|
|
<NavLink class="onglet" href="" Match="NavLinkMatch.All">Catalogue</NavLink>
|
|
<NavLink class="onglet" href="auteurs">Auteurs</NavLink>
|
|
<NavLink class="onglet" href="series">Séries</NavLink>
|
|
<NavLink class="onglet" href="revues">Revues</NavLink>
|
|
<NavLink class="onglet" href="prets">Prêts</NavLink>
|
|
<NavLink class="onglet" href="souhaits">Envies</NavLink>
|
|
</nav>
|
|
|
|
@code {
|
|
private UtilisateurCourant? _utilisateur;
|
|
private bool _etaitEnLigne = true;
|
|
private bool _synchroEnCours;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
Reseau.Change += SurChangementReseau;
|
|
Reseau.SynchroChange += SurSynchro;
|
|
|
|
// Écoute des bascules online/offline avant tout appel : un démarrage hors-ligne doit
|
|
// aller directement au cache, sans attendre l'échec d'une requête.
|
|
await Reseau.DemarrerAsync();
|
|
_etaitEnLigne = Reseau.EnLigne;
|
|
|
|
_utilisateur = await Api.ObtenirUtilisateurAsync();
|
|
|
|
// Rafraîchit tout le fonds, pas seulement l'écran ouvert : c'est ce qui rend la
|
|
// bibliothèque entière consultable et cherchable après la coupure.
|
|
await SynchroniserAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Au retour du réseau, on recharge : la bibliothèque a pu changer depuis un autre appareil,
|
|
/// et les actions d'écriture redeviennent disponibles dans la foulée.
|
|
/// </summary>
|
|
private void SurChangementReseau()
|
|
{
|
|
var revenu = Reseau.EnLigne && !_etaitEnLigne;
|
|
_etaitEnLigne = Reseau.EnLigne;
|
|
|
|
_ = InvokeAsync(async () =>
|
|
{
|
|
StateHasChanged();
|
|
|
|
if (revenu)
|
|
{
|
|
_utilisateur = await Api.ObtenirUtilisateurAsync();
|
|
await SynchroniserAsync();
|
|
StateHasChanged();
|
|
}
|
|
});
|
|
}
|
|
|
|
private async Task SynchroniserAsync()
|
|
{
|
|
if (_synchroEnCours)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_synchroEnCours = true;
|
|
|
|
try
|
|
{
|
|
await Api.SynchroniserAsync();
|
|
}
|
|
finally
|
|
{
|
|
_synchroEnCours = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>Date de synchronisation en clair : l'heure suffit le jour même.</summary>
|
|
private static string Quand(DateTimeOffset instant)
|
|
{
|
|
var local = instant.ToLocalTime();
|
|
|
|
return local.Date == DateTimeOffset.Now.Date
|
|
? $"aujourd'hui à {local:HH:mm}"
|
|
: $"le {local:dd/MM/yyyy} à {local:HH:mm}";
|
|
}
|
|
|
|
/// <summary>La date affichée vient de changer : rien à recharger, juste à redessiner.</summary>
|
|
private void SurSynchro() => _ = InvokeAsync(StateHasChanged);
|
|
|
|
public void Dispose()
|
|
{
|
|
Reseau.Change -= SurChangementReseau;
|
|
Reseau.SynchroChange -= SurSynchro;
|
|
}
|
|
}
|