learn-morse-code/src/App.js

173 lines
5.1 KiB
JavaScript
Raw Normal View History

2019-12-21 23:48:36 +01:00
import React, { useEffect, useState } from 'react';
2019-12-27 09:41:53 +01:00
import './css/App.css';
2019-12-21 23:48:36 +01:00
import MorseDisplay from './components/MorseDisplay'
import MorseBufferDisplay from './components/MorseBufferDisplay'
import MorseButton from './components/MorseButton'
2019-12-27 09:41:53 +01:00
import ModePicker from './components/ModePicker'
2019-12-21 23:48:36 +01:00
// import LettersDisplay from './components/LettersDisplay'
2019-12-21 23:40:54 +01:00
function App() {
2019-12-21 23:48:36 +01:00
const [morseCharBuffer, setMorseCharBuffer] = useState('') // e.g. '-..'
const [morseWords, setMorseWords] = useState([]) // e.g. [['-..','.','-,'], ['...','---','...']]
let charTimer = 0
let charTime = 0
let gapTimer = 0
let gapTime = 0
const timingUnit = 15 // default: 25
const ditMaxTime = 5 // default: 3
const letterGapMinTime = ditMaxTime*3
const wordGapMaxTime = ditMaxTime*7
2020-01-03 08:53:56 +01:00
const morseHistorySize = 5
2019-12-27 09:41:53 +01:00
// 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
}
2019-12-21 23:48:36 +01:00
let o
2019-12-27 09:41:53 +01:00
let frequency = 550.0
2019-12-21 23:48:36 +01:00
function handleInputStart(event) {
2019-12-27 09:41:53 +01:00
event.preventDefault()
2019-12-21 23:48:36 +01:00
if ((event.keyCode !== 32 && event.target.id !== "morseButton") ||
(event.repeat)) {
return
}
2019-12-27 09:41:53 +01:00
if (context.state === 'interrupted') {
context.resume()
}
2019-12-21 23:48:36 +01:00
o = context.createOscillator()
2019-12-27 09:41:53 +01:00
o.frequency.value = frequency
o.type = "sine"
2019-12-22 09:21:52 +01:00
let g = context.createGain()
g.gain.exponentialRampToValueAtTime(0.08, context.currentTime)
o.connect(g)
g.connect(context.destination)
2019-12-21 23:48:36 +01:00
o.start()
2019-12-27 09:41:53 +01:00
// if (gapTimer===0) { setMorseLettersBuffer('') }
checkGapBetweenInputs()
clearInterval(gapTimer)
2019-12-21 23:48:36 +01:00
startCharTimer()
}
function startCharTimer() {
// Reset character time
charTime = 0
// Start Character Timer
charTimer = setInterval(() => {
charTime += 1
}, timingUnit);
}
function handleInputEnd(event) {
2019-12-27 09:41:53 +01:00
event.preventDefault()
2019-12-21 23:48:36 +01:00
if ((event.keyCode !== 32 && event.target.id !== "morseButton") ||
(event.repeat)) {
return
}
if (charTime <= ditMaxTime) {
setMorseCharBuffer(prev => prev + '.')
} else {
setMorseCharBuffer(prev => prev + '-')
}
stopCharTimer()
startGapTimer()
o.stop()
}
function stopCharTimer() {
clearInterval(charTimer)
charTimer = 0
}
function startGapTimer() {
gapTime = 0
gapTimer = setInterval(() => {
gapTime += 1
// Gap between words
if (gapTime >= wordGapMaxTime) {
setMorseCharBuffer(prev => prev + '/')
clearInterval(gapTimer)
gapTimer = 0
gapTime = 0
}
}, timingUnit);
}
function checkGapBetweenInputs() {
// Check Gap between letters
if ((gapTime >= letterGapMinTime) && (gapTime < wordGapMaxTime)) {
// setMorseLettersBuffer(prev => [...prev, morseCharBuffer])
setMorseCharBuffer(prev => prev + ' ')
// morseLettersBuffer = [...morseLettersBuffer, morseCharBuffer]
// setMorseCharBuffer('')
clearInterval(gapTimer)
gapTimer = 0
}
}
useEffect(() => {
document.addEventListener('keydown', handleInputStart)
document.addEventListener('keyup', handleInputEnd)
document.getElementById('morseButton').addEventListener('mousedown', handleInputStart)
2019-12-27 09:41:53 +01:00
document.getElementById('morseButton').addEventListener('touchstart', handleInputStart)
2019-12-21 23:48:36 +01:00
document.getElementById('morseButton').addEventListener('mouseup', handleInputEnd)
2019-12-27 09:41:53 +01:00
document.getElementById('morseButton').addEventListener('touchend', handleInputEnd)
2019-12-21 23:48:36 +01:00
// eslint-disable-next-line
}, [])
useEffect(() => {
if (morseCharBuffer.slice(-1) === ' ') {
// setMorseLettersBuffer([morseCharBuffer])
// setMorseCharBuffer('')
}
if (morseCharBuffer.slice(-1) === '/') {
// Remove forward slash
let val = morseCharBuffer.slice(0,morseCharBuffer.length-1)
console.log('val: ', val);
setMorseWords(prev => [val, ...prev])
if (morseWords.length >= morseHistorySize) {
setMorseWords(prev => prev.slice(0,prev.length-1))
}
setMorseCharBuffer('')
}
// setMorseLettersBuffer(prev => [...prev, morseCharBuffer])
// eslint-disable-next-line
}, [morseCharBuffer])
2020-01-03 08:53:56 +01:00
console.log('App.js rendered')
2019-12-21 23:48:36 +01:00
return (
2019-12-27 09:41:53 +01:00
<div id='main-content'>
<ModePicker />
2019-12-21 23:48:36 +01:00
morseCharBuffer:<br/>
<MorseBufferDisplay buffer={morseCharBuffer} /><br/>
<MorseDisplay morseWords={morseWords}/>
2019-12-27 09:41:53 +01:00
<MorseButton />
2019-12-21 23:48:36 +01:00
</div>
);
2019-12-21 23:40:54 +01:00
}
2020-01-03 08:53:56 +01:00
export default React.memo(App);