-
Notifications
You must be signed in to change notification settings - Fork 0
/
timer.tsx
133 lines (114 loc) · 3.74 KB
/
timer.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import useAudio from "./useAudio"
import { displayNotification, requestNotificationPermission } from "./notifications"
import { useLocalStorageState } from './localStorage';
import { Status, timerType } from '../shared/types';
export type LocalStateContextType = {
playPause: Function,
reset: Function,
skip: Function,
now: number,
}
export const LocalStateContext = createContext<LocalStateContextType>({
playPause: () => console.warn("no local state yet"),
reset: () => console.warn("no local state yet"),
skip: () => console.warn("no local state yet"),
now: 0,
});
export const LocalStateProvider = LocalStateContext.Provider;
export default function TimerProvider({ children }: { children: ReactNode }) {
const [now, setNow] = useState(0)
const { timerSettings, playlist, setPlaylist, timer, setTimer, timeRemaining, setTimeRemaining, status, setStatus, endTime, setEndTime } = useLocalStorageState()
const { playAudio: playAlarm, stopAudio: stopAlarm, audio } = useAudio(
"/alarm.ogg"
);
const playPause = () => {
requestNotificationPermission()
switch (status) {
case Status.Play:
pause()
break
case (Status.Start):
case Status.Pause:
play()
break
case Status.Ended:
skip()
break
default:
console.error("Play status not recognized")
}
}
const play = () => {
setStatus(Status.Play)
setEndTime(timeRemaining + now)
}
const pause = () => {
setStatus(Status.Pause)
setTimeRemaining(endTime - now)
}
const reset = () => {
setStatus(Status.Start)
setTimeRemaining(timer.duration)
}
const ended = () => {
playAlarm()
setStatus(Status.Ended)
displayNotification(`${timer.name} ended.`, { body: "You are doing great!" })
setTimeRemaining(0)
}
const skip = () => {
//Sending the first item in the playlist to the last spot
const _playlist = playlist;
const _firstItem = _playlist[0]
_playlist.shift()
_playlist.push(_firstItem)
const newTimer = timerSettings[_playlist[0]]
setPlaylist(_playlist)
setUpNewTimer(newTimer)
}
const setUpNewTimer = (newTimer: timerType) => {
setTimer(newTimer)
setTimeRemaining(newTimer.duration)
setStatus(Status.Start)
}
useEffect(() => {
const interval = setInterval(() => {
setNow(Date.now())
}, 250)
return () => clearInterval(interval)
}, [])
useEffect(() => {
//This stops the alarm when you click anywhere or change to the tab with the timer
if (audio) {
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'visible') {
stopAlarm()
}
})
document.addEventListener('click', function () {
stopAlarm()
})
}
}, [audio])
useEffect(() => {
//This is a listener of sorts. When it notices that the timer reaches zero, it sends the ended function which sounds the alarm
if (status == Status.Play && (endTime - now) < 0) {
ended()
}
}, [now])
return <LocalStateProvider value={
{
playPause,
reset,
skip,
now,
}
}>
{children}</LocalStateProvider>
}
function useTimer() {
const all = useContext(LocalStateContext);
return all;
}
export { TimerProvider, useTimer };