Kopie van https://gitlab.com/studieverenigingvia/ict/centurion met een paar aanpassingen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

313 lines
8.1 KiB

import { useState } from "react";
import {
Button,
Card,
Col,
Divider,
Form,
Input,
InputNumber,
Row,
Select,
Badge,
} from "antd";
import { red } from "@ant-design/colors";
import connection, {
useConfig,
useIsConnected,
useRoom,
useTimelineSongFileChanged,
} from "../lib/Connection";
import "../css/lobby.css";
import logo from "../img/via-logo.svg";
import haramlogo from "../img/harambee_logo.png";
import beer from "../img/beer.png";
import { RoomOptions } from "../types/types";
const { Option } = Select;
export interface PropType {
currentUserReady: boolean;
onCurrentUserReadyChange?: (ready: boolean) => void;
}
const Lobby = (props: PropType) => {
// Form/control states.
const [selectedRoomId, setSelectedRoomId] = useState(1);
const [seekTime, setSeekTime] = useState(0);
const [timelineName, setTimelineName] = useState(null);
const [joiningLobby, setJoiningLobby] = useState(false);
const [joinLobbyError, setJoinLobbyError] = useState(false);
const [isPreloading, setIsPreloading] = useState(false);
const timeline = useTimelineSongFileChanged();
// Room and logic states.
const isConnected = useIsConnected();
const room = useRoom();
const config = useConfig();
const isLeader = room?.isLeader || false;
const userCount = room?.userCount || 0;
async function handleJoin() {
await preloadAudio();
connection.requestSetReady();
props.onCurrentUserReadyChange?.(true);
}
async function applyRoomId(v: number) {
setJoiningLobby(true);
await connection.requestJoin(v);
setJoiningLobby(false);
setJoinLobbyError(!v);
}
function handleJoinRandomLobby() {
connection.requestJoinRandom();
setJoinLobbyError(false);
}
function handleTimelineNameSet(timelineName: any) {
setTimelineName(timelineName);
connection.setRoomOptions(
new RoomOptions(
seekTime * 1000 || 0,
timelineName || room?.timelineName || ""
)
);
}
function handleSetSeekTime(seekTime: number) {
setSeekTime(seekTime);
connection.setRoomOptions(
new RoomOptions(
seekTime * 1000 || 0,
timelineName || room?.timelineName || ""
)
);
}
function preloadAudio(): Promise<boolean> {
setIsPreloading(true);
const songFile = timeline?.songFile;
if (!songFile) {
return Promise.resolve(false);
}
return new Promise<boolean>((resolve) => {
const audioElement = new Audio();
audioElement.addEventListener("canplaythrough", () => {
// 'canplaythrough' means the browser thinks it has buffered enough to play
// until the end.
setIsPreloading(false);
resolve(true);
});
audioElement.src = songFile;
});
}
const leaderConfig = (
<Row justify="center">
<Col>
<Form
layout="horizontal"
labelCol={{ span: 8 }}
wrapperCol={{ span: 24 }}
>
<Form.Item label="Starttijd">
<Input
type="number"
suffix="sec"
value={seekTime}
onChange={(v) => handleSetSeekTime(parseInt(v.target.value) || 0)}
/>
</Form.Item>
<Form.Item label="Nummer">
<Select
defaultValue={(room && room.timelineName) || ""}
onChange={(e) => handleTimelineNameSet(e)}
>
{config &&
config.availableTimelines.map((item, i) => (
<Option key={item} value={item}>
{item}
</Option>
))}
</Select>
</Form.Item>
</Form>
<Button
block
type="primary"
loading={isPreloading}
onClick={handleJoin}
>
Start
</Button>
</Col>
</Row>
);
const nonLeaderConfig = (
<Row justify="center">
<Col>
<p>
{room?.running ? "We luisteren naar" : "We gaan luisteren naar"}{" "}
<b>{room && room.timelineName}</b> en
{room?.running && <span> zijn al gestart!</span>}
{!room?.running && (
<span> starten op {(room?.seekTime || 0) / 1000} seconden</span>
)}
</p>
<Button
block
type="primary"
disabled={!room || props.currentUserReady}
loading={isPreloading}
onClick={handleJoin}
>
{room && props.currentUserReady
? "Wachten op het startsein"
: "Kom erbij"}
</Button>
</Col>
</Row>
);
return (
<div className="lobby">
<Row className="centurion-title" justify="center">
<Col span={4} md={4}>
<img
src={beer}
className={`beer beer-flipped ${
isConnected ? "connected" : "connecting"
}`}
alt="beer"
/>
</Col>
<Col span={12} md={6}>
Centurion!
</Col>
<Col span={4} md={4}>
<img
src={beer}
className={`beer ${isConnected ? "connected" : "connecting"}`}
alt="beer"
/>
</Col>
</Row>
<Row>
<Col className="hints" span={24}>
<div>Honderd minuten...</div>
<div>Honderd shots...</div>
<div>Kun jij het aan?</div>
</Col>
</Row>
<br />
{!isConnected && (
<Row justify="center">
<Col className="lobby-connecting">
<h2>Verbinden...</h2>
</Col>
</Row>
)}
{isConnected && (
<Row justify="center">
<Col xs={24} sm={16} md={12} xl={10}>
<Card>
<h3>
Huidige lobby: <b>{room ? `#${room.id}` : "Geen lobby"}</b>
</h3>
{room && (
<Row>
{userCount === 1 ? (
<span>Er is één gebruiker aanwezig.</span>
) : (
<span>Er zijn {userCount} gebruikers aanwezig.</span>
)}
</Row>
)}
<Row justify="center">
{room?.users?.map((u) => (
<Badge
key={u.id}
status={u.readyToParticipate ? "success" : "error"}
/>
))}
</Row>
{room && <Row>Deel de link met je vrienden om mee te doen!</Row>}
<Divider />
{room && (isLeader ? leaderConfig : nonLeaderConfig)}
<Divider />
<Row justify="center">
<Col>
<InputNumber
style={{ width: "calc(100% - 150px)" }}
min={1}
max={100000}
value={selectedRoomId || room?.id || 0}
onChange={(v) => setSelectedRoomId(v || 0)}
/>
<Button
style={{ width: "150px" }}
type="primary"
loading={joiningLobby}
onClick={async () => {
await applyRoomId(selectedRoomId);
}}
>
Ga naar die lobby
</Button>
{joinLobbyError && (
<span style={{ color: red[4] }}>
Die lobby bestaat niet
</span>
)}
</Col>
</Row>
<Row justify="center">
<span className={"lobby-options-or"}>of</span>
</Row>
<Row justify="center">
<Col>
<Button
type="primary"
onClick={() => {
handleJoinRandomLobby();
}}
>
Join een nieuwe lobby
</Button>
</Col>
</Row>
</Card>
</Col>
</Row>
)}
<img src={haramlogo} className="haram-logo" alt="haramlogo"/>
<img src={logo} className="via-logo" alt="logo" />
</div>
);
};
export default Lobby;