+ {loadingDocument || !documentProxy ? (
Ouverture PDF
- ) : mode === "vertical" ? (
-
- {Array.from({ length: pages }, (_, index) => (
-
- ))}
+ ) : pageError ? (
+
+
+
{pageError.detail}
+
+
+ Détail technique
+ {pageError.technicalDetail}
+
+
) : (
-
+
+ {(!viewportSize || loadingPage || !pageRendered) && (
+
+ Page {currentPage}
+
+ )}
+
+
)}
);
diff --git a/apps/web/src/reader/ReaderShell.tsx b/apps/web/src/reader/ReaderShell.tsx
index 0141280..b53d269 100644
--- a/apps/web/src/reader/ReaderShell.tsx
+++ b/apps/web/src/reader/ReaderShell.tsx
@@ -1,180 +1,79 @@
-import { ArrowLeft, ArrowRight, ArrowUp, Columns2, Maximize2, Minimize2, RotateCcw, Rows3, Save } from "lucide-react";
-import { useCallback, useEffect, useState, type ReactNode } from "react";
-import { ErrorRibbon, Meter } from "../components/ui";
+import { ArrowLeft, ArrowRight } from "lucide-react";
+import { useEffect, type ReactNode } from "react";
+import { ErrorRibbon } from "../components/ui";
import { navigate } from "../router";
-import type { ReaderMode } from "../api/types";
export type ReaderControls = {
canPrevious: boolean;
canNext: boolean;
- canTop?: boolean;
positionLabel: string;
onPrevious: () => void;
onNext: () => void;
- onTop?: () => void;
};
type ReaderShellProps = {
title: string;
- status: string;
backHref: string;
- progress: number;
error?: string;
onRetry?: () => void;
- mode: ReaderMode;
- onModeChange: (mode: ReaderMode) => void;
controls: ReaderControls;
- controlsVisible: boolean;
- onToggleControls: () => void;
children: ReactNode;
};
-export function ReaderShell({
- title,
- status,
- backHref,
- progress,
- error,
- onRetry,
- mode,
- onModeChange,
- controls,
- controlsVisible,
- onToggleControls,
- children
-}: ReaderShellProps) {
- const [isFullscreen, setIsFullscreen] = useState(false);
- const toggleFullscreen = useCallback(() => {
- const root = document.querySelector(".reader-page");
- if (!document.fullscreenElement) void root?.requestFullscreen();
- else void document.exitFullscreen();
- }, []);
+function isFormField(target: EventTarget | null) {
+ const element = target as HTMLElement | null;
+ const tagName = element?.tagName.toLowerCase();
+ return Boolean(element?.isContentEditable || tagName === "input" || tagName === "textarea" || tagName === "select");
+}
+export function ReaderShell({ title, backHref, error, onRetry, controls, children }: ReaderShellProps) {
useEffect(() => {
- const updateFullscreen = () => setIsFullscreen(Boolean(document.fullscreenElement));
- updateFullscreen();
- document.addEventListener("fullscreenchange", updateFullscreen);
- return () => document.removeEventListener("fullscreenchange", updateFullscreen);
- }, []);
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (isFormField(event.target)) return;
+ if (event.key === "ArrowLeft" && controls.canPrevious) {
+ event.preventDefault();
+ controls.onPrevious();
+ }
+ if (event.key === "ArrowRight" && controls.canNext) {
+ event.preventDefault();
+ controls.onNext();
+ }
+ };
+ window.addEventListener("keydown", handleKeyDown);
+ return () => window.removeEventListener("keydown", handleKeyDown);
+ }, [controls]);
return (
-
-
event.stopPropagation()}>
+