SocketIOWrapper

master
Wilco Kruijer 4 years ago
parent 509b1cfdc5
commit 8482deb7e5
  1. 4
      backend/src/Lobby.js
  2. 4
      backend/src/index.js
  3. 67
      frontend/src/App.tsx
  4. 79
      frontend/src/Wrapper.tsx
  5. 40
      frontend/src/components/Feed.tsx
  6. 59
      frontend/src/components/Lobby.tsx
  7. 42
      frontend/src/components/NextShot.tsx
  8. 23
      frontend/src/components/ShotsTaken.tsx
  9. 19
      frontend/src/util/socket.ts

@ -67,10 +67,6 @@ module.exports = class Lobby {
setTimeout(doTick, Math.floor(waitTime / this.speedFactor));
};
if (false) {
this.seek(ioLobby, 500);
}
doTick();
}

@ -40,10 +40,6 @@ io.on('connection', socket => {
socket.join(lobby.name);
if (lobby.running) {
socket.emit('seek', lobby.currentSeconds);
}
callback(null, {
status: 'ok',
lobby: lobby

@ -1,68 +1,13 @@
import React, {useEffect, useRef, useState} from 'react';
import React from 'react';
import './App.sass';
import logo from "./via-logo.svg"
import {Row} from "antd"
import socket from "./util/socket";
import NextShot from "./components/NextShot";
import ShotsTaken from "./components/ShotsTaken";
import Feed from "./components/Feed";
import Lobby from "./components/Lobby";
import {Tick} from "./types/types";
import {SocketIOProvider} from "use-socketio/lib";
import Wrapper from "./Wrapper";
const App = () => {
const [started, setStarted] = useState(false);
const player = useRef(new Audio("centurion.m4a"));
useEffect(() => {
socket.on('started', async () => {
setStarted(true);
await player.current.play();
// player.current.volume = 0;
});
socket.on('seek', async (sec: number) => {
if (player.current.paused) {
await player.current.play();
}
socket.once("tick_event", (tick: Tick) => {
// Wait till the next tick to actually start so we more closely match the leader's sound
setStarted(true);
player.current.currentTime = tick.current
});
});
return () => {
socket.off("started");
socket.off("seek");
}
});
const feedContent = (
<Row>
<NextShot/>
<Feed/>
<ShotsTaken/>
</Row>
);
const lobbyContent = (
<Lobby/>
);
const content = started ? feedContent : lobbyContent;
return (
<>
<section className="content">
{content}
</section>
<footer>
<img src={logo} className="via-logo" alt="logo"/>
</footer>
</>
<SocketIOProvider url={window.location.protocol + "//" + window.location.hostname}>
<Wrapper/>
</SocketIOProvider>
);
};

@ -0,0 +1,79 @@
import React, {useEffect, useRef, useState} from "react";
import {Row} from "antd";
import NextShot from "./components/NextShot";
import Feed from "./components/Feed";
import ShotsTaken from "./components/ShotsTaken";
import Lobby from "./components/Lobby";
import {useSocket} from "use-socketio";
import logo from "./via-logo.svg";
import {Tick} from "./types/types";
import {NumberParam, useQueryParam} from "use-query-params";
const Wrapper = () => {
const [started, setStarted] = useState(false);
const [wantsToStart, setWantsToStart] = useState(false);
const player = useRef(new Audio("centurion.m4a"));
const [noSound] = useQueryParam('noSound', NumberParam);
function goStart() {
console.log("Starting from wrapper..");
setWantsToStart(true);
}
const {socket} = useSocket("started", async (obj: any) => {
console.log("got started");
setStarted(true);
if (typeof noSound === 'undefined') {
await player.current.play();
}
});
useEffect(() => {
if (noSound === 1) {
// Won't play sound so we don't get DOM Interaction errors.
setWantsToStart(true);
}
}, []);
useSocket("tick_event", async (tick: Tick) => {
if (!started && wantsToStart) {
if (player.current.paused) {
if (typeof noSound === 'undefined') {
await player.current.play();
}
}
setStarted(true);
player.current.currentTime = tick.current;
}
});
const feedContent = (
<Row>
<NextShot/>
<Feed/>
<ShotsTaken/>
</Row>
);
const lobbyContent = (
<Lobby start={goStart}/>
);
const content = started ? feedContent : lobbyContent;
return (
<>
<section className="content">
{content}
</section>
<footer>
<img src={logo} className="via-logo" alt="logo"/>
</footer>
</>
);
};
export default Wrapper;

@ -1,11 +1,11 @@
import React, {useEffect, useState} from 'react';
import React, {useState} from 'react';
import {Col, Timeline} from "antd"
import socket from "../util/socket";
import {Tick, TimestampEvent} from "../types/types";
import shot from "../img/shot.png";
import song from "../img/song.png";
import talk from "../img/talk.png";
import time from "../img/time.png";
import {useSocket} from "use-socketio/lib";
const images = {
shot, song, talk, time
@ -18,32 +18,26 @@ interface Event extends TimestampEvent {
const Feed = () => {
const [feedItems, setFeedItems] = useState<Event[]>([]);
useEffect(() => {
socket.on("tick_event", (tick: Tick) => {
if (!tick.next) {
return;
}
if (tick.current === tick.next.timestamp) {
// Current tick is a new event.
useSocket("tick_event", async (tick: Tick) => {
if (!tick.next) {
return;
}
const newItems: any[] = [];
for (let i = 0; i < feedItems.length; i++) {
newItems.push(feedItems[i]);
}
for (let j = 0; j < tick.next.events.length; j++) {
newItems.push(tick.next.events[j]);
}
if (tick.current === tick.next.timestamp) {
// Current tick is a new event.
// @ts-ignore
// setFeedItems(newItems);
const newItems: any[] = [];
for (let i = 0; i < feedItems.length; i++) {
newItems.push(feedItems[i]);
}
for (let j = 0; j < tick.next.events.length; j++) {
newItems.push(tick.next.events[j]);
}
});
return () => {
socket.off("tick_event");
// @ts-ignore
// setFeedItems(newItems);
}
}, [feedItems]);
});
return (
// <Col className="feed" span={16}>

@ -1,47 +1,50 @@
import React, {useEffect, useState} from 'react';
import React, {useEffect, useRef, useState} from 'react';
import {Card, Col, InputNumber, Row} from "antd"
import socket, {emit} from "../util/socket";
import {emit} from "../util/socket";
import "../css/lobby.sass";
import beer from "../img/beer.png"
import {NumberParam, useQueryParam} from 'use-query-params';
import {useSocket} from "use-socketio/lib";
const Lobby = () => {
const Lobby = (props: any) => {
const [lobbyId, setLobbyId] = useQueryParam('lobby', NumberParam);
const [isLeader, setIsLeader] = useState(false);
const [isRunning, setIsRunning] = useState(false);
const [seekTime, setSeekTime] = useState(0);
const [userCount, setUserCount] = useState(0);
const {socket} = useSocket("welcome", async (obj: any) => {
if (lobbyId) {
// lobbyId is already defined, this means we have a queryparam set.
await onChangeLobbyInput(lobbyId);
return;
}
console.log("Got welcome", lobbyId);
setLobbyId(obj.lobby.name);
setIsLeader(socket.id === obj.lobby.leaderId);
setUserCount(obj.lobby.users?.length || 0);
});
const socketRef = useRef<SocketIOClient.Socket>(socket);
async function onChangeLobbyInput(i: any) {
setLobbyId(i);
const result: any = await emit('join_lobby', i);
const result: any = await emit(socket,'join_lobby', i);
setIsLeader(socket.id === result.lobby.leaderId);
setUserCount(result.lobby.users?.length || 0);
setIsRunning(result.lobby.running);
}
useEffect(() => {
socket.on('welcome', async (obj: any) => {
if (lobbyId) {
// lobbyId is already defined, this means we have a queryparam set.
await onChangeLobbyInput(lobbyId);
return;
}
console.log("Got welcome", lobbyId);
setLobbyId(obj.lobby.name);
setIsLeader(socket.id === obj.lobby.leaderId);
setUserCount(obj.lobby.users?.length || 0);
});
return () => {
socket.off("welcome");
}
});
useEffect(() => {
async function wrapper() {
const result: any = await emit('lobby_info');
setIsLeader(socket.id === result.lobby.leaderId);
const result: any = await emit(socketRef.current,'lobby_info');
setIsLeader(socketRef.current.id === result.lobby.leaderId);
setUserCount(result.lobby.users?.length || 0);
setIsRunning(result.lobby.running);
console.log("Got lobby_info");
}
wrapper();
@ -59,7 +62,9 @@ const Lobby = () => {
<div className="lobby">
<Row>
<Col span={24}>
<h1 id="centurion-title">Centurion! <img src={beer} className="beer" alt="beer"/></h1>
<h1 id="centurion-title">
<img src={beer} className="beer" alt="beer"/>Centurion!
<img src={beer} className="beer" alt="beer"/></h1>
</Col>
</Row>
<Row>
@ -73,9 +78,9 @@ const Lobby = () => {
<Col className="control" span={8} offset={8}>
<Card title={`Lobby setup (${lobbyId}):`} actions={isLeader ? [
<span onClick={async () => {
await emit('request_start', seekTime)
await emit(socket,'request_start', seekTime)
}}>Start</span>,
] : []}>
] : [<span onClick={props.start}>Join</span>]}>
<span>
Huidige lobby <InputNumber size="small" min={100} max={100000} value={lobbyId}
onChange={onChangeLobbyInput}/>

@ -1,7 +1,7 @@
import React, {useEffect, useRef, useState} from 'react';
import {Col, Progress} from "antd"
import socket from "../util/socket";
import {Tick} from "../types/types";
import {useSocket} from "use-socketio/lib";
const NextShot = () => {
@ -9,34 +9,28 @@ const NextShot = () => {
const [remainingPercentage, setRemainingPercentage] = useState(100);
const fullTime = useRef(0);
useEffect(() => {
socket.on("tick_event", (tick: Tick) => {
if (!tick.nextShot || !tick.next) {
setRemaining(0);
return;
}
if (fullTime.current === 0) {
fullTime.current = tick.nextShot.timestamp - tick.current;
}
useSocket("tick_event", async (tick: Tick) => {
if (!tick.nextShot || !tick.next) {
setRemaining(0);
return;
}
const shotEvent = tick.next.events.find(e => e.type === 'shot');
if (fullTime.current === 0) {
fullTime.current = tick.nextShot.timestamp - tick.current;
}
if (shotEvent && tick.current === tick.next.timestamp) {
fullTime.current = 0;
}
const shotEvent = tick.next.events.find(e => e.type === 'shot');
const timeRemaining = tick.nextShot.timestamp - tick.current;
if (shotEvent && tick.current === tick.next.timestamp) {
fullTime.current = 0;
}
setRemaining(timeRemaining);
// Fix divide by zero (.. || 1)
setRemainingPercentage(Math.ceil(timeRemaining / (fullTime.current || 1) * 100));
});
const timeRemaining = tick.nextShot.timestamp - tick.current;
return () => {
socket.off("tick_event");
}
}, []);
setRemaining(timeRemaining);
// Fix divide by zero (.. || 1)
setRemainingPercentage(Math.ceil(timeRemaining / (fullTime.current || 1) * 100));
});
return (
<Col className="sider" span={4}>

@ -1,26 +1,21 @@
import React, {useEffect, useRef, useState} from 'react';
import React, {useState} from 'react';
import {Col, Progress} from "antd"
import socket from "../util/socket";
import {Tick} from "../types/types";
import {useSocket} from "use-socketio/lib";
const ShotsTaken = () => {
const [taken, setTaken] = useState(100);
useEffect(() => {
socket.on("tick_event", (tick: Tick) => {
if (!tick.nextShot) {
setTaken(100);
return;
}
useSocket("tick_event", async (tick: Tick) => {
if (!tick.nextShot) {
setTaken(100);
return;
}
setTaken(tick.nextShot.count - 1);
});
setTaken(tick.nextShot.count - 1);
});
return () => {
socket.off("tick_event");
}
}, []);
return (
<Col className="sider" span={4}>

@ -1,7 +1,20 @@
import io from "socket.io-client";
// const socket = io(window.location.protocol + "//" + window.location.hostname + ":3001");
const socket = {
on: (...args: any[]) => {
},
once: (...args: any[]) => {
},
off: (...args: any[]) => {
},
id: '1'
};
const socket = io(window.location.protocol + "//" + window.location.hostname);
export default socket;
/**
@ -9,7 +22,7 @@ export default socket;
* @param event
* @param arg
*/
export function emit(event: string, arg: any = null) {
export function emit(socket: SocketIOClient.Socket, event: string, arg: any = null) {
return new Promise((resolve, reject) => {
const cb = (err: any, res: any) => {
if (err) {

Loading…
Cancel
Save