aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/preview/AssetContentSection.tsx
diff options
context:
space:
mode:
authorAhmad Mujahid <55625580+AhmadMuj@users.noreply.github.com>2025-02-17 13:25:16 +0400
committerGitHub <noreply@github.com>2025-02-17 09:25:16 +0000
commite5cb9aa848009ea22c1385e4d33b7edf372979fb (patch)
tree89470d8da8aab10f30bbfccea8d1b0cea08a1408 /apps/web/components/dashboard/preview/AssetContentSection.tsx
parenta14be108736133535e2828b6bbdc8d0a69accd63 (diff)
downloadkarakeep-e5cb9aa848009ea22c1385e4d33b7edf372979fb.tar.zst
feat: Add PDF screenshot generation and display (#995)
* Updated pdf2json to 3.1.5 * Extract and store a screenshot from PDF files using pdf2pic * Installing graphicsmagick and ghostscript * Generate Missing PDF screenshot with tidyAssets worker for backward support * Display PDF screenshot instead of the PDF in web if it exists. * Display PDF screenshot in mobile app if exists. * Updated pnpm-lock.yaml * Removed console.log * Revert the unnecessary changes in package.json * Revert pnpm-lock changes * Prevent rendering PDF files if the screenshot is not generated * refactor: replace useEffect with useMemo for section initialization * feat: show PDF file download button and handle large PDFs by defaulting to screenshot view * feat: add file size to openapi spec * feature: Add Assets preprocessing in fix mode to admin actions * i18n: add reprocess_assets_fix_mode translation * i18n: Add missing ar translations * A bunch of fixes * Fix openspec schema --------- Co-authored-by: Mohamed Bassem <me@mbassem.com>
Diffstat (limited to 'apps/web/components/dashboard/preview/AssetContentSection.tsx')
-rw-r--r--apps/web/components/dashboard/preview/AssetContentSection.tsx131
1 files changed, 103 insertions, 28 deletions
diff --git a/apps/web/components/dashboard/preview/AssetContentSection.tsx b/apps/web/components/dashboard/preview/AssetContentSection.tsx
index 03ab8a43..8590d2ad 100644
--- a/apps/web/components/dashboard/preview/AssetContentSection.tsx
+++ b/apps/web/components/dashboard/preview/AssetContentSection.tsx
@@ -1,42 +1,117 @@
+import { useMemo, useState } from "react";
import Image from "next/image";
import Link from "next/link";
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import { useTranslation } from "@/lib/i18n/client";
+import { getAssetUrl } from "@hoarder/shared-react/utils/assetUtils";
import { BookmarkTypes, ZBookmark } from "@hoarder/shared/types/bookmarks";
-export function AssetContentSection({ bookmark }: { bookmark: ZBookmark }) {
+// 20 MB
+const BIG_FILE_SIZE = 20 * 1024 * 1024;
+
+function PDFContentSection({ bookmark }: { bookmark: ZBookmark }) {
if (bookmark.content.type != BookmarkTypes.ASSET) {
throw new Error("Invalid content type");
}
+ const { t } = useTranslation();
- switch (bookmark.content.assetType) {
- case "image": {
- return (
- <div className="relative h-full min-w-full">
- <Link
- href={`/api/assets/${bookmark.content.assetId}`}
- target="_blank"
- >
- <Image
- alt="asset"
- fill={true}
- className="object-contain"
- src={`/api/assets/${bookmark.content.assetId}`}
- />
- </Link>
- </div>
- );
+ const initialSection = useMemo(() => {
+ if (bookmark.content.type != BookmarkTypes.ASSET) {
+ throw new Error("Invalid content type");
}
- case "pdf": {
- return (
- <iframe
- title={bookmark.content.assetId}
- className="h-full w-full"
- src={`/api/assets/${bookmark.content.assetId}`}
- />
- );
+
+ const screenshot = bookmark.assets.find(
+ (item) => item.assetType === "assetScreenshot",
+ );
+ const bigSize =
+ bookmark.content.size && bookmark.content.size > BIG_FILE_SIZE;
+ if (bigSize && screenshot) {
+ return "screenshot";
}
- default: {
+ return "pdf";
+ }, [bookmark]);
+ const [section, setSection] = useState(initialSection);
+
+ const screenshot = bookmark.assets.find(
+ (r) => r.assetType === "assetScreenshot",
+ )?.id;
+
+ const content =
+ section === "screenshot" && screenshot ? (
+ <div className="relative h-full min-w-full">
+ <Image
+ alt="screenshot"
+ src={getAssetUrl(screenshot)}
+ fill={true}
+ className="object-contain"
+ />
+ </div>
+ ) : (
+ <iframe
+ title={bookmark.content.assetId}
+ className="h-full w-full"
+ src={getAssetUrl(bookmark.content.assetId)}
+ />
+ );
+
+ return (
+ <div className="flex h-full flex-col items-center gap-2">
+ <div className="flex w-full items-center justify-center gap-4">
+ <Select onValueChange={setSection} value={section}>
+ <SelectTrigger className="w-fit">
+ <SelectValue />
+ </SelectTrigger>
+ <SelectContent>
+ <SelectGroup>
+ <SelectItem value="screenshot" disabled={!screenshot}>
+ {t("common.screenshot")}
+ </SelectItem>
+ <SelectItem value="pdf">PDF</SelectItem>
+ </SelectGroup>
+ </SelectContent>
+ </Select>
+ </div>
+ {content}
+ </div>
+ );
+}
+
+function ImageContentSection({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type != BookmarkTypes.ASSET) {
+ throw new Error("Invalid content type");
+ }
+ return (
+ <div className="relative h-full min-w-full">
+ <Link href={getAssetUrl(bookmark.content.assetId)} target="_blank">
+ <Image
+ alt="asset"
+ fill={true}
+ className="object-contain"
+ src={getAssetUrl(bookmark.content.assetId)}
+ />
+ </Link>
+ </div>
+ );
+}
+
+export function AssetContentSection({ bookmark }: { bookmark: ZBookmark }) {
+ if (bookmark.content.type != BookmarkTypes.ASSET) {
+ throw new Error("Invalid content type");
+ }
+ switch (bookmark.content.assetType) {
+ case "image":
+ return <ImageContentSection bookmark={bookmark} />;
+ case "pdf":
+ return <PDFContentSection bookmark={bookmark} />;
+ default:
return <div>Unsupported asset type</div>;
- }
}
}