@@ -3,19 +3,51 @@ import {
33 Button ,
44 ButtonGroup ,
55 FormControl ,
6+ FormControlLabel ,
67 Grid ,
78 TextField ,
9+ Switch ,
810} from '@material-ui/core' ;
911import { useStyles } from '../../utils/hooks' ;
1012import { TimePaper } from './TimePaper' ;
1113
14+ function sleep ( ms : number ) {
15+ return new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
16+ }
17+
18+ const audioContext = new AudioContext ( ) ;
19+ const beep = ( frequency : number ) => {
20+ const beep_decay = 1.5 ;
21+ const o = audioContext . createOscillator ( ) ;
22+ const g = audioContext . createGain ( ) ;
23+ o . connect ( g ) ;
24+ o . type = 'sine' ;
25+ o . frequency . value = frequency ;
26+ g . connect ( audioContext . destination ) ;
27+ o . start ( ) ;
28+ g . gain . exponentialRampToValueAtTime (
29+ 0.00001 ,
30+ audioContext . currentTime + beep_decay ,
31+ ) ;
32+ } ;
33+
34+ async function playAlert ( ) {
35+ beep ( 440.0 ) ;
36+ await sleep ( 200 ) ;
37+ beep ( 440.0 ) ;
38+ await sleep ( 200 ) ;
39+ beep ( 440.0 ) ;
40+ }
41+
1242const Countdown = ( ) => {
1343 const [ secondsLeft , setSecondsLeft ] = useState ( 0 ) ;
1444 const [ hours , setHours ] = useState ( 0 ) ;
1545 const [ minutes , setMinutes ] = useState ( 0 ) ;
1646 const [ seconds , setSeconds ] = useState ( 0 ) ;
1747 const styles = useStyles ( ) ;
1848 const [ isRunning , setIsRunning ] = useState ( false ) ;
49+ const [ chime , setChime ] = useState ( true ) ;
50+
1951 const formatTime = ( timeInSeconds : number ) => {
2052 const hoursLeft = Math . floor ( timeInSeconds / 3600 ) ;
2153 const minutesLeft = Math . floor ( ( timeInSeconds / 60 ) % 60 ) ;
@@ -46,22 +78,29 @@ const Countdown = () => {
4678 }
4779 } ;
4880
81+ const handleChimeToggle = ( event : React . ChangeEvent < HTMLInputElement > ) => {
82+ setChime ( event . target . checked ) ;
83+ } ;
84+
4985 useEffect ( ( ) => {
5086 let intervalId : NodeJS . Timer | undefined ;
5187
5288 if ( isRunning ) {
5389 intervalId = setInterval ( ( ) => {
5490 const time = secondsLeft - 1 ;
55- if ( time >= 0 ) {
91+ if ( time > 0 ) {
5692 setSecondsLeft ( time ) ;
57- } else if ( time < 0 ) {
93+ } else if ( time <= 0 ) {
5894 setIsRunning ( false ) ;
95+ if ( chime ) {
96+ playAlert ( ) ;
97+ }
5998 }
6099 } , 1000 ) ;
61100 }
62101
63102 return ( ) => clearInterval ( intervalId ) ;
64- } , [ hours , minutes , seconds , secondsLeft , isRunning ] ) ;
103+ } , [ hours , minutes , seconds , secondsLeft , isRunning , chime ] ) ;
65104
66105 const timeLeft = formatTime ( secondsLeft ) ;
67106 return (
@@ -92,6 +131,11 @@ const Countdown = () => {
92131 Reset
93132 </ Button >
94133 </ ButtonGroup >
134+ < FormControlLabel
135+ control = { < Switch defaultChecked onChange = { handleChimeToggle } /> }
136+ label = "Chime"
137+ labelPlacement = "start"
138+ />
95139 </ Grid >
96140 </ Grid >
97141 </ FormControl >
0 commit comments