diff --git a/src/components/party/Party.js b/src/components/party/Party.js index 1caeb36..3578dd5 100644 --- a/src/components/party/Party.js +++ b/src/components/party/Party.js @@ -17,8 +17,10 @@ function Party({ partyStreams, onStreamStart, onStreamEnd, + timer, + partyTimers, onTimerStart, - onTimerEnd, + onTimerStop, }) { return ( - + diff --git a/src/components/party/StartTimerButton.js b/src/components/party/StartTimerButton.js index 2782647..266ba6f 100644 --- a/src/components/party/StartTimerButton.js +++ b/src/components/party/StartTimerButton.js @@ -4,7 +4,7 @@ import { IconButton } from "theme-ui"; import StartTimerModal from "../../modals/StartTimerModal"; import StartTimerIcon from "../../icons/StartTimerIcon"; -function StartTimerButton() { +function StartTimerButton({ onTimerStart, onTimerStop, timer }) { const [isTimerModalOpen, setIsTimerModalOpen] = useState(false); function openModal() { @@ -24,7 +24,13 @@ function StartTimerButton() { > - + ); } diff --git a/src/modals/StartTimerModal.js b/src/modals/StartTimerModal.js index 1af6c55..ddfd7e5 100644 --- a/src/modals/StartTimerModal.js +++ b/src/modals/StartTimerModal.js @@ -3,7 +3,13 @@ import { Box, Label, Input, Button, Flex, Text } from "theme-ui"; import Modal from "../components/Modal"; -function StartTimerModal({ isOpen, onRequestClose }) { +function StartTimerModal({ + isOpen, + onRequestClose, + onTimerStart, + onTimerStop, + timer, +}) { const inputRef = useRef(); function focusInput() { inputRef.current && inputRef.current.focus(); @@ -15,6 +21,11 @@ function StartTimerModal({ isOpen, onRequestClose }) { function handleSubmit(event) { event.preventDefault(); + if (timer) { + onTimerStop(); + } else { + onTimerStart({ hour, minute, second }); + } } const inputStyle = { @@ -59,9 +70,10 @@ function StartTimerModal({ isOpen, onRequestClose }) { setHour(parseValue(e.target.value, 24))} type="number" + disabled={timer} min={0} max={24} /> @@ -70,10 +82,11 @@ function StartTimerModal({ isOpen, onRequestClose }) { setMinute(parseValue(e.target.value, 59))} type="number" ref={inputRef} + disabled={timer} min={0} max={59} /> @@ -82,9 +95,10 @@ function StartTimerModal({ isOpen, onRequestClose }) { setSecond(parseValue(e.target.value, 59))} type="number" + disabled={timer} min={0} max={59} /> @@ -94,7 +108,7 @@ function StartTimerModal({ isOpen, onRequestClose }) { sx={{ flexGrow: 1 }} disabled={hour === 0 && minute === 0 && second === 0} > - Start Timer + {timer ? "Stop Timer" : "Start Timer"} diff --git a/src/network/NetworkedParty.js b/src/network/NetworkedParty.js index 68bd59a..0152160 100644 --- a/src/network/NetworkedParty.js +++ b/src/network/NetworkedParty.js @@ -23,10 +23,12 @@ function NetworkedParty({ gameId, session }) { const [partyNicknames, setPartyNicknames] = useState({}); const [stream, setStream] = useState(null); const [partyStreams, setPartyStreams] = useState({}); + const [timer, setTimer] = useState(null); + const [partyTimers, setPartyTimers] = useState({}); - function handleNicknameChange(nickname) { - setNickname(nickname); - session.send("nickname", { [session.id]: nickname }); + function handleNicknameChange(newNickname) { + setNickname(newNickname); + session.send("nickname", { [session.id]: newNickname }); } function handleStreamStart(localStream) { @@ -59,16 +61,57 @@ function NetworkedParty({ gameId, session }) { [session] ); + function handleTimerStart(newTimer) { + setTimer(newTimer); + session.send("timer", { [session.id]: newTimer }); + } + + function handleTimerStop() { + setTimer(null); + session.send("timer", { [session.id]: null }); + } + + useEffect(() => { + function decreaseTimer(previousTimer) { + if (previousTimer.second > 0) { + return { ...previousTimer, second: previousTimer.second - 1 }; + } else if (previousTimer.minute > 0) { + return { + ...previousTimer, + minute: previousTimer.minute - 1, + second: 59, + }; + } else if (previousTimer.hour > 0) { + return { hour: previousTimer.hour - 1, minute: 59, second: 59 }; + } else return { hour: 0, minute: 0, second: 0 }; + } + function updateTimers() { + if (timer) { + const newTimer = decreaseTimer(timer); + setTimer(newTimer); + session.send("timer", { [session.id]: newTimer }); + } + } + const interval = setInterval(updateTimers, 1000); + return () => { + clearInterval(interval); + }; + }, [timer, session]); + useEffect(() => { function handlePeerConnect({ peer, reply }) { reply("nickname", { [session.id]: nickname }); if (stream) { peer.connection.addStream(stream); } + if (timer) { + reply("timer", { [session.id]: timer }); + } } function handlePeerDisconnect({ peer }) { setPartyNicknames((prevNicknames) => omit(prevNicknames, [peer.id])); + setPartyTimers((prevTimers) => omit(prevTimers, [peer.id])); } function handlePeerData({ id, data }) { @@ -78,6 +121,12 @@ function NetworkedParty({ gameId, session }) { ...data, })); } + if (id === "timer") { + setPartyTimers((prevTimers) => ({ + ...prevTimers, + ...data, + })); + } } function handlePeerTrackAdded({ peer, stream: remoteStream }) { @@ -111,7 +160,7 @@ function NetworkedParty({ gameId, session }) { session.off("trackAdded", handlePeerTrackAdded); session.off("trackRemoved", handlePeerTrackRemoved); }; - }, [session, nickname, stream]); + }, [session, nickname, stream, timer]); useEffect(() => { if (stream) { @@ -139,6 +188,10 @@ function NetworkedParty({ gameId, session }) { partyNicknames={partyNicknames} stream={stream} partyStreams={partyStreams} + timer={timer} + partyTimers={partyTimers} + onTimerStart={handleTimerStart} + onTimerStop={handleTimerStop} /> ); }