diff --git a/frontend/src/components/pageEditor/PageEditor.tsx b/frontend/src/components/pageEditor/PageEditor.tsx index 9a8382d94..1f7db7a1c 100644 --- a/frontend/src/components/pageEditor/PageEditor.tsx +++ b/frontend/src/components/pageEditor/PageEditor.tsx @@ -320,6 +320,20 @@ const PageEditor = ({ undoManagerRef.current.executeCommand(pageBreakAllCommand); }, [displayDocument]); + const handleSelectAll = useCallback(() => { + if (!displayDocument) return; + const allPageNumbers = Array.from({ length: displayDocument.pages.length }, (_, i) => i + 1); + setSelectedPageNumbers(allPageNumbers); + }, [displayDocument]); + + const handleDeselectAll = useCallback(() => { + setSelectedPageNumbers([]); + }, []); + + const handleSetSelectedPages = useCallback((pageNumbers: number[]) => { + setSelectedPageNumbers(pageNumbers); + }, []); + const handleReorderPages = useCallback((sourcePageNumber: number, targetIndex: number, selectedPages?: number[]) => { if (!displayDocument) return; @@ -548,6 +562,9 @@ const PageEditor = ({ handleSplitAll, handlePageBreak, handlePageBreakAll, + handleSelectAll, + handleDeselectAll, + handleSetSelectedPages, showExportPreview: handleExportPreview, onExportSelected, onExportAll, @@ -562,7 +579,7 @@ const PageEditor = ({ } }, [ onFunctionsReady, handleUndo, handleRedo, canUndo, canRedo, handleRotate, handleDelete, handleSplit, handleSplitAll, - handlePageBreak, handlePageBreakAll, handleExportPreview, onExportSelected, onExportAll, applyChanges, exportLoading, + handlePageBreak, handlePageBreakAll, handleSelectAll, handleDeselectAll, handleSetSelectedPages, handleExportPreview, onExportSelected, onExportAll, applyChanges, exportLoading, selectionMode, selectedPageNumbers, splitPositions, displayDocument?.pages.length, closePdf ]); diff --git a/frontend/src/components/pageEditor/PageThumbnail.tsx b/frontend/src/components/pageEditor/PageThumbnail.tsx index 1530531be..b35e09620 100644 --- a/frontend/src/components/pageEditor/PageThumbnail.tsx +++ b/frontend/src/components/pageEditor/PageThumbnail.tsx @@ -226,14 +226,12 @@ const PageThumbnail: React.FC = ({ // Handle click vs drag differentiation const handleMouseDown = useCallback((e: React.MouseEvent) => { - if (!selectionMode) return; - setIsMouseDown(true); setMouseStartPos({ x: e.clientX, y: e.clientY }); - }, [selectionMode]); + }, []); const handleMouseUp = useCallback((e: React.MouseEvent) => { - if (!selectionMode || !isMouseDown || !mouseStartPos) { + if (!isMouseDown || !mouseStartPos) { setIsMouseDown(false); setMouseStartPos(null); return; @@ -251,7 +249,7 @@ const PageThumbnail: React.FC = ({ setIsMouseDown(false); setMouseStartPos(null); - }, [selectionMode, isMouseDown, mouseStartPos, isDragging, page.pageNumber, onTogglePage]); + }, [isMouseDown, mouseStartPos, isDragging, page.pageNumber, onTogglePage]); const handleMouseLeave = useCallback(() => { setIsMouseDown(false); diff --git a/frontend/src/components/shared/RightRail.tsx b/frontend/src/components/shared/RightRail.tsx index eade0a066..1b25a84ae 100644 --- a/frontend/src/components/shared/RightRail.tsx +++ b/frontend/src/components/shared/RightRail.tsx @@ -45,19 +45,14 @@ export default function RightRail() { } if (currentView === 'pageEditor') { - let totalItems = 0; - fileRecords.forEach(rec => { - const pf = rec.processedFile; - if (pf) { - totalItems += (pf.totalPages as number) || (pf.pages?.length || 0); - } - }); - const selectedCount = Array.isArray(selectedPageNumbers) ? selectedPageNumbers.length : 0; + // Use PageEditor's own state + const totalItems = pageEditorFunctions?.totalPages || 0; + const selectedCount = pageEditorFunctions?.selectedPages?.length || 0; return { totalItems, selectedCount }; } return { totalItems: 0, selectedCount: 0 }; - }, [currentView, activeFiles, fileRecords, selectedFileIds, selectedPageNumbers]); + }, [currentView, activeFiles, selectedFileIds, pageEditorFunctions]); const { totalItems, selectedCount } = getSelectionState(); @@ -70,19 +65,10 @@ export default function RightRail() { } if (currentView === 'pageEditor') { - let totalPages = 0; - fileRecords.forEach(rec => { - const pf = rec.processedFile; - if (pf) { - totalPages += (pf.totalPages as number) || (pf.pages?.length || 0); - } - }); - - if (totalPages > 0) { - setSelectedPages(Array.from({ length: totalPages }, (_, i) => i + 1)); - } + // Use PageEditor's select all function + pageEditorFunctions?.handleSelectAll?.(); } - }, [currentView, state.files.ids, fileRecords, setSelectedFiles, setSelectedPages]); + }, [currentView, state.files.ids, setSelectedFiles, pageEditorFunctions]); const handleDeselectAll = useCallback(() => { if (currentView === 'fileEditor' || currentView === 'viewer') { @@ -90,9 +76,10 @@ export default function RightRail() { return; } if (currentView === 'pageEditor') { - setSelectedPages([]); + // Use PageEditor's deselect all function + pageEditorFunctions?.handleDeselectAll?.(); } - }, [currentView, setSelectedFiles, setSelectedPages]); + }, [currentView, setSelectedFiles, pageEditorFunctions]); const handleExportAll = useCallback(() => { if (currentView === 'fileEditor' || currentView === 'viewer') { @@ -151,24 +138,21 @@ export default function RightRail() { const updatePagesFromCSV = useCallback(() => { const rawPages = parseCSVInput(csvInput); - // Determine max page count from processed records - const maxPages = fileRecords.reduce((sum, rec) => { - const pf = rec.processedFile; - if (!pf) return sum; - return sum + ((pf.totalPages as number) || (pf.pages?.length || 0)); - }, 0); + // Use PageEditor's total pages for validation + const maxPages = pageEditorFunctions?.totalPages || 0; const normalized = Array.from(new Set(rawPages.filter(n => Number.isFinite(n) && n > 0 && n <= maxPages))).sort((a,b)=>a-b); - setSelectedPages(normalized); - }, [csvInput, parseCSVInput, fileRecords, setSelectedPages]); + // Use PageEditor's function to set selected pages + pageEditorFunctions?.handleSetSelectedPages?.(normalized); + }, [csvInput, parseCSVInput, pageEditorFunctions]); - // Sync csvInput with selectedPageNumbers changes + // Sync csvInput with PageEditor's selected pages useEffect(() => { - const sortedPageNumbers = Array.isArray(selectedPageNumbers) - ? [...selectedPageNumbers].sort((a, b) => a - b) + const sortedPageNumbers = Array.isArray(pageEditorFunctions?.selectedPages) + ? [...pageEditorFunctions.selectedPages].sort((a, b) => a - b) : []; const newCsvInput = sortedPageNumbers.join(', '); setCsvInput(newCsvInput); - }, [selectedPageNumbers]); + }, [pageEditorFunctions?.selectedPages]); // Clear CSV input when files change (use stable signature to avoid ref churn) useEffect(() => { @@ -278,7 +262,7 @@ export default function RightRail() { @@ -299,8 +283,8 @@ export default function RightRail() { variant="subtle" radius="md" className="right-rail-icon" - onClick={() => { pageEditorFunctions?.handleDelete?.(); setSelectedPages([]); }} - disabled={!pageControlsVisible || (Array.isArray(selectedPageNumbers) ? selectedPageNumbers.length === 0 : true)} + onClick={() => { pageEditorFunctions?.handleDelete?.(); }} + disabled={!pageControlsVisible || (pageEditorFunctions?.selectedPages?.length || 0) === 0} aria-label={typeof t === 'function' ? t('rightRail.deleteSelected', 'Delete Selected Pages') : 'Delete Selected Pages'} > diff --git a/frontend/src/types/pageEditor.ts b/frontend/src/types/pageEditor.ts index 5e638f02d..21f803021 100644 --- a/frontend/src/types/pageEditor.ts +++ b/frontend/src/types/pageEditor.ts @@ -53,6 +53,9 @@ export interface PageEditorFunctions { handleSplitAll: () => void; handlePageBreak: () => void; handlePageBreakAll: () => void; + handleSelectAll: () => void; + handleDeselectAll: () => void; + handleSetSelectedPages: (pageNumbers: number[]) => void; onExportSelected: () => void; onExportAll: () => void; exportLoading: boolean;