"use client"; import { useState, useEffect, Suspense } from "react"; import { useSearchParams } from "next/navigation"; import { Folder, File, Image, Film, Play } from "lucide-react"; import Link from "next/link"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import InlineVideoPlayer from "@/components/inline-video-player"; import { createPortal } from "react-dom"; interface FileSystemItem { name: string; path: string; isDirectory: boolean; size: number; thumbnail?: string; type?: string; id?: number; } const FolderViewerPage = () => { const searchParams = useSearchParams(); const path = searchParams.get("path"); const [items, setItems] = useState([]); const [loading, setLoading] = useState(false); const [selectedVideo, setSelectedVideo] = useState(null); const [isPlayerOpen, setIsPlayerOpen] = useState(false); const [isVideoLoading, setIsVideoLoading] = useState(false); useEffect(() => { if (path) { fetchItems(path); } }, [path]); const fetchItems = async (currentPath: string) => { setLoading(true); try { const res = await fetch(`/api/files?path=${currentPath}`); const data = await res.json(); setItems(data); } catch (error) { console.error('Error fetching items:', error); } finally { setLoading(false); } }; const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const getFileIcon = (item: FileSystemItem) => { if (item.isDirectory) return ; if (item.type === 'photo') return ; if (item.type === 'video') return ; return ; }; const isMediaFile = (item: FileSystemItem) => { return item.type === 'video' || item.type === 'photo'; }; const handleVideoClick = (item: FileSystemItem) => { if (item.type === 'video' && item.id) { setIsVideoLoading(true); setSelectedVideo(item); setIsPlayerOpen(true); // Reset loading state after a short delay to allow player to initialize setTimeout(() => setIsVideoLoading(false), 500); } }; const handleClosePlayer = () => { setIsPlayerOpen(false); setSelectedVideo(null); }; if (!path) { return (

Select a library from the sidebar

Choose a media library above to browse its contents

); } return (
{loading && (
Loading directory...
)}
{!path ? (

Select a Library

Choose a media library from the sidebar to browse your files

) : ( <>

{path.split('/').pop()}

{items.map((item) => (
{ if (item.type === 'video' && item.id) { e.preventDefault(); handleVideoClick(item); } }}>
{item.isDirectory ? (
) : isMediaFile(item) ? (
{item.name}
{item.type === 'video' ? (
) : (
)}
{item.type === 'video' && ( <> {/* Always visible small play icon */}
{/* Large play button on hover */}
{/* Loading overlay when video is being opened */} {isVideoLoading && selectedVideo?.id === item.id && (
)} )}
) : (
{getFileIcon(item)}
)}

{item.name}

{formatFileSize(item.size)}

))}
{items.length === 0 && !loading && (

Empty Directory

No files or folders found in this location.

)} )}
{/* Inline Video Player - Rendered as Portal */} {selectedVideo && isPlayerOpen && typeof window !== 'undefined' && createPortal( , document.body )}
); }; const FolderViewerPageWrapper = () => ( Loading...
}> ) export default FolderViewerPageWrapper;