Implemented session management in game route

This commit is contained in:
Mitchell McCaffrey 2020-03-17 20:09:23 +11:00
parent 673320988f
commit d88eefc3a7
4 changed files with 102 additions and 58 deletions

92
src/helpers/useSession.js Normal file
View File

@ -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;

View File

@ -1,10 +1,18 @@
import React, { useContext } from "react"; import React, { useContext, useEffect } from "react";
import { A } from "hookrouter"; import { A } from "hookrouter";
import GameContext from "../contexts/GameContext"; import GameContext from "../contexts/GameContext";
import useSession from "../helpers/useSession";
function Game() { function Game() {
const [gameId, setGameId] = useContext(GameContext); const [gameId, setGameId] = useContext(GameContext);
const [peer, peerId, connections, connectTo] = useSession();
useEffect(() => {
if (gameId !== null && peerId !== null) {
connectTo(gameId);
}
}, [gameId, peerId]);
return ( return (
<div> <div>

View File

@ -24,7 +24,7 @@ function Join() {
my={4} my={4}
id="id" id="id"
name="id" name="id"
value={gameId} value={gameId || ""}
onChange={handleChange} onChange={handleChange}
/> />
<Button>Go ʕʔ</Button> <Button>Go ʕʔ</Button>

View File

@ -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;