Browse Source

fix: select whole group on righclick & few lock-related fixes (#5022)

David Luzar 3 years ago
parent
commit
58fe639b8d

+ 18 - 6
src/components/App.tsx

@@ -3976,13 +3976,16 @@ class App extends React.Component<AppProps, AppState> {
             pointerDownState.hit.element?.id ||
           pointerDownState.hit.hasHitElementInside)
       ) {
-        // Marking that click was used for dragging to check
-        // if elements should be deselected on pointerup
-        pointerDownState.drag.hasOccurred = true;
         const selectedElements = getSelectedElements(
           this.scene.getElements(),
           this.state,
         );
+        if (selectedElements.every((element) => element.locked)) {
+          return;
+        }
+        // Marking that click was used for dragging to check
+        // if elements should be deselected on pointerup
+        pointerDownState.drag.hasOccurred = true;
         // prevent dragging even if we're no longer holding cmd/ctrl otherwise
         // it would have weird results (stuff jumping all over the screen)
         if (selectedElements.length > 0 && !pointerDownState.withCmdOrCtrl) {
@@ -5337,9 +5340,18 @@ class App extends React.Component<AppProps, AppState> {
     const top = event.clientY - offsetTop;
 
     if (element && !this.state.selectedElementIds[element.id]) {
-      this.setState({ selectedElementIds: { [element.id]: true } }, () => {
-        this._openContextMenu({ top, left }, type);
-      });
+      this.setState(
+        selectGroupsForSelectedElements(
+          {
+            ...this.state,
+            selectedElementIds: { [element.id]: true },
+          },
+          this.scene.getElements(),
+        ),
+        () => {
+          this._openContextMenu({ top, left }, type);
+        },
+      );
     } else {
       this._openContextMenu({ top, left }, type);
     }

+ 3 - 1
src/renderer/renderScene.ts

@@ -413,7 +413,9 @@ export const renderScene = (
         "mouse",
         OMIT_SIDES_FOR_MULTIPLE_ELEMENTS,
       );
-      renderTransformHandles(context, renderConfig, transformHandles, 0);
+      if (locallySelectedElements.some((element) => !element.locked)) {
+        renderTransformHandles(context, renderConfig, transformHandles, 0);
+      }
     }
     context.restore();
   }

+ 172 - 0
src/tests/__snapshots__/contextmenu.test.tsx.snap

@@ -1,5 +1,177 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] appState 1`] = `
+Object {
+  "activeTool": Object {
+    "lastActiveToolBeforeEraser": null,
+    "locked": false,
+    "type": "selection",
+  },
+  "collaborators": Map {},
+  "currentChartType": "bar",
+  "currentItemBackgroundColor": "transparent",
+  "currentItemEndArrowhead": "arrow",
+  "currentItemFillStyle": "hachure",
+  "currentItemFontFamily": 1,
+  "currentItemFontSize": 20,
+  "currentItemLinearStrokeSharpness": "round",
+  "currentItemOpacity": 100,
+  "currentItemRoughness": 1,
+  "currentItemStartArrowhead": null,
+  "currentItemStrokeColor": "#000000",
+  "currentItemStrokeSharpness": "sharp",
+  "currentItemStrokeStyle": "solid",
+  "currentItemStrokeWidth": 1,
+  "currentItemTextAlign": "left",
+  "cursorButton": "up",
+  "draggingElement": null,
+  "editingElement": null,
+  "editingGroupId": null,
+  "editingLinearElement": null,
+  "errorMessage": null,
+  "exportBackground": true,
+  "exportEmbedScene": false,
+  "exportScale": 1,
+  "exportWithDarkMode": false,
+  "fileHandle": null,
+  "gridSize": null,
+  "height": 100,
+  "isBindingEnabled": true,
+  "isLibraryOpen": false,
+  "isLoading": false,
+  "isResizing": false,
+  "isRotating": false,
+  "lastPointerDownWith": "mouse",
+  "multiElement": null,
+  "name": "Untitled-201933152653",
+  "offsetLeft": 20,
+  "offsetTop": 10,
+  "openMenu": null,
+  "openPopup": null,
+  "pasteDialog": Object {
+    "data": null,
+    "shown": false,
+  },
+  "penDetected": false,
+  "penMode": false,
+  "pendingImageElement": null,
+  "previousSelectedElementIds": Object {},
+  "resizingElement": null,
+  "scrollX": 0,
+  "scrollY": 0,
+  "scrolledOutside": false,
+  "selectedElementIds": Object {
+    "id0": true,
+    "id1": true,
+  },
+  "selectedGroupIds": Object {
+    "g1": true,
+  },
+  "selectionElement": null,
+  "shouldCacheIgnoreZoom": false,
+  "showHelpDialog": false,
+  "showHyperlinkPopup": false,
+  "showStats": false,
+  "startBoundElement": null,
+  "suggestedBindings": Array [],
+  "theme": "light",
+  "toastMessage": null,
+  "viewBackgroundColor": "#ffffff",
+  "viewModeEnabled": false,
+  "width": 200,
+  "zenModeEnabled": false,
+  "zoom": Object {
+    "value": 1,
+  },
+}
+`;
+
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] element 0 1`] = `
+Object {
+  "angle": 0,
+  "backgroundColor": "red",
+  "boundElements": null,
+  "fillStyle": "solid",
+  "groupIds": Array [
+    "g1",
+  ],
+  "height": 100,
+  "id": "id0",
+  "isDeleted": false,
+  "link": null,
+  "locked": false,
+  "opacity": 100,
+  "roughness": 1,
+  "seed": 337897,
+  "strokeColor": "#000000",
+  "strokeSharpness": "sharp",
+  "strokeStyle": "solid",
+  "strokeWidth": 1,
+  "type": "rectangle",
+  "updated": 1,
+  "version": 1,
+  "versionNonce": 0,
+  "width": 100,
+  "x": 0,
+  "y": 0,
+}
+`;
+
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] element 1 1`] = `
+Object {
+  "angle": 0,
+  "backgroundColor": "red",
+  "boundElements": null,
+  "fillStyle": "solid",
+  "groupIds": Array [
+    "g1",
+  ],
+  "height": 100,
+  "id": "id1",
+  "isDeleted": false,
+  "link": null,
+  "locked": false,
+  "opacity": 100,
+  "roughness": 1,
+  "seed": 1278240551,
+  "strokeColor": "#000000",
+  "strokeSharpness": "sharp",
+  "strokeStyle": "solid",
+  "strokeWidth": 1,
+  "type": "rectangle",
+  "updated": 1,
+  "version": 1,
+  "versionNonce": 0,
+  "width": 100,
+  "x": 0,
+  "y": 0,
+}
+`;
+
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] history 1`] = `
+Object {
+  "recording": false,
+  "redoStack": Array [],
+  "stateHistory": Array [
+    Object {
+      "appState": Object {
+        "editingGroupId": null,
+        "editingLinearElement": null,
+        "name": "Untitled-201933152653",
+        "selectedElementIds": Object {},
+        "selectedGroupIds": Object {},
+        "viewBackgroundColor": "#ffffff",
+      },
+      "elements": Array [],
+    },
+  ],
+}
+`;
+
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] number of elements 1`] = `2`;
+
+exports[`contextMenu element right-clicking on a group should select whole group: [end of test] number of renders 1`] = `5`;
+
 exports[`contextMenu element selecting 'Add to library' in context menu adds element to library: [end of test] appState 1`] = `
 Object {
   "activeTool": Object {

+ 25 - 0
src/tests/contextmenu.test.tsx

@@ -557,4 +557,29 @@ describe("contextMenu element", () => {
     expect(h.elements[0].groupIds).toHaveLength(0);
     expect(h.elements[1].groupIds).toHaveLength(0);
   });
+
+  it("right-clicking on a group should select whole group", () => {
+    const rectangle1 = API.createElement({
+      type: "rectangle",
+      width: 100,
+      backgroundColor: "red",
+      fillStyle: "solid",
+      groupIds: ["g1"],
+    });
+    const rectangle2 = API.createElement({
+      type: "rectangle",
+      width: 100,
+      backgroundColor: "red",
+      fillStyle: "solid",
+      groupIds: ["g1"],
+    });
+    h.elements = [rectangle1, rectangle2];
+
+    mouse.rightClickAt(50, 50);
+    expect(API.getSelectedElements().length).toBe(2);
+    expect(API.getSelectedElements()).toEqual([
+      expect.objectContaining({ id: rectangle1.id }),
+      expect.objectContaining({ id: rectangle2.id }),
+    ]);
+  });
 });