-
-
+
e.stopPropagation()}>
+
1}
+ >
+ {pageCelebrities.length > 0 && (
+
+
+
+
Detected in this image:
-
Detected in this image:
-
-
- {pageCelebrities.map((celeb, idx) => (
-
- {celeb.name}
- ({Math.round(celeb.confidence)}%)
-
- ))}
+
+ {pageCelebrities.map((celeb, idx) => (
+
+ {celeb.name}
+ ({Math.round(celeb.confidence)}%)
+
+ ))}
+
+
-
-
- )}
+ )}
+
);
})}
diff --git a/app/file/[...path]/page.tsx b/app/file/[...path]/page.tsx
index 8b005cc..5f8abb2 100644
--- a/app/file/[...path]/page.tsx
+++ b/app/file/[...path]/page.tsx
@@ -1,12 +1,12 @@
"use client";
-import { use, useEffect, useState, useRef, useCallback, useMemo } from "react";
-import Link from "next/link";
-import { useRouter, useSearchParams } from "next/navigation";
+import { CelebrityDisclaimer } from "@/components/celebrity-disclaimer";
import { getPdfPages, setPdfPages } from "@/lib/cache";
-import { useFiles } from "@/lib/files-context";
import { CELEBRITY_DATA } from "@/lib/celebrity-data";
-import { CelebrityDisclaimer } from "@/components/celebrity-disclaimer";
+import { useFiles } from "@/lib/files-context";
+import Link from "next/link";
+import { useRouter, useSearchParams } from "next/navigation";
+import { use, useCallback, useEffect, useMemo, useRef, useState } from "react";
const WORKER_URL = process.env.NODE_ENV === "development"
? "http://localhost:8787"
@@ -89,33 +89,117 @@ function getCelebritiesForPage(filePath: string, pageNumber: number): { name: st
return celebrities.sort((a, b) => b.confidence - a.confidence).filter(celeb => celeb.confidence > 99);
}
-// Component to display a page with its celebrity info
+// Zoom levels for PDF pages
+const ZOOM_LEVELS = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;
+
+// Component to display a page with its celebrity info and zoom controls
function PageWithCelebrities({
dataUrl,
pageNumber,
- filePath
+ filePath,
+ showPageNumber = true,
}: {
dataUrl: string;
pageNumber: number;
filePath: string;
+ showPageNumber?: boolean;
}) {
+ const [zoomIndex, setZoomIndex] = useState(2); // Default 100%
+ const zoom = ZOOM_LEVELS[zoomIndex];
+ const zoomPercent = Math.round(zoom * 100);
+
+ const zoomIn = () => setZoomIndex((prev) => Math.min(prev + 1, ZOOM_LEVELS.length - 1));
+ const zoomOut = () => setZoomIndex((prev) => Math.max(prev - 1, 0));
+ const resetZoom = () => setZoomIndex(2);
+
+ const canZoomIn = zoomIndex < ZOOM_LEVELS.length - 1;
+ const canZoomOut = zoomIndex > 0;
+ const isDefaultZoom = zoomIndex === 2;
+
const celebrities = useMemo(() => getCelebritiesForPage(filePath, pageNumber), [filePath, pageNumber]);
return (
- {/* Page number badge */}
-
- Page {pageNumber}
+ {/* Controls bar */}
+
+ {/* Page number */}
+ {showPageNumber && (
+
+ Page {pageNumber}
+
+ )}
+
+ {/* Zoom controls */}
+
+
+
+
+ {zoomPercent}%
+
+
+
+
+ {!isDefaultZoom && (
+
+ )}
+
+
+
+ {/* Image container with zoom */}
+
1 ? "max-h-[80vh]" : ""}`}>
+
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+
- {/* eslint-disable-next-line @next/next/no-img-element */}
-
+
{celebrities.length > 0 && (
@@ -127,8 +211,7 @@ function PageWithCelebrities({
Detected in this image:
- {celebrities
- .map((celeb, idx) => (
+ {celebrities.map((celeb, idx) => (