Replie les blocs de série au catalogue, cycle par cycle

Le catalogue ne rangeait un livre que sous sa série directe : il n'y avait
qu'un seul niveau, donc rien à replier « à chaque niveau ». Le regroupement
devient un arbre — un cycle coiffe ses séries, comme sur /series — et chaque
nœud porte sa bascule.

Tout reste déplié par défaut ; un bloc replié annonce ce qu'il contient, et
l'état de repli appartient à l'écran, sans quoi une frappe dans la recherche
le perdrait.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-22 01:34:04 +02:00
co-authored by Claude Opus 5
parent 7d2f3dc5d9
commit e85867014c
6 changed files with 411 additions and 48 deletions
+18 -18
View File
@@ -157,29 +157,18 @@ else if (_livres is not null)
eux : l'ordre général du catalogue ne bouge pas, on ne perd donc pas un livre qu'on
cherchait à sa lettre. Le nom du bloc MÈNE À LA SÉRIE, où figurent aussi les tomes qu'on
ne possède pas — ce que le catalogue, lui, ne peut pas montrer.
Chaque bloc se REPLIE, et un cycle replie chacun de ses niveaux : un cycle de vingt
tomes occupait tout l'écran alors qu'on cherchait un livre rangé après lui. Replier ne
retire rien de la liste — le compteur du haut ne bouge pas, et le bloc replié dit
toujours ce qu'il contient.
*@
<ul class="liste-livres">
@foreach (var entree in Entrees)
{
@if (entree.Serie is { } serie)
@if (entree.EstGroupe)
{
<li class="groupe-serie" @key="serie">
<a class="groupe-serie-titre" href="@($"series/{serie.Id}")">
<span class="groupe-serie-nom">@serie.Titre</span>
<span class="groupe-serie-compte">
@entree.Livres.Count tome@(entree.Livres.Count > 1 ? "s" : "")
</span>
</a>
<ul class="liste-livres">
@foreach (var livre in entree.Livres)
{
<li @key="livre.Id">
<CarteLivre Livre="livre" />
</li>
}
</ul>
</li>
<GroupeCatalogue Entree="entree" Replies="_replies" />
}
else
{
@@ -236,6 +225,17 @@ else if (_livres is not null)
/// <summary>Regroupement actif — l'utilisateur peut le défaire, rien ne disparaît alors.</summary>
private bool _grouper = true;
/// <summary>
/// Blocs repliés à la main, par identifiant de série. Tout est déplié par défaut.
/// </summary>
/// <remarks>
/// ⚠️ Le jeu appartient à l'ÉCRAN, et non aux blocs : le catalogue se relit à chaque frappe
/// dans la recherche, et un état porté par les composants se perdrait à chaque caractère.
/// Il n'est pas persistant d'une visite à l'autre pour autant — c'est un confort de
/// lecture, pas une propriété de la série, même règle que l'arbre des séries.
/// </remarks>
private readonly HashSet<int> _replies = [];
/// <summary>Le catalogue tel qu'il s'affiche : livres seuls et blocs de série mêlés.</summary>
private IReadOnlyList<EntreeCatalogue> Entrees =>
GroupementCatalogue.Grouper(_livres ?? [], _grouper ? _series : null);