perf(reader): windowing + eager loading sur l'InfiniteReader

- Windowing côté rendu : seules les pages dans une fenêtre de ±3 autour
  de la page visible sont montées en tant que ReaderPage ; les autres
  sont remplacées par des placeholders dimensionnés via aspect-ratio CSS
  pour maintenir la hauteur de scroll sans saut
- IntersectionObserver utilise le minimum des indices intersectants pour
  éviter que les entrées simultanées au chargement ne décalent la fenêtre
- Prop initialPage passé depuis ChapterReader pour ancrer la fenêtre sur
  la page courante dès le montage
- loading="eager" sur les ReaderPage montés (le windowing est le mécanisme
  de lazy-loading, pas l'attribut HTML natif)
- Prop loading bindé sur les 3 balises <img> de ReaderPage
This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2026-03-15 17:46:00 +01:00
parent be8a3c6de8
commit 74f033f5d1
4 changed files with 102 additions and 25 deletions

View File

@@ -15,6 +15,7 @@
:alt="`Page ${pageNumber} (Double page)`"
class="page-image rotated"
:style="doublePageRotatedStyle"
:loading="loading"
@load="handleImageLoad"
ref="imageRef" />
<div class="rotation-hint">
@@ -33,6 +34,7 @@
:alt="`Page ${pageNumber} (Double page)`"
class="page-image scrollable"
:style="doublePageScrollStyle"
:loading="loading"
@load="handleImageLoad"
ref="imageRef" />
</div>
@@ -52,6 +54,7 @@
:alt="`Page ${pageNumber}`"
class="page-image"
:style="imageStyle"
:loading="loading"
@load="handleImageLoad"
ref="imageRef" />
</div>
@@ -78,6 +81,10 @@ import { useReaderStore } from '../../application/store/readerStore';
type: String,
default: 'rotate', // 'rotate', 'scroll', 'normal'
validator: (value) => ['rotate', 'scroll', 'normal'].includes(value)
},
loading: {
type: String,
default: 'lazy',
}
});