Fix right rail interaction

This commit is contained in:
Reece Browne 2025-08-25 19:24:11 +01:00
parent e63572197d
commit 2c5354fa1d
4 changed files with 46 additions and 44 deletions

View File

@ -320,6 +320,20 @@ const PageEditor = ({
undoManagerRef.current.executeCommand(pageBreakAllCommand); undoManagerRef.current.executeCommand(pageBreakAllCommand);
}, [displayDocument]); }, [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[]) => { const handleReorderPages = useCallback((sourcePageNumber: number, targetIndex: number, selectedPages?: number[]) => {
if (!displayDocument) return; if (!displayDocument) return;
@ -548,6 +562,9 @@ const PageEditor = ({
handleSplitAll, handleSplitAll,
handlePageBreak, handlePageBreak,
handlePageBreakAll, handlePageBreakAll,
handleSelectAll,
handleDeselectAll,
handleSetSelectedPages,
showExportPreview: handleExportPreview, showExportPreview: handleExportPreview,
onExportSelected, onExportSelected,
onExportAll, onExportAll,
@ -562,7 +579,7 @@ const PageEditor = ({
} }
}, [ }, [
onFunctionsReady, handleUndo, handleRedo, canUndo, canRedo, handleRotate, handleDelete, handleSplit, handleSplitAll, 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 selectionMode, selectedPageNumbers, splitPositions, displayDocument?.pages.length, closePdf
]); ]);

View File

@ -226,14 +226,12 @@ const PageThumbnail: React.FC<PageThumbnailProps> = ({
// Handle click vs drag differentiation // Handle click vs drag differentiation
const handleMouseDown = useCallback((e: React.MouseEvent) => { const handleMouseDown = useCallback((e: React.MouseEvent) => {
if (!selectionMode) return;
setIsMouseDown(true); setIsMouseDown(true);
setMouseStartPos({ x: e.clientX, y: e.clientY }); setMouseStartPos({ x: e.clientX, y: e.clientY });
}, [selectionMode]); }, []);
const handleMouseUp = useCallback((e: React.MouseEvent) => { const handleMouseUp = useCallback((e: React.MouseEvent) => {
if (!selectionMode || !isMouseDown || !mouseStartPos) { if (!isMouseDown || !mouseStartPos) {
setIsMouseDown(false); setIsMouseDown(false);
setMouseStartPos(null); setMouseStartPos(null);
return; return;
@ -251,7 +249,7 @@ const PageThumbnail: React.FC<PageThumbnailProps> = ({
setIsMouseDown(false); setIsMouseDown(false);
setMouseStartPos(null); setMouseStartPos(null);
}, [selectionMode, isMouseDown, mouseStartPos, isDragging, page.pageNumber, onTogglePage]); }, [isMouseDown, mouseStartPos, isDragging, page.pageNumber, onTogglePage]);
const handleMouseLeave = useCallback(() => { const handleMouseLeave = useCallback(() => {
setIsMouseDown(false); setIsMouseDown(false);

View File

@ -45,19 +45,14 @@ export default function RightRail() {
} }
if (currentView === 'pageEditor') { if (currentView === 'pageEditor') {
let totalItems = 0; // Use PageEditor's own state
fileRecords.forEach(rec => { const totalItems = pageEditorFunctions?.totalPages || 0;
const pf = rec.processedFile; const selectedCount = pageEditorFunctions?.selectedPages?.length || 0;
if (pf) {
totalItems += (pf.totalPages as number) || (pf.pages?.length || 0);
}
});
const selectedCount = Array.isArray(selectedPageNumbers) ? selectedPageNumbers.length : 0;
return { totalItems, selectedCount }; return { totalItems, selectedCount };
} }
return { totalItems: 0, selectedCount: 0 }; return { totalItems: 0, selectedCount: 0 };
}, [currentView, activeFiles, fileRecords, selectedFileIds, selectedPageNumbers]); }, [currentView, activeFiles, selectedFileIds, pageEditorFunctions]);
const { totalItems, selectedCount } = getSelectionState(); const { totalItems, selectedCount } = getSelectionState();
@ -70,19 +65,10 @@ export default function RightRail() {
} }
if (currentView === 'pageEditor') { if (currentView === 'pageEditor') {
let totalPages = 0; // Use PageEditor's select all function
fileRecords.forEach(rec => { pageEditorFunctions?.handleSelectAll?.();
const pf = rec.processedFile;
if (pf) {
totalPages += (pf.totalPages as number) || (pf.pages?.length || 0);
} }
}); }, [currentView, state.files.ids, setSelectedFiles, pageEditorFunctions]);
if (totalPages > 0) {
setSelectedPages(Array.from({ length: totalPages }, (_, i) => i + 1));
}
}
}, [currentView, state.files.ids, fileRecords, setSelectedFiles, setSelectedPages]);
const handleDeselectAll = useCallback(() => { const handleDeselectAll = useCallback(() => {
if (currentView === 'fileEditor' || currentView === 'viewer') { if (currentView === 'fileEditor' || currentView === 'viewer') {
@ -90,9 +76,10 @@ export default function RightRail() {
return; return;
} }
if (currentView === 'pageEditor') { if (currentView === 'pageEditor') {
setSelectedPages([]); // Use PageEditor's deselect all function
pageEditorFunctions?.handleDeselectAll?.();
} }
}, [currentView, setSelectedFiles, setSelectedPages]); }, [currentView, setSelectedFiles, pageEditorFunctions]);
const handleExportAll = useCallback(() => { const handleExportAll = useCallback(() => {
if (currentView === 'fileEditor' || currentView === 'viewer') { if (currentView === 'fileEditor' || currentView === 'viewer') {
@ -151,24 +138,21 @@ export default function RightRail() {
const updatePagesFromCSV = useCallback(() => { const updatePagesFromCSV = useCallback(() => {
const rawPages = parseCSVInput(csvInput); const rawPages = parseCSVInput(csvInput);
// Determine max page count from processed records // Use PageEditor's total pages for validation
const maxPages = fileRecords.reduce((sum, rec) => { const maxPages = pageEditorFunctions?.totalPages || 0;
const pf = rec.processedFile;
if (!pf) return sum;
return sum + ((pf.totalPages as number) || (pf.pages?.length || 0));
}, 0);
const normalized = Array.from(new Set(rawPages.filter(n => Number.isFinite(n) && n > 0 && n <= maxPages))).sort((a,b)=>a-b); const normalized = Array.from(new Set(rawPages.filter(n => Number.isFinite(n) && n > 0 && n <= maxPages))).sort((a,b)=>a-b);
setSelectedPages(normalized); // Use PageEditor's function to set selected pages
}, [csvInput, parseCSVInput, fileRecords, setSelectedPages]); pageEditorFunctions?.handleSetSelectedPages?.(normalized);
}, [csvInput, parseCSVInput, pageEditorFunctions]);
// Sync csvInput with selectedPageNumbers changes // Sync csvInput with PageEditor's selected pages
useEffect(() => { useEffect(() => {
const sortedPageNumbers = Array.isArray(selectedPageNumbers) const sortedPageNumbers = Array.isArray(pageEditorFunctions?.selectedPages)
? [...selectedPageNumbers].sort((a, b) => a - b) ? [...pageEditorFunctions.selectedPages].sort((a, b) => a - b)
: []; : [];
const newCsvInput = sortedPageNumbers.join(', '); const newCsvInput = sortedPageNumbers.join(', ');
setCsvInput(newCsvInput); setCsvInput(newCsvInput);
}, [selectedPageNumbers]); }, [pageEditorFunctions?.selectedPages]);
// Clear CSV input when files change (use stable signature to avoid ref churn) // Clear CSV input when files change (use stable signature to avoid ref churn)
useEffect(() => { useEffect(() => {
@ -278,7 +262,7 @@ export default function RightRail() {
<BulkSelectionPanel <BulkSelectionPanel
csvInput={csvInput} csvInput={csvInput}
setCsvInput={setCsvInput} setCsvInput={setCsvInput}
selectedPages={Array.isArray(selectedPageNumbers) ? selectedPageNumbers : []} selectedPages={Array.isArray(pageEditorFunctions?.selectedPages) ? pageEditorFunctions.selectedPages : []}
onUpdatePagesFromCSV={updatePagesFromCSV} onUpdatePagesFromCSV={updatePagesFromCSV}
/> />
</div> </div>
@ -299,8 +283,8 @@ export default function RightRail() {
variant="subtle" variant="subtle"
radius="md" radius="md"
className="right-rail-icon" className="right-rail-icon"
onClick={() => { pageEditorFunctions?.handleDelete?.(); setSelectedPages([]); }} onClick={() => { pageEditorFunctions?.handleDelete?.(); }}
disabled={!pageControlsVisible || (Array.isArray(selectedPageNumbers) ? selectedPageNumbers.length === 0 : true)} disabled={!pageControlsVisible || (pageEditorFunctions?.selectedPages?.length || 0) === 0}
aria-label={typeof t === 'function' ? t('rightRail.deleteSelected', 'Delete Selected Pages') : 'Delete Selected Pages'} aria-label={typeof t === 'function' ? t('rightRail.deleteSelected', 'Delete Selected Pages') : 'Delete Selected Pages'}
> >
<LocalIcon icon="delete-outline-rounded" width="1.5rem" height="1.5rem" /> <LocalIcon icon="delete-outline-rounded" width="1.5rem" height="1.5rem" />

View File

@ -53,6 +53,9 @@ export interface PageEditorFunctions {
handleSplitAll: () => void; handleSplitAll: () => void;
handlePageBreak: () => void; handlePageBreak: () => void;
handlePageBreakAll: () => void; handlePageBreakAll: () => void;
handleSelectAll: () => void;
handleDeselectAll: () => void;
handleSetSelectedPages: (pageNumbers: number[]) => void;
onExportSelected: () => void; onExportSelected: () => void;
onExportAll: () => void; onExportAll: () => void;
exportLoading: boolean; exportLoading: boolean;