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]);
|
||||
|
||||
// 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)}
|
||||
|
|
|
|||
Loading…
Reference in New Issue