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]);
// 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 = () => {
setIsPhotoLoading(false);
onClose();
@ -84,19 +117,19 @@ export default function PhotoViewer({
};
const handleBookmark = () => {
if (onBookmark && 'id' in photo) {
if (onBookmark && 'id' in photo && photo.id !== undefined) {
onBookmark(photo.id);
}
};
const handleUnbookmark = () => {
if (onUnbookmark && 'id' in photo) {
if (onUnbookmark && 'id' in photo && photo.id !== undefined) {
onUnbookmark(photo.id);
}
};
const handleRate = (rating: number) => {
if (onRate && 'id' in photo) {
if (onRate && 'id' in photo && photo.id !== undefined) {
onRate(photo.id, rating);
}
};
@ -130,6 +163,11 @@ export default function PhotoViewer({
return 0;
};
const getPhotoId = () => {
if ('id' in photo && photo.id !== undefined) return photo.id;
return 0;
};
if (!isOpen || typeof window === 'undefined') return null;
return createPortal(
@ -175,7 +213,7 @@ export default function PhotoViewer({
)}
<img
src={`/api/photos/${('id' in photo ? photo.id : photo.id) || ''}`}
src={`/api/photos/${getPhotoId()}`}
alt={getPhotoTitle()}
className={`max-w-full max-h-[90vh] w-auto h-auto object-contain rounded-lg ${isPhotoLoading ? 'hidden' : ''}`}
onLoad={() => setIsPhotoLoading(false)}