diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..108abc7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+* eol=lf
\ No newline at end of file
diff --git a/.vscode/TableTop.code-workspace b/.vscode/TableTop.code-workspace
index 56a28a9..2a0ed79 100644
--- a/.vscode/TableTop.code-workspace
+++ b/.vscode/TableTop.code-workspace
@@ -1,7 +1,7 @@
{
"folders": [
{
- "path": "C:\\Users\\josep\\Documents\\Programming\\TypeScript\\TableTop"
+ "path": ".."
}
]
}
\ No newline at end of file
diff --git a/e2e/select-theme.spec.ts b/e2e/select-theme.spec.ts
index 0303695..c30fb2b 100644
--- a/e2e/select-theme.spec.ts
+++ b/e2e/select-theme.spec.ts
@@ -1,4 +1,5 @@
import { firefox, chromium, webkit, Browser, Page } from "playwright";
+import { v4 as uuidv4} from "uuid";
jest.setTimeout(10000);
@@ -42,6 +43,14 @@ describe.each([
{
page = await browser.newPage({ colorScheme: preferredTheme });
await page.goto("http://localhost:8080");
+
+ const roomNameInput = await page.waitForSelector(
+ "input[type=text]:near(:text('Room Name'))"
+ );
+
+ await roomNameInput.type(uuidv4());
+
+ await (await page.$("input[type=submit]:text('Join!')")).click();
});
afterEach(async () =>
@@ -73,6 +82,14 @@ describe.each([
{
page = await browser.newPage({ colorScheme: "light" });
await page.goto("http://localhost:8080");
+
+ const roomNameInput = await page.waitForSelector(
+ "input[type=text]:near(:text('Room Name'))"
+ );
+
+ await roomNameInput.type(uuidv4());
+
+ await (await page.$("input[type=submit]:text('Join!')")).click();
});
afterEach(async () =>
@@ -80,6 +97,7 @@ describe.each([
await page.close();
});
+ // Flaky test, fails on random expects in random browsers.
it("Selects that theme regardless of browser preference.", async () =>
{
const selector = `input[type=radio]:left-of(:text("Dark"))`;
@@ -94,6 +112,14 @@ describe.each([
await page.reload();
+ const roomNameInput = await page.waitForSelector(
+ "input[type=text]:near(:text('Room Name'))"
+ );
+
+ await roomNameInput.type(uuidv4());
+
+ await (await page.$("input[type=submit]:text('Join!')")).click();
+
const reloadedOption = await page.waitForSelector(selector);
expect(await reloadedOption.isChecked()).toBe(true);
diff --git a/package-lock.json b/package-lock.json
index 14005d6..df0dc1c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,6 +28,7 @@
"@semantic-release/git": "^9.0.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.2",
+ "@testing-library/user-event": "^13.2.1",
"@types/jest": "^26.0.24",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
@@ -1718,6 +1719,22 @@
"react-dom": "*"
}
},
+ "node_modules/@testing-library/user-event": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.2.1.tgz",
+ "integrity": "sha512-cczlgVl+krjOb3j1625usarNEibI0IFRJrSWX9UsJ1HKYFgCQv9Nb7QAipUDXl3Xdz8NDTsiS78eAkPSxlzTlw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -18368,6 +18385,15 @@
"@testing-library/dom": "^7.28.1"
}
},
+ "@testing-library/user-event": {
+ "version": "13.2.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.2.1.tgz",
+ "integrity": "sha512-cczlgVl+krjOb3j1625usarNEibI0IFRJrSWX9UsJ1HKYFgCQv9Nb7QAipUDXl3Xdz8NDTsiS78eAkPSxlzTlw==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.12.5"
+ }
+ },
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
diff --git a/package.json b/package.json
index e8d78cd..aeab05f 100644
--- a/package.json
+++ b/package.json
@@ -52,6 +52,7 @@
"@semantic-release/git": "^9.0.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.2",
+ "@testing-library/user-event": "^13.2.1",
"@types/jest": "^26.0.24",
"@types/react": "^16.14.2",
"@types/react-dom": "^16.9.10",
diff --git a/src/App.tsx b/src/App.tsx
index 2bdc264..a312888 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,16 +1,51 @@
import * as React from "react"
+import { v4 as uuidv4 } from "uuid";
+
+import { useLocalStore } from "./store/local";
+import { useSharedStoreFactory } from "./store/shared";
import Tabletop from "~/components/tabletop/Tabletop";
import { RectangularGrid } from "~/components/tabletop/RectangularGrid";
import ControlPanel from "./components/control-panel/ControlPanel";
+import JoinForm from "./components/join-form/JoinForm";
-export const App = () =>
-(
-
-
- } />
-
+export const SharedStoreContext = React.createContext(
+ useSharedStoreFactory(uuidv4())
);
+export const App = () =>
+{
+ const { room } = useLocalStore();
+
+ const useSharedStore = React.useMemo(
+ () => useSharedStoreFactory(room),
+ [ room ]
+ );
+
+ return (
+
+ {
+ room === ""
+ ? (
+
+ )
+ : (
+
+
+ } />
+
+ )
+ }
+
+ )
+}
+
export default App;
\ No newline at end of file
diff --git a/src/components/control-panel/ActorList.spec.tsx b/src/components/control-panel/ActorList.spec.tsx
index abc5a8e..7ab0be4 100644
--- a/src/components/control-panel/ActorList.spec.tsx
+++ b/src/components/control-panel/ActorList.spec.tsx
@@ -1,20 +1,42 @@
import React from "react";
+import { UseStore } from "zustand";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
-import { useSharedStore } from "~/store/shared";
+import { useLocalStore } from "~/store/local";
+import { SharedState, useSharedStoreFactory } from "~/store/shared";
import { Actor } from "~/core/Actor";
import ActorList, { actorListItemTestId, } from "./ActorList";
+import { SharedStoreContext } from "~/App";
+
+import { v4 as uuidv4 } from "uuid";
describe("Connected ActorList", () =>
{
+ let useSharedStore: UseStore;
+
+ beforeEach(() =>
+ {
+ useLocalStore.setState(() => ({ room: uuidv4() }));
+ useSharedStore = useSharedStoreFactory(useLocalStore.getState().room);
+ });
+
+ afterEach(() =>
+ {
+ useLocalStore.setState(() => ({ room: "" }));
+ });
+
it("Displays 'no actors' when there are no actors in state.", () =>
{
useSharedStore.setState(() => ({ actors: [] }));
- const { getByText } = render();
+ const { getByText } = render(
+
+
+
+ );
expect(getByText(/no actors/i)).toBeInTheDocument();
});
@@ -36,7 +58,11 @@ describe("Connected ActorList", () =>
for (let actorNumber of actorList)
useSharedStore.getState().addActor({ id: `${actorNumber}` } as Actor);
- const { getAllByTestId } = render();
+ const { getAllByTestId } = render(
+
+
+
+ );
expect(getAllByTestId(actorListItemTestId)).toHaveLength(actorList.length);
});
@@ -46,9 +72,13 @@ describe("Connected ActorList", () =>
useSharedStore.setState(() => ({ actors: [] }));
useSharedStore.getState().addActor({ id: `1`, name: `Actor 1` } as Actor);
- const { getByText } = render();
+ const { queryByText } = render(
+
+
+
+ );
- expect(getByText("Actor 1")).toBeInTheDocument();
+ expect(queryByText("Actor 1")).toBeInTheDocument();
});
it("Displays Actors sorted from highest initiative to lowest.", () =>
@@ -57,7 +87,11 @@ describe("Connected ActorList", () =>
useSharedStore.getState().addActor({ id: `1`, name: `Actor 1`, initiative: 1 } as Actor);
useSharedStore.getState().addActor({ id: `2`, name: `Actor 2`, initiative: 2 } as Actor);
- const { getAllByTestId } = render();
+ const { getAllByTestId } = render(
+
+
+
+ );
expect(getAllByTestId(actorListItemTestId)[0]).toHaveTextContent("Actor 2");
expect(getAllByTestId(actorListItemTestId)[1]).toHaveTextContent("Actor 1");
@@ -70,7 +104,11 @@ describe("Connected ActorList", () =>
useSharedStore.getState().addActor({ id: "1", name: "Actor 1", initiative: 2 } as Actor);
useSharedStore.getState().addActor({ id: "2", name: "Actor 2", initiative: 1 } as Actor);
- const { getAllByTestId } = render();
+ const { getAllByTestId } = render(
+
+
+
+ );
fireEvent.click(getAllByTestId(actorListItemTestId)[0]);
diff --git a/src/components/control-panel/ActorList.tsx b/src/components/control-panel/ActorList.tsx
index 39007f2..e446c66 100644
--- a/src/components/control-panel/ActorList.tsx
+++ b/src/components/control-panel/ActorList.tsx
@@ -1,5 +1,6 @@
import React from "react";
-import { useSharedStore } from "~/store/shared";
+import { SharedStoreContext } from "~/App";
+// import { useSharedStore } from "~/store/shared";
import "./ActorList.module.css";
import styles from "./ActorList.module.css";
@@ -9,6 +10,8 @@ export const actorListItemTestId = "actor-list-item";
export const ActorList = () =>
{
+ const useSharedStore = React.useContext(SharedStoreContext);
+
const { actors, removeActor } = useSharedStore(({ actors, removeActor }) =>
({
actors,
diff --git a/src/components/control-panel/AddActor.spec.tsx b/src/components/control-panel/AddActor.spec.tsx
index 53ca8f9..8dec6a9 100644
--- a/src/components/control-panel/AddActor.spec.tsx
+++ b/src/components/control-panel/AddActor.spec.tsx
@@ -1,8 +1,12 @@
import React from "react";
-import { fireEvent, render } from "@testing-library/react";
+import { act, fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
-import { useSharedStore } from "~/store/shared";
+import { v4 as uuidv4 } from "uuid";
+import { UseStore } from "zustand";
+
+import { SharedState, useSharedStoreFactory } from "~/store/shared";
+import { SharedStoreContext } from "~/App";
import AddActor, { AddActor as DisconnectedAddActor} from "./AddActor";
@@ -23,10 +27,15 @@ describe("Connected AddActor", () =>
{
it("Adds an actor when clicked.", () =>
{
+ let useSharedStore: UseStore;
+
+ useSharedStore = useSharedStoreFactory(uuidv4());
useSharedStore.setState(() => ({ actors: [] }));
const { getByText } = render(
-
+
+
+
);
const button = getByText("Add Actor");
diff --git a/src/components/control-panel/AddActor.tsx b/src/components/control-panel/AddActor.tsx
index 63b96ab..fa42be3 100644
--- a/src/components/control-panel/AddActor.tsx
+++ b/src/components/control-panel/AddActor.tsx
@@ -1,13 +1,15 @@
import React from "react";
-import { useSharedStore } from "~/store/shared";
import { v4 as uuid } from "uuid";
+import { SharedStoreContext } from "~/App";
import { Button } from "~/components/util/Button";
import "./AddActor.module.css";
export const AddActor = () =>
{
+ const useSharedStore = React.useContext(SharedStoreContext);
+
const addActor = useSharedStore((state) => state.addActor);
return (
diff --git a/src/components/control-panel/ControlPanel.spec.tsx b/src/components/control-panel/ControlPanel.spec.tsx
index 6d06ae8..032f001 100644
--- a/src/components/control-panel/ControlPanel.spec.tsx
+++ b/src/components/control-panel/ControlPanel.spec.tsx
@@ -2,10 +2,15 @@ import React from "react";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
-import { useSharedStore } from "~/store/shared";
+import { v4 as uuidv4 } from "uuid";
+
+import { useSharedStoreFactory, SharedState } from "~/store/shared";
+import { UseStore } from "zustand";
import { useLocalStore } from "~/store/local";
import ControlPanel from "./ControlPanel";
+import { SharedStoreContext } from "~/App";
+import { act } from "react-dom/test-utils";
Object.defineProperty(window, 'matchMedia', {
writable: true,
@@ -23,11 +28,35 @@ Object.defineProperty(window, 'matchMedia', {
describe("Connected ControlPanel", () =>
{
+ let useSharedStore: UseStore;
+
+ beforeEach(() =>
+ {
+ act(() =>
+ {
+ useLocalStore.setState(() => ({ room: uuidv4() }));
+ });
+
+ useSharedStore = useSharedStoreFactory(useLocalStore.getState().room);
+ });
+
+ afterEach(() =>
+ {
+ act(() =>
+ {
+ useLocalStore.setState(() => ({ room: "" }));
+ });
+ });
+
it("Adds an actor to app store when 'Add Actor' is pressed.", () =>
{
useSharedStore.setState(() => ({ actors: [] }));
- const { getByText } = render();
+ const { getByText } = render(
+
+
+
+ );
fireEvent.click(getByText("Add Actor"));
@@ -44,7 +73,11 @@ describe("Connected ControlPanel", () =>
y: 0
})
- const { getByText } = render();
+ const { getByText } = render(
+
+
+
+ );
expect(getByText("Actor 1")).toBeInTheDocument();
});
@@ -103,7 +136,11 @@ describe("Connected ControlPanel", () =>
for (let actor of testActors)
useSharedStore.getState().addActor(actor);
- const { getAllByText } = render();
+ const { getAllByText } = render(
+
+
+
+ );
const entries = getAllByText(/.*/i, { selector: "li" })
@@ -125,7 +162,11 @@ describe("Connected ControlPanel", () =>
y: 0
});
- const { getByText } = render();
+ const { getByText } = render(
+
+
+
+ );
fireEvent.click(getByText("Actor 1"));
diff --git a/src/components/join-form/JoinForm.module.css b/src/components/join-form/JoinForm.module.css
new file mode 100644
index 0000000..ff77e42
--- /dev/null
+++ b/src/components/join-form/JoinForm.module.css
@@ -0,0 +1,54 @@
+form {
+ display: grid;
+ row-gap: 0.5rem;
+}
+
+label {
+ justify-self: start;
+
+ font-weight: bold;
+}
+
+input[type=text] {
+ justify-self: center;
+ width: 25vw;
+
+ color: var(--black);
+ background-color: var(--white);
+
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ font-size: 1.2rem;
+ border: 2px solid #111;
+
+ padding: 0.5rem;
+}
+
+input[type=text]:focus {
+ border-color: var(--brand-primary);
+ border-radius: 0.5rem;
+}
+
+
+input[type=submit] {
+ justify-self: end;
+
+ width: 33.3%;
+
+ appearance: none;
+
+ border: none;
+ outline: none;
+
+ color: var(--white);
+ background-color: var(--brand-primary);
+
+ padding: 0.5rem 1rem;
+
+ font-family: Germania One, Impact, system-ui, sans-serif;
+ font-size: 1.5rem;
+
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/src/components/join-form/JoinForm.spec.tsx b/src/components/join-form/JoinForm.spec.tsx
new file mode 100644
index 0000000..da6ea88
--- /dev/null
+++ b/src/components/join-form/JoinForm.spec.tsx
@@ -0,0 +1,44 @@
+import React from "react";
+import { fireEvent, render } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import "@testing-library/jest-dom/extend-expect";
+
+import JoinForm, { joinFormTestId } from "./JoinForm";
+import { useLocalStore } from "~/store/local";
+
+describe("JoinForm component", () =>
+{
+ it("Is a form.", () =>
+ {
+ const { getByTestId } = render();
+ expect(getByTestId(joinFormTestId).tagName.toLowerCase()).toBe("form");
+ });
+
+ it("Has an input field labelled 'Room Name'.", () =>
+ {
+ const { getByLabelText } = render();
+ expect((getByLabelText("Room Name") as HTMLInputElement).type).toBe("text");
+ });
+
+ it("Has a submit button that says 'Join!'.", () =>
+ {
+ const { getByText } = render();
+ expect((getByText("Join!") as HTMLInputElement).type).toBe("submit")
+ });
+
+ it.each([
+ [ "room" ],
+ [ "antechamber" ]
+ ])("Sets room code ('%s') when you press 'Join!'.", (roomName) =>
+ {
+ useLocalStore.setState(() => ({ room: "", }));
+
+ global.HTMLFormElement.prototype.submit = jest.fn();
+ const { getByLabelText, getByTestId } = render();
+
+ userEvent.type(getByLabelText(/room name/i), roomName);
+ fireEvent.submit(getByTestId(joinFormTestId));
+
+ expect(useLocalStore.getState().room).toBe(roomName);
+ });
+});
\ No newline at end of file
diff --git a/src/components/join-form/JoinForm.tsx b/src/components/join-form/JoinForm.tsx
new file mode 100644
index 0000000..c1798a0
--- /dev/null
+++ b/src/components/join-form/JoinForm.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+import { useLocalStore } from "~/store/local";
+
+export const joinFormTestId = "join-form"
+
+import "./JoinForm.module.css";
+
+export const JoinForm = () =>
+{
+ const { setRoom } = useLocalStore();
+ const [ roomName, setRoomName ] = React.useState("");
+
+ return (
+
+ );
+}
+
+export default JoinForm;
\ No newline at end of file
diff --git a/src/components/tabletop/Tabletop.spec.tsx b/src/components/tabletop/Tabletop.spec.tsx
index fe9621d..40279a5 100644
--- a/src/components/tabletop/Tabletop.spec.tsx
+++ b/src/components/tabletop/Tabletop.spec.tsx
@@ -2,11 +2,13 @@ import * as React from "react";
import { render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
-import { useSharedStore } from "~/store/shared";
+import { useSharedStoreFactory } from "~/store/shared";
+import { v4 as uuidv4 } from "uuid";
import Tabletop, { Tabletop as DisconnectedTabletop } from "./Tabletop";
import { tokenTestId } from "./Token";
import { Actor } from "~/core/Actor";
+import { SharedStoreContext } from "~/App";
describe("Disconnected Tabletop component", () =>
{
@@ -54,6 +56,7 @@ describe("Connected Tabletop component", () =>
"Has a number of Tokens equal to the number of Actors in the app store",
(actorList, expectedTokenCount) =>
{
+ const useSharedStore = useSharedStoreFactory(uuidv4());
for (var actor of actorList)
useSharedStore.setState(
@@ -67,7 +70,9 @@ describe("Connected Tabletop component", () =>
);
const { queryAllByTestId } = render(
-
+
+
+
);
expect(queryAllByTestId(tokenTestId).length).toBe(expectedTokenCount);
diff --git a/src/components/tabletop/Tabletop.tsx b/src/components/tabletop/Tabletop.tsx
index 0edd704..5813184 100644
--- a/src/components/tabletop/Tabletop.tsx
+++ b/src/components/tabletop/Tabletop.tsx
@@ -1,6 +1,5 @@
import * as React from "react";
-
-import { useSharedStore } from "~/store/shared";
+import { SharedStoreContext } from "~/App";
import Token from "./Token";
@@ -10,6 +9,8 @@ type TabletopProps = React.HTMLAttributes<{}> &
};
export const Tabletop = ({ grid, }: TabletopProps) =>
{
+ const useSharedStore = React.useContext(SharedStoreContext);
+
const {
actors,
setActorPosition
diff --git a/src/components/tabletop/Token.spec.tsx b/src/components/tabletop/Token.spec.tsx
index 60f9a88..ef26af5 100644
--- a/src/components/tabletop/Token.spec.tsx
+++ b/src/components/tabletop/Token.spec.tsx
@@ -3,17 +3,19 @@ import { fireEvent } from "@testing-library/react";
import { renderSVG } from "~/test-utilities";
import "@testing-library/jest-dom/extend-expect";
+import { v4 as uuidv4 } from "uuid";
+
import "~/pointer-event";
import { useLocalStore } from "~/store/local";
import { identityTransform, scale, translation } from "~/core/Transform";
import Token, { Token as DisconnectedToken, tokenTestId } from "./Token";
-import { useSharedStore } from "~/store/shared";
import { Actor } from "~/core/Actor";
-import create from "zustand";
+import { useSharedStoreFactory } from "~/store/shared";
+import { SharedStoreContext } from "~/App";
-describe("Disconnected Token", () =>
+describe("Token", () =>
{
it("Has a SVG rect.", () =>
{
@@ -354,12 +356,16 @@ describe("Disconnected Token", () =>
"Follows pointer when user clicks and drags, relative to cursor. (#%#)",
(transform, [ initX, initY ], [ endX, endY ], [ expectedX, expectedY ]) =>
{
+ const useSharedStore = useSharedStoreFactory(uuidv4());
+
useSharedStore.setState(() => ({ actors: [] }));
useSharedStore.getState().addActor({ id: "1", x: 0, y: 0 } as Actor);
useLocalStore.getState().setViewTransform(transform);
const Component = () =>
{
+ const useSharedStore = React.useContext(SharedStoreContext);
+
const { x, y } = useSharedStore((state) =>
{
const index = state.actors.findIndex(({ id }) => id === "1");
@@ -383,7 +389,11 @@ describe("Disconnected Token", () =>
);
};
- const { getByTestId } = renderSVG();
+ const { getByTestId } = renderSVG(
+
+
+
+ );
const token = getByTestId(tokenTestId);
@@ -410,6 +420,8 @@ describe("Disconnected Token", () =>
it("Snaps to grid when snapToGrid is true", () =>
{
+ const useSharedStore = useSharedStoreFactory(uuidv4());
+
useSharedStore.setState(() => ({ actors: [] }));
useSharedStore.getState().addActor({ id: "1", x: 0, y: 0 } as Actor);
@@ -418,6 +430,8 @@ describe("Disconnected Token", () =>
const Component = () =>
{
+ const useSharedStore = React.useContext(SharedStoreContext);
+
const { x, y } = useSharedStore((state) =>
{
const index = state.actors.findIndex(({ id }) => id === "1");
@@ -441,7 +455,11 @@ describe("Disconnected Token", () =>
);
};
- const { getByTestId } = renderSVG();
+ const { getByTestId } = renderSVG(
+
+
+
+ );
const token = getByTestId(tokenTestId);
diff --git a/src/store/local.ts b/src/store/local.ts
index 34f56e9..6a68c6e 100644
--- a/src/store/local.ts
+++ b/src/store/local.ts
@@ -13,6 +13,9 @@ type LocalState =
snapToGrid: boolean,
setSnapToGrid: (snapToGrid: boolean) => void,
+
+ room: string,
+ setRoom: (roomName: string) => void,
};
export const useLocalStore = create(
@@ -36,5 +39,9 @@ export const useLocalStore = create(
setSnapToGrid:
(snapToGrid: boolean) =>
set((_) => ({ snapToGrid })),
+
+ room: "",
+ setRoom: (roomName) =>
+ set(() => ({ room: roomName })),
})
);
\ No newline at end of file
diff --git a/src/store/shared.ts b/src/store/shared.ts
index 768e187..d23315f 100644
--- a/src/store/shared.ts
+++ b/src/store/shared.ts
@@ -6,7 +6,7 @@ import { WebrtcProvider } from "y-webrtc";
import { Actor } from "~/core/Actor";
-type SharedState =
+export type SharedState =
{
actors: Actor[],
addActor: (actor: Actor) => void,
@@ -14,48 +14,51 @@ type SharedState =
setActorPosition: (actorId: string, x: number, y: number) => void,
};
-const doc = new Y.Doc();
-new WebrtcProvider("repeated-pleasant-games", doc);
+export const useSharedStoreFactory = (roomName: string) =>
+{
+ const doc = new Y.Doc();
+ new WebrtcProvider(roomName, doc);
-export const useSharedStore = create(
- yjs(
- doc,
- "shared-state",
- (set) =>
- ({
- actors: [],
- addActor:
- (actor: Actor) =>
- set((state) => ({ actors: [ ...state.actors, actor ] })),
- removeActor:
- (actorId: string) =>
- set(
- (state) =>
- ({
- actors: state.actors.filter(({ id }) => id !== actorId)
- })
- ),
- setActorPosition:
- (actorId: string, x: number, y: number) =>
- set(
- (state) =>
- ({
- actors: state.actors.map(
- (actor) =>
- {
- if (actor.id === actorId)
- return {
- ...actor,
- x,
- y,
- };
+ return create(
+ yjs(
+ doc,
+ "shared-state",
+ (set) =>
+ ({
+ actors: [],
+ addActor:
+ (actor: Actor) =>
+ set((state) => ({ actors: [ ...state.actors, actor ] })),
+ removeActor:
+ (actorId: string) =>
+ set(
+ (state) =>
+ ({
+ actors: state.actors.filter(({ id }) => id !== actorId)
+ })
+ ),
+ setActorPosition:
+ (actorId: string, x: number, y: number) =>
+ set(
+ (state) =>
+ ({
+ actors: state.actors.map(
+ (actor) =>
+ {
+ if (actor.id === actorId)
+ return {
+ ...actor,
+ x,
+ y,
+ };
- else
- return actor;
- }
- )
- })
- )
- })
- )
-);
\ No newline at end of file
+ else
+ return actor;
+ }
+ )
+ })
+ )
+ })
+ )
+ );
+};
\ No newline at end of file
diff --git a/src/styles/style.css b/src/styles/style.css
index 4f25470..1003fb7 100644
--- a/src/styles/style.css
+++ b/src/styles/style.css
@@ -63,6 +63,8 @@ body {
}
.control-panel {
+ place-self: start;
+
position: absolute;
z-index: 1;