diff --git a/ui/src/components/DatasetImageViewer.tsx b/ui/src/components/DatasetImageViewer.tsx index f973a00a..1a86561d 100644 --- a/ui/src/components/DatasetImageViewer.tsx +++ b/ui/src/components/DatasetImageViewer.tsx @@ -2,7 +2,7 @@ import { useState, useEffect, useMemo, useCallback, useRef } from 'react'; import { createPortal } from 'react-dom'; import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react'; -import { Cog, SquareDashed, Pencil } from 'lucide-react'; +import { Cog, SquareDashed } from 'lucide-react'; import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'; import classNames from 'classnames'; import { openConfirm } from './ConfirmModal'; @@ -10,7 +10,7 @@ import { apiClient } from '@/utils/api'; import { isVideo, isAudio } from '@/utils/basic'; import AudioPlayer from './AudioPlayer'; import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'; -import BoundingBoxOverlay, { BoundingBoxEditor, parseBoundingBoxes, extractBoxes } from './BoundingBoxOverlay'; +import { BoundingBoxEditor, parseBoundingBoxes, extractBoxes } from './BoundingBoxOverlay'; function safeParse(text: string): any { try { @@ -35,7 +35,6 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre const [savedCaption, setSavedCaption] = useState(''); const [isCaptionLoaded, setIsCaptionLoaded] = useState(false); const [showBoxes, setShowBoxes] = useState(false); - const [isEditingBoxes, setIsEditingBoxes] = useState(false); const [selectedBoxIndex, setSelectedBoxIndex] = useState(null); const [isDrawing, setIsDrawing] = useState(false); const captionRef = useRef(''); @@ -45,9 +44,8 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre useEffect(() => setMounted(true), []); - // Leave box-edit mode whenever the image changes, to avoid accidental edits. + // Clear box selection / draw mode whenever the image changes. useEffect(() => { - setIsEditingBoxes(false); setSelectedBoxIndex(null); setIsDrawing(false); }, [imgPath]); @@ -321,8 +319,8 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre break; case 'Delete': case 'Backspace': - // While editing boxes, Delete removes the selected box (never the image). - if (isEditingBoxes) { + // With boxes shown, Delete removes the selected box (never the image). + if (showBoxes) { if (selectedBoxIndex != null) handleDeleteBox(selectedBoxIndex); } else { handleDelete(); @@ -334,7 +332,7 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); - }, [isOpen, onCancel, handlePrev, handleNext, handleDelete, isEditingBoxes, selectedBoxIndex, handleDeleteBox]); + }, [isOpen, onCancel, handlePrev, handleNext, handleDelete, showBoxes, selectedBoxIndex, handleDeleteBox]); // Touch swipe navigation const touchStartRef = useRef<{ x: number; y: number } | null>(null); @@ -413,18 +411,19 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre transition onTouchStart={onTouchStart} onTouchEnd={onTouchEnd} - className="relative transform rounded-none sm:rounded-lg bg-gray-800 text-left shadow-xl transition-all data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in w-full sm:w-auto sm:max-w-[95%] sm:max-h-[95vh] data-closed:sm:translate-y-0 data-closed:sm:scale-95 flex flex-col overflow-hidden touch-pan-y" + className="relative transform rounded-none sm:rounded-lg bg-gray-800 text-left shadow-xl transition-all data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in w-full sm:w-auto sm:max-w-[95vw] sm:max-h-[95vh] data-closed:sm:translate-y-0 data-closed:sm:scale-95 flex flex-col sm:flex-row overflow-hidden touch-pan-y" > -
+ {/* Image / media area */} +
{imgPath && (isAudio(imgPath) ? ( -
+
) : isVideo(imgPath) ? (
))} + + {/* Controls over the image */} +
+ {canShowBoxes && ( + + )} +
+ + + + + + {imgPath && isAudio(imgPath) && ( + + + Download + + + )} + +
+ Delete Image +
+
+
+
+
+
-
-
+ + {/* Right sidebar: file info + caption + box editor */} +
+
File: {filename} @@ -480,23 +531,22 @@ export default function DatasetImageViewer({ imgPath, imageList, onChange, refre