Skip to content

Commit 67e4326

Browse files
rajat1saxenaRajat
andauthored
PDF download button in community posts (#737)
* PDF download button in community posts * codex issue resolved --------- Co-authored-by: Rajat <[email protected]>
1 parent fd9a109 commit 67e4326

File tree

2 files changed

+116
-15
lines changed

2 files changed

+116
-15
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
import { getMedia } from "@/services/medialit";
3+
import { Constants } from "@courselit/common-models";
4+
5+
export async function GET(
6+
request: NextRequest,
7+
{ params }: { params: Promise<{ mediaId: string }> },
8+
) {
9+
const mediaId = (await params).mediaId;
10+
11+
if (!mediaId) {
12+
return new NextResponse("Missing mediaId parameter", { status: 400 });
13+
}
14+
15+
try {
16+
const media = await getMedia(mediaId);
17+
18+
if (!media) {
19+
return new NextResponse("Media not found", { status: 404 });
20+
}
21+
22+
if (media.access !== Constants.MediaAccessType.PUBLIC) {
23+
return new NextResponse("Media not found", { status: 404 });
24+
}
25+
26+
if (!media.file) {
27+
return new NextResponse("Media file URL not available", {
28+
status: 404,
29+
});
30+
}
31+
32+
const response = await fetch(media.file);
33+
34+
if (!response.ok) {
35+
throw new Error(`Failed to fetch file: ${response.statusText}`);
36+
}
37+
38+
const headers = new Headers();
39+
headers.set(
40+
"Content-Type",
41+
response.headers.get("Content-Type") ||
42+
media.mimeType ||
43+
"application/octet-stream",
44+
);
45+
46+
const fileName = media.originalFileName || "file";
47+
headers.set(
48+
"Content-Disposition",
49+
`attachment; filename="${fileName}"`,
50+
);
51+
52+
return new NextResponse(response.body, {
53+
status: 200,
54+
headers,
55+
});
56+
} catch (error) {
57+
console.error("Error downloading file:", error);
58+
return new NextResponse("Error downloading file", { status: 500 });
59+
}
60+
}

apps/web/components/community/index.tsx

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
FlagTriangleRight,
2626
Maximize2,
2727
ArrowLeft,
28+
Download,
2829
} from "lucide-react";
2930
import {
3031
Dialog,
@@ -103,7 +104,8 @@ export function CommunityForum({
103104
() => categories.filter((x) => x !== "All"),
104105
[categories],
105106
);
106-
const [fullscreenImage, setFullscreenImage] = useState<string | null>(null);
107+
const [fullscreenMedia, setFullscreenMedia] =
108+
useState<CommunityMedia | null>(null);
107109
const [page, setPage] = useState(1);
108110
const [totalPosts, setTotalPosts] = useState(0);
109111
const [postToDelete, setPostToDelete] = useState<CommunityPost | null>(
@@ -650,7 +652,7 @@ export function CommunityForum({
650652
type="button"
651653
onClick={(e) => {
652654
e.stopPropagation();
653-
setFullscreenImage(media.media!.file!);
655+
setFullscreenMedia(media);
654656
}}
655657
className="absolute top-2 right-2 rounded-md bg-black/60 text-white p-1.5 opacity-0 group-hover:opacity-100 transition-opacity hover:bg-black/80"
656658
aria-label="View full screen"
@@ -733,10 +735,40 @@ export function CommunityForum({
733735
if (options && options.renderActualFile) {
734736
// embed pdf
735737
return (
736-
<iframe
737-
src={media.media?.file}
738-
className="w-full h-48"
739-
></iframe>
738+
<div
739+
className="relative group w-full h-48"
740+
onContextMenu={(e) => e.preventDefault()}
741+
>
742+
<div className="absolute inset-0 z-10" />
743+
<iframe
744+
src={`${media.media?.file}#toolbar=0&view=FitH`}
745+
className="w-full h-full pointer-events-none"
746+
onContextMenu={(e) => e.preventDefault()}
747+
></iframe>
748+
<div className="absolute top-2 right-2 flex gap-2 opacity-0 group-hover:opacity-100 transition-opacity z-20">
749+
{media.media?.mediaId && (
750+
<a
751+
href={`/api/media/${encodeURIComponent(media.media.mediaId)}`}
752+
onClick={(e) => e.stopPropagation()}
753+
className="rounded-md bg-black/60 text-white p-1.5 hover:bg-black/80"
754+
aria-label="Download"
755+
>
756+
<Download className="h-4 w-4" />
757+
</a>
758+
)}
759+
<button
760+
type="button"
761+
onClick={(e) => {
762+
e.stopPropagation();
763+
setFullscreenMedia(media);
764+
}}
765+
className="rounded-md bg-black/60 text-white p-1.5 hover:bg-black/80"
766+
aria-label="View full screen"
767+
>
768+
<Maximize2 className="h-4 w-4" />
769+
</button>
770+
</div>
771+
</div>
740772
);
741773
}
742774
return (
@@ -1376,7 +1408,7 @@ export function CommunityForum({
13761408
onOpenChange={(open) => {
13771409
if (!open) {
13781410
setOpenPostId(null);
1379-
setFullscreenImage(null);
1411+
setFullscreenMedia(null);
13801412
}
13811413
}}
13821414
>
@@ -1387,25 +1419,34 @@ export function CommunityForum({
13871419
<VisuallyHidden>
13881420
<DialogTitle>Post&apos; content</DialogTitle>
13891421
</VisuallyHidden>
1390-
{openPost && fullscreenImage ? (
1391-
<div className="flex flex-col items-center gap-4">
1422+
{openPost && fullscreenMedia ? (
1423+
<div className="flex flex-col items-center gap-4 w-full">
13921424
<div className="flex w-full justify-start">
13931425
<button
13941426
type="button"
13951427
onClick={() =>
1396-
setFullscreenImage(null)
1428+
setFullscreenMedia(null)
13971429
}
13981430
className="rounded-md bg-muted text-muted-foreground p-1.5 hover:bg-accent transition-colors"
13991431
aria-label="Back to post"
14001432
>
14011433
<ArrowLeft className="h-5 w-5" />
14021434
</button>
14031435
</div>
1404-
<img
1405-
src={fullscreenImage}
1406-
alt="Full size preview"
1407-
className="max-w-full max-h-[65vh] object-contain rounded-md"
1408-
/>
1436+
{fullscreenMedia.type === "pdf" ? (
1437+
<div className="w-full h-[70vh] relative">
1438+
<iframe
1439+
src={`${fullscreenMedia.media?.file}#toolbar=0&view=FitH`}
1440+
className="w-full h-full rounded-md"
1441+
/>
1442+
</div>
1443+
) : (
1444+
<img
1445+
src={fullscreenMedia.media?.file}
1446+
alt="Full size preview"
1447+
className="max-w-full max-h-[65vh] object-contain rounded-md"
1448+
/>
1449+
)}
14091450
</div>
14101451
) : openPost ? (
14111452
<div className="grid gap-4">

0 commit comments

Comments
 (0)