Skip to content

Commit 3d89fe8

Browse files
authored
Merge pull request #42 from efenner-cambia/add-chime-to-countdown-timer
feat: add chime to countdown timer
2 parents 9caafe5 + ff6d759 commit 3d89fe8

File tree

3 files changed

+243
-193
lines changed

3 files changed

+243
-193
lines changed
Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,37 @@
1-
import {Button, Tooltip} from "@material-ui/core";
2-
import AttachFile from "@material-ui/icons/AttachFile";
3-
import React from "react";
1+
import { Button, Tooltip } from '@material-ui/core';
2+
import AttachFile from '@material-ui/icons/AttachFile';
3+
import React from 'react';
44

55
type Props = {
6-
onFileLoad: (input: File) => void;
7-
id: string;
8-
buttonText?: string;
6+
onFileLoad: (input: File) => void;
7+
id: string;
8+
buttonText?: string;
99
};
1010

1111
export const FileUploadButton = (props: Props) => {
12-
const { onFileLoad, id, buttonText = "Upload File" } = props;
12+
const { onFileLoad, id, buttonText = 'Upload File' } = props;
1313

14-
return (
15-
<>
16-
<Tooltip arrow title="Upload File">
17-
<label htmlFor={id}>
18-
<Button
19-
component="span"
20-
size="small"
21-
startIcon={<AttachFile />}
22-
>
23-
{buttonText}
24-
</Button>
25-
</label>
26-
</Tooltip>
27-
<input
28-
type="file"
29-
accept="*/*"
30-
id={id}
31-
hidden
32-
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
33-
if (!e?.target?.files?.length) {
34-
return null;
35-
}
36-
return onFileLoad(e.target.files[0]);
37-
}}
38-
/>
39-
</>
40-
);
41-
};
14+
return (
15+
<>
16+
<Tooltip arrow title="Upload File">
17+
<label htmlFor={id}>
18+
<Button component="span" size="small" startIcon={<AttachFile />}>
19+
{buttonText}
20+
</Button>
21+
</label>
22+
</Tooltip>
23+
<input
24+
type="file"
25+
accept="*/*"
26+
id={id}
27+
hidden
28+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
29+
if (!e?.target?.files?.length) {
30+
return null;
31+
}
32+
return onFileLoad(e.target.files[0]);
33+
}}
34+
/>
35+
</>
36+
);
37+
};

plugins/toolbox/src/components/Misc/Countdown.tsx

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,51 @@ import {
33
Button,
44
ButtonGroup,
55
FormControl,
6+
FormControlLabel,
67
Grid,
78
TextField,
9+
Switch,
810
} from '@material-ui/core';
911
import { useStyles } from '../../utils/hooks';
1012
import { 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+
1242
const 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

Comments
 (0)