diff --git a/src/App.js b/src/App.js index 28efb40..f98920d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,8 +1,9 @@ import React, { useEffect, useState } from 'react'; -import './App.css'; +import './css/App.css'; import MorseDisplay from './components/MorseDisplay' import MorseBufferDisplay from './components/MorseBufferDisplay' import MorseButton from './components/MorseButton' +import ModePicker from './components/ModePicker' // import LettersDisplay from './components/LettersDisplay' function App() { @@ -21,30 +22,46 @@ function App() { const ditMaxTime = 5 // default: 3 const letterGapMinTime = ditMaxTime*3 const wordGapMaxTime = ditMaxTime*7 - const morseHistorySize = 3 + const morseHistorySize = 1 + + // Tone Setup + let AudioContext = window.AudioContext || window.webkitAudioContext || false + let context + window.AudioContext = window.AudioContext || window.webkitAudioContext; + if (AudioContext) { + context = new AudioContext() + } else { + context = null + } - let context = new AudioContext() let o + let frequency = 550.0 function handleInputStart(event) { + event.preventDefault() if ((event.keyCode !== 32 && event.target.id !== "morseButton") || (event.repeat)) { return } + if (context.state === 'interrupted') { + context.resume() + } + + o = context.createOscillator() + o.frequency.value = frequency + o.type = "sine" + + let g = context.createGain() + g.gain.exponentialRampToValueAtTime(0.08, context.currentTime) + o.connect(g) + g.connect(context.destination) + o.start() + // if (gapTimer===0) { setMorseLettersBuffer('') } checkGapBetweenInputs() clearInterval(gapTimer) - o = context.createOscillator() - let g = context.createGain() - g.gain.exponentialRampToValueAtTime(0.08, context.currentTime) - o.type = "sine" - let frequency = 550.0 - o.frequency.value = frequency - o.connect(g) - g.connect(context.destination) - o.start() startCharTimer() } @@ -58,6 +75,7 @@ function App() { } function handleInputEnd(event) { + event.preventDefault() if ((event.keyCode !== 32 && event.target.id !== "morseButton") || (event.repeat)) { return @@ -111,7 +129,9 @@ function App() { document.addEventListener('keydown', handleInputStart) document.addEventListener('keyup', handleInputEnd) document.getElementById('morseButton').addEventListener('mousedown', handleInputStart) + document.getElementById('morseButton').addEventListener('touchstart', handleInputStart) document.getElementById('morseButton').addEventListener('mouseup', handleInputEnd) + document.getElementById('morseButton').addEventListener('touchend', handleInputEnd) // eslint-disable-next-line }, []) @@ -139,12 +159,12 @@ function App() { }, [morseCharBuffer]) return ( -
charTime: {charTime}
- +
+ morseCharBuffer:

- +
); } diff --git a/src/App.css b/src/App_original.css similarity index 75% rename from src/App.css rename to src/App_original.css index 5aaefc8..a323969 100644 --- a/src/App.css +++ b/src/App_original.css @@ -11,8 +11,17 @@ html, body { align-items: center; width: 100%; } -#root div { +#mode-picker { + display: flex; +} +#mode-picker div { + margin: 15px; + padding: 5px; + box-shadow: 0px 0px 15px #000; +} +#main-content { width: 95vw; + border: 1px solid red; } #morseButton { @@ -25,7 +34,7 @@ html, body { #morseBufferDisplay { display: flex; justify-content: center; - /* border: 1px solid green; */ + border: 1px solid green; width: 100%; height: 40px; } @@ -71,42 +80,46 @@ html, body { font-weight: bold; } #morseDisplay { - /* border: 2px solid red; */ + /* border: 1px solid blue; */ display: flex; - flex-direction: row; + flex-direction: column; } -#cardContainer div .morseCard:nth-child(1){ +#morseDisplay .morseCard:nth-child(1){ opacity: 100%; } -#cardContainer div .morseCard:nth-child(2){ +#morseDisplay .morseCard:nth-child(2){ opacity: 70%; } -#cardContainer div .morseCard:nth-child(3){ +#morseDisplay .morseCard:nth-child(3){ opacity: 50%; } -#cardContainer div .morseCard:nth-child(4){ +#morseDisplay .morseCard:nth-child(4){ opacity: 30%; } -#cardContainer div .morseCard:nth-child(5){ +#morseDisplay .morseCard:nth-child(5){ opacity: 10%; } .morseCard { display: flex; flex-direction: row !important; justify-content: center; - /* border: 1px solid blue; */ + /* border: 1px solid orange; */ margin-bottom: 2px; font-size: 40px; font-family: 'Courier'; font-weight: bold; + /* width: 100%; */ } .morseCard div { /* border: 1px solid green; */ padding: 5px; margin: 2px; - /* border: 1px solid #EEE; */ + /* border: 1px solid purple; */ background: #EEE; + /* background-image: linear-gradient(90deg, transparent, #EEE); */ /* box-shadow: 0px 2px 2px -2px #666; */ + /* justify-content: space-around; */ + width: 50%; } .morseCard .ditDahs { display: flex; diff --git a/src/components/ModePicker.js b/src/components/ModePicker.js new file mode 100644 index 0000000..f04ca2d --- /dev/null +++ b/src/components/ModePicker.js @@ -0,0 +1,16 @@ +import React from "react" + +function ModePicker() { + return ( +
+
+ Practice +
+
+ Timed Mode +
+
+ ) +} + +export default ModePicker \ No newline at end of file diff --git a/src/components/MorseDisplay.js b/src/components/MorseDisplay.js index 90d9e21..2bec5c1 100644 --- a/src/components/MorseDisplay.js +++ b/src/components/MorseDisplay.js @@ -7,9 +7,7 @@ function MorseDisplay(props) { return (
-
-
{morseCards}
-
+ {morseCards}
) } diff --git a/src/css/App.css b/src/css/App.css new file mode 100644 index 0000000..8f88edf --- /dev/null +++ b/src/css/App.css @@ -0,0 +1,197 @@ +html, body { + margin: 0px; + padding: 0px; + height: 100%; + width: 100%; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +#root { + height: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + width: 100%; +} + +#mode-picker { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} + +#mode-picker div { + margin: 15px; + padding: 5px; + -webkit-box-shadow: 0px 0px 15px #000; + box-shadow: 0px 0px 15px #000; +} + +#main-content { + width: 95vw; + border: 1px solid red; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +#morseButton { + width: 200px !important; + height: 200px; + margin: 30px; + background: goldenrod; + border-radius: 50%; + -ms-flex-item-align: center; + -ms-grid-row-align: center; + align-self: center; +} + +#morseBufferDisplay { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + border: 1px solid green; + width: 100%; + height: 40px; +} + +#morseBufferDisplay #ditDahs { + width: 50%; + padding-right: 5px; + border-right: 2px solid #000; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; +} + +#morseBufferDisplay #ditDahs .ditDah { + background: #DDD; + height: 40px; + width: 30px !important; + margin-left: 3px; + -webkit-box-shadow: 0px 1px 0px #000; + box-shadow: 0px 1px 0px #000; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-size: 35px; + font-family: 'Courier'; + font-weight: bold; +} + +#morseBufferDisplay #alphanumeric { + padding-left: 5px; + border-left: 2px solid #000; + width: 50%; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; +} + +.space { + font-size: 20px; +} + +.morseError { + background: rgba(255, 0, 0, 0.4); +} + +#morseDisplay { + /* border: 1px solid blue; */ + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} + +#morseDisplay .morseCard:nth-child(1) { + opacity: 100%; +} + +#morseDisplay .morseCard:nth-child(2) { + opacity: 70%; +} + +#morseDisplay .morseCard:nth-child(3) { + opacity: 50%; +} + +#morseDisplay .morseCard:nth-child(4) { + opacity: 30%; +} + +#morseDisplay .morseCard:nth-child(5) { + opacity: 10%; +} + +.morseCard { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal !important; + -webkit-box-direction: normal !important; + -ms-flex-direction: row !important; + flex-direction: row !important; + -webkit-box-pack: center; + -ms-flex-pack: center; + justify-content: center; + /* border: 1px solid orange; */ + margin-bottom: 2px; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; + /* width: 100%; */ +} + +.morseCard div { + /* border: 1px solid purple; */ + padding: 5px; + margin: 2px; + background: #EEE; + width: 50%; + white-space: nowrap; +} + +.morseCard .ditDahs { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + overflow-wrap: break-word; +} +/*# sourceMappingURL=App.css.map */ \ No newline at end of file diff --git a/src/css/App.css.map b/src/css/App.css.map new file mode 100644 index 0000000..5617bd2 --- /dev/null +++ b/src/css/App.css.map @@ -0,0 +1,9 @@ +{ + "version": 3, + "mappings": "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", + "sources": [ + "../scss/App.scss" + ], + "names": [], + "file": "App.css" +} \ No newline at end of file diff --git a/src/scss/App.scss b/src/scss/App.scss new file mode 100644 index 0000000..cb8fac0 --- /dev/null +++ b/src/scss/App.scss @@ -0,0 +1,135 @@ +html, body { + margin: 0px; + padding: 0px; + height: 100%; + width: 100%; + box-sizing: border-box; +} +#root { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + width: 100%; +} +#mode-picker { + display: flex; + + div { + margin: 15px; + padding: 5px; + box-shadow: 0px 0px 15px #000; + } +} +#main-content { + width: 95vw; + border: 1px solid red; + display: flex; + flex-direction: column; +} + +#morseButton { + width: 200px !important; + height: 200px; + margin: 30px; + background: goldenrod; + border-radius: 50%; + align-self: center; +} + +#morseBufferDisplay { + display: flex; + justify-content: center; + border: 1px solid green; + width: 100%; + height: 40px; + + #ditDahs { + width: 50%; + padding-right: 5px; + border-right: 2px solid #000; + display: flex; + flex-direction: row; + justify-content: flex-end; + + .ditDah { + background: #DDD; + height: 40px; + width: 30px !important; + margin-left: 3px; + box-shadow: 0px 1px 0px #000; + display: flex; + justify-content: center; + align-items: center; + font-size: 35px; + font-family: 'Courier'; + font-weight: bold; + } + } + + #alphanumeric { + padding-left: 5px; + border-left: 2px solid #000; + width: 50%; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; + } +} + +.space { + font-size: 20px; +} +.morseError { + background: rgba(255,0,0,0.4); +} + +#morseDisplay { + /* border: 1px solid blue; */ + display: flex; + flex-direction: column; + + .morseCard:nth-child(1){ + opacity: 100%; + } + .morseCard:nth-child(2){ + opacity: 70%; + } + .morseCard:nth-child(3){ + opacity: 50%; + } + .morseCard:nth-child(4){ + opacity: 30%; + } + .morseCard:nth-child(5){ + opacity: 10%; + } +} + +.morseCard { + display: flex; + flex-direction: row !important; + justify-content: center; + /* border: 1px solid orange; */ + margin-bottom: 2px; + font-size: 40px; + font-family: 'Courier'; + font-weight: bold; + /* width: 100%; */ + + div { + /* border: 1px solid purple; */ + padding: 5px; + margin: 2px; + background: #EEE; + width: 50%; + white-space: nowrap; + } + + .ditDahs { + display: flex; + justify-content: flex-end; + align-items: center; + overflow-wrap: break-word; + } +} \ No newline at end of file