import React, { useState, useEffect } from 'react'; import { ActionIcon, Popover } from '@mantine/core'; import { useTranslation } from 'react-i18next'; import LocalIcon from '../LocalIcon'; import { Tooltip } from '../Tooltip'; import { ViewerContext } from '../../../contexts/ViewerContext'; import { useSignature } from '../../../contexts/SignatureContext'; import { ColorSwatchButton, ColorPicker } from '../../annotation/shared/ColorPicker'; import { useFileState, useFileContext } from '../../../contexts/FileContext'; import { generateThumbnailWithMetadata } from '../../../utils/thumbnailUtils'; import { createProcessedFile } from '../../../contexts/file/fileActions'; import { createStirlingFile, createNewStirlingFileStub } from '../../../types/fileContext'; import { useNavigationState } from '../../../contexts/NavigationContext'; interface ViewerAnnotationControlsProps { currentView: string; disabled?: boolean; } export default function ViewerAnnotationControls({ currentView, disabled = false }: ViewerAnnotationControlsProps) { const { t } = useTranslation(); const [selectedColor, setSelectedColor] = useState('#000000'); const [isColorPickerOpen, setIsColorPickerOpen] = useState(false); const [isHoverColorPickerOpen, setIsHoverColorPickerOpen] = useState(false); // Viewer context for PDF controls - safely handle when not available const viewerContext = React.useContext(ViewerContext); // Signature context for accessing drawing API const { signatureApiRef, isPlacementMode } = useSignature(); // File state for save functionality const { state, selectors } = useFileState(); const { actions: fileActions } = useFileContext(); const activeFiles = selectors.getFiles(); // Check if we're in sign mode const { selectedTool } = useNavigationState(); const isSignMode = selectedTool === 'sign'; // Turn off annotation mode when switching away from viewer useEffect(() => { if (currentView !== 'viewer' && viewerContext?.isAnnotationMode) { viewerContext.setAnnotationMode(false); } }, [currentView, viewerContext]); // Don't show any annotation controls in sign mode if (isSignMode) { return null; } return ( <> {/* Annotation Visibility Toggle */} { viewerContext?.toggleAnnotationsVisibility(); }} disabled={disabled || currentView !== 'viewer' || viewerContext?.isAnnotationMode || isPlacementMode} > {/* Annotation Mode Toggle with Drawing Controls */} {viewerContext?.isAnnotationMode ? ( // When active: Show color picker on hover
setIsHoverColorPickerOpen(true)} onMouseLeave={() => setIsHoverColorPickerOpen(false)} style={{ display: 'inline-flex' }} > setIsHoverColorPickerOpen(false)} position="left" withArrow shadow="md" offset={8} > { viewerContext?.toggleAnnotationMode(); setIsHoverColorPickerOpen(false); // Close hover color picker when toggling off // Deactivate drawing tool when exiting annotation mode if (signatureApiRef?.current) { try { signatureApiRef.current.deactivateTools(); } catch (error) { console.log('Signature API not ready:', error); } } }} disabled={disabled} aria-label="Drawing mode active" >
Drawing Color
{ setIsHoverColorPickerOpen(false); // Close hover picker setIsColorPickerOpen(true); // Open main color picker modal }} />
) : ( // When inactive: Show "Draw" tooltip { viewerContext?.toggleAnnotationMode(); // Activate ink drawing tool when entering annotation mode if (signatureApiRef?.current && currentView === 'viewer') { try { signatureApiRef.current.activateDrawMode(); signatureApiRef.current.updateDrawSettings(selectedColor, 2); } catch (error) { console.log('Signature API not ready:', error); } } }} disabled={disabled} aria-label={typeof t === 'function' ? t('rightRail.draw', 'Draw') : 'Draw'} > )} {/* Save PDF with Annotations */} { if (viewerContext?.exportActions?.saveAsCopy && currentView === 'viewer') { try { const pdfArrayBuffer = await viewerContext.exportActions.saveAsCopy(); if (pdfArrayBuffer) { // Create new File object with flattened annotations const blob = new Blob([pdfArrayBuffer], { type: 'application/pdf' }); // Get the original file name or use a default const originalFileName = activeFiles.length > 0 ? activeFiles[0].name : 'document.pdf'; const newFile = new File([blob], originalFileName, { type: 'application/pdf' }); // Replace the current file in context with the saved version (exact same logic as Sign tool) if (activeFiles.length > 0) { // Generate thumbnail and metadata for the saved file const thumbnailResult = await generateThumbnailWithMetadata(newFile); const processedFileMetadata = createProcessedFile(thumbnailResult.pageCount, thumbnailResult.thumbnail); // Get current file info const currentFileIds = state.files.ids; if (currentFileIds.length > 0) { const currentFileId = currentFileIds[0]; const currentRecord = selectors.getStirlingFileStub(currentFileId); if (!currentRecord) { console.error('No file record found for:', currentFileId); return; } // Create output stub and file (exact same as Sign tool) const outputStub = createNewStirlingFileStub(newFile, undefined, thumbnailResult.thumbnail, processedFileMetadata); const outputStirlingFile = createStirlingFile(newFile, outputStub.id); // Replace the original file with the saved version await fileActions.consumeFiles([currentFileId], [outputStirlingFile], [outputStub]); } } } } catch (error) { console.error('Error saving PDF:', error); } } }} disabled={disabled} > {/* Color Picker Modal */} setIsColorPickerOpen(false)} selectedColor={selectedColor} onColorChange={(color) => { setSelectedColor(color); // Update drawing tool color if annotation mode is active if (viewerContext?.isAnnotationMode && signatureApiRef?.current && currentView === 'viewer') { try { signatureApiRef.current.updateDrawSettings(color, 2); } catch (error) { console.log('Unable to update drawing settings:', error); } } }} title="Choose Drawing Color" /> ); }