grub/client/Grub.tsx
2023-08-10 23:09:24 -05:00

87 lines
2.2 KiB
TypeScript

import * as Automerge from "@automerge/automerge";
import { useContext, useState } from "react";
import useWebSocket from "react-use-websocket";
import { wsUrl } from "./constants";
import CBOR from "cbor";
import { RoomContext } from "./lib/roomContext";
export default function Grub() {
const { roomId, clientId } = useContext(RoomContext);
const [doc, setDoc] = useState(Automerge.init());
const [syncState, setSyncState] = useState(Automerge.initSyncState());
const [addItemName, setAddItemName] = useState("");
function updateDoc(newDoc) {
setDoc(newDoc);
}
const { sendMessage } = useWebSocket(wsUrl, {
share: true,
onOpen: ({}) => {
console.log("Shiet, connected.");
},
onMessage: async (event) => {
const data = CBOR.decode(await event.data.arrayBuffer());
if (data.type === "Automerge") {
const [nextDoc, nextSyncState, patch] = Automerge.receiveSyncMessage(
doc,
syncState,
data.message[1]
);
setDoc(nextDoc);
setSyncState(nextSyncState);
console.log("patch", patch);
}
},
});
function sendCborMessage(data) {
let cbor = CBOR.encode(data);
sendMessage(cbor);
}
function addItem(e) {
e.preventDefault();
const newDoc = Automerge.change(doc, (doc) => {
if (!doc.items) doc.items = [];
doc.items.push({
id: uuid.v4(),
content: addItemName,
});
});
updateDoc(newDoc);
const [syncMessage, binary] = Automerge.generateSyncMessage(doc, syncState);
if (syncMessage)
sendCborMessage({
type: "Automerge",
client_id: clientId,
room_id: roomId,
message: binary,
});
setAddItemName("");
}
const items = doc.items || [];
return (
<>
Grubs:
<ul>
{items.map((x) => (
<li key={x.id}>{x.content}</li>
))}
</ul>
<form onSubmit={addItem}>
<input
type="text"
value={addItemName}
onChange={(e) => setAddItemName(e.target.value)}
placeholder="Type a message..."
/>
<button type="submit">add item</button>
</form>
</>
);
}