diff --git a/src/components/timer/Timer.tsx b/src/components/timer/Timer.tsx index fc4289ed..27b32e5f 100644 --- a/src/components/timer/Timer.tsx +++ b/src/components/timer/Timer.tsx @@ -1,14 +1,9 @@ -import { useEffect, useRef, useState } from "react"; -import { Solve } from "@/interfaces/Solve"; -import { TimerStatus } from "@/interfaces/TimerStatus"; -import genId from "@/lib/genId"; import { useTimerStore } from "@/store/timerStore"; -import addSolve from "@/lib/addSolve"; -import findCube from "@/lib/findCube"; import SolveOptions from "./SolveOptions"; import { useSettingsModalStore } from "@/store/SettingsModalStore"; import formatTime from "@/lib/formatTime"; import translation from "@/translations/global.json"; +import useTimer from "@/hooks/useTimer"; const timerStatusClasses = { idle: "light:text-neutral-900 dark:text-white", @@ -18,261 +13,9 @@ const timerStatusClasses = { }; export default function Timer() { - const { - selectedCube, - scramble, - setNewScramble, - setCubes, - setSelectedCube, - lastSolve, - setLastSolve, - solvingTime, - setSolvingTime, - isSolving, - setIsSolving, - } = useTimerStore(); - - const { settings, lang } = useSettingsModalStore(); - - const holdTimeRequired = settings.timer.holdToStart.status ? 500 : 0; - const [timerStatus, setTimerStatus] = useState("idle"); - const endTimeRef = useRef(0); - const holdingTimeRef = useRef(0); - const startTime = useRef(0); - const runningTimeId = useRef(null); - const isHolding = useRef(false); - const isReleased = useRef(true); - const hideWhileSolving = settings.features.hideWhileSolving.status; - - const handleHold = (event: KeyboardEvent) => { - if ((selectedCube && event.code === "Space") || event.code === "Escape") { - if (event.code === "Escape") { - clearInterval(runningTimeId.current); - setIsSolving(false); - isReleased.current = false; - startTime.current = 0; - holdingTimeRef.current = 0; - setLastSolve(null); - setTimerStatus("idle"); - setSolvingTime(0); - return; - } - - if (isSolving) { - clearInterval(runningTimeId.current); - setIsSolving(false); - isReleased.current = false; - - if (selectedCube && scramble) { - const lastSolve: Solve = { - id: genId(), - startTime: startTime.current, - endTime: endTimeRef.current, - scramble: scramble, - bookmark: false, - time: solvingTime, - dnf: false, - plus2: false, - rating: Math.floor(Math.random() * 20) + scramble.length, - category: selectedCube.category, - cubeId: selectedCube.id, - }; - - setLastSolve(lastSolve); - - if (selectedCube) { - const newCubes = addSolve({ - cubeId: selectedCube.id, - solve: lastSolve, - }); - - setCubes(newCubes); - - const currentCube = findCube({ cubeId: selectedCube.id }); - - if (currentCube) setSelectedCube(currentCube); - } - - setNewScramble(selectedCube); - } - - startTime.current = 0; - holdingTimeRef.current = 0; - setTimerStatus("idle"); - return; - } - - const now = Date.now(); - const difference = now - holdingTimeRef.current; - - if (!isReleased.current) return; - - if (!isHolding.current) { - holdingTimeRef.current = now; - isHolding.current = true; - - if (settings.timer.holdToStart.status) { - setTimerStatus("holdingKey"); - } else { - setTimerStatus("ready"); - } - } else { - if (difference >= holdTimeRequired) { - setTimerStatus("ready"); - } - } - } - }; - - const handleRelease = (event: KeyboardEvent) => { - if (event.code === "Space" || event.code === "Escape") { - isReleased.current = true; - if (event.code === "Escape") return; - - const now = Date.now(); - const difference: number = now - holdingTimeRef.current; - - if (isHolding.current && !isSolving) { - if (difference >= holdTimeRequired) { - setIsSolving(true); - isHolding.current = false; - holdingTimeRef.current = 0; - startTime.current = Date.now(); - runningTimeId.current = setInterval(() => { - endTimeRef.current = Date.now(); - setSolvingTime(endTimeRef.current - (startTime.current || 0)); - }); - setTimerStatus("solving"); - return; - } - - if (difference <= holdTimeRequired) { - setIsSolving(false); - isHolding.current = false; - holdingTimeRef.current = 0; - setTimerStatus("idle"); - return; - } - } - } - }; - - const handleTouchStart = (event: any) => { - event.preventDefault(); - if (isSolving) { - clearInterval(runningTimeId.current); - setIsSolving(false); - isReleased.current = false; - - if (selectedCube && scramble) { - const lastSolve: Solve = { - id: genId(), - startTime: startTime.current, - endTime: endTimeRef.current, - scramble: scramble, - bookmark: false, - time: solvingTime, - dnf: false, - plus2: false, - rating: Math.floor(Math.random() * 20) + scramble.length, - category: selectedCube.category, - cubeId: selectedCube.id, - }; - - setLastSolve(lastSolve); - - if (selectedCube) { - const newCubes = addSolve({ - cubeId: selectedCube.id, - solve: lastSolve, - }); - - setCubes(newCubes); - - const currentCube = findCube({ cubeId: selectedCube.id }); - - if (currentCube) setSelectedCube(currentCube); - } - - setNewScramble(selectedCube); - } - - startTime.current = 0; - holdingTimeRef.current = 0; - setTimerStatus("idle"); - } - const now = Date.now(); - const difference = now - holdingTimeRef.current; - - if (!isReleased.current) return; - - console.log("asdawsa"); - - if (!isHolding.current) { - holdingTimeRef.current = now; - isHolding.current = true; - - if (settings.timer.holdToStart.status) { - setTimerStatus("holdingKey"); - } else { - setTimerStatus("ready"); - } - } else { - if (difference >= holdTimeRequired) { - setTimerStatus("ready"); - } - } - }; - - const handleTouchEnd = (event: any) => { - event.preventDefault(); - isReleased.current = true; - - const now = Date.now(); - const difference: number = now - holdingTimeRef.current; - - if (isHolding.current && !isSolving) { - if (difference >= holdTimeRequired) { - setIsSolving(true); - isHolding.current = false; - holdingTimeRef.current = 0; - startTime.current = Date.now(); - runningTimeId.current = setInterval(() => { - endTimeRef.current = Date.now(); - setSolvingTime(endTimeRef.current - (startTime.current || 0)); - }); - setTimerStatus("solving"); - return; - } - - if (difference <= holdTimeRequired) { - setIsSolving(false); - isHolding.current = false; - holdingTimeRef.current = 0; - setTimerStatus("idle"); - return; - } - } - }; - - useEffect(() => { - window.addEventListener("keydown", handleHold); - window.addEventListener("keyup", handleRelease); - const touchElements = document.querySelectorAll("#touch"); - - touchElements.forEach((element) => { - element.addEventListener("touchstart", handleTouchStart); - element.addEventListener("touchend", handleTouchEnd); - }); - return () => { - window.removeEventListener("keydown", handleHold); - window.removeEventListener("keyup", handleRelease); - touchElements.forEach((element) => { - element.removeEventListener("touchstart", handleTouchStart); - element.removeEventListener("touchend", handleTouchEnd); - }); - }; - }); + const { lang, settings } = useSettingsModalStore(); + const { selectedCube, isSolving, lastSolve } = useTimerStore(); + const { timerStatus, hideWhileSolving, solvingTime } = useTimer(); if (selectedCube === null) return; diff --git a/src/hooks/useClick.ts b/src/hooks/useClick.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/hooks/useTimer.ts b/src/hooks/useTimer.ts new file mode 100644 index 00000000..4f40078e --- /dev/null +++ b/src/hooks/useTimer.ts @@ -0,0 +1,190 @@ +import { Solve } from "@/interfaces/Solve"; +import { TimerStatus } from "@/interfaces/TimerStatus"; +import addSolve from "@/lib/addSolve"; +import findCube from "@/lib/findCube"; +import genId from "@/lib/genId"; +import { useSettingsModalStore } from "@/store/SettingsModalStore"; +import { useTimerStore } from "@/store/timerStore"; +import { useEffect, useRef, useState } from "react"; + +export default function useTimer() { + const { + selectedCube, + scramble, + setNewScramble, + setCubes, + setSelectedCube, + setLastSolve, + solvingTime, + setSolvingTime, + isSolving, + setIsSolving, + } = useTimerStore(); + + const { settings } = useSettingsModalStore(); + + const holdTimeRequired = settings.timer.holdToStart.status ? 500 : 0; + const [timerStatus, setTimerStatus] = useState("idle"); + const endTimeRef = useRef(0); + const holdingTimeRef = useRef(0); + const startTime = useRef(0); + const runningTimeId = useRef(null); + const isHolding = useRef(false); + const isReleased = useRef(true); + const hideWhileSolving = settings.features.hideWhileSolving.status; + + function holding() { + if (isSolving) { + clearInterval(runningTimeId.current); + setIsSolving(false); + isReleased.current = false; + + if (selectedCube && scramble) { + const lastSolve: Solve = { + id: genId(), + startTime: startTime.current, + endTime: endTimeRef.current, + scramble: scramble, + bookmark: false, + time: solvingTime, + dnf: false, + plus2: false, + rating: Math.floor(Math.random() * 20) + scramble.length, + category: selectedCube.category, + cubeId: selectedCube.id, + }; + + setLastSolve(lastSolve); + + if (selectedCube) { + const newCubes = addSolve({ + cubeId: selectedCube.id, + solve: lastSolve, + }); + + setCubes(newCubes); + + const currentCube = findCube({ cubeId: selectedCube.id }); + + if (currentCube) setSelectedCube(currentCube); + } + + setNewScramble(selectedCube); + } + + startTime.current = 0; + holdingTimeRef.current = 0; + setTimerStatus("idle"); + return; + } + + const now = Date.now(); + const difference = now - holdingTimeRef.current; + + if (!isReleased.current) return; + + if (!isHolding.current) { + holdingTimeRef.current = now; + isHolding.current = true; + + if (settings.timer.holdToStart.status) { + setTimerStatus("holdingKey"); + } else { + setTimerStatus("ready"); + } + } else { + if (difference >= holdTimeRequired) { + setTimerStatus("ready"); + } + } + } + + function releasing() { + const now = Date.now(); + const difference: number = now - holdingTimeRef.current; + + if (isHolding.current && !isSolving) { + if (difference >= holdTimeRequired) { + setIsSolving(true); + isHolding.current = false; + holdingTimeRef.current = 0; + startTime.current = Date.now(); + runningTimeId.current = setInterval(() => { + endTimeRef.current = Date.now(); + setSolvingTime(endTimeRef.current - (startTime.current || 0)); + }); + setTimerStatus("solving"); + return; + } + + if (difference <= holdTimeRequired) { + setIsSolving(false); + isHolding.current = false; + holdingTimeRef.current = 0; + setTimerStatus("idle"); + return; + } + } + } + + const handleHold = (event: KeyboardEvent) => { + if ((selectedCube && event.code === "Space") || event.code === "Escape") { + if (event.code === "Escape") { + clearInterval(runningTimeId.current); + setIsSolving(false); + isReleased.current = false; + startTime.current = 0; + holdingTimeRef.current = 0; + setLastSolve(null); + setTimerStatus("idle"); + setSolvingTime(0); + return; + } + holding(); + } + }; + + const handleRelease = (event: KeyboardEvent) => { + if (event.code === "Space" || event.code === "Escape") { + isReleased.current = true; + if (event.code === "Escape") return; + releasing(); + } + }; + + const handleTouchStart = (event: any) => { + event.preventDefault(); + holding(); + }; + + const handleTouchEnd = (event: any) => { + event.preventDefault(); + isReleased.current = true; + releasing(); + }; + + useEffect(() => { + window.addEventListener("keydown", handleHold); + window.addEventListener("keyup", handleRelease); + const touchElements = document.querySelectorAll("#touch"); + + touchElements.forEach((element) => { + element.addEventListener("touchstart", handleTouchStart); + element.addEventListener("touchend", handleTouchEnd); + }); + return () => { + window.removeEventListener("keydown", handleHold); + window.removeEventListener("keyup", handleRelease); + touchElements.forEach((element) => { + element.removeEventListener("touchstart", handleTouchStart); + element.removeEventListener("touchend", handleTouchEnd); + }); + }; + }); + + return { + timerStatus, + hideWhileSolving, + solvingTime, + }; +}