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}
/>
);
}