From a74dbe06d3967e7359be2ffef024c7481d4a8ad7 Mon Sep 17 00:00:00 2001 From: Roman Pominov Date: Fri, 21 Apr 2023 19:03:58 +0400 Subject: [PATCH] Fix bugs with creating component by DnD to canvas (#1510) ## Description https://discord.com/channels/955905230107738152/1098959267396059228 There were two bugs: 1. Same as in https://github.com/webstudio-is/webstudio-builder/pull/1483 setState didn't work correctly after React update 2. Scrub used to call `onStatusChange("idle")` at unmount (now fixed). We use scrub for canvas resize, and restore pointer events when status changes to "idle". But we also unmount scrub on DnD start. So on DnD start we ended up with pointer events turned on. ## Steps for reproduction 1. DnD of components to canvas should work well now --- .../canvas-tools/use-subscribe-drag-drop-state.ts | 8 ++++---- .../components/primitives/numeric-gesture-control.ts | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/builder/app/builder/features/workspace/canvas-tools/use-subscribe-drag-drop-state.ts b/apps/builder/app/builder/features/workspace/canvas-tools/use-subscribe-drag-drop-state.ts index 840ee09adb..d314dafccd 100644 --- a/apps/builder/app/builder/features/workspace/canvas-tools/use-subscribe-drag-drop-state.ts +++ b/apps/builder/app/builder/features/workspace/canvas-tools/use-subscribe-drag-drop-state.ts @@ -2,20 +2,20 @@ import { useSubscribe } from "~/shared/pubsub"; import { useDragAndDropState } from "~/shared/nano-states"; export const useSubscribeDragAndDropState = () => { - const [state, setState] = useDragAndDropState(); + const [, setState] = useDragAndDropState(); useSubscribe("dragStart", (dragPayload) => { // It's possible that dropTargetChange comes before dragStart. // So it's important to spread the current ...state here. - setState({ ...state, isDragging: true, dragPayload }); + setState((state) => ({ ...state, isDragging: true, dragPayload })); }); useSubscribe("dropTargetChange", (dropTarget) => { - setState({ ...state, dropTarget }); + setState((state) => ({ ...state, dropTarget })); }); useSubscribe("placementIndicatorChange", (placementIndicator) => { - setState({ ...state, placementIndicator }); + setState((state) => ({ ...state, placementIndicator })); }); useSubscribe("dragEnd", () => { diff --git a/packages/design-system/src/components/primitives/numeric-gesture-control.ts b/packages/design-system/src/components/primitives/numeric-gesture-control.ts index 5c174f35df..eb147f3508 100644 --- a/packages/design-system/src/components/primitives/numeric-gesture-control.ts +++ b/packages/design-system/src/components/primitives/numeric-gesture-control.ts @@ -46,6 +46,7 @@ type NumericScrubState = { cursor?: SVGElement; direction: string; timerId?: ReturnType; + status: "idle" | "scrubbing"; }; const getValueDefault = ( @@ -86,6 +87,7 @@ export const numericScrubControl = ( cursor: undefined, direction: direction, timerId: undefined, + status: "idle", }; let exitPointerLock: (() => void) | undefined = undefined; @@ -94,7 +96,12 @@ export const numericScrubControl = ( const cleanup = () => { targetNode.removeEventListener("pointermove", handleEvent); - onStatusChange?.("idle"); + + if (state.status === "scrubbing") { + state.status = "idle"; + onStatusChange?.("idle"); + } + clearTimeout(state.timerId); exitPointerLock?.(); @@ -162,7 +169,9 @@ export const numericScrubControl = ( exitPointerLock = requestPointerLock(state, event, targetNode); }, 150); + state.status = "scrubbing"; onStatusChange?.("scrubbing"); + targetNode.addEventListener("pointermove", handleEvent); originalUserSelect = targetNode.ownerDocument.documentElement.style.userSelect;