mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-01-14 20:11:17 +01:00
Enhance DragDropGrid and PageEditor with improved undo manager functionality and scroll handling during drag operations
This commit is contained in:
parent
be037b727f
commit
ddefe81082
@ -23,12 +23,8 @@ interface DragDropItem {
|
|||||||
|
|
||||||
interface DragDropGridProps<T extends DragDropItem> {
|
interface DragDropGridProps<T extends DragDropItem> {
|
||||||
items: T[];
|
items: T[];
|
||||||
selectedItems: string[];
|
|
||||||
selectionMode: boolean;
|
|
||||||
isAnimating: boolean;
|
|
||||||
onReorderPages: (sourcePageNumber: number, targetIndex: number, selectedPageIds?: string[]) => void;
|
onReorderPages: (sourcePageNumber: number, targetIndex: number, selectedPageIds?: string[]) => void;
|
||||||
renderItem: (item: T, index: number, refs: React.MutableRefObject<Map<string, HTMLDivElement>>, boxSelectedIds: string[], clearBoxSelection: () => void, getBoxSelection: () => string[], activeId: string | null, isOver: boolean, dragHandleProps?: any, zoomLevel?: number) => React.ReactNode;
|
renderItem: (item: T, index: number, refs: React.MutableRefObject<Map<string, HTMLDivElement>>, boxSelectedIds: string[], clearBoxSelection: () => void, getBoxSelection: () => string[], activeId: string | null, isOver: boolean, dragHandleProps?: any, zoomLevel?: number) => React.ReactNode;
|
||||||
renderSplitMarker?: (item: T, index: number) => React.ReactNode;
|
|
||||||
getThumbnailData?: (itemId: string) => { src: string; rotation: number } | null;
|
getThumbnailData?: (itemId: string) => { src: string; rotation: number } | null;
|
||||||
zoomLevel?: number;
|
zoomLevel?: number;
|
||||||
}
|
}
|
||||||
@ -109,6 +105,10 @@ const DragDropGrid = <T extends DragDropItem>({
|
|||||||
const itemRefs = useRef<Map<string, HTMLDivElement>>(new Map());
|
const itemRefs = useRef<Map<string, HTMLDivElement>>(new Map());
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const getScrollElement = useCallback(() => {
|
||||||
|
return containerRef.current?.closest('[data-scrolling-container]') as HTMLElement | null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Filter out placeholder items (invisible pages for deselected files)
|
// Filter out placeholder items (invisible pages for deselected files)
|
||||||
const visibleItems = items.filter(item => !item.isPlaceholder);
|
const visibleItems = items.filter(item => !item.isPlaceholder);
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ const DragDropGrid = <T extends DragDropItem>({
|
|||||||
// Virtualization with react-virtual library
|
// Virtualization with react-virtual library
|
||||||
const rowVirtualizer = useVirtualizer({
|
const rowVirtualizer = useVirtualizer({
|
||||||
count: Math.ceil(visibleItems.length / itemsPerRow),
|
count: Math.ceil(visibleItems.length / itemsPerRow),
|
||||||
getScrollElement: () => containerRef.current?.closest('[data-scrolling-container]') as Element,
|
getScrollElement,
|
||||||
estimateSize: () => {
|
estimateSize: () => {
|
||||||
const remToPx = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
const remToPx = parseFloat(getComputedStyle(document.documentElement).fontSize);
|
||||||
return parseFloat(GRID_CONSTANTS.ITEM_HEIGHT) * remToPx * zoomLevel;
|
return parseFloat(GRID_CONSTANTS.ITEM_HEIGHT) * remToPx * zoomLevel;
|
||||||
@ -495,6 +495,24 @@ const DragDropGrid = <T extends DragDropItem>({
|
|||||||
};
|
};
|
||||||
}, [hoveredItemId, dropSide, activeId, itemGap, zoomLevel]);
|
}, [hoveredItemId, dropSide, activeId, itemGap, zoomLevel]);
|
||||||
|
|
||||||
|
const handleWheelWhileDragging = useCallback((event: React.WheelEvent<HTMLDivElement>) => {
|
||||||
|
if (!activeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollElement = getScrollElement();
|
||||||
|
if (!scrollElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollElement.scrollBy({
|
||||||
|
top: event.deltaY,
|
||||||
|
left: event.deltaX,
|
||||||
|
});
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}, [activeId, getScrollElement]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DndContext
|
<DndContext
|
||||||
sensors={sensors}
|
sensors={sensors}
|
||||||
@ -508,6 +526,7 @@ const DragDropGrid = <T extends DragDropItem>({
|
|||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
onMouseUp={handleMouseUp}
|
onMouseUp={handleMouseUp}
|
||||||
|
onWheel={handleWheelWhileDragging}
|
||||||
style={{
|
style={{
|
||||||
// Basic container styles
|
// Basic container styles
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|||||||
@ -265,9 +265,14 @@ const PageEditor = ({
|
|||||||
|
|
||||||
// Update undo/redo state
|
// Update undo/redo state
|
||||||
const updateUndoRedoState = useCallback(() => {
|
const updateUndoRedoState = useCallback(() => {
|
||||||
setCanUndo(undoManagerRef.current.canUndo());
|
const undoManager = undoManagerRef.current;
|
||||||
setCanRedo(undoManagerRef.current.canRedo());
|
setCanUndo(undoManager.canUndo());
|
||||||
}, []);
|
setCanRedo(undoManager.canRedo());
|
||||||
|
|
||||||
|
if (!undoManager.hasHistory()) {
|
||||||
|
setHasUnsavedChanges(false);
|
||||||
|
}
|
||||||
|
}, [setHasUnsavedChanges]);
|
||||||
|
|
||||||
// Set up undo manager callback
|
// Set up undo manager callback
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -1074,9 +1079,6 @@ const PageEditor = ({
|
|||||||
{/* Pages Grid */}
|
{/* Pages Grid */}
|
||||||
<DragDropGrid
|
<DragDropGrid
|
||||||
items={displayedPages}
|
items={displayedPages}
|
||||||
selectedItems={selectedPageIds}
|
|
||||||
selectionMode={selectionMode}
|
|
||||||
isAnimating={isAnimating}
|
|
||||||
onReorderPages={handleReorderPages}
|
onReorderPages={handleReorderPages}
|
||||||
zoomLevel={zoomLevel}
|
zoomLevel={zoomLevel}
|
||||||
getThumbnailData={(pageId) => {
|
getThumbnailData={(pageId) => {
|
||||||
|
|||||||
@ -905,6 +905,10 @@ export class UndoManager {
|
|||||||
return this.redoStack.length > 0;
|
return this.redoStack.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasHistory(): boolean {
|
||||||
|
return this.undoStack.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
clear(): void {
|
clear(): void {
|
||||||
this.undoStack = [];
|
this.undoStack = [];
|
||||||
this.redoStack = [];
|
this.redoStack = [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user