Browse Source

Fix actions and revert to previous logic updated

Jeremie Pardou-Piquemal 2 years ago
parent
commit
b8f474a8fc

+ 3 - 3
package-lock.json

@@ -9299,9 +9299,9 @@
       }
     },
     "react-sync-board": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.1.0.tgz",
-      "integrity": "sha512-5ar4fB/2CgVfIDU4xY1jATXEV8Kqfgj5nMW4ofi+uYu6W8CCDZFIRhYZbIz8r5sR70bFh0wX4rasrzH3PBLrnw==",
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.1.1.tgz",
+      "integrity": "sha512-+fiP3DxF3L+55mKo5N7Asi+xpn2YgOjKjzraqRawsbNVi0k8jwR/FYSYxeHp9BuWFLeXE/lEeLURJuApl8VuDg==",
       "requires": {
         "@emotion/react": "^11.4.0",
         "@emotion/styled": "^11.3.0",

+ 1 - 1
package.json

@@ -33,7 +33,7 @@
     "react-query": "^3.13.4",
     "react-router": "^5.2.0",
     "react-router-dom": "^5.2.0",
-    "react-sync-board": "^0.1.0",
+    "react-sync-board": "^0.1.1",
     "react-toastify": "^6.1.0",
     "react-useportal": "^1.0.14",
     "recoil": "^0.3.1",

+ 3 - 3
src/components/ItemLibrary.jsx

@@ -5,7 +5,7 @@ import styled from "styled-components";
 import { useRecoilCallback } from "recoil";
 import debounce from "lodash.debounce";
 
-import { useItemBaseActions } from "react-sync-board";
+import { useItemActions } from "react-sync-board";
 
 import { search } from "../views/utils";
 
@@ -63,7 +63,7 @@ const StyledItem = styled.li`
 const size = 60;
 
 const NewItem = memo(({ type, template, component: Component, name }) => {
-  const { pushItem } = useItemBaseActions();
+  const { pushItem } = useItemActions();
 
   const addItem = React.useCallback(async () => {
     pushItem({
@@ -88,7 +88,7 @@ NewItem.displayName = "NewItem";
 const SubItemList = ({ name, items }) => {
   const { t } = useTranslation();
   const [open, setOpen] = React.useState(false);
-  const { pushItems } = useItemBaseActions();
+  const { pushItems } = useItemActions();
 
   const addItems = useRecoilCallback(
     async (itemsToAdd) => {

+ 2 - 2
src/components/mediaLibrary/ImageDropNPaste.jsx

@@ -2,7 +2,7 @@ import React from "react";
 import { nanoid } from "nanoid";
 import { useDropzone } from "react-dropzone";
 import { useTranslation } from "react-i18next";
-import { useItemBaseActions } from "react-sync-board";
+import { useItemActions } from "react-sync-board";
 
 import { useMediaLibrary } from "./MediaLibraryProvider";
 import Waiter from "../ui/Waiter";
@@ -10,7 +10,7 @@ import Waiter from "../ui/Waiter";
 const ImageDropNPaste = ({ children }) => {
   const { t } = useTranslation();
   const [uploading, setUploading] = React.useState(false);
-  const { pushItem } = useItemBaseActions();
+  const { pushItem } = useItemActions();
 
   const { addMedia, libraries } = useMediaLibrary();
 

+ 2 - 2
src/gameComponents/Zone.jsx

@@ -4,7 +4,7 @@ import styled, { css } from "styled-components";
 import { useItemInteraction } from "react-sync-board";
 
 import { isItemInsideElement } from "../views/utils";
-import { useItemActions } from "react-sync-board";
+import useGameItemActions from "./useGameItemActions";
 
 const ZoneWrapper = styled.div`
   ${({ width = 200, height = 200 }) => css`
@@ -34,7 +34,7 @@ const ZoneWrapper = styled.div`
 const Zone = ({ width, height, label, onItem }) => {
   const { register } = useItemInteraction("place");
   const zoneRef = React.useRef(null);
-  const actionMap = useItemActions();
+  const { actionMap } = useGameItemActions();
 
   const onInsideItem = React.useCallback(
     (itemIds) => {

+ 2 - 2
src/gameComponents/useGameItemActionMap.jsx

@@ -4,7 +4,7 @@ import { nanoid } from "nanoid";
 import { toast } from "react-toastify";
 import { useSetRecoilState, useRecoilCallback } from "recoil";
 
-import { useItemBaseActions } from "../components/board/Items";
+import { useItemActions } from "../components/board/Items";
 import { SelectedItemsAtom } from "../components/board";
 import { useUsers } from "../components/users";
 import { ItemMapAtom } from "../components/board";
@@ -33,7 +33,7 @@ export const useGameItemActionMap = () => {
     insertItemBefore,
     reverseItemsOrder,
     swapItems,
-  } = useItemBaseActions();
+  } = useItemActions();
 
   const { t } = useTranslation();
 

+ 619 - 0
src/gameComponents/useGameItemActions.js

@@ -0,0 +1,619 @@
+import React from "react";
+
+import { useTranslation } from "react-i18next";
+import { nanoid } from "nanoid";
+import { toast } from "react-toastify";
+import { useItemActions, useUsers, useSelectedItems } from "react-sync-board";
+
+import { shuffle as shuffleArray, randInt } from "../views/utils";
+
+import deleteIcon from "../images/delete.svg";
+import stackToCenterIcon from "../images/stackToCenter.svg";
+import stackToTopLeftIcon from "../images/stackToTopLeft.svg";
+import alignAsLineIcon from "../images/alignAsLine.svg";
+import alignAsSquareIcon from "../images/alignAsSquare.svg";
+import duplicateIcon from "../images/duplicate.svg";
+import seeIcon from "../images/see.svg";
+import flipIcon from "../images/flip.svg";
+import lockIcon from "../images/lock.svg";
+import rotateIcon from "../images/rotate.svg";
+import shuffleIcon from "../images/shuffle.svg";
+import tapIcon from "../images/tap.svg";
+
+import useLocalStorage from "../hooks/useLocalStorage";
+
+export const useGameItemActions = () => {
+  const {
+    batchUpdateItems,
+    removeItems,
+    insertItemBefore,
+    reverseItemsOrder,
+    swapItems,
+    getItems,
+  } = useItemActions();
+
+  const { t } = useTranslation();
+
+  const [isFirstLock, setIsFirstLock] = useLocalStorage("isFirstLock", true);
+
+  const { currentUser } = useUsers();
+
+  const selectedItems = useSelectedItems();
+
+  const getItemListOrSelected = React.useCallback(
+    async (itemIds) => {
+      if (itemIds) {
+        return [itemIds, await getItems(itemIds)];
+      } else {
+        return [selectedItems, await getItems(selectedItems)];
+      }
+    },
+    [getItems, selectedItems]
+  );
+
+  const isMountedRef = React.useRef(false);
+
+  React.useEffect(() => {
+    // Mounted guard
+    isMountedRef.current = true;
+    return () => {
+      isMountedRef.current = false;
+    };
+  }, []);
+
+  // Stack selection to Center
+  const stackToCenter = React.useCallback(
+    async (
+      itemIds,
+      {
+        stackThicknessMin = 0.5,
+        stackThicknessMax = 1,
+        limitCardsNumber = 32,
+      } = {}
+    ) => {
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      // Rule to manage thickness of the stack.
+      let stackThickness = stackThicknessMax;
+      if (items.length >= limitCardsNumber) {
+        stackThickness = stackThicknessMin;
+      }
+
+      // To avoid displacement effects.
+      let isSameGap = true;
+      for (let i = 1; i < items.length; i++) {
+        if (Math.abs(items[i].x - items[i - 1].x) != stackThickness) {
+          isSameGap = false;
+          break;
+        }
+        if (Math.abs(items[i].y - items[i - 1].y) != stackThickness) {
+          isSameGap = false;
+          break;
+        }
+      }
+      if (isSameGap == true) {
+        return;
+      }
+
+      // Compute middle position
+      const minMax = { min: {}, max: {} };
+      minMax.min.x = Math.min(...items.map(({ x }) => x));
+      minMax.min.y = Math.min(...items.map(({ y }) => y));
+      minMax.max.x = Math.max(
+        ...items.map(({ x, id }) => x + document.getElementById(id).clientWidth)
+      );
+      minMax.max.y = Math.max(
+        ...items.map(
+          ({ y, id }) => y + document.getElementById(id).clientHeight
+        )
+      );
+      const { clientWidth, clientHeight } = document.getElementById(
+        items[0].id
+      );
+      let newX =
+        minMax.min.x + (minMax.max.x - minMax.min.x) / 2 - clientWidth / 2;
+      let newY =
+        minMax.min.y + (minMax.max.y - minMax.min.y) / 2 - clientHeight / 2;
+
+      batchUpdateItems(ids, (item) => {
+        const newItem = {
+          ...item,
+          x: newX,
+          y: newY,
+        };
+        newX += stackThickness;
+        newY -= stackThickness;
+        return newItem;
+      });
+    },
+    [batchUpdateItems, getItemListOrSelected]
+  );
+
+  // Stack selection to Top Left
+  const stackToTopLeft = React.useCallback(
+    async (
+      itemIds,
+      {
+        stackThicknessMin = 0.5,
+        stackThicknessMax = 1,
+        limitCardsNumber = 32,
+      } = {}
+    ) => {
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      let { x: newX, y: newY } = items[0];
+
+      // Rule to manage thickness of the stack.
+      let stackThickness = stackThicknessMax;
+      if (items.length >= limitCardsNumber) {
+        stackThickness = stackThicknessMin;
+      }
+
+      batchUpdateItems(ids, (item) => {
+        const newItem = {
+          ...item,
+          x: newX,
+          y: newY,
+        };
+        newX += stackThickness;
+        newY -= stackThickness;
+        return newItem;
+      });
+    },
+    [batchUpdateItems, getItemListOrSelected]
+  );
+
+  // Align selection to a line
+  const alignAsLine = React.useCallback(
+    async (itemIds, { gapBetweenItems = 5 } = {}) => {
+      // Negative value is possible for 'gapBetweenItems'.
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      let { x: newX, y: newY } = items[0];
+
+      batchUpdateItems(ids, (item) => {
+        const { clientWidth } = document.getElementById(item.id);
+        const newItem = {
+          ...item,
+          x: newX,
+          y: newY,
+        };
+        newX += clientWidth + gapBetweenItems;
+        return newItem;
+      });
+    },
+    [getItemListOrSelected, batchUpdateItems]
+  );
+
+  // Align selection to an array
+  const alignAsSquare = React.useCallback(
+    async (itemIds, { gapBetweenItems = 5 } = {}) => {
+      // Negative value is possible for 'gapBetweenItems'.
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      // Count number of elements
+      const numberOfElements = items.length;
+      const numberOfColumns = Math.ceil(Math.sqrt(numberOfElements));
+
+      let { x: newX, y: newY } = items[0];
+
+      let currentColumn = 1;
+
+      batchUpdateItems(ids, (item) => {
+        const { clientWidth, clientHeight } = document.getElementById(item.id);
+        const newItem = {
+          ...item,
+          x: newX,
+          y: newY,
+        };
+        newX += clientWidth + gapBetweenItems;
+        currentColumn += 1;
+        if (currentColumn > numberOfColumns) {
+          currentColumn = 1;
+          newX = items[0].x;
+          newY += clientHeight + gapBetweenItems;
+        }
+        return newItem;
+      });
+    },
+    [getItemListOrSelected, batchUpdateItems]
+  );
+
+  const shuffleItems = React.useCallback(
+    async (itemIds) => {
+      const [ids] = await getItemListOrSelected(itemIds);
+
+      ids.forEach((itemId) => {
+        const elem = document.getElementById(itemId);
+        elem.firstChild.className = "hvr-wobble-horizontal";
+      });
+      const shuffledItems = shuffleArray([...ids]);
+      swapItems(ids, shuffledItems);
+    },
+    [getItemListOrSelected, swapItems]
+  );
+
+  const randomlyRotateSelectedItems = React.useCallback(
+    async (itemIds, { angle, maxRotateCount }) => {
+      const [ids] = await getItemListOrSelected(itemIds);
+
+      batchUpdateItems(ids, (item) => {
+        const rotation =
+          ((item.rotation || 0) + angle * randInt(0, maxRotateCount)) % 360;
+        return { ...item, rotation };
+      });
+    },
+    [getItemListOrSelected, batchUpdateItems]
+  );
+
+  // Tap/Untap elements
+  const toggleTap = React.useCallback(
+    async (itemIds) => {
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      const tappedCount = items.filter(({ rotation }) => rotation === 90)
+        .length;
+
+      let untap = false;
+      if (tappedCount > ids.length / 2) {
+        untap = true;
+      }
+
+      batchUpdateItems(ids, (item) => ({
+        ...item,
+        rotation: untap ? 0 : 90,
+      }));
+    },
+    [getItemListOrSelected, batchUpdateItems]
+  );
+
+  // Lock / unlock elements
+  const toggleLock = React.useCallback(
+    async (itemIds) => {
+      const [ids] = await getItemListOrSelected(itemIds);
+
+      batchUpdateItems(ids, (item) => ({
+        ...item,
+        locked: !item.locked,
+      }));
+
+      // Help user on first lock
+      if (isFirstLock) {
+        toast.info(
+          t("You've locked your first element. Long click to select it again."),
+          { autoClose: false }
+        );
+        setIsFirstLock(false);
+      }
+    },
+    [getItemListOrSelected, batchUpdateItems, isFirstLock, t, setIsFirstLock]
+  );
+
+  // Flip or reveal items
+  const setFlip = React.useCallback(
+    async (itemIds, { flip = true, reverseOrder = true } = {}) => {
+      batchUpdateItems(itemIds, (item) => ({
+        ...item,
+        flipped: flip,
+        unflippedFor:
+          !Array.isArray(item.unflippedFor) || item.unflippedFor.length > 0
+            ? null
+            : item.unflippedFor,
+      }));
+      if (reverseOrder) {
+        reverseItemsOrder(itemIds);
+      }
+    },
+    [batchUpdateItems, reverseItemsOrder]
+  );
+
+  // Toggle flip state
+  const toggleFlip = React.useCallback(
+    async (itemIds, { reverseOrder = true } = {}) => {
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      const flippedCount = items.filter(({ flipped }) => flipped).length;
+
+      setFlip(ids, {
+        flip: flippedCount < ids.length / 2,
+        reverseOrder,
+      });
+    },
+    [getItemListOrSelected, setFlip]
+  );
+
+  // Rotate element
+  const rotate = React.useCallback(
+    async (itemIds, { angle }) => {
+      const [ids] = await getItemListOrSelected(itemIds);
+
+      batchUpdateItems(ids, (item) => ({
+        ...item,
+        rotation: (item.rotation || 0) + angle,
+      }));
+    },
+    [getItemListOrSelected, batchUpdateItems]
+  );
+
+  // Reveal for player only
+  const setFlipSelf = React.useCallback(
+    async (itemIds, { flipSelf = true } = {}) => {
+      batchUpdateItems(itemIds, (item) => {
+        let { unflippedFor = [] } = item;
+
+        if (!Array.isArray(item.unflippedFor)) {
+          unflippedFor = [];
+        }
+
+        if (flipSelf && !unflippedFor.includes(currentUser.uid)) {
+          unflippedFor = [...unflippedFor, currentUser.uid];
+        }
+        if (!flipSelf && unflippedFor.includes(currentUser.uid)) {
+          unflippedFor = unflippedFor.filter((id) => id !== currentUser.uid);
+        }
+        return {
+          ...item,
+          flipped: true,
+          unflippedFor,
+        };
+      });
+    },
+    [batchUpdateItems, currentUser.uid]
+  );
+
+  // Reveal for player only
+  const toggleFlipSelf = React.useCallback(
+    async (itemIds) => {
+      const [ids, items] = await getItemListOrSelected(itemIds);
+
+      const flippedSelfCount = items.filter(
+        ({ unflippedFor }) =>
+          Array.isArray(unflippedFor) && unflippedFor.includes(currentUser.uid)
+      ).length;
+
+      let flipSelf = true;
+      if (flippedSelfCount > ids.length / 2) {
+        flipSelf = false;
+      }
+
+      setFlipSelf(ids, { flipSelf });
+    },
+    [getItemListOrSelected, setFlipSelf, currentUser.uid]
+  );
+
+  const remove = React.useCallback(
+    async (itemIds) => {
+      const [ids] = await getItemListOrSelected(itemIds);
+      removeItems(ids);
+    },
+    [getItemListOrSelected, removeItems]
+  );
+
+  const cloneItem = React.useCallback(
+    async (itemIds) => {
+      const [, items] = await getItemListOrSelected(itemIds);
+      items.forEach((itemToClone) => {
+        const newItem = JSON.parse(JSON.stringify(itemToClone));
+        newItem.id = nanoid();
+        delete newItem.move;
+        insertItemBefore(newItem, itemToClone.id);
+      });
+    },
+    [getItemListOrSelected, insertItemBefore]
+  );
+
+  const actionMap = React.useMemo(
+    () => ({
+      flip: {
+        action: toggleFlip,
+        label: t("Reveal") + "/" + t("Hide"),
+        shortcut: "f",
+        icon: flipIcon,
+      },
+      reveal: {
+        action: (itemIds) => setFlip(itemIds, { flip: false }),
+        label: t("Reveal"),
+        icon: flipIcon,
+      },
+      hide: {
+        action: (itemIds) => setFlip(itemIds, { flip: true }),
+        label: t("Hide"),
+        icon: flipIcon,
+      },
+      flipSelf: {
+        action: toggleFlipSelf,
+        label: t("Reveal for me"),
+        shortcut: "o",
+        icon: seeIcon,
+      },
+      revealSelf: {
+        action: (itemIds) => setFlipSelf(itemIds, { flipSelf: true }),
+        label: t("Reveal for me"),
+        icon: seeIcon,
+      },
+      hideSelf: {
+        action: (itemIds) => setFlipSelf(itemIds, { flipSelf: false }),
+        label: t("Hide for me"),
+        icon: seeIcon,
+      },
+      tap: {
+        action: toggleTap,
+        label: t("Tap") + "/" + t("Untap"),
+        shortcut: "t",
+        icon: tapIcon,
+      },
+      stackToCenter: {
+        action: stackToCenter,
+        label: t("Stack To Center"),
+        shortcut: "",
+        multiple: true,
+        icon: stackToCenterIcon,
+      },
+      stack: {
+        action: stackToTopLeft,
+        label: t("Stack To Top Left"),
+        multiple: true,
+        icon: stackToTopLeftIcon,
+      },
+      alignAsLine: {
+        action: alignAsLine,
+        label: t("Align as line"),
+        multiple: true,
+        icon: alignAsLineIcon,
+      },
+      alignAsSquare: {
+        action: alignAsSquare,
+        label: t("Align as square"),
+        multiple: true,
+        icon: alignAsSquareIcon,
+      },
+      shuffle: {
+        action: shuffleItems,
+        label: t("Shuffle"),
+        multiple: true,
+        icon: shuffleIcon,
+      },
+      randomlyRotate30: {
+        action: (itemIds) =>
+          randomlyRotateSelectedItems(itemIds, {
+            angle: 30,
+            maxRotateCount: 11,
+          }),
+        label: t("Rotate randomly 30"),
+        multiple: false,
+        icon: rotateIcon,
+      },
+      randomlyRotate45: {
+        action: (itemIds) =>
+          randomlyRotateSelectedItems(itemIds, {
+            angle: 45,
+            maxRotateCount: 7,
+          }),
+        label: t("Rotate randomly 45"),
+        shortcut: "",
+        multiple: false,
+        icon: rotateIcon,
+      },
+      randomlyRotate60: {
+        action: (itemIds) =>
+          randomlyRotateSelectedItems(itemIds, {
+            angle: 60,
+            maxRotateCount: 5,
+          }),
+        label: t("Rotate randomly 60"),
+        shortcut: "",
+        multiple: false,
+        icon: rotateIcon,
+      },
+      randomlyRotate90: {
+        action: (itemIds) =>
+          randomlyRotateSelectedItems(itemIds, {
+            angle: 90,
+            maxRotateCount: 3,
+          }),
+        label: t("Rotate randomly 90"),
+        shortcut: "",
+        multiple: false,
+        icon: rotateIcon,
+      },
+      randomlyRotate180: {
+        action: (itemIds) =>
+          randomlyRotateSelectedItems(itemIds, {
+            angle: 180,
+            maxRotateCount: 1,
+          }),
+        label: t("Rotate randomly 180"),
+        shortcut: "",
+        multiple: false,
+        icon: rotateIcon,
+      },
+      rotate30: {
+        action: (itemIds) => rotate(itemIds, { angle: 30 }),
+        label: t("Rotate 30"),
+        shortcut: "r",
+        icon: rotateIcon,
+      },
+      rotate45: {
+        action: (itemIds) => rotate(itemIds, { angle: 45 }),
+        label: t("Rotate 45"),
+        shortcut: "r",
+        icon: rotateIcon,
+      },
+      rotate60: {
+        action: (itemIds) => rotate(itemIds, { angle: 60 }),
+        label: t("Rotate 60"),
+        shortcut: "r",
+        icon: rotateIcon,
+      },
+      rotate90: {
+        action: (itemIds) => rotate(itemIds, { angle: 90 }),
+        label: t("Rotate 90"),
+        shortcut: "r",
+        icon: rotateIcon,
+      },
+      rotate180: {
+        action: (itemIds) => rotate(itemIds, { angle: 180 }),
+        label: t("Rotate 180"),
+        shortcut: "r",
+        icon: rotateIcon,
+      },
+      clone: {
+        action: cloneItem,
+        label: t("Clone"),
+        shortcut: "c",
+        disableDblclick: true,
+        edit: true,
+        icon: duplicateIcon,
+      },
+      lock: {
+        action: toggleLock,
+        label: t("Unlock") + "/" + t("Lock"),
+        disableDblclick: true,
+        icon: lockIcon,
+      },
+      remove: {
+        action: remove,
+        label: t("Remove all"),
+        shortcut: "Delete",
+        edit: true,
+        disableDblclick: true,
+        icon: deleteIcon,
+      },
+    }),
+    [
+      toggleFlip,
+      t,
+      toggleFlipSelf,
+      toggleTap,
+      stackToCenter,
+      stackToTopLeft,
+      alignAsLine,
+      alignAsSquare,
+      shuffleItems,
+      cloneItem,
+      toggleLock,
+      remove,
+      setFlip,
+      setFlipSelf,
+      randomlyRotateSelectedItems,
+      rotate,
+    ]
+  );
+
+  return {
+    stack: stackToTopLeft,
+    remove,
+    setFlip,
+    setFlipSelf,
+    toggleFlip,
+    toggleFlipSelf,
+    toggleLock,
+    toggleTap,
+    shuffle: shuffleItems,
+    rotate,
+    actionMap,
+    randomlyRotate: randomlyRotateSelectedItems,
+  };
+};
+
+export default useGameItemActions;

+ 2 - 2
src/hooks/useGame.jsx

@@ -2,12 +2,12 @@ import React, { useContext } from "react";
 
 import { updateGame } from "../utils/api";
 
-import { useBoardConfig, useItemBaseActions } from "react-sync-board";
+import { useBoardConfig, useItemActions } from "react-sync-board";
 
 export const GameContext = React.createContext({});
 
 export const GameProvider = ({ gameId, game, children }) => {
-  const { setItemList, getItemList } = useItemBaseActions();
+  const { setItemList, getItemList } = useItemActions();
   const [availableItems, setAvailableItems] = React.useState([]);
   const [boardConfig, setBoardConfig] = useBoardConfig();
 

+ 2 - 2
src/hooks/useSession.jsx

@@ -1,6 +1,6 @@
 import React, { useContext } from "react";
 import {
-  useItemBaseActions,
+  useItemActions,
   useMessage,
   useBoardConfig,
   useC2C,
@@ -33,7 +33,7 @@ const emtpyBoard = {
 };
 
 export const SessionProvider = ({ sessionId, fromGameId, children }) => {
-  const { setItemList, getItemList } = useItemBaseActions();
+  const { setItemList, getItemList } = useItemActions();
   const { messages, setMessages } = useMessage();
   const [availableItems, setAvailableItems] = React.useState([]);
   const [boardConfig, setBoardConfig] = useBoardConfig();

+ 0 - 2
src/index.jsx

@@ -10,8 +10,6 @@ import "./i18n"; // load translation system
 import App from "./App";
 import * as serviceWorker from "./serviceWorker";
 
-import styled from "styled-components";
-
 ReactDOM.render(
   <React.StrictMode>
     <App />

+ 6 - 2
src/views/BoardView/BoardView.jsx

@@ -8,7 +8,7 @@ import NavBar from "./NavBar";
 import BoardForm from "./BoardForm";
 import SelectedItemPane from "./SelectedItemsPane";
 
-import { ItemForm } from "../../gameComponents";
+import { ItemForm, itemTemplates } from "../../gameComponents";
 
 import ActionBar from "./ActionBar";
 
@@ -37,7 +37,11 @@ export const BoardView = ({ mediaLibraries, edit, itemLibraries }) => {
   return (
     <MediaLibraryProvider libraries={mediaLibraries}>
       <ImageDropNPaste>
-        <Board moveFirst={moveFirst} style={style} />
+        <Board
+          moveFirst={moveFirst}
+          style={style}
+          itemTemplates={itemTemplates}
+        />
         <NavBar editMode={edit} />
         <ActionBar
           editMode={edit}

+ 2 - 2
src/views/BoardView/ItemFormFactory.jsx

@@ -3,7 +3,7 @@ import { Form } from "react-final-form";
 
 import AutoSave from "../../components/ui/formUtils/AutoSave";
 import {
-  useItemBaseActions,
+  useItemActions,
   useSelectedItems,
   useItems,
 } from "react-sync-board";
@@ -16,7 +16,7 @@ export const getFormFieldComponent = (type, itemMap) => {
 };
 
 const ItemFormFactory = ({ ItemFormComponent }) => {
-  const { batchUpdateItems } = useItemBaseActions();
+  const { batchUpdateItems } = useItemActions();
   const items = useItems();
   const selectedItems = useSelectedItems();
 

+ 2 - 2
src/views/BoardView/SelectedItemsPane.jsx

@@ -8,11 +8,11 @@ import SidePanel from "../../components/ui/SidePanel";
 import ItemFormFactory from "./ItemFormFactory";
 import {
   useAvailableActions,
-  useItemActions,
   useSelectionBox,
   useSelectedItems,
   useBoardState,
 } from "react-sync-board";
+import useGameItemActions from "../../gameComponents/useGameItemActions";
 
 const ActionPane = styled.div.attrs(({ top, left, height }) => {
   if (top < 120) {
@@ -80,7 +80,7 @@ const CardContent = styled.div.attrs(() => ({ className: "content" }))`
 `;
 
 const SelectedItemsPane = ({ hideMenu = false, ItemFormComponent }) => {
-  const actionMap = useItemActions();
+  const { actionMap } = useGameItemActions();
 
   const { availableActions } = useAvailableActions();
   const [showEdit, setShowEdit] = React.useState(false);

+ 1 - 5
src/views/Session.jsx

@@ -4,7 +4,7 @@ import useAsyncEffect from "use-async-effect";
 import { BoardWrapper, useC2C } from "react-sync-board";
 import { nanoid } from "nanoid";
 
-import { itemTemplates, itemLibrary, actionMap } from "../gameComponents";
+import { itemTemplates, itemLibrary } from "../gameComponents";
 
 import BoardView from "./BoardView";
 import Waiter from "./Waiter";
@@ -160,13 +160,9 @@ const ConnectedSessionView = ({ sessionId, fromGame }) => {
     <BoardWrapper
       room={`room_${sessionId}`}
       session={sessionId}
-      itemTemplates={itemTemplates}
-      actions={actionMap}
       style={{
         position: "fixed",
         inset: "0",
-        //width: "100vw",
-        //height: "100vh",
         overflow: "hidden",
       }}
       socket={socket}