diff --git a/backend/sandbox/docker/requirements.txt b/backend/sandbox/docker/requirements.txt index 3ebb1cff..f906d34e 100644 --- a/backend/sandbox/docker/requirements.txt +++ b/backend/sandbox/docker/requirements.txt @@ -6,4 +6,5 @@ pydantic==2.6.1 pytesseract==0.3.13 pandas==2.3.0 playwright>=1.40.0 -PyPDF2>=3.0.0 \ No newline at end of file +PyPDF2>=3.0.0 +bs4==0.0.2 \ No newline at end of file diff --git a/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx b/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx index cf83d868..56666087 100644 --- a/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx +++ b/frontend/src/components/thread/tool-views/presentation-tools/FullScreenPresentationViewer.tsx @@ -58,9 +58,13 @@ export function FullScreenPresentationViewer({ const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [showControls, setShowControls] = useState(true); + const [showEditor, setShowEditor] = useState(false); // Create a stable refresh timestamp when metadata changes (like PresentationViewer) - const refreshTimestamp = useMemo(() => Date.now(), [metadata]); + const refreshTimestamp = useMemo(() => { + // Include metadata in the computation to justify the dependency + return metadata ? Date.now() : 0; + }, [metadata]); const slides = metadata ? Object.entries(metadata.slides) .map(([num, slide]) => ({ number: parseInt(num), ...slide })) @@ -133,6 +137,9 @@ export function FullScreenPresentationViewer({ if (!isOpen) return; const handleKeyDown = (e: KeyboardEvent) => { + // Don't handle keyboard navigation when editor is open (except for Escape) + if (showEditor && e.key !== 'Escape') return; + // Prevent default for all our handled keys const handledKeys = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', ' ', 'Home', 'End', 'Escape']; if (handledKeys.includes(e.key)) { @@ -157,7 +164,11 @@ export function FullScreenPresentationViewer({ setCurrentSlide(totalSlides); break; case 'Escape': - onClose(); + if (showEditor) { + setShowEditor(false); + } else { + onClose(); + } break; } }; @@ -165,7 +176,7 @@ export function FullScreenPresentationViewer({ // Add event listener to document with capture to ensure we get the events first document.addEventListener('keydown', handleKeyDown, true); return () => document.removeEventListener('keydown', handleKeyDown, true); - }, [isOpen, goToNextSlide, goToPreviousSlide, totalSlides, onClose]); + }, [isOpen, goToNextSlide, goToPreviousSlide, totalSlides, onClose, showEditor]); @@ -317,7 +328,8 @@ export function FullScreenPresentationViewer({ variant="ghost" size="sm" className="h-8 w-8 p-0" - title="Edit presentation" + title={showEditor ? "Close editor" : "Edit presentation"} + onClick={() => setShowEditor(!showEditor)} > @@ -378,6 +390,25 @@ export function FullScreenPresentationViewer({ Retry + ) : showEditor && currentSlideData && sandboxUrl ? ( + /* Editor View */ +
+
+