Delete and selection

This commit is contained in:
Reece Browne 2025-08-23 02:04:58 +01:00
parent 86221c2082
commit fd1b8e7e2a
3 changed files with 117 additions and 52 deletions

View File

@ -366,7 +366,6 @@ const PageEditor = ({
const [selectedPageNumbers, setSelectedPageNumbers] = useState<number[]>([]); const [selectedPageNumbers, setSelectedPageNumbers] = useState<number[]>([]);
const [movingPage, setMovingPage] = useState<number | null>(null); const [movingPage, setMovingPage] = useState<number | null>(null);
const [isAnimating, setIsAnimating] = useState(false); const [isAnimating, setIsAnimating] = useState(false);
const [csvInput, setCsvInput] = useState('');
// Position-based split tracking (replaces page-based splitAfter) // Position-based split tracking (replaces page-based splitAfter)
const [splitPositions, setSplitPositions] = useState<Set<number>>(new Set()); const [splitPositions, setSplitPositions] = useState<Set<number>>(new Set());
@ -404,31 +403,6 @@ const PageEditor = ({
); );
}, [mergedPdfDocument]); }, [mergedPdfDocument]);
// CSV page selection
const updatePagesFromCSV = useCallback(() => {
if (!csvInput.trim()) return;
const pageNumbers: number[] = [];
const ranges = csvInput.split(',').map(s => s.trim());
ranges.forEach(range => {
if (range.includes('-')) {
const [start, end] = range.split('-').map(n => parseInt(n.trim()));
if (!isNaN(start) && !isNaN(end)) {
for (let i = start; i <= end; i++) {
pageNumbers.push(i);
}
}
} else {
const num = parseInt(range);
if (!isNaN(num)) {
pageNumbers.push(num);
}
}
});
setSelectedPageNumbers(pageNumbers);
}, [csvInput]);
// Animation helpers // Animation helpers
const animateReorder = useCallback(() => { const animateReorder = useCallback(() => {
@ -507,8 +481,103 @@ const PageEditor = ({
}, [displayDocument, selectedPageNumbers, handleRotatePages]); }, [displayDocument, selectedPageNumbers, handleRotatePages]);
const handleDelete = useCallback(() => { const handleDelete = useCallback(() => {
if (!displayDocument) return;
if (selectedPageNumbers.length === 0) {
console.log('No pages selected for deletion');
return;
}
console.log('Delete selected pages:', selectedPageNumbers); console.log('Delete selected pages:', selectedPageNumbers);
}, [selectedPageNumbers]);
// Filter out the selected pages
const remainingPages = displayDocument.pages.filter(
page => !selectedPageNumbers.includes(page.pageNumber)
);
if (remainingPages.length === 0) {
console.log('Cannot delete all pages - at least one page must remain');
return;
}
// Re-number the remaining pages sequentially
remainingPages.forEach((page, index) => {
page.pageNumber = index + 1;
});
// Create updated document with remaining pages
const updatedDocument: PDFDocument = {
...displayDocument,
pages: remainingPages,
totalPages: remainingPages.length,
};
// Update the document state
setEditedDocument(updatedDocument);
// Clear selection since the selected pages are now deleted
setSelectedPageNumbers([]);
// Adjust split positions - remove any splits that are now out of bounds
setSplitPositions(prev => {
const newPositions = new Set<number>();
prev.forEach(pos => {
if (pos < remainingPages.length - 1) {
newPositions.add(pos);
}
});
return newPositions;
});
console.log(`Deleted ${displayDocument.pages.length - remainingPages.length} pages. ${remainingPages.length} pages remaining.`);
}, [selectedPageNumbers, displayDocument]);
const handleDeletePage = useCallback((pageNumber: number) => {
if (!displayDocument) return;
console.log('Delete individual page:', pageNumber);
// Filter out the specific page
const remainingPages = displayDocument.pages.filter(
page => page.pageNumber !== pageNumber
);
if (remainingPages.length === 0) {
console.log('Cannot delete the last remaining page');
return;
}
// Re-number the remaining pages sequentially
remainingPages.forEach((page, index) => {
page.pageNumber = index + 1;
});
// Create updated document with remaining pages
const updatedDocument: PDFDocument = {
...displayDocument,
pages: remainingPages,
totalPages: remainingPages.length,
};
// Update the document state
setEditedDocument(updatedDocument);
// Remove the deleted page from selection if it was selected
setSelectedPageNumbers(prev => prev.filter(num => num !== pageNumber));
// Adjust split positions - remove any splits that are now out of bounds
setSplitPositions(prev => {
const newPositions = new Set<number>();
prev.forEach(pos => {
if (pos < remainingPages.length - 1) {
newPositions.add(pos);
}
});
return newPositions;
});
console.log(`Deleted page ${pageNumber}. ${remainingPages.length} pages remaining.`);
}, [displayDocument]);
const handleSplit = useCallback(() => { const handleSplit = useCallback(() => {
if (!displayDocument || selectedPageNumbers.length === 0) return; if (!displayDocument || selectedPageNumbers.length === 0) return;
@ -826,15 +895,6 @@ const PageEditor = ({
</Group> </Group>
</Group> </Group>
{/* Bulk selection panel - only show in selection mode */}
{selectionMode && (
<BulkSelectionPanel
csvInput={csvInput}
setCsvInput={setCsvInput}
selectedPages={selectedPageNumbers}
onUpdatePagesFromCSV={updatePagesFromCSV}
/>
)}
{/* Split Lines Overlay */} {/* Split Lines Overlay */}
<div <div
@ -903,6 +963,7 @@ const PageEditor = ({
onExecuteCommand={executeCommand} onExecuteCommand={executeCommand}
onSetStatus={() => {}} onSetStatus={() => {}}
onSetMovingPage={setMovingPage} onSetMovingPage={setMovingPage}
onDeletePage={handleDeletePage}
RotatePagesCommand={RotatePagesCommand} RotatePagesCommand={RotatePagesCommand}
DeletePagesCommand={DeletePagesCommand} DeletePagesCommand={DeletePagesCommand}
ToggleSplitCommand={ToggleSplitCommand} ToggleSplitCommand={ToggleSplitCommand}

View File

@ -159,17 +159,19 @@ const PageEditorControls = ({
<RotateRightIcon /> <RotateRightIcon />
</ActionIcon> </ActionIcon>
</Tooltip> </Tooltip>
<Tooltip label={selectionMode ? "Delete Selected" : "Delete All"}> {selectionMode && (
<ActionIcon <Tooltip label="Delete Selected">
onClick={onDelete} <ActionIcon
disabled={selectionMode && selectedPages.length === 0} onClick={onDelete}
color="red" disabled={selectedPages.length === 0}
variant={selectionMode && selectedPages.length > 0 ? "light" : "default"} color="red"
size="lg" variant={selectedPages.length > 0 ? "light" : "default"}
> size="lg"
<DeleteIcon /> >
</ActionIcon> <DeleteIcon />
</Tooltip> </ActionIcon>
</Tooltip>
)}
<Tooltip label={getSplitAllTooltip()}> <Tooltip label={getSplitAllTooltip()}>
<ActionIcon <ActionIcon
onClick={selectionMode ? onSplit : onSplitAll} onClick={selectionMode ? onSplit : onSplitAll}
@ -185,13 +187,13 @@ const PageEditorControls = ({
<div style={{ width: 1, height: 28, backgroundColor: 'var(--mantine-color-gray-3)', margin: '0 8px' }} /> <div style={{ width: 1, height: 28, backgroundColor: 'var(--mantine-color-gray-3)', margin: '0 8px' }} />
{/* Export Controls */} {/* Export Controls */}
{selectionMode && selectedPages.length > 0 && ( {selectionMode && (
<Tooltip label="Export Selected"> <Tooltip label="Export Selected">
<ActionIcon <ActionIcon
onClick={onExportSelected} onClick={onExportSelected}
disabled={exportLoading} disabled={exportLoading || selectedPages.length === 0}
color="blue" color="blue"
variant="light" variant={selectedPages.length > 0 ? "light" : "default"}
size="lg" size="lg"
> >
<DownloadIcon /> <DownloadIcon />

View File

@ -34,6 +34,7 @@ interface PageThumbnailProps {
onExecuteCommand: (command: DOMCommand) => void; onExecuteCommand: (command: DOMCommand) => void;
onSetStatus: (status: string) => void; onSetStatus: (status: string) => void;
onSetMovingPage: (page: number | null) => void; onSetMovingPage: (page: number | null) => void;
onDeletePage: (pageNumber: number) => void;
RotatePagesCommand: any; RotatePagesCommand: any;
DeletePagesCommand: any; DeletePagesCommand: any;
ToggleSplitCommand: any; ToggleSplitCommand: any;
@ -58,6 +59,7 @@ const PageThumbnail: React.FC<PageThumbnailProps> = ({
onExecuteCommand, onExecuteCommand,
onSetStatus, onSetStatus,
onSetMovingPage, onSetMovingPage,
onDeletePage,
RotatePagesCommand, RotatePagesCommand,
DeletePagesCommand, DeletePagesCommand,
ToggleSplitCommand, ToggleSplitCommand,
@ -190,9 +192,9 @@ const PageThumbnail: React.FC<PageThumbnailProps> = ({
const handleDelete = useCallback((e: React.MouseEvent) => { const handleDelete = useCallback((e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
console.log('Delete page:', page.pageNumber); onDeletePage(page.pageNumber);
onSetStatus(`Deleted page ${page.pageNumber}`); onSetStatus(`Deleted page ${page.pageNumber}`);
}, [page.pageNumber, onSetStatus]); }, [page.pageNumber, onDeletePage, onSetStatus]);
const handleSplit = useCallback((e: React.MouseEvent) => { const handleSplit = useCallback((e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();