Added offline mode

This commit is contained in:
Mitchell McCaffrey 2020-11-26 11:09:48 +11:00
parent 9131557b71
commit 5209317d1e
2 changed files with 68 additions and 37 deletions

View File

@ -27,8 +27,8 @@ import { logError } from "../helpers/logging";
* - error
* - authenticationSuccess
* - authenticationError
* - connected: You have connected
* - disconnected: You have disconnected
* - connected: You have connected to the party
* - disconnected: You have disconnected from the party
*/
class Session extends EventEmitter {
/**
@ -45,8 +45,15 @@ class Session extends EventEmitter {
*/
peers;
/**
* The state of the session
*
* @type {('unknown'|'online'|'offline')}
*/
state;
get id() {
return this.socket.id;
return this.socket && this.socket.id;
}
_iceServers;
@ -57,27 +64,43 @@ class Session extends EventEmitter {
constructor() {
super();
this.socket = io(process.env.REACT_APP_BROKER_URL, {
transports: ["websocket"],
});
this.socket.on(
"party member joined",
this._handlePartyMemberJoined.bind(this)
);
this.socket.on("party member left", this._handlePartyMemberLeft.bind(this));
this.socket.on("joined party", this._handleJoinedParty.bind(this));
this.socket.on("signal", this._handleSignal.bind(this));
this.socket.on("auth error", this._handleAuthError.bind(this));
this.socket.on("disconnect", this._handleSocketDisconnect.bind(this));
this.socket.io.on("reconnect", this._handleSocketReconnect.bind(this));
this.peers = {};
this.state = "unknown";
// Signal connected peers of a closure on refresh
window.addEventListener("beforeunload", this._handleUnload.bind(this));
}
async connect() {
try {
const response = await fetch(process.env.REACT_APP_ICE_SERVERS_URL);
const data = await response.json();
this._iceServers = data.iceServers;
this.socket = io(process.env.REACT_APP_BROKER_URL, {
transports: ["websocket"],
});
this.socket.on(
"party member joined",
this._handlePartyMemberJoined.bind(this)
);
this.socket.on(
"party member left",
this._handlePartyMemberLeft.bind(this)
);
this.socket.on("joined party", this._handleJoinedParty.bind(this));
this.socket.on("signal", this._handleSignal.bind(this));
this.socket.on("auth error", this._handleAuthError.bind(this));
this.socket.on("disconnect", this._handleSocketDisconnect.bind(this));
this.socket.io.on("reconnect", this._handleSocketReconnect.bind(this));
this.state = "online";
} catch (error) {
logError(error);
this.state = "offline";
}
}
/**
* Send data to all connected peers
*
@ -104,21 +127,12 @@ class Session extends EventEmitter {
partyId,
password
);
this.emit("disconnected");
return;
}
this._partyId = partyId;
this._password = password;
try {
const response = await fetch(process.env.REACT_APP_ICE_SERVERS_URL);
const data = await response.json();
this._iceServers = data.iceServers;
this.socket.emit("join party", partyId, password);
} catch (error) {
logError(error);
this.emit("disconnected");
}
this.socket.emit("join party", partyId, password);
}
_addPeer(id, initiator, sync) {

View File

@ -17,8 +17,6 @@ import NetworkedParty from "../network/NetworkedParty";
import Session from "../network/Session";
const session = new Session();
function Game() {
const { id: gameId } = useParams();
const {
@ -28,6 +26,18 @@ function Game() {
} = useContext(AuthContext);
const { databaseStatus } = useContext(DatabaseContext);
const [session] = useState(new Session());
const [offline, setOffline] = useState(false);
useEffect(() => {
async function connect() {
await session.connect();
if (session.state === "offline") {
setOffline(true);
}
}
connect();
}, [session]);
// Handle authentication status
useEffect(() => {
function handleAuthSuccess() {
@ -43,7 +53,7 @@ function Game() {
session.off("authenticationSuccess", handleAuthSuccess);
session.off("authenticationError", handleAuthError);
};
}, [setAuthenticationStatus]);
}, [setAuthenticationStatus, session]);
// Handle session errors
const [peerError, setPeerError] = useState(null);
@ -59,7 +69,7 @@ function Game() {
return () => {
session.off("error", handlePeerError);
};
}, []);
}, [session]);
// Handle connection
const [connected, setConnected] = useState(false);
@ -79,14 +89,14 @@ function Game() {
session.off("connected", handleConnected);
session.off("disconnected", handleDisconnected);
};
}, []);
}, [session]);
// Join game
useEffect(() => {
if (databaseStatus !== "loading") {
if (session.state === "online" && databaseStatus !== "loading") {
session.joinParty(gameId, password);
}
}, [gameId, password, databaseStatus]);
}, [gameId, password, databaseStatus, session]);
// A ref to the Konva stage
// the ref will be assigned in the MapInteraction component
@ -114,6 +124,13 @@ function Game() {
</Text>
</Box>
</Banner>
<Banner isOpen={offline} onRequestClose={() => {}} allowClose={false}>
<Box p={1}>
<Text as="p" variant="body2">
Offline, refresh to reconnect.
</Text>
</Box>
</Banner>
<Banner
isOpen={!connected && authenticationStatus === "authenticated"}
onRequestClose={() => {}}
@ -126,7 +143,7 @@ function Game() {
</Box>
</Banner>
<AuthModal isOpen={authenticationStatus === "unauthenticated"} />
{authenticationStatus === "unknown" && <LoadingOverlay />}
{authenticationStatus === "unknown" && !offline && <LoadingOverlay />}
</MapStageProvider>
);
}