diff --git a/package-lock.json b/package-lock.json index 76c2576..1b0d405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4190,26 +4190,6 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@testing-library/dom": { - "version": "10.4.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", - "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "picocolors": "1.1.1", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@testing-library/jest-dom": { "version": "5.17.0", "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", @@ -4377,13 +4357,6 @@ "node": ">=10.13.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "license": "MIT", - "peer": true - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -19503,20 +19476,6 @@ } } }, - "node_modules/tailwindcss/node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/tapable": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", @@ -20016,20 +19975,6 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", diff --git a/public/index.html b/public/index.html index 24639aa..9ea38f4 100644 --- a/public/index.html +++ b/public/index.html @@ -2,8 +2,7 @@
- - + diff --git a/src/App.js b/src/App.js index 8a14fa4..d3902cf 100644 --- a/src/App.js +++ b/src/App.js @@ -1,4 +1,21 @@ -// src/App.js +import { useEffect, useState, useMemo, useCallback, useRef } from "react"; +import { nanoid } from "nanoid"; +import "./App.css"; +import SingleCard from "./components/singlecard/SingleCard"; +import Celebration from "./components/celebration/Celebration"; +import ToggleTheme from "./components/toggleTheme/toggleTheme"; +import ShowConfetti from "./components/confetti/Confetti"; +import GameOver from "./components/gameover/GameOver"; +import CustomCursor from "./components/CustomCursor/CustomCursor"; + +import { cardImages } from "./data/cardImages"; +import { numbers } from "./constants/numbers"; +import { secureShuffleArray, pickRandomImages } from "./utils/logic"; +import { useHint } from "./utils/useHint"; + +const crypto = globalThis.crypto || globalThis.msCrypto; +import useTrackViewCounter from "./hooks/useTrackViewCounter"; + import { useEffect, useState, useMemo, useCallback, useRef } from 'react'; import { nanoid } from 'nanoid'; import './App.css'; @@ -25,12 +42,6 @@ function App() { const [celebrationStatus, setCelebrationStatus] = useState(false); const [elapsedTime, setElapsedTime] = useState(undefined); const intervalRef = useRef(null); - const hintTimeoutRef = useRef(null); - const hintIntervalRef = useRef(null); - const hintLockedRef = useRef(false); - const [hintCount, setHintCount] = useState(3); - const [hintCooldown, setHintCooldown] = useState(0); - const [hintActive, setHintActive] = useState(false); const [animateCollapse, setAnimateCollapse] = useState(false); const [gameOverMessage, setGameOverMessage] = useState(false); const viewCounter = useTrackViewCounter(); @@ -72,6 +83,21 @@ function App() { } }, []); + const { + hintCount, + hintCooldown, + hintActive, + hintCards, + resetHints, + } = useHint({ + cards, + handleTime, + setChoiceOne, + setChoiceTwo, + setTurns, + setDisabled, + }); + const clearTimer = useCallback(() => { if (intervalRef.current) { clearInterval(intervalRef.current); @@ -162,8 +188,12 @@ function App() { const selected = pickRandomImages(cardImages, 6); const dup = [...selected, ...selected] .sort(() => nanoid(16).localeCompare(nanoid(16))) + .map((card) => { + // const crypto = globalThis.crypto || globalThis.msCrypto; + .map(card => { const crypto = globalThis.crypto || globalThis.msCrypto; + const rand = new Uint32Array(1); crypto.getRandomValues(rand); return { ...card, id: rand[0], matched: false }; @@ -177,18 +207,20 @@ function App() { setMatched(0); setCelebrationStatus(false); setElapsedTime(undefined); - clearTimer(); + setAnimateCollapse(true); setTimeout(() => setAnimateCollapse(false), 1200); setGameOverMessage(false); - }, [clearTimer]); + }, []); const handleNewGame = useCallback(() => { + resetHints(); + playSound("audio/start.mp3"); setHintCount(3); setHintCooldown(0); playSound('audio/start.mp3'); shuffledCards(); - }, [playSound, shuffledCards]); + }, [playSound, shuffledCards, resetHints]); const handleChoice = useCallback( card => { @@ -219,7 +251,7 @@ function App() { } else if (choiceOne) { playSound('/audio/swap.wav'); } - }, [choiceOne, choiceTwo, resetTurn, playSound]); + }, [choiceOne, choiceTwo, resetTurn, playSound, hintActive]); useEffect(() => { if (matched === cards.length && turns) { @@ -250,18 +282,9 @@ function App() { setHighScore(hs); return () => { clearTimer(); - if (hintTimeoutRef.current) { - clearTimeout(hintTimeoutRef.current); - hintTimeoutRef.current = null; - } - if (hintIntervalRef.current) { - clearInterval(hintIntervalRef.current); - hintIntervalRef.current = null; - } - hintLockedRef.current = false; - setHintCooldown(0); + resetHints(); }; - }, [shuffledCards, clearTimer]); + }, [shuffledCards, clearTimer, resetHints]); return (
+ {hintCount === 1 ? "Hint Remaining: " : "Hints Remaining: "}