181 lines
5.2 KiB
JavaScript
181 lines
5.2 KiB
JavaScript
import React, { useEffect } from "react";
|
|
import { Flex, Box, Text } from "theme-ui";
|
|
import SimpleBar from "simplebar-react";
|
|
|
|
import AddPartyMemberButton from "./AddPartyMemberButton";
|
|
import Nickname from "./Nickname";
|
|
import ChangeNicknameButton from "./ChangeNicknameButton";
|
|
import StartStreamButton from "./StartStreamButton";
|
|
import SettingsButton from "../SettingsButton";
|
|
import StartTimerButton from "./StartTimerButton";
|
|
import Timer from "./Timer";
|
|
import DiceTrayButton from "./DiceTrayButton";
|
|
|
|
import useSetting from "../../hooks/useSetting";
|
|
|
|
import { useParty } from "../../contexts/PartyContext";
|
|
import { usePlayerState, usePlayerUpdater } from "../../contexts/PlayerContext";
|
|
|
|
function Party({ gameId, stream, partyStreams, onStreamStart, onStreamEnd }) {
|
|
const setPlayerState = usePlayerUpdater();
|
|
const playerState = usePlayerState();
|
|
const partyState = useParty();
|
|
|
|
const [fullScreen] = useSetting("map.fullScreen");
|
|
const [shareDice, setShareDice] = useSetting("dice.shareDice");
|
|
|
|
function handleTimerStart(newTimer) {
|
|
setPlayerState((prevState) => ({ ...prevState, timer: newTimer }));
|
|
}
|
|
|
|
function handleTimerStop() {
|
|
setPlayerState((prevState) => ({ ...prevState, timer: null }));
|
|
}
|
|
|
|
useEffect(() => {
|
|
let prevTime = performance.now();
|
|
let request = requestAnimationFrame(update);
|
|
let counter = 0;
|
|
function update(time) {
|
|
request = requestAnimationFrame(update);
|
|
const deltaTime = time - prevTime;
|
|
prevTime = time;
|
|
|
|
if (playerState.timer) {
|
|
counter += deltaTime;
|
|
// Update timer every second
|
|
if (counter > 1000) {
|
|
const newTimer = {
|
|
...playerState.timer,
|
|
current: playerState.timer.current - counter,
|
|
};
|
|
if (newTimer.current < 0) {
|
|
setPlayerState((prevState) => ({ ...prevState, timer: null }));
|
|
} else {
|
|
setPlayerState((prevState) => ({ ...prevState, timer: newTimer }));
|
|
}
|
|
counter = 0;
|
|
}
|
|
}
|
|
}
|
|
return () => {
|
|
cancelAnimationFrame(request);
|
|
};
|
|
}, [playerState.timer, setPlayerState]);
|
|
|
|
function handleNicknameChange(newNickname) {
|
|
setPlayerState((prevState) => ({ ...prevState, nickname: newNickname }));
|
|
}
|
|
|
|
function handleDiceRollsChange(newDiceRolls) {
|
|
setPlayerState(
|
|
(prevState) => ({
|
|
...prevState,
|
|
dice: { share: shareDice, rolls: newDiceRolls },
|
|
}),
|
|
shareDice
|
|
);
|
|
}
|
|
|
|
function handleShareDiceChange(newShareDice) {
|
|
setShareDice(newShareDice);
|
|
setPlayerState((prevState) => ({
|
|
...prevState,
|
|
dice: { ...prevState.dice, share: newShareDice },
|
|
}));
|
|
}
|
|
|
|
return (
|
|
<Box
|
|
bg="background"
|
|
sx={{
|
|
position: "relative",
|
|
// width: fullScreen ? "0" : "112px",
|
|
// minWidth: fullScreen ? "0" : "112px",
|
|
}}
|
|
>
|
|
<Box
|
|
sx={{
|
|
flexDirection: "column",
|
|
overflow: "visible",
|
|
alignItems: "center",
|
|
height: "100%",
|
|
display: fullScreen ? "none" : "flex",
|
|
width: "112px",
|
|
minWidth: "112px",
|
|
}}
|
|
p={3}
|
|
>
|
|
<Box
|
|
sx={{
|
|
width: "100%",
|
|
}}
|
|
>
|
|
<Text mb={1} variant="heading" as="h1">
|
|
Party
|
|
</Text>
|
|
</Box>
|
|
<SimpleBar
|
|
style={{
|
|
flexGrow: 1,
|
|
width: "100%",
|
|
minWidth: "112px",
|
|
padding: "0 16px",
|
|
height: "calc(100% - 232px)",
|
|
}}
|
|
>
|
|
<Nickname
|
|
nickname={`${playerState.nickname} (you)`}
|
|
diceRolls={shareDice && playerState.dice.rolls}
|
|
/>
|
|
{Object.entries(partyState).map(([id, { nickname, dice }]) => (
|
|
<Nickname
|
|
nickname={nickname}
|
|
key={id}
|
|
stream={partyStreams[id]}
|
|
diceRolls={dice.share && dice.rolls}
|
|
/>
|
|
))}
|
|
{playerState.timer && <Timer timer={playerState.timer} index={0} />}
|
|
{Object.entries(partyState)
|
|
.filter(([_, { timer }]) => timer)
|
|
.map(([id, { timer }], index) => (
|
|
<Timer
|
|
timer={timer}
|
|
key={id}
|
|
// Put party timers above your timer if there is one
|
|
index={playerState.timer ? index + 1 : index}
|
|
/>
|
|
))}
|
|
</SimpleBar>
|
|
<Flex sx={{ flexDirection: "column" }}>
|
|
<ChangeNicknameButton
|
|
nickname={playerState.nickname}
|
|
onChange={handleNicknameChange}
|
|
/>
|
|
<AddPartyMemberButton gameId={gameId} />
|
|
<StartStreamButton
|
|
onStreamStart={onStreamStart}
|
|
onStreamEnd={onStreamEnd}
|
|
stream={stream}
|
|
/>
|
|
<StartTimerButton
|
|
onTimerStart={handleTimerStart}
|
|
onTimerStop={handleTimerStop}
|
|
timer={playerState.timer}
|
|
/>
|
|
<SettingsButton />
|
|
</Flex>
|
|
</Box>
|
|
<DiceTrayButton
|
|
shareDice={shareDice}
|
|
onShareDiceChage={handleShareDiceChange}
|
|
diceRolls={(playerState.dice && playerState.dice.rolls) || []}
|
|
onDiceRollsChange={handleDiceRollsChange}
|
|
/>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
export default Party;
|