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:
parent
2ac68f9a69
commit
933d12dd14
|
|
@ -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)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue