feat: implement metadata generation for file details and improve error handling
This commit is contained in:
		
							parent
							
								
									011695cf46
								
							
						
					
					
						commit
						6115851147
					
				| @ -2,8 +2,12 @@ import { notFound } from "next/navigation"; | |||||||
| import { FilePreview } from "~/app/_components/FilePreview"; | import { FilePreview } from "~/app/_components/FilePreview"; | ||||||
| import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
 | import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
 | ||||||
| import { Toaster } from "react-hot-toast"; | import { Toaster } from "react-hot-toast"; | ||||||
| import { FileActionsContainer, FileDescriptionContainer } from "~/app/_components/ActionButtons"; // Import the client component
 | import { | ||||||
|  |   FileActionsContainer, | ||||||
|  |   FileDescriptionContainer, | ||||||
|  | } from "~/app/_components/ActionButtons"; // Import the client component
 | ||||||
| import Head from "next/head"; | import Head from "next/head"; | ||||||
|  | import type { Metadata } from "next"; | ||||||
| 
 | 
 | ||||||
| interface FileDetails { | interface FileDetails { | ||||||
|   name: string; |   name: string; | ||||||
| @ -18,6 +22,46 @@ interface FileDetails { | |||||||
|   description: string; |   description: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export async function generateMetadata({ | ||||||
|  |   searchParams, | ||||||
|  | }: { | ||||||
|  |   searchParams: { id?: string }; | ||||||
|  | }): Promise<Metadata> { | ||||||
|  |   const fileId = searchParams.id; | ||||||
|  | 
 | ||||||
|  |   if (!fileId) { | ||||||
|  |     return { | ||||||
|  |       title: "File Not Found", | ||||||
|  |       description: "The file you are looking for does not exist.", | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const fileDetails = await fetchFileDetails(fileId); | ||||||
|  | 
 | ||||||
|  |   if (!fileDetails) { | ||||||
|  |     return { | ||||||
|  |       title: "File Not Found", | ||||||
|  |       description: "The file you are looking for does not exist.", | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return { | ||||||
|  |     title: fileDetails.name, | ||||||
|  |     description: fileDetails.description || fileDetails.name, | ||||||
|  |     openGraph: { | ||||||
|  |       title: fileDetails.name, | ||||||
|  |       description: fileDetails.description || fileDetails.name, | ||||||
|  |       url: `${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileDetails.id}`, | ||||||
|  |       images: [ | ||||||
|  |         { | ||||||
|  |           url: `${process.env.NEXT_PUBLIC_PAGE_URL}/api/files/serv?id=${fileDetails.id}`, | ||||||
|  |           alt: `${fileDetails.name} preview`, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| async function fetchFileDetails(fileId: string): Promise<FileDetails | null> { | async function fetchFileDetails(fileId: string): Promise<FileDetails | null> { | ||||||
|   try { |   try { | ||||||
|     const response = await fetch( |     const response = await fetch( | ||||||
| @ -41,10 +85,9 @@ async function fetchFileDetails(fileId: string): Promise<FileDetails | null> { | |||||||
| export default async function FilePreviewContainer({ | export default async function FilePreviewContainer({ | ||||||
|   searchParams, |   searchParams, | ||||||
| }: { | }: { | ||||||
|   searchParams: Promise<{ id?: string }>; |   searchParams: { id?: string }; | ||||||
| }) { | }) { | ||||||
|   const resolvedSearchParams = await searchParams; // Resolve the promise
 |   const fileId = searchParams.id; | ||||||
|   const fileId = resolvedSearchParams.id; |  | ||||||
| 
 | 
 | ||||||
|   if (!fileId) { |   if (!fileId) { | ||||||
|     notFound(); |     notFound(); | ||||||
| @ -54,22 +97,6 @@ export default async function FilePreviewContainer({ | |||||||
| 
 | 
 | ||||||
|   if (!fileDetails) { |   if (!fileDetails) { | ||||||
|     return ( |     return ( | ||||||
|       <> |  | ||||||
|         <Head> |  | ||||||
|           <title>No File Found</title> |  | ||||||
|           <meta property="og:title" content="No File Found" /> |  | ||||||
|           <meta |  | ||||||
|             property="og:description" |  | ||||||
|             content="The file you are looking for does not exist." |  | ||||||
|           /> |  | ||||||
|           <meta property="og:type" content="website" /> |  | ||||||
|           <meta property="og:image" content="/images/no-file.png" /> |  | ||||||
|           <meta property="og:image:alt" content="No file found" /> |  | ||||||
|           <meta |  | ||||||
|             property="og:url" |  | ||||||
|             content={`${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileId}`} |  | ||||||
|           /> |  | ||||||
|         </Head> |  | ||||||
|       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> |       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||||
|         <Toaster position="top-right" reverseOrder={false} /> |         <Toaster position="top-right" reverseOrder={false} /> | ||||||
|         <div className="absolute top-4 left-4"> |         <div className="absolute top-4 left-4"> | ||||||
| @ -81,43 +108,10 @@ export default async function FilePreviewContainer({ | |||||||
|           </h1> |           </h1> | ||||||
|         </div> |         </div> | ||||||
|       </main> |       </main> | ||||||
|       </> |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <> |  | ||||||
|       <Head> |  | ||||||
|         <title>{fileDetails.name} - File Details</title> |  | ||||||
|         <meta |  | ||||||
|           property="og:title" |  | ||||||
|           content={`${fileDetails.name} - File Details`} |  | ||||||
|         /> |  | ||||||
|         <meta |  | ||||||
|           property="og:description" |  | ||||||
|           content={`Size: ${ |  | ||||||
|             fileDetails.size > 1024 * 1024 * 1024 |  | ||||||
|               ? (fileDetails.size / (1024 * 1024 * 1024)).toFixed(2) + " GB" |  | ||||||
|               : fileDetails.size > 1024 * 1024 |  | ||||||
|               ? (fileDetails.size / (1024 * 1024)).toFixed(2) + " MB" |  | ||||||
|               : fileDetails.size > 1024 |  | ||||||
|               ? (fileDetails.size / 1024).toFixed(2) + " KB" |  | ||||||
|               : fileDetails.size + " Bytes" |  | ||||||
|           }, Owner: ${fileDetails.owner}, Uploaded on: ${new Date( |  | ||||||
|             fileDetails.uploadDate |  | ||||||
|           ).toLocaleString()}`}
 |  | ||||||
|         /> |  | ||||||
|         <meta property="og:type" content="website" /> |  | ||||||
|         <meta |  | ||||||
|           property="og:image" |  | ||||||
|           content={`${process.env.NEXT_PUBLIC_PAGE_URL}/api/files/serv?id=${fileId}`} |  | ||||||
|         /> |  | ||||||
|         <meta property="og:image:alt" content={`${fileDetails.name} preview`} /> |  | ||||||
|         <meta |  | ||||||
|           property="og:url" |  | ||||||
|           content={`${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileId}`} |  | ||||||
|         /> |  | ||||||
|       </Head> |  | ||||||
|     <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> |     <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||||
|       <div className="absolute top-4 left-4"> |       <div className="absolute top-4 left-4"> | ||||||
|         <HomeButton /> |         <HomeButton /> | ||||||
| @ -129,13 +123,10 @@ export default async function FilePreviewContainer({ | |||||||
|         </h1> |         </h1> | ||||||
|         <div className="mt-6"> |         <div className="mt-6"> | ||||||
|           {fileDetails.type !== "unknown" && ( |           {fileDetails.type !== "unknown" && ( | ||||||
|               <FilePreview |             <FilePreview fileId={fileDetails.id} fileType={fileDetails.type} /> | ||||||
|                 fileId={fileDetails.id} |  | ||||||
|                 fileType={fileDetails.type} |  | ||||||
|               /> |  | ||||||
|           )} |           )} | ||||||
|         </div> |         </div> | ||||||
|           <div className="bg-white/10 shadow-md rounded-lg p-6 w-full max-w-md text-white"> |         <div className="w-full max-w-md rounded-lg bg-white/10 p-6 text-white shadow-md"> | ||||||
|           <p> |           <p> | ||||||
|             <strong>Name:</strong> {fileDetails.name} |             <strong>Name:</strong> {fileDetails.name} | ||||||
|           </p> |           </p> | ||||||
| @ -152,7 +143,7 @@ export default async function FilePreviewContainer({ | |||||||
|           <p> |           <p> | ||||||
|             <strong>Owner:</strong>{" "} |             <strong>Owner:</strong>{" "} | ||||||
|             <img |             <img | ||||||
|                 className="rounded-md inline size-5" |               className="inline size-5 rounded-md" | ||||||
|               src={fileDetails.ownerAvatar || ""} |               src={fileDetails.ownerAvatar || ""} | ||||||
|               alt="Owner avatar" |               alt="Owner avatar" | ||||||
|             />{" "} |             />{" "} | ||||||
| @ -164,7 +155,10 @@ export default async function FilePreviewContainer({ | |||||||
|           </p> |           </p> | ||||||
|           <div> |           <div> | ||||||
|             <strong>Description:</strong>{" "} |             <strong>Description:</strong>{" "} | ||||||
|               <FileDescriptionContainer fileId={fileDetails.id} fileDescription={fileDetails.description}/> |             <FileDescriptionContainer | ||||||
|  |               fileId={fileDetails.id} | ||||||
|  |               fileDescription={fileDetails.description} | ||||||
|  |             /> | ||||||
|           </div> |           </div> | ||||||
|           <div className="mt-4 flex justify-center"> |           <div className="mt-4 flex justify-center"> | ||||||
|             <FileActionsContainer |             <FileActionsContainer | ||||||
| @ -177,7 +171,5 @@ export default async function FilePreviewContainer({ | |||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </main> |     </main> | ||||||
|     </> |  | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user