grub/client/Room.tsx

129 lines
3.4 KiB
TypeScript
Raw Permalink Normal View History

2023-08-10 21:10:48 +00:00
import CBOR from "cbor";
import { useEffect, useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket";
import * as Automerge from "@automerge/automerge";
import * as uuid from "uuid";
2023-08-10 23:37:53 +00:00
import { wsUrl } from "./constants";
2023-08-11 04:09:24 +00:00
import { Tab, Tabs } from "react-bootstrap";
import Upload from "./Upload";
import Chat from "./Chat";
import Grub from "./Grub";
import { RoomContext } from "./lib/roomContext";
import { Wifi } from "react-bootstrap-icons";
2023-08-10 21:10:48 +00:00
const connectionStatusMap = {
[ReadyState.CONNECTING]: "Connecting",
[ReadyState.OPEN]: "Open",
[ReadyState.CLOSING]: "Closing",
[ReadyState.CLOSED]: "Closed",
[ReadyState.UNINSTANTIATED]: "Uninstantiated",
};
export default function Room({ roomId }) {
const [readyState, setReadyState] = useState(ReadyState.CLOSED);
const [connectedClients, setConnectedClients] = useState([]);
2023-08-10 21:20:21 +00:00
const [clientId, setClientId] = useState<string | null>(null);
2023-08-10 21:10:48 +00:00
const {
sendMessage,
lastJsonMessage,
readyState: newReadyState,
2023-08-10 23:37:53 +00:00
} = useWebSocket(wsUrl, {
2023-08-10 22:55:32 +00:00
share: true,
2023-08-10 21:10:48 +00:00
onOpen: ({}) => {
console.log("Shiet, connected.");
},
onMessage: async (event) => {
const data = CBOR.decode(await event.data.arrayBuffer());
console.log("received", data);
if (data.type === "ServerHello") {
setClientId(uuid.stringify(data.client_id));
}
if (data.type === "RoomClientList") {
setConnectedClients(data.clients.map((x) => uuid.stringify(x)));
}
if (data.type === "Automerge") {
const [nextDoc, nextSyncState, patch] = Automerge.receiveSyncMessage(
doc,
syncState,
data.message[1]
);
setDoc(nextDoc);
setSyncState(nextSyncState);
console.log("patch", patch);
}
},
});
function sendWtfMessage(data) {
let cbor = CBOR.encode(data);
console.log(
"cbor-encoded",
[...new Uint8Array(cbor)]
.map((x) => x.toString(16).padStart(2, "0"))
.join(" ")
);
sendMessage(cbor);
}
useEffect(() => {
if (
readyState === ReadyState.CONNECTING &&
newReadyState === ReadyState.OPEN
) {
// On Open
sendWtfMessage({ type: "JoinRoom", room_id: roomId });
console.log("Sent connection message");
}
setReadyState(newReadyState);
}, [newReadyState]);
2023-08-10 21:20:21 +00:00
const connectionStatus = connectionStatusMap[readyState];
if (newReadyState !== ReadyState.OPEN) return <>Connecting...</>;
2023-08-10 21:10:48 +00:00
return (
2023-08-11 04:09:24 +00:00
<RoomContext.Provider value={{ roomId, clientId }}>
2023-08-10 21:20:21 +00:00
<p>Room Id: {roomId}</p>
2023-08-11 04:09:24 +00:00
<p>
Connection status: <ConnectionStatus readyState={readyState} />
</p>
2023-08-10 21:10:48 +00:00
Connected:
<ul>
{connectedClients.map((x) => (
<li key={x}>{x}</li>
))}
</ul>
2023-08-11 04:09:24 +00:00
<Tabs
defaultActiveKey="file-transfer"
id="uncontrolled-tab-example"
className="mb-3"
>
<Tab eventKey="file-transfer" title="File Transfer">
<Upload />
</Tab>
<Tab eventKey="grocery-tracking" title="Grocery Tracking">
<Grub />
</Tab>
<Tab eventKey="chat" title="Chat">
<Chat />
</Tab>
</Tabs>
</RoomContext.Provider>
2023-08-10 21:10:48 +00:00
);
}
2023-08-11 04:09:24 +00:00
function ConnectionStatus({ readyState }) {
switch (readyState) {
case ReadyState.CONNECTING:
return <Wifi color="yellow" />;
case ReadyState.OPEN:
return <Wifi color="green" />;
default:
return null;
}
}