feat: enhance PhotoViewer with keyboard navigation and ID retrieval

- Implemented keyboard navigation for the PhotoViewer, allowing users to close the viewer with 'Escape' and navigate through photos using 'ArrowLeft' and 'ArrowRight' keys.
- Added a utility function to safely retrieve the photo ID, ensuring it is defined before use in various functionalities like bookmarking and rating.
This commit is contained in:
tigeren 2025-08-26 18:17:36 +00:00
parent 2ac68f9a69
commit 933d12dd14
1 changed files with 42 additions and 4 deletions

View File

@ -64,6 +64,39 @@ export default function PhotoViewer({
} }
}, [isOpen, photo]); }, [isOpen, photo]);
// Keyboard navigation
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (!isOpen) return;
switch (event.key) {
case 'Escape':
handleClose();
break;
case 'ArrowLeft':
if (onPrev) {
event.preventDefault();
handlePrev();
}
break;
case 'ArrowRight':
if (onNext) {
event.preventDefault();
handleNext();
}
break;
}
};
if (isOpen) {
document.addEventListener('keydown', handleKeyDown);
}
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, [isOpen, onNext, onPrev]);
const handleClose = () => { const handleClose = () => {
setIsPhotoLoading(false); setIsPhotoLoading(false);
onClose(); onClose();
@ -84,19 +117,19 @@ export default function PhotoViewer({
}; };
const handleBookmark = () => { const handleBookmark = () => {
if (onBookmark && 'id' in photo) { if (onBookmark && 'id' in photo && photo.id !== undefined) {
onBookmark(photo.id); onBookmark(photo.id);
} }
}; };
const handleUnbookmark = () => { const handleUnbookmark = () => {
if (onUnbookmark && 'id' in photo) { if (onUnbookmark && 'id' in photo && photo.id !== undefined) {
onUnbookmark(photo.id); onUnbookmark(photo.id);
} }
}; };
const handleRate = (rating: number) => { const handleRate = (rating: number) => {
if (onRate && 'id' in photo) { if (onRate && 'id' in photo && photo.id !== undefined) {
onRate(photo.id, rating); onRate(photo.id, rating);
} }
}; };
@ -130,6 +163,11 @@ export default function PhotoViewer({
return 0; return 0;
}; };
const getPhotoId = () => {
if ('id' in photo && photo.id !== undefined) return photo.id;
return 0;
};
if (!isOpen || typeof window === 'undefined') return null; if (!isOpen || typeof window === 'undefined') return null;
return createPortal( return createPortal(
@ -175,7 +213,7 @@ export default function PhotoViewer({
)} )}
<img <img
src={`/api/photos/${('id' in photo ? photo.id : photo.id) || ''}`} src={`/api/photos/${getPhotoId()}`}
alt={getPhotoTitle()} alt={getPhotoTitle()}
className={`max-w-full max-h-[90vh] w-auto h-auto object-contain rounded-lg ${isPhotoLoading ? 'hidden' : ''}`} className={`max-w-full max-h-[90vh] w-auto h-auto object-contain rounded-lg ${isPhotoLoading ? 'hidden' : ''}`}
onLoad={() => setIsPhotoLoading(false)} onLoad={() => setIsPhotoLoading(false)}