diff --git a/src/helpers/useSession.js b/src/helpers/useSession.js new file mode 100644 index 0000000..25f1517 --- /dev/null +++ b/src/helpers/useSession.js @@ -0,0 +1,92 @@ +import { useEffect, useState } from "react"; +import Peer from "peerjs"; + +function useSession(onConnectionOpen) { + const [peerId, setPeerId] = useState(null); + const [peer, setPeer] = useState(null); + const [connections, setConnections] = useState({}); + function addConnection(connection) { + setConnections(prevConnnections => ({ + ...prevConnnections, + [connection.peer]: connection + })); + } + + useEffect(() => { + setPeer(new Peer()); + }, []); + + useEffect(() => { + function handleOpen(id) { + setPeerId(id); + } + + function handleConnection(connection) { + connection.on("open", () => { + connection.send( + JSON.stringify({ + id: "sync", + data: Object.keys(connections) + }) + ); + + addConnection(connection); + + if (onConnectionOpen) { + onConnectionOpen(); + } + }); + + function removeConnection() { + setConnections(prevConnections => { + const { [connection.peer]: old, ...rest } = prevConnections; + return rest; + }); + } + + connection.on("close", removeConnection); + connection.on("error", removeConnection); + } + + if (!peer) { + return; + } + + peer.on("open", handleOpen); + peer.on("connection", handleConnection); + return () => { + peer.removeListener("open", handleOpen); + peer.removeListener("connection", handleConnection); + }; + }, [peer, peerId, connections]); + + function sync(connectionIds) { + for (let connectionId of connectionIds) { + if (connectionId in connections) { + continue; + } + const connection = peer.connect(connectionId); + addConnection(connection); + } + } + + function connectTo(connectionId) { + if (connectionId in connections) { + return; + } + const connection = peer.connect(connectionId); + connection.on("open", () => { + connection.on("data", json => { + const data = JSON.parse(json); + if (data.id === "sync") { + sync(data.data); + } + }); + }); + addConnection(connection); + } + + return [peer, peerId, connections, connectTo]; +} + +export default useSession; diff --git a/src/routes/Game.js b/src/routes/Game.js index 6de3741..c37cf09 100644 --- a/src/routes/Game.js +++ b/src/routes/Game.js @@ -1,10 +1,18 @@ -import React, { useContext } from "react"; +import React, { useContext, useEffect } from "react"; import { A } from "hookrouter"; import GameContext from "../contexts/GameContext"; +import useSession from "../helpers/useSession"; function Game() { const [gameId, setGameId] = useContext(GameContext); + const [peer, peerId, connections, connectTo] = useSession(); + + useEffect(() => { + if (gameId !== null && peerId !== null) { + connectTo(gameId); + } + }, [gameId, peerId]); return (
diff --git a/src/routes/Join.js b/src/routes/Join.js index 20cb833..b05289a 100644 --- a/src/routes/Join.js +++ b/src/routes/Join.js @@ -24,7 +24,7 @@ function Join() { my={4} id="id" name="id" - value={gameId} + value={gameId || ""} onChange={handleChange} /> diff --git a/src/useSession.js b/src/useSession.js deleted file mode 100644 index 60a488c..0000000 --- a/src/useSession.js +++ /dev/null @@ -1,56 +0,0 @@ -import { useEffect, useState } from "react"; -import Peer from "peerjs"; - -function useSession(imgRef) { - const [peerId, setPeerId] = useState(null); - const [peer, setPeer] = useState(null); - const [connections, setConnections] = useState({}); - - useEffect(() => { - setPeer(new Peer()); - }, []); - - useEffect(() => { - function handleOpen(id) { - setPeerId(id); - } - - function handleConnection(connection) { - setConnections(prevConnnections => ({ - ...prevConnnections, - [connection.peer]: connection - })); - - connection.on("open", () => { - if (imgRef.current) { - connection.send(imgRef.current); - } - }); - - function removeConnection() { - setConnections(prevConnections => { - const { [connection.peer]: old, ...rest } = prevConnections; - return rest; - }); - } - - connection.on("close", removeConnection); - connection.on("error", removeConnection); - } - - if (!peer) { - return; - } - - peer.on("open", handleOpen); - peer.on("connection", handleConnection); - return () => { - peer.removeListener("open", handleOpen); - peer.removeListener("connection", handleConnection); - }; - }, [peer, peerId, connections, imgRef]); - - return [peer, peerId, connections]; -} - -export default useSession;