Переглянути джерело

feat: Save penDetected and penMode, and detect pen already on ToolButton click (#4955)

* save penMode and penDetected to browser cache

* added on pointer down

* added onPointerDown

* factor out and merge handlers

Co-authored-by: dwelle <luzar.david@gmail.com>
zsviczian 3 роки тому
батько
коміт
ed31980f84
3 змінених файлів з 70 додано та 40 видалено
  1. 2 2
      src/appState.ts
  2. 66 38
      src/components/Actions.tsx
  3. 2 0
      src/components/ToolButton.tsx

+ 2 - 2
src/appState.ts

@@ -132,8 +132,8 @@ const APP_STATE_STORAGE_CONF = (<
   editingLinearElement: { browser: false, export: false, server: false },
   elementLocked: { browser: true, export: false, server: false },
   elementType: { browser: true, export: false, server: false },
-  penMode: { browser: false, export: false, server: false },
-  penDetected: { browser: false, export: false, server: false },
+  penMode: { browser: true, export: false, server: false },
+  penDetected: { browser: true, export: false, server: false },
   errorMessage: { browser: false, export: false, server: false },
   exportBackground: { browser: true, export: false, server: false },
   exportEmbedScene: { browser: true, export: false, server: false },

+ 66 - 38
src/components/Actions.tsx

@@ -15,7 +15,12 @@ import {
 } from "../scene";
 import { SHAPES } from "../shapes";
 import { AppState, Zoom } from "../types";
-import { capitalizeString, isTransparent, setCursorForShape } from "../utils";
+import {
+  capitalizeString,
+  isTransparent,
+  setCursorForShape,
+  withBatchedUpdates,
+} from "../utils";
 import Stack from "./Stack";
 import { ToolButton } from "./ToolButton";
 import { hasStrokeColor } from "../scene/comparisons";
@@ -192,43 +197,66 @@ export const ShapesSwitcher = ({
   setAppState: React.Component<any, AppState>["setState"];
   onImageAction: (data: { pointerType: PointerType | null }) => void;
   appState: AppState;
-}) => (
-  <>
-    {SHAPES.map(({ value, icon, key }, index) => {
-      const label = t(`toolBar.${value}`);
-      const letter = key && (typeof key === "string" ? key : key[0]);
-      const shortcut = letter
-        ? `${capitalizeString(letter)} ${t("helpDialog.or")} ${index + 1}`
-        : `${index + 1}`;
-      return (
-        <ToolButton
-          className="Shape"
-          key={value}
-          type="radio"
-          icon={icon}
-          checked={elementType === value}
-          name="editor-current-shape"
-          title={`${capitalizeString(label)} — ${shortcut}`}
-          keyBindingLabel={`${index + 1}`}
-          aria-label={capitalizeString(label)}
-          aria-keyshortcuts={shortcut}
-          data-testid={value}
-          onChange={({ pointerType }) => {
-            setAppState({
-              elementType: value,
-              multiElement: null,
-              selectedElementIds: {},
-            });
-            setCursorForShape(canvas, { ...appState, elementType: value });
-            if (value === "image") {
-              onImageAction({ pointerType });
-            }
-          }}
-        />
-      );
-    })}
-  </>
-);
+}) => {
+  const onChange = withBatchedUpdates(
+    ({
+      elementType,
+      pointerType,
+    }: {
+      elementType: typeof SHAPES[number]["value"];
+      pointerType: PointerType | null;
+    }) => {
+      if (!appState.penDetected && pointerType === "pen") {
+        setAppState({
+          penDetected: true,
+          penMode: true,
+        });
+      }
+      setAppState({
+        elementType,
+        multiElement: null,
+        selectedElementIds: {},
+      });
+      setCursorForShape(canvas, { ...appState, elementType });
+      if (elementType === "image") {
+        onImageAction({ pointerType });
+      }
+    },
+  );
+
+  return (
+    <>
+      {SHAPES.map(({ value, icon, key }, index) => {
+        const label = t(`toolBar.${value}`);
+        const letter = key && (typeof key === "string" ? key : key[0]);
+        const shortcut = letter
+          ? `${capitalizeString(letter)} ${t("helpDialog.or")} ${index + 1}`
+          : `${index + 1}`;
+        return (
+          <ToolButton
+            className="Shape"
+            key={value}
+            type="radio"
+            icon={icon}
+            checked={elementType === value}
+            name="editor-current-shape"
+            title={`${capitalizeString(label)} — ${shortcut}`}
+            keyBindingLabel={`${index + 1}`}
+            aria-label={capitalizeString(label)}
+            aria-keyshortcuts={shortcut}
+            data-testid={value}
+            onPointerDown={({ pointerType }) => {
+              onChange({ elementType: value, pointerType });
+            }}
+            onChange={({ pointerType }) => {
+              onChange({ elementType: value, pointerType });
+            }}
+          />
+        );
+      })}
+    </>
+  );
+};
 
 export const ZoomActions = ({
   renderAction,

+ 2 - 0
src/components/ToolButton.tsx

@@ -48,6 +48,7 @@ type ToolButtonProps =
       type: "radio";
       checked: boolean;
       onChange?(data: { pointerType: PointerType | null }): void;
+      onPointerDown?(data: { pointerType: PointerType }): void;
     });
 
 export const ToolButton = React.forwardRef((props: ToolButtonProps, ref) => {
@@ -149,6 +150,7 @@ export const ToolButton = React.forwardRef((props: ToolButtonProps, ref) => {
       title={props.title}
       onPointerDown={(event) => {
         lastPointerTypeRef.current = event.pointerType || null;
+        props.onPointerDown?.({ pointerType: event.pointerType || null });
       }}
       onPointerUp={() => {
         requestAnimationFrame(() => {