mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
Delete and selection
This commit is contained in:
parent
86221c2082
commit
fd1b8e7e2a
@ -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}
|
||||||
|
@ -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 />
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user