Challenge start overlay style/function, gameclock bug fixes

This commit is contained in:
Gene Mecija 2020-02-04 13:38:22 -08:00
parent 77dbbc09e9
commit 2b15d7c04b
12 changed files with 424 additions and 75 deletions

View file

@ -23,6 +23,8 @@ import Footer from './components/Footer';
import Info from './components/Info';
import { GameClockContextProvider } from './contexts/gameClockContext';
import ChallengeOverlay from './components/ChallengeOverlay';
import { KeyTypeContextProvider } from './contexts/keyTypeContext';
import { WPMContextProvider } from './contexts/wpmContext';
export default React.memo(function App() {
@ -34,9 +36,12 @@ export default React.memo(function App() {
<>
<Header />
<div id='main-content'>
<KeyTypeContextProvider>
<WPMContextProvider>
<MorseBufferContextProvider>
<WordListPickerContextProvider>
<WordFeederContextProvider>
<GameClockContextProvider>
<div className="sidebar" id="left">
<Info />
</div>
@ -57,10 +62,10 @@ export default React.memo(function App() {
} */}
{gameMode === 'challenge' &&
<GameClockContextProvider>
<>
<ChallengeOverlay />
<ChallengeMode />
</GameClockContextProvider>
</>
}
<MorseButtons />
@ -77,9 +82,12 @@ export default React.memo(function App() {
</div>
<Legend />
</div>
</GameClockContextProvider>
</WordFeederContextProvider>
</WordListPickerContextProvider>
</MorseBufferContextProvider>
</WPMContextProvider>
</KeyTypeContextProvider>
</div>
<Footer />
</>

View file

@ -11,11 +11,13 @@ import { GameClockContext } from '../contexts/gameClockContext';
import { KeyTypeContext } from '../contexts/keyTypeContext';
import StraightKey from '../components/StraightKey';
import ElectronicKey from '../components/ElectronicKey';
import ChallengeControls from '../components/ChallengeControls';
export default React.memo(function ChallengeMode(props) {
const {stopGameClock, clockIsRunning, cleanup} = useContext(GameClockContext)
const {stopGameClock, clockIsRunning, intervals} = useContext(GameClockContext)
const {word, getNextWord, resetFeeder} = useContext(WordFeederContext)
const {morseCharBuffer, setMorseCharBuffer} = useContext(MorseBufferContext)
const {keyType} = useContext(KeyTypeContext)
@ -34,9 +36,7 @@ export default React.memo(function ChallengeMode(props) {
if (!word) {
console.log('FINISHED ALL WORDS!')
stopGameClock()
cleanup()
resetFeeder()
stopChallenge()
// Show a card showing challenge completion stats and option to restart word list
try { alert(`Time: ${document.getElementById('gameClock').innerText}`) }
@ -44,6 +44,14 @@ export default React.memo(function ChallengeMode(props) {
return
}
function stopChallenge() {
stopGameClock()
for (let i = 0; i < intervals.length; i++) {
clearInterval(intervals[i]);
}
resetFeeder()
}
let challengeLetters = word.split('')
@ -107,12 +115,14 @@ export default React.memo(function ChallengeMode(props) {
}, 1000)
}
return (
<>
{clockIsRunning ? (keyType === "straight" ?
<StraightKey /> : <ElectronicKey />) : <></>
}
<GameClock />
<ChallengeControls stopChallenge={stopChallenge} />
<GameClock stopChallenge={stopChallenge}/>
<ChallengeWord className={challengeWordClass} word={word} />
<ChallengeBufferDisplay morseArray={morseArray} incorrectMorseIndexes={incorrectMorseIndexes} />
</>

View file

@ -0,0 +1,30 @@
import React from "react"
export default (function ChallengeControls(props) {
// const {startGameClock} = useContext(GameClockContext)
// function startChallenge(e) {
// let countdown
// let count = 3
// document.getElementById('challengeReady').classList.add('starting')
// document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>`
// countdown = setInterval(() => {
// count--
// document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>`
// if (count === 0) {
// // Do this when countdown hits 0
// document.getElementById('challenge-overlay').classList.add('hide')
// clearInterval(countdown)
// startGameClock()
// }
// }, 1000)
// }
return (
<div id="challengeControls">
<button onClick={props.stopChallenge}>Exit</button>
</div>
)
})

View file

@ -1,28 +1,33 @@
import React, { useContext } from "react"
import React, { useContext, useEffect } from "react"
import { GameClockContext } from "../contexts/gameClockContext"
import WordListPicker from "./WordListPicker"
// import { GameModeContext } from "../contexts/gameModeContext"
export default (function ChallengeOverlay() {
const {startGameClock} = useContext(GameClockContext)
// const {gameMode} = useContext(GameModeContext)
function startChallenge(e) {
let countdown
let count = 3
document.getElementById('challengeReady').innerText = `Challenge starting in ${count}`
document.getElementById('challengeReady').classList.add('starting')
document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>`
countdown = setInterval(() => {
count--
document.getElementById('challengeReady').innerText = `Challenge starting in ${count}`
if (count === 0) {
// Do this when countdown hits 0
document.getElementById('challenge-overlay').classList.add('hide')
clearInterval(countdown)
startGameClock()
}
document.getElementById('challengeReady').innerHTML = `<span id="message">Challenge starting in</span><span id="count">${count}</span>`
}, 1000)
}
return (
<div id="challenge-overlay">
<div id="challengeReady" className="notify">

View file

@ -2,12 +2,14 @@ import React, {useContext} from "react"
import {GameModeContext} from "../contexts/gameModeContext"
import { MorseBufferContext } from "../contexts/morseBufferContext"
import { WordFeederContext } from "../contexts/wordFeederContext"
import { GameClockContext } from "../contexts/gameClockContext"
function ModePicker() {
const {setGameMode} = useContext(GameModeContext)
const {setMorseCharBuffer} = useContext(MorseBufferContext)
const {resetFeeder} = useContext(WordFeederContext)
const {stopGameClock, clockIsRunning} = useContext(GameClockContext)
function handleClick(e) {
setMorseCharBuffer('')
@ -15,6 +17,8 @@ function ModePicker() {
setGameMode(e.target.id)
if (clockIsRunning) { stopGameClock() }
let buttons = document.querySelector(".mode-picker#gameMode #buttons").childNodes
buttons.forEach(button => {
if (button.id === e.target.id) {

View file

@ -28,7 +28,7 @@ export default React.memo(function WordListPicker() {
}
return (
<>
<div id="challengeOptions">
<div id="wordListPicker" className="mode-picker">
<div id="title">
Word List
@ -38,19 +38,9 @@ export default React.memo(function WordListPicker() {
<option value="alphabet">Alphabet</option>
<option value="common100">100 Most Common Words</option>
<option value="test">Test List</option>
<option value="short">Short List</option>
</select>
</div>
{/* <div id="buttons">
<button id="alphabet" class="selected" onClick={handleClick}>
Alphabet
</button>
<button id="common100" onClick={handleClick}>
100 Most Common Words
</button>
<button id="test" onClick={handleClick}>
Test List
</button>
</div> */}
</div>
<div id="wordOrderPicker" className="mode-picker">
<div id="title">
@ -65,6 +55,6 @@ export default React.memo(function WordListPicker() {
</button>
</div>
</div>
</>
</div>
)
})

View file

@ -1,47 +1,44 @@
import React, {useState, useEffect, useContext} from "react"
import { KeyTypeContext } from "./keyTypeContext"
import React, {useState} from "react"
// import { KeyTypeContext } from "./keyTypeContext"
const GameClockContext = React.createContext()
function GameClockContextProvider(props) {
const [gameClockTime, setGameClockTime] = useState(0)
const [clockIsRunning, setClockIsRunning] = useState(false)
const [gameClockTimer, setGameClockTimer] = useState(0)
const {keyType} = useContext(KeyTypeContext)
// const [gameClockTimer, setGameClockTimer] = useState(0)
let intervals = []
// let intervals = []
const [intervals, setIntervals] = useState([])
function startGameClock() {
if (!clockIsRunning) {
setClockIsRunning(true)
setGameClockTimer(setInterval(() => {
setIntervals(prev => [...prev, (setInterval(() => {
if (document.getElementById('gameClock') === null) {
stopGameClock()
return
}
document.getElementById('gameClock').innerText = Number(document.getElementById('gameClock').innerText) + 1
}, 1000))
])
}
}
function stopGameClock() {
if (clockIsRunning) {
clearInterval(gameClockTimer)
cleanup()
setClockIsRunning(false)
}
}
function cleanup() {
clearInterval(gameClockTimer)
setGameClockTimer(0)
// for (let i = 0; i < intervals.length; i++) {
// clearInterval(intervals[i]);
// }
// clearInterval(gameClockTimer)
// setGameClockTimer(0)
for (let i = 0; i < intervals.length; i++) {
clearInterval(intervals[i]);
}
useEffect(() => {
console.log('KEYTYPE CHANGE');
return function () {
cleanup()
}
}, [keyType])
return (
@ -51,7 +48,8 @@ function GameClockContextProvider(props) {
startGameClock: startGameClock,
stopGameClock: stopGameClock,
cleanup: cleanup,
clockIsRunning: clockIsRunning
clockIsRunning: clockIsRunning,
intervals: intervals
}}>
{props.children}
</GameClockContext.Provider>

View file

@ -10,6 +10,7 @@ function WordListPickerContextProvider(props) {
const [wordListCategory, setWordListCategory] = useState('alphabet')
let wordList = []
const testList = ['gene', 'anya', 'ali', 'liam', 'last']
const short = ['gene']
if (wordListCategory === 'alphabet') {
wordList = alphabet.words
@ -17,6 +18,8 @@ function WordListPickerContextProvider(props) {
wordList = common100.words
} else if (wordListCategory === 'test') {
wordList = testList
} else if (wordListCategory === 'short') {
wordList = short
}

View file

@ -54,7 +54,6 @@ header {
}
#main-content .sidebar#left {
border: 1px solid yellowgreen;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -69,10 +68,11 @@ header {
min-width: 400px;
width: 400px;
padding: 1.5em;
-webkit-box-shadow: inset -3px 0px 5px rgba(0, 0, 0, 0.2);
box-shadow: inset -3px 0px 5px rgba(0, 0, 0, 0.2);
}
#main-content .sidebar#right {
border: 1px solid green;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@ -88,6 +88,8 @@ header {
width: 400px;
padding: 1.5em;
right: 0px;
-webkit-box-shadow: inset 3px 0px 5px rgba(0, 0, 0, 0.2);
box-shadow: inset 3px 0px 5px rgba(0, 0, 0, 0.2);
}
#main-content #main-interface {
@ -411,6 +413,28 @@ i[class*="ri-"] {
justify-content: space-around;
}
@-webkit-keyframes hideOverlay {
0% {
opacity: 100%;
z-index: 1000;
}
100% {
opacity: 0%;
z-index: -1000;
}
}
@keyframes hideOverlay {
0% {
opacity: 100%;
z-index: 1000;
}
100% {
opacity: 0%;
z-index: -1000;
}
}
#challenge-overlay {
position: absolute;
display: inline-block;
@ -419,26 +443,181 @@ i[class*="ri-"] {
width: 100%;
height: 100%;
z-index: 100;
background-color: rgba(0, 0, 0, 0.3);
background: rgba(255, 255, 255, 0.3);
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
#challenge-overlay.hide {
-webkit-animation: hideOverlay 3s ease-out forwards;
animation: hideOverlay 3s ease-out forwards;
}
#challenge-overlay .notify {
width: 400px;
height: 250px;
background: #f1f1f1;
margin-top: 150px;
border-radius: 5px;
-webkit-box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.5);
}
#challenge-overlay #challengeReady {
position: relative;
width: 400px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: space-evenly;
-ms-flex-pack: space-evenly;
justify-content: space-evenly;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
#challenge-overlay #challengeReady #message {
font-size: 2em;
font-weight: bold;
}
#challenge-overlay #challengeReady #count {
font-size: 4.5em;
font-weight: bold;
}
#challenge-overlay #challengeReady.starting {
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
#challenge-overlay #challengeReady button {
background: #f1f1f1;
-webkit-box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.3), 0px -1px 1px white;
box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.3), 0px -1px 1px white;
border-radius: 3px;
border: 0px;
padding: 0.3em;
margin-left: 10px;
margin-right: 10px;
font-size: 0.75em;
color: #333;
max-width: 250px;
}
#challenge-overlay #challengeReady button.selected {
-webkit-box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.3), inset 0px -1px 1px white;
box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.3), inset 0px -1px 1px white;
}
#challenge-overlay #challengeReady #challengeOptions {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
#challenge-overlay.hide {
display: none;
#challenge-overlay #challengeReady #challengeOptions .mode-picker {
width: 300px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-line-pack: center;
align-content: center;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
}
#challenge-overlay .notify {
width: 300px;
height: 250px;
background: #DDD;
#challenge-overlay #challengeReady #challengeOptions .mode-picker div {
padding: 5px;
height: 2.4em;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#title {
font-weight: bold;
font-size: 1.08em;
height: 100%;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding-left: 0px;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#buttons {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input {
margin-left: 10px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input input {
width: 50px;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
text-align: center;
border-radius: 3px;
border: 1px solid #ddd;
height: 1.3rem;
font-size: 0.75em;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input select {
height: 1.4rem;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input button {
width: 20px;
height: 20px;
border-radius: 3px;
}
#challenge-overlay #challengeReady #challengeOptions .mode-picker div#input button i {
position: relative;
left: -1px;
font-size: 1.1em;
font-weight: bold;
}
#challengeWord {

File diff suppressed because one or more lines are too long

View file

@ -4,18 +4,12 @@ import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {GameModeContextProvider} from "./contexts/gameModeContext"
import { KeyTypeContextProvider } from './contexts/keyTypeContext';
import { WPMContextProvider } from './contexts/wpmContext';
ReactDOM.render(
<KeyTypeContextProvider>
<WPMContextProvider>
<GameModeContextProvider>
<App />
</GameModeContextProvider>
</WPMContextProvider>
</KeyTypeContextProvider>
, document.getElementById('root'));

View file

@ -60,7 +60,7 @@ header {
.sidebar#left {
border: 1px solid yellowgreen;
// border: 1px solid yellowgreen;
display: flex;
flex-direction: column;
justify-content: flex-start;
@ -68,9 +68,10 @@ header {
min-width: 400px;
width: 400px;
padding: 1.5em;
box-shadow: inset -3px 0px 5px rgba(0,0,0,0.2);
}
.sidebar#right {
border: 1px solid green;
// border: 1px solid green;
display: flex;
flex-direction: column;
justify-content: space-between;
@ -79,6 +80,7 @@ header {
width: 400px;
padding: 1.5em;
right: 0px;
box-shadow: inset 3px 0px 5px rgba(0,0,0,0.2);
}
#main-interface {
// border: 1px solid blue;
@ -383,6 +385,17 @@ $button-height: 60px;
// }
// }
@keyframes hideOverlay {
0% {
opacity: 100%;
z-index: 1000;
}
100% {
opacity: 0%;
z-index: -1000;
}
}
#challenge-overlay {
position: absolute;
display: inline-block;
@ -391,19 +404,134 @@ $button-height: 60px;
width: 100%;
height: 100%;
z-index: 100;
background-color: rgba(0,0,0,0.3);
// background-color: rgba(0,0,0,0.4);
background: rgba(255,255,255,0.3);
// background-image: linear-gradient(0deg, transparent, rgba(1,1,1,1));
display: flex;
justify-content: center;
align-items: center;
// align-items: center;
&.hide {
display: none;
// animation: hideOverlay 2000ms 1 ease-out forwards;
animation: hideOverlay 3s ease-out forwards;
}
.notify {
width: 300px;
width: 400px;
height: 250px;
background: #DDD;
background: $main-bg-color-light;
margin-top: 150px;
border-radius: 5px;
box-shadow: 0px 5px 15px rgba(0,0,0,0.5);
}
#challengeReady {
position: relative;
width: 400px;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
#message {
font-size: 2em;
font-weight: bold;
}
#count {
font-size: 4.5em;
font-weight: bold;
}
&.starting {
justify-content: center;
}
button {
background: $main-bg-color-light;
box-shadow: $main-box-shadow-light;
border-radius: $main-border-radius;
border: 0px;
padding: 0.3em;
margin-left: 10px;
margin-right: 10px;
font-size: 0.75em;
color: $main-font-color-light;
max-width: 250px;
&.selected {
box-shadow: $main-box-shadow-light-selected;
}
}
#challengeOptions {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
// border: 1px solid blue;
.mode-picker {
// border: 1px solid green;
width: 300px;
display: flex;
// align-self: flex-start;s
align-content: center;
justify-content: flex-start;
div {
padding: 5px;
height: 2.4em;
}
div#title {
font-weight: bold;
font-size: 1.08em;
// border: 1px solid red;
height: 100%;
display: flex;
padding-left: 0px;
justify-content: flex-start;
align-items: center;
}
div#buttons {
// border: 1px solid blue;
display: flex;
justify-content: space-between;
align-items: center;
}
div#input {
margin-left: 10px;
display: flex;
align-items: center;
input {
width: 50px;
appearance: textfield;
text-align: center;
border-radius: 3px;
border: 1px solid #ddd;
height: 1.3rem;
font-size: 0.75em;
}
select {
height: 1.4rem;
}
button {
width: 20px;
height: 20px;
border-radius: 3px;
// line-height: 10px;
i {
position: relative;
left: -1px;
// top: -2px;
font-size: 1.1em;
font-weight: bold;
}
}
}
}
}
}
}
#challengeWord {