fix(web): lecteur PDF/CBZ — pages blanches, timeouts et modes fullscreen

- Rendu PDF via module dédié pdfRender (worker), correction des pages
  blanches et gestion des timeouts de rendu
- Lecteur comics : crop plein écran, locators de page unifiés (pdf/cbz/cbr)
  avec ancrage pour le calcul de progression
- Sauvegarde de progression mise en file (queueSave) pour éviter les
  pertes lors des navigations rapides
- nginx/vite : en-têtes et proxy alignés pour le streaming des livres

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Git Agent
2026-08-24 09:11:25 +02:00
parent d79f502dd2
commit 84e789acc4
11 changed files with 494 additions and 104 deletions

View File

@ -0,0 +1,34 @@
import type { ReaderMode } from "../api/types";
const PDF_RENDER_BACKGROUND = { red: 247, green: 240, blue: 223 };
const PDF_BLANK_THRESHOLD = 245;
const PDF_BACKGROUND_TOLERANCE = 4;
export function pdfRenderScale(mode: ReaderMode, frameSize: { width: number; height: number }, pageSize: { width: number; height: number }) {
if (pageSize.width <= 0 || pageSize.height <= 0) return 1;
const fitWidth = frameSize.width / pageSize.width;
if (mode === "vertical") return Math.min(1.65, fitWidth);
return Math.min(fitWidth, frameSize.height / pageSize.height);
}
function isNearRenderBackground(red: number, green: number, blue: number) {
return (
Math.abs(red - PDF_RENDER_BACKGROUND.red) <= PDF_BACKGROUND_TOLERANCE &&
Math.abs(green - PDF_RENDER_BACKGROUND.green) <= PDF_BACKGROUND_TOLERANCE &&
Math.abs(blue - PDF_RENDER_BACKGROUND.blue) <= PDF_BACKGROUND_TOLERANCE
);
}
export function pdfCanvasHasVisibleInk(imageData: Pick<ImageData, "data">) {
const data = imageData.data;
for (let index = 0; index < data.length; index += 4) {
const red = data[index] ?? 255;
const green = data[index + 1] ?? 255;
const blue = data[index + 2] ?? 255;
const alpha = data[index + 3] ?? 255;
if (alpha === 0) continue;
const nearWhite = red >= PDF_BLANK_THRESHOLD && green >= PDF_BLANK_THRESHOLD && blue >= PDF_BLANK_THRESHOLD;
if (!nearWhite && !isNearRenderBackground(red, green, blue)) return true;
}
return false;
}