fix(web): lecteur PDF — pages blanches après rendu et base minimale stable

Le canvas PDF restait vide après rendu (blank-detected): la détection d'encre
reposait sur un seuil de blanc trop sensible et un fond de canvas non maîtrisé.
Le rendu passe à un fond sentinel explicite avec classification
rendered-ok/blank-detected et un seuil de pixels visibles.

Le lecteur est par ailleurs ramené à une base minimale stable: layout plein
viewport (app-main-reader), suppression des modes de lecture et des préférences
par livre, helpers de pagination/viewport extraits dans readerLayout.ts. Shell,
lecteurs CBZ/EPUB et styles alignés sur cette base.

Refs #31

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Git Agent
2026-08-24 12:52:49 +02:00
parent 7cc44871d9
commit 50a0b392e1
10 changed files with 662 additions and 714 deletions

View File

@ -0,0 +1,54 @@
export type ReaderSize = {
width: number;
height: number;
};
export function clampReaderPage(page: number, pageCount: number) {
const safePageCount = Math.max(1, Math.floor(pageCount));
return Math.max(1, Math.min(Math.floor(page), safePageCount));
}
export function previousReaderPage(page: number, pageCount: number) {
return clampReaderPage(page - 1, pageCount);
}
export function nextReaderPage(page: number, pageCount: number) {
return clampReaderPage(page + 1, pageCount);
}
export function readerPositionLabel(page: number, pageCount: number) {
return `Page ${clampReaderPage(page, pageCount)} / ${Math.max(1, Math.floor(pageCount))}`;
}
export function containPageSize(viewport: ReaderSize, page: ReaderSize): ReaderSize {
if (viewport.width <= 0 || viewport.height <= 0 || page.width <= 0 || page.height <= 0) {
return { width: 0, height: 0 };
}
const scale = Math.min(viewport.width / page.width, viewport.height / page.height);
return {
width: Math.max(1, Math.floor(page.width * scale)),
height: Math.max(1, Math.floor(page.height * scale))
};
}
export function orientedContainPageSize(viewport: ReaderSize, page: ReaderSize): ReaderSize {
if (viewport.width <= 0 || viewport.height <= 0 || page.width <= 0 || page.height <= 0) {
return { width: 0, height: 0 };
}
const fitByHeight = page.height >= page.width;
const primaryScale = fitByHeight ? viewport.height / page.height : viewport.width / page.width;
const crossScale = fitByHeight ? viewport.width / page.width : viewport.height / page.height;
const scale = Math.min(primaryScale, crossScale);
return {
width: Math.max(1, Math.floor(page.width * scale)),
height: Math.max(1, Math.floor(page.height * scale))
};
}
export function readableViewportSize(size: ReaderSize): ReaderSize | null {
if (size.width < 32 || size.height < 32) return null;
return {
width: Math.floor(size.width),
height: Math.floor(size.height)
};
}