Compare commits

..

No commits in common. "854afd4c4154866fa9a7fd5034b803444bc23f6c" and "848578c136ec7606b5b8dce5b3425bb0bdb577d7" have entirely different histories.

6 changed files with 13 additions and 157 deletions

View File

@ -28,11 +28,6 @@ UI:
8. the video card can be clicked, once clicked, a poped up video player will be displayed. it can be closed, fast forward, expand to full screen, etc.
9. can bookmark/un-bookmark the video, can star the video
Deployment:
1. use docker compose to deploy the service
2. Dockerfile should be defined
3. docker-compose.yml should be defined.
Development Rules:
1. Everytime after making all the changes, run 'pnpm build' to verify the changes are compiling correct.
2. Once added debug logs, don't delete it until told so.

View File

@ -148,6 +148,7 @@ const FolderViewerPage = () => {
const handlePhotoClick = (item: FileSystemItem, index: number) => {
if (item.type === 'photo' && item.id) {
setSelectedPhoto(item);
setCurrentPhotoIndex(index);
setIsPhotoViewerOpen(true);
}
};
@ -157,40 +158,16 @@ const FolderViewerPage = () => {
setSelectedPhoto(null);
};
const [currentItems, setCurrentItems] = useState<FileSystemItem[]>([]);
const handleNextPhoto = () => {
// Navigate to next photo, skipping videos
const photos = currentItems.filter(item => item.type === 'photo' && item.id);
if (photos.length === 0) return;
const currentPhotoId = selectedPhoto?.id;
if (!currentPhotoId) return;
const currentIndexInPhotos = photos.findIndex(p => p.id === currentPhotoId);
if (currentIndexInPhotos === -1) return;
const nextIndex = (currentIndexInPhotos + 1) % photos.length;
const nextPhoto = photos[nextIndex];
setSelectedPhoto(nextPhoto);
// This would need to be implemented with the current items list
// For now, just close the viewer
handleClosePhotoViewer();
};
const handlePrevPhoto = () => {
// Navigate to previous photo, skipping videos
const photos = currentItems.filter(item => item.type === 'photo' && item.id);
if (photos.length === 0) return;
const currentPhotoId = selectedPhoto?.id;
if (!currentPhotoId) return;
const currentIndexInPhotos = photos.findIndex(p => p.id === currentPhotoId);
if (currentIndexInPhotos === -1) return;
const prevIndex = (currentIndexInPhotos - 1 + photos.length) % photos.length;
const prevPhoto = photos[prevIndex];
setSelectedPhoto(prevPhoto);
// This would need to be implemented with the current items list
// For now, just close the viewer
handleClosePhotoViewer();
};
if (!path) {
@ -223,7 +200,6 @@ const FolderViewerPage = () => {
onBreadcrumbClick={handleBreadcrumbClick}
breadcrumbs={getBreadcrumbs(path)}
libraries={libraries}
onItemsLoaded={setCurrentItems}
/>
{/* Photo Viewer */}
@ -233,7 +209,7 @@ const FolderViewerPage = () => {
onClose={handleClosePhotoViewer}
onNext={handleNextPhoto}
onPrev={handlePrevPhoto}
showNavigation={true}
showNavigation={false}
showBookmarks={false}
showRatings={false}
formatFileSize={formatFileSize}

View File

@ -19,49 +19,12 @@ interface Photo {
export default function PhotosPage() {
const [selectedPhoto, setSelectedPhoto] = useState<Photo | null>(null);
const [isViewerOpen, setIsViewerOpen] = useState(false);
const [photosList, setPhotosList] = useState<Photo[]>([]);
const [currentPhotoIndex, setCurrentPhotoIndex] = useState(0);
const handlePhotoClick = (photo: Photo, index?: number) => {
const handlePhotoClick = (photo: Photo) => {
setSelectedPhoto(photo);
if (index !== undefined) {
setCurrentPhotoIndex(index);
}
setIsViewerOpen(true);
};
const handlePhotosData = (photos: Photo[]) => {
setPhotosList(photos);
};
const handleNextPhoto = () => {
if (photosList.length === 0) return;
const currentPhotoId = selectedPhoto?.id;
if (!currentPhotoId) return;
const currentIndex = photosList.findIndex(p => p.id === currentPhotoId);
if (currentIndex === -1) return;
const nextIndex = (currentIndex + 1) % photosList.length;
setSelectedPhoto(photosList[nextIndex]);
setCurrentPhotoIndex(nextIndex);
};
const handlePrevPhoto = () => {
if (photosList.length === 0) return;
const currentPhotoId = selectedPhoto?.id;
if (!currentPhotoId) return;
const currentIndex = photosList.findIndex(p => p.id === currentPhotoId);
if (currentIndex === -1) return;
const prevIndex = (currentIndex - 1 + photosList.length) % photosList.length;
setSelectedPhoto(photosList[prevIndex]);
setCurrentPhotoIndex(prevIndex);
};
const handleCloseViewer = () => {
setIsViewerOpen(false);
setSelectedPhoto(null);
@ -103,7 +66,6 @@ export default function PhotosPage() {
onBookmark={handleBookmark}
onUnbookmark={handleUnbookmark}
onRate={handleRate}
onDataUpdate={handlePhotosData}
/>
{/* Photo Viewer */}
@ -111,9 +73,6 @@ export default function PhotosPage() {
photo={selectedPhoto!}
isOpen={isViewerOpen}
onClose={handleCloseViewer}
onNext={handleNextPhoto}
onPrev={handlePrevPhoto}
showNavigation={true}
showBookmarks={true}
showRatings={true}
onBookmark={handleBookmark}

View File

@ -21,11 +21,10 @@ interface MediaItem {
interface InfiniteVirtualGridProps {
type: 'video' | 'photo' | 'bookmark';
onItemClick: (item: MediaItem, index?: number) => void;
onItemClick: (item: MediaItem) => void;
onBookmark: (id: number) => Promise<void>;
onUnbookmark: (id: number) => Promise<void>;
onRate: (id: number, rating: number) => Promise<void>;
onDataUpdate?: (items: MediaItem[]) => void;
}
const ITEM_HEIGHT = 220;
@ -37,8 +36,7 @@ export default function InfiniteVirtualGrid({
onItemClick,
onBookmark,
onUnbookmark,
onRate,
onDataUpdate
onRate
}: InfiniteVirtualGridProps) {
const [totalItems, setTotalItems] = useState(0);
const [searchTerm, setSearchTerm] = useState('');
@ -326,23 +324,6 @@ export default function InfiniteVirtualGrid({
fetchItems(nextBatchStart, batchEnd);
}
}
// Collect all available items and notify parent
if (onDataUpdate) {
const allItems: MediaItem[] = [];
const sortedKeys = Array.from(dataCacheRef.current.keys()).sort((a, b) => a - b);
for (const batchKey of sortedKeys) {
const items = dataCacheRef.current.get(batchKey);
if (items) {
allItems.push(...items);
}
}
if (allItems.length > 0) {
onDataUpdate(allItems);
}
}
}, [totalItems, fetchItems, getColumnCount]);
const Cell = ({ columnIndex, rowIndex, style }: any) => {
@ -371,7 +352,7 @@ export default function InfiniteVirtualGrid({
<div style={style} className="p-2">
<Card
className="group hover:shadow-lg transition-all duration-300 hover:-translate-y-1 cursor-pointer border-border overflow-hidden h-full"
onClick={() => onItemClick(item, index)}
onClick={() => onItemClick(item)}
>
<div className="relative overflow-hidden bg-muted aspect-video">
<img

View File

@ -86,53 +86,6 @@ export default function VideoViewer({
}
}, [isOpen, video]);
// Keyboard shortcuts
useEffect(() => {
if (!isOpen) return;
const handleKeyDown = (e: KeyboardEvent) => {
if (!videoRef.current) return;
switch (e.key) {
case 'Escape':
e.preventDefault();
onClose();
break;
case 'ArrowRight':
e.preventDefault();
videoRef.current.currentTime = Math.min(
videoRef.current.currentTime + 10,
videoRef.current.duration || 0
);
break;
case 'ArrowLeft':
e.preventDefault();
videoRef.current.currentTime = Math.max(
videoRef.current.currentTime - 10,
0
);
break;
case ' ':
e.preventDefault();
handlePlayPause();
break;
case 'f':
case 'F':
e.preventDefault();
handleFullscreen();
break;
case 'm':
case 'M':
e.preventDefault();
handleMute();
break;
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [isOpen, onClose]);
const handlePlayPause = () => {
if (videoRef.current) {
if (isPlaying) {

View File

@ -34,7 +34,6 @@ interface VirtualizedFolderGridProps {
onBreadcrumbClick: (path: string) => void;
breadcrumbs: BreadcrumbItem[];
libraries: {id: number, path: string}[];
onItemsLoaded?: (items: FileSystemItem[]) => void;
}
const ITEM_HEIGHT = 280; // Increased for folder cards
@ -46,8 +45,7 @@ export default function VirtualizedFolderGrid({
onBackClick,
onBreadcrumbClick,
breadcrumbs,
libraries,
onItemsLoaded
libraries
}: VirtualizedFolderGridProps) {
const [items, setItems] = useState<FileSystemItem[]>([]);
const [loading, setLoading] = useState(false);
@ -205,12 +203,6 @@ export default function VirtualizedFolderGrid({
}
}, [currentPath, fetchItems]);
useEffect(() => {
if (onItemsLoaded) {
onItemsLoaded(items);
}
}, [items, onItemsLoaded]);
const Cell = ({ columnIndex, rowIndex, style }: any) => {
const columnCount = getColumnCount();
const index = rowIndex * columnCount + columnIndex;