From a68f995699db5563ea10cd9e37426c2112ba810a Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Sun, 9 Feb 2025 12:29:13 +0000 Subject: [PATCH] feat: place back blocks when canceling selection and create history entry --- src/components/canvas/Canvas.tsx | 24 ++++++++++---- src/components/canvas/SelectionBar.tsx | 46 +++++++++++++++++++++++--- src/components/sidebar/History.tsx | 2 ++ src/context/Selection.tsx | 15 +-------- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/components/canvas/Canvas.tsx b/src/components/canvas/Canvas.tsx index f9ec202..c7bca4d 100644 --- a/src/components/canvas/Canvas.tsx +++ b/src/components/canvas/Canvas.tsx @@ -41,7 +41,7 @@ PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST; function Canvas() { const { stageSize, canvasSize, blocks, coords, scale, version, setStageSize, setBlocks, setCoords, setScale } = useContext(CanvasContext); const { addHistory, undo, redo } = useContext(HistoryContext); - const { selectionCoords, selectionLayerBlocks, setSelectionCoords, setSelectionLayerBlocks, confirmSelection } = useContext(SelectionContext); + const { selectionCoords, selectionLayerBlocks, setSelectionCoords, setSelectionLayerBlocks } = useContext(SelectionContext); const { settings } = useContext(SettingsContext); const { missingTexture } = useContext(TexturesContext); const { isDark } = useContext(ThemeContext); @@ -245,11 +245,23 @@ function Canvas() { async (e: React.KeyboardEvent) => { switch (e.key) { case "Escape": + setBlocks(startBlocksRef.current); setSelectionLayerBlocks([]); break; - case "Enter": - confirmSelection(); + case "Enter": { + const combinedBlocks = [...blocks, ...selectionLayerBlocks]; + const uniqueBlocks = Array.from(new Map(combinedBlocks.map((block) => [`${block.x},${block.y}`, block])).values()); + + setBlocks(uniqueBlocks); + setSelectionLayerBlocks([]); + + addHistory( + "Move Selection", + () => setBlocks(uniqueBlocks), + () => setBlocks(startBlocksRef.current) + ); break; + } case " ": // Space setDragging(true); oldToolRef.current = tool; @@ -364,11 +376,11 @@ function Canvas() { }, [ tool, - blocks, selectionCoords, - selectionLayerBlocks, canvasSize, blockData, + blocks, + selectionLayerBlocks, clipboard, setBlocks, setSelectionCoords, @@ -487,7 +499,7 @@ function Canvas() { - + ); } diff --git a/src/components/canvas/SelectionBar.tsx b/src/components/canvas/SelectionBar.tsx index 6fcfa78..665fba8 100644 --- a/src/components/canvas/SelectionBar.tsx +++ b/src/components/canvas/SelectionBar.tsx @@ -1,15 +1,52 @@ import { useContext, useEffect, useState } from "react"; import { CheckIcon, XIcon } from "lucide-react"; +import { HistoryContext } from "@/context/History"; import { SelectionContext } from "@/context/Selection"; import { Button } from "@/components/ui/button"; +import { CanvasContext } from "@/context/Canvas"; -function SelectionBar() { - const { selectionLayerBlocks, setSelectionLayerBlocks, confirmSelection } = useContext(SelectionContext); +interface Props { + startBlocks: Block[]; + startSelectionCoords: CoordinateArray; +} + +function SelectionBar({ startBlocks, startSelectionCoords }: Props) { + const { blocks, setBlocks } = useContext(CanvasContext); + const { addHistory } = useContext(HistoryContext); + const { selectionCoords, selectionLayerBlocks, setSelectionCoords, setSelectionLayerBlocks } = useContext(SelectionContext); const [isVisible, setIsVisible] = useState(false); + const confirm = () => { + const oldSelectionCoords = [...selectionCoords]; + + const combinedBlocks = [...blocks, ...selectionLayerBlocks]; + const uniqueBlocks = Array.from(new Map(combinedBlocks.map((block) => [`${block.x},${block.y}`, block])).values()); + + setBlocks(uniqueBlocks); + setSelectionLayerBlocks([]); + + addHistory( + "Move Selection", + () => { + setBlocks(uniqueBlocks); + setSelectionCoords(oldSelectionCoords); + }, + () => { + setBlocks(startBlocks); + setSelectionCoords(startSelectionCoords); + } + ); + }; + + const cancel = () => { + setBlocks(startBlocks); + setSelectionLayerBlocks([]); + setSelectionCoords(startSelectionCoords); + }; + useEffect(() => { setIsVisible(selectionLayerBlocks.length !== 0); }, [selectionLayerBlocks]); @@ -20,12 +57,11 @@ function SelectionBar() { ${isVisible ? "opacity-100 translate-y-0" : "opacity-0 translate-y-6 pointer-events-none"} `} > - {/* todo: place back blocks removed */} - Confirm selection? - diff --git a/src/components/sidebar/History.tsx b/src/components/sidebar/History.tsx index 0b92a13..fdf9068 100644 --- a/src/components/sidebar/History.tsx +++ b/src/components/sidebar/History.tsx @@ -5,6 +5,7 @@ import { FileIcon, ImageIcon, LassoIcon, + MoveIcon, PaintBucketIcon, PencilIcon, PresentationIcon, @@ -24,6 +25,7 @@ const iconMap = { Eraser: EraserIcon, Lasso: LassoIcon, "Magic Wand": WandIcon, + "Move Selection": MoveIcon, "New Canvas": PresentationIcon, "Open Image": ImageIcon, "Open Schematic": FileIcon, diff --git a/src/context/Selection.tsx b/src/context/Selection.tsx index ab6a955..8f088f3 100644 --- a/src/context/Selection.tsx +++ b/src/context/Selection.tsx @@ -1,5 +1,4 @@ -import { createContext, ReactNode, useContext, useState } from "react"; -import { CanvasContext } from "./Canvas"; +import { createContext, ReactNode, useState } from "react"; interface Context { selectionCoords: CoordinateArray; @@ -7,7 +6,6 @@ interface Context { setSelectionCoords: React.Dispatch>; setSelectionLayerBlocks: React.Dispatch>; isInSelection: (x: number, y: number) => boolean; - confirmSelection: () => void; } interface Props { @@ -17,8 +15,6 @@ interface Props { export const SelectionContext = createContext({} as Context); export const SelectionProvider = ({ children }: Props) => { - const { blocks, setBlocks } = useContext(CanvasContext); - const [selectionCoords, setSelectionCoords] = useState([]); const [selectionLayerBlocks, setSelectionLayerBlocks] = useState([]); @@ -29,14 +25,6 @@ export const SelectionProvider = ({ children }: Props) => { return true; }; - const confirmSelection = () => { - const combinedBlocks = [...blocks, ...selectionLayerBlocks]; - const uniqueBlocks = Array.from(new Map(combinedBlocks.map((block) => [`${block.x},${block.y}`, block])).values()); - - setBlocks(uniqueBlocks); - setSelectionLayerBlocks([]); - }; - return ( { setSelectionCoords, setSelectionLayerBlocks, isInSelection, - confirmSelection, }} > {children}