From d178751a7e10719fba26ae5ba337bb9315a62323 Mon Sep 17 00:00:00 2001 From: Amith102 Date: Mon, 16 Feb 2026 20:55:01 +0530 Subject: [PATCH 1/2] feat: implement recently deleted files with premium UI --- app/tool/[id]/processing/page.tsx | 49 +++++++++++++++++++++-------- components/RecentFiles.tsx | 46 ++++++++++++++++----------- components/RecentlyDeletedFiles.tsx | 40 +++++++++++++---------- 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/app/tool/[id]/processing/page.tsx b/app/tool/[id]/processing/page.tsx index 33dce37..61d2d71 100644 --- a/app/tool/[id]/processing/page.tsx +++ b/app/tool/[id]/processing/page.tsx @@ -6,6 +6,7 @@ import { useParams, useRouter } from "next/navigation"; import Tesseract from "tesseract.js"; import { getStoredFiles, clearStoredFiles } from "@/lib/fileStore"; import { PDFDocument } from "pdf-lib"; +import { useRecentFiles } from "@/lib/hooks/useRecentFiles"; type StoredFile = { data: string; @@ -17,6 +18,7 @@ export default function ProcessingPage() { const router = useRouter(); const params = useParams(); const toolId = params.id as string; + const { addRecentFile } = useRecentFiles(); const [status, setStatus] = useState<"processing" | "done" | "error">( "processing" @@ -26,6 +28,7 @@ export default function ProcessingPage() { const [error, setError] = useState(""); const [copied, setCopied] = useState(false); const [downloadUrl, setDownloadUrl] = useState(null); + const [processedFile, setProcessedFile] = useState(null); /* ================= RUN TOOL ================= */ useEffect(() => { @@ -37,22 +40,28 @@ export default function ProcessingPage() { return; } + setProcessedFile(stored[0]); // Keep reference for recent files + try { - if (toolId === "ocr") await runOCR(stored[0].data); + if (toolId === "ocr") await runOCR(stored[0]); else if (toolId === "pdf-protect") - await protectPDF(stored[0].data); + await protectPDF(stored[0]); else if (toolId === "jpeg-to-pdf") - await imageToPdf(stored[0].data, "jpg"); + await imageToPdf(stored[0], "jpg"); else if (toolId === "png-to-pdf") - await imageToPdf(stored[0].data, "png"); + await imageToPdf(stored[0], "png"); else if (toolId === "pdf-compress") await startCompressFlow(stored); - else setStatus("done"); + else { + // Default success case + addToRecent(stored[0].name); + setStatus("done"); + } } catch (e) { console.error(e); setError("Processing failed"); @@ -65,9 +74,17 @@ export default function ProcessingPage() { run(); }, [toolId, router]); + const addToRecent = (fileName: string) => { + addRecentFile({ + fileName, + tool: toolId, + time: new Date().toLocaleString(), + }); + }; + /* ================= OCR ================= */ - const runOCR = async (base64: string) => { - const res = await Tesseract.recognize(base64, "eng", { + const runOCR = async (file: StoredFile) => { + const res = await Tesseract.recognize(file.data, "eng", { logger: (m) => { if (m.status === "recognizing text") { setProgress(Math.round(m.progress * 100)); @@ -76,6 +93,7 @@ export default function ProcessingPage() { }); setText(res.data.text); + addToRecent(file.name); setStatus("done"); }; @@ -110,23 +128,27 @@ export default function ProcessingPage() { ); setDownloadUrl(makeBlobUrl(bytes)); + addToRecent(files[0].name); // Add the first file to recent setProgress(100); setStatus("done"); }; + + /* ================= PDF PROTECT ================= */ - const protectPDF = async (base64: string) => { - const bytes = base64ToBytes(base64); + const protectPDF = async (file: StoredFile) => { + const bytes = base64ToBytes(file.data); const pdf = await PDFDocument.load(bytes); const saved = await pdf.save(); setDownloadUrl(makeBlobUrl(saved)); + addToRecent(file.name); setStatus("done"); }; /* ================= IMAGE → PDF ================= */ - const imageToPdf = async (base64: string, type: "jpg" | "png") => { - const bytes = base64ToBytes(base64); + const imageToPdf = async (file: StoredFile, type: "jpg" | "png") => { + const bytes = base64ToBytes(file.data); const pdf = await PDFDocument.create(); const img = @@ -145,6 +167,7 @@ export default function ProcessingPage() { const saved = await pdf.save(); setDownloadUrl(makeBlobUrl(saved)); + addToRecent(file.name); setStatus("done"); }; @@ -207,8 +230,8 @@ export default function ProcessingPage() { {toolId === "jpeg-to-pdf" ? "JPEG Converted to PDF!" : toolId === "png-to-pdf" - ? "PNG Converted to PDF!" - : "Completed Successfully"} + ? "PNG Converted to PDF!" + : "Completed Successfully"} {downloadUrl && ( diff --git a/components/RecentFiles.tsx b/components/RecentFiles.tsx index ec49a8c..9522b4c 100644 --- a/components/RecentFiles.tsx +++ b/components/RecentFiles.tsx @@ -1,6 +1,6 @@ "use client"; -import { Trash2 } from "lucide-react"; +import { Trash2, FileText as FileIcon } from "lucide-react"; export type RecentFile = { fileName: string; @@ -19,13 +19,12 @@ export default function RecentFiles({ files, onDelete, onClear }: RecentFilesPro return (
- {/* Header with Clear Button */} -
-

Recent Files

+
+

Recent Files

@@ -35,23 +34,32 @@ export default function RecentFiles({ files, onDelete, onClear }: RecentFilesPro {files.map((file, index) => (
-
-

{file.fileName}

-

- {file.tool} • {file.time} -

+
+
+ +
+
+

{file.fileName}

+
+ + {file.tool.replace("-", " ")} + + {file.time} +
+
- {/* Delete Button */} - +
+ +
))}
diff --git a/components/RecentlyDeletedFiles.tsx b/components/RecentlyDeletedFiles.tsx index 27697fe..bf552dd 100644 --- a/components/RecentlyDeletedFiles.tsx +++ b/components/RecentlyDeletedFiles.tsx @@ -1,6 +1,6 @@ "use client"; -import { Trash2, RotateCcw } from "lucide-react"; +import { Trash2, RotateCcw, FileText as FileIcon } from "lucide-react"; import { DeletedFile } from "@/lib/hooks/useRecentFiles"; interface RecentlyDeletedFilesProps { @@ -20,12 +20,15 @@ export default function RecentlyDeletedFiles({ return (
-
-

Recently Deleted

+
+

+ + Recently Deleted +

@@ -35,29 +38,34 @@ export default function RecentlyDeletedFiles({ {deletedFiles.map((file, index) => (
-
-

{file.fileName}

-

- {file.tool} • {file.time} -

-

- Deleted: {file.deletedTime} -

+
+
+ +
+
+

{file.fileName}

+
+ + {file.tool.replace("-", " ")} + + Deleted: {file.deletedTime} +
+
-
+
+ +
+
+ + + +
+ )} + + ); +} diff --git a/components/RecentlyDeletedFiles.tsx b/components/RecentlyDeletedFiles.tsx index bf552dd..91930c0 100644 --- a/components/RecentlyDeletedFiles.tsx +++ b/components/RecentlyDeletedFiles.tsx @@ -1,7 +1,7 @@ -"use client"; - +import { useState } from "react"; import { Trash2, RotateCcw, FileText as FileIcon } from "lucide-react"; import { DeletedFile } from "@/lib/hooks/useRecentFiles"; +import { ConfirmationModal } from "./ConfirmationModal"; interface RecentlyDeletedFilesProps { deletedFiles: DeletedFile[]; @@ -16,8 +16,24 @@ export default function RecentlyDeletedFiles({ onPermanentDelete, onClear, }: RecentlyDeletedFilesProps) { + const [confirmAction, setConfirmAction] = useState<{ + type: "delete" | "clear"; + index?: number; + } | null>(null); + if (deletedFiles.length === 0) return null; + const handleConfirm = () => { + if (!confirmAction) return; + + if (confirmAction.type === "delete" && confirmAction.index !== undefined) { + onPermanentDelete(confirmAction.index); + } else if (confirmAction.type === "clear") { + onClear(); + } + setConfirmAction(null); + }; + return (
@@ -27,7 +43,7 @@ export default function RecentlyDeletedFiles({
))}
+ + setConfirmAction(null)} + onConfirm={handleConfirm} + title={ + confirmAction?.type === "delete" + ? "Delete File Permanently?" + : "Clear Deletion History?" + } + message={ + confirmAction?.type === "delete" + ? "This action cannot be undone. The file will be permanently removed from your history." + : "This will permanently remove all files from your deletion history. This action cannot be undone." + } + confirmText="Delete" + cancelText="Cancel" + />
); }