adds room join form

This commit is contained in:
bhushan6
2023-08-15 00:18:11 +05:30
parent fae9c8ae1a
commit ac7c635239
9 changed files with 332 additions and 85 deletions
+75
View File
@@ -14,6 +14,7 @@
"@radix-ui/colors": "^2.0.1", "@radix-ui/colors": "^2.0.1",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-form": "^0.0.3",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-menubar": "^1.0.3", "@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-popover": "^1.0.6",
@@ -1320,6 +1321,34 @@
} }
} }
}, },
"node_modules/@radix-ui/react-form": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.0.3.tgz",
"integrity": "sha512-kgE+Z/haV6fxE5WqIXj05KkaXa3OkZASoTDy25yX2EIp/x0c54rOH/vFr5nOZTg7n7T1z8bSyXmiVIFP9bbhPQ==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-label": "2.0.2",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-icons": { "node_modules/@radix-ui/react-icons": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
@@ -1346,6 +1375,29 @@
} }
} }
}, },
"node_modules/@radix-ui/react-label": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
"dependencies": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-menu": { "node_modules/@radix-ui/react-menu": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.5.tgz",
@@ -6473,6 +6525,20 @@
"@radix-ui/react-use-callback-ref": "1.0.1" "@radix-ui/react-use-callback-ref": "1.0.1"
} }
}, },
"@radix-ui/react-form": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.0.3.tgz",
"integrity": "sha512-kgE+Z/haV6fxE5WqIXj05KkaXa3OkZASoTDy25yX2EIp/x0c54rOH/vFr5nOZTg7n7T1z8bSyXmiVIFP9bbhPQ==",
"requires": {
"@babel/runtime": "^7.13.10",
"@radix-ui/primitive": "1.0.1",
"@radix-ui/react-compose-refs": "1.0.1",
"@radix-ui/react-context": "1.0.1",
"@radix-ui/react-id": "1.0.1",
"@radix-ui/react-label": "2.0.2",
"@radix-ui/react-primitive": "1.0.3"
}
},
"@radix-ui/react-icons": { "@radix-ui/react-icons": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
@@ -6488,6 +6554,15 @@
"@radix-ui/react-use-layout-effect": "1.0.1" "@radix-ui/react-use-layout-effect": "1.0.1"
} }
}, },
"@radix-ui/react-label": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
"integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
"requires": {
"@babel/runtime": "^7.13.10",
"@radix-ui/react-primitive": "1.0.3"
}
},
"@radix-ui/react-menu": { "@radix-ui/react-menu": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.5.tgz",
+1
View File
@@ -16,6 +16,7 @@
"@radix-ui/colors": "^2.0.1", "@radix-ui/colors": "^2.0.1",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-form": "^0.0.3",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-menubar": "^1.0.3", "@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-popover": "^1.0.6",
+18 -6
View File
@@ -1,29 +1,41 @@
/* eslint-disable react/prop-types */
import "./App.css"; import "./App.css";
import { useEffect, useRef } from "react"; import { useEffect, useState } from "react";
import { LegoRoom } from "./components/3D"; import { LegoRoom } from "./components/3D";
import { useStore } from "./store"; import { useStore } from "./store";
import { Loader } from "./components/UI/Loader"; import { Loader } from "./components/UI/Loader";
import { JoinRoomScreen } from "./components/UI/JoinRoomForm";
const CONNECTED = "connected"; const CONNECTED = "connected";
function App() { const Lobby = ({ roomId }) => {
const enterRoom = useStore((state) => state.liveblocks.enterRoom); const enterRoom = useStore((state) => state.liveblocks.enterRoom);
const leaveRoom = useStore((state) => state.liveblocks.leaveRoom); const leaveRoom = useStore((state) => state.liveblocks.leaveRoom);
const status = useStore((state) => state.liveblocks.status); const status = useStore((state) => state.liveblocks.status);
useEffect(() => { useEffect(() => {
enterRoom("lego-test-room"); enterRoom(roomId);
return () => leaveRoom("lego-test-room", { bricks: [] }); return () => leaveRoom(roomId, { bricks: [] });
}, [enterRoom, leaveRoom]); }, [enterRoom, leaveRoom, roomId]);
if (status !== CONNECTED) { if (status !== CONNECTED) {
return <Loader />; return <Loader />;
} }
return <LegoRoom />;
};
function App() {
const [roomId, setRoomId] = useState(null);
return ( return (
<div className="App"> <div className="App">
<LegoRoom /> {roomId ? (
<Lobby roomId={roomId} />
) : (
<JoinRoomScreen setRoomId={setRoomId} />
)}
</div> </div>
); );
} }
+38 -25
View File
@@ -4,43 +4,56 @@
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
import { Canvas } from "@react-three/fiber"; import { Canvas } from "@react-three/fiber";
import React, { Suspense } from "react"; import React, { Suspense } from "react";
import { LinearToneMapping } from "three"; // import { LinearToneMapping } from "three";
import { ControlsWrapper, Scene } from "."; import { ControlsWrapper, Scene } from ".";
import { DialogBox } from "../UI"; import { DialogBox } from "../UI";
import { Perf } from "r3f-perf"; // import { Perf } from "r3f-perf";
import { ModeToggleBar } from "../UI/ModeToggleBar"; import { ModeToggleBar } from "../UI/ModeToggleBar";
import { Panel } from "../UI/Panel"; import { Panel } from "../UI/Panel";
import { BottomBar } from "../UI/BottomBar"; import { BottomBar } from "../UI/BottomBar";
export const LegoRoom = () => { const UI = () => {
return ( return (
<> <>
<DialogBox /> <DialogBox />
<ModeToggleBar /> <ModeToggleBar />
<Panel /> <Panel />
<BottomBar /> <BottomBar />
<Canvas </>
gl={{ );
alpha: false, };
antialias: true,
powerPreference: "high-performance", const ThreeD = () => {
toneMapping: LinearToneMapping, return (
}} <Canvas
camera={{ gl={{
position: [17.43, 657.76, 943.51], alpha: false,
near: 0.1, antialias: true,
far: 20000, powerPreference: "high-performance",
}} // toneMapping: LinearToneMapping,
colormanagement={"true"} }}
shadows={true} camera={{
dpr={Math.min(2, window.devicePixelRatio)} position: [17.43, 657.76, 943.51],
> near: 0.1,
<Suspense fallback={null}> far: 20000,
<Scene /> }}
<ControlsWrapper /> colormanagement={"true"}
</Suspense> shadows={true}
{/* <Perf position="bottom-left" matrixUpdate={true} /> */} dpr={Math.min(2, window.devicePixelRatio)}
</Canvas> >
<Suspense fallback={null}>
<Scene />
<ControlsWrapper />
</Suspense>
</Canvas>
);
};
export const LegoRoom = () => {
return (
<>
<UI />
<ThreeD />
</> </>
); );
}; };
+98
View File
@@ -0,0 +1,98 @@
/* eslint-disable react/prop-types */
import * as Form from "@radix-ui/react-form";
import "./styles.css";
import { useRef } from "react";
import { useStore } from "../../../store";
const JoinRoomForm = ({ setRoomId }) => {
const form = useRef();
const name = useRef();
const room = useRef();
const setSelfName = useStore((state) => state.setSelfName);
const submit = (e) => {
e.preventDefault();
setSelfName(name.current);
setRoomId(room.current);
};
return (
<Form.Root ref={form} className="FormRoot" onSubmit={submit}>
<Form.Field className="FormField" name="email">
<div
style={{
display: "flex",
alignItems: "baseline",
justifyContent: "space-between",
}}
>
<Form.Label className="FormLabel">Name</Form.Label>
<Form.Message className="FormMessage" match="valueMissing">
Please enter your Name
</Form.Message>
</div>
<Form.Control asChild>
<input
className="Input"
type="text"
required
onChange={(e) => {
name.current = e.target.value;
}}
/>
</Form.Control>
</Form.Field>
<Form.Field className="FormField" name="question">
<div
style={{
display: "flex",
alignItems: "baseline",
justifyContent: "space-between",
}}
>
<Form.Label className="FormLabel">Room ID</Form.Label>
<Form.Message className="FormMessage" match="valueMissing">
Please enter a room ID
</Form.Message>
</div>
<Form.Control asChild>
<input
className="Input"
type="text"
required
onChange={(e) => {
room.current = e.target.value;
}}
/>
</Form.Control>
</Form.Field>
<Form.Submit asChild>
<button className="FormButton" style={{ marginTop: 10 }}>
Enter In Room
</button>
</Form.Submit>
</Form.Root>
);
};
export const JoinRoomScreen = ({ setRoomId }) => {
return (
<div
style={{
width: "100vw",
height: "100vh",
boxSizing: "border-box",
margin: 0,
padding: 0,
background: "black",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<JoinRoomForm setRoomId={setRoomId} />
</div>
);
};
+95
View File
@@ -0,0 +1,95 @@
@import "@radix-ui/colors/black-alpha.css";
@import "@radix-ui/colors/violet.css";
@import "@radix-ui/colors/mauve.css";
/* reset */
input,
textarea,
button {
all: unset;
box-sizing: border-box;
}
.FormRoot {
width: 260px;
}
.FormField {
display: grid;
margin-bottom: 10px;
}
.FormLabel {
font-size: 14px;
font-weight: 500;
line-height: 35px;
color: white;
}
.FormMessage {
font-size: 13px;
color: white;
opacity: 0.8;
}
.Input,
.Textarea {
width: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 4px;
font-size: 15px;
color: white;
background-color: gray;
box-shadow: 0 0 0 1px var(--black-a9);
}
.Input:hover,
.Textarea:hover {
box-shadow: 0 0 0 1px white;
}
.Input:focus,
.Textarea:focus {
box-shadow: 0 0 0 2px white;
}
.Input::selection,
.Textarea::selection {
background-color: var(--black-a9);
color: white;
}
.Input {
padding: 0 10px;
height: 35px;
line-height: 1;
}
.Textarea {
resize: none;
padding: 10px;
}
.FormButton {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 4px;
padding: 0 15px;
font-size: 15px;
line-height: 1;
font-weight: 500;
height: 35px;
width: 100%;
background-color: white;
color: black;
box-shadow: 0 2px 10px var(--black-a7);
}
.FormButton:hover {
background-color: var(--mauve-3);
cursor: pointer;
}
.FormButton:focus {
box-shadow: 0 0 0 2px black;
}
+1 -1
View File
@@ -40,8 +40,8 @@ const PeopleList = () => {
return user.presence?.self ? ( return user.presence?.self ? (
<Person <Person
key={user.presence.self.id} key={user.presence.self.id}
name={"Person"}
color={user.presence.self.color} color={user.presence.self.color}
name={user.presence.self.name}
/> />
) : null; ) : null;
})} })}
+2 -53
View File
@@ -13,59 +13,6 @@ const client = createClient({
publicApiKey: import.meta.env.VITE_LIVEBLOCKS_API_KEY, publicApiKey: import.meta.env.VITE_LIVEBLOCKS_API_KEY,
}); });
// export const useStore = create((set) => ({
// mode: CREATE_MODE,
// setMode: (newMode) => set({ mode: newMode }),
// width: defaultWidth,
// setWidth: (newWidth) => set({ width: newWidth }),
// depth: defaultWidth,
// setDepth: (newDepth) => set({ depth: newDepth }),
// anchorX: defaultAnchor,
// setAnchorX: (newAnchorPoint) => set({ anchorX: newAnchorPoint }),
// anchorZ: defaultAnchor,
// setAnchorZ: (newAnchorPoint) => set({ anchorZ: newAnchorPoint }),
// rotate: false,
// setRotate: (bool) => set({ rotate: bool }),
// color: "#ff0000",
// setColor: (newColor) => set({ color: newColor }),
// selectedBricks: [],
// setSelectedBricks: ({ object, shift }) =>
// set((state) => {
// if (object === undefined) return { selectedBricks: [] };
// else if (Array.isArray(object)) return { selectedBricks: object };
// else if (!shift)
// return state.selectedBricks[0] === object
// ? { selectedBricks: [] }
// : { selectedBricks: [object] };
// else if (state.selectedBricks.includes(object))
// return {
// selectedBricks: state.selectedBricks.filter((o) => o !== object),
// };
// else return { selectedBricks: [object, ...state.selectedBricks] };
// }),
// bricks: [],
// setBricks: (getBricks) =>
// set((state) => ({ bricks: getBricks(state.bricks) })),
// clearBricks: () => set({ bricks: [] }),
// cursor: {
// x: 0,
// z: 0,
// w: 0,
// d: 0,
// },
// setCursor: (newState) => set({ cursor: newState }),
// }));
const id = uID(); const id = uID();
const color = generateSoftColors(); const color = generateSoftColors();
@@ -115,6 +62,8 @@ export const useStore = create(
clearBricks: () => set({ bricks: [] }), clearBricks: () => set({ bricks: [] }),
self: { id: id, color: color }, self: { id: id, color: color },
setSelfName: (name) =>
set((state) => ({ self: { ...state.self, name: name } })),
cursorColors: {}, cursorColors: {},
setCursorColors: (newCursorColor) => setCursorColors: (newCursorColor) =>
+4
View File
@@ -127,3 +127,7 @@ export function generateSoftColors() {
return hexColor; return hexColor;
} }
export function isBlank(str) {
return !str || /^\s*$/.test(str);
}