blob: 5ff0b8bc7183fea4b1e43207df15abaa05ef2ac8 (
plain)
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
|
(* Audio *)
let c3 = Audio.create "sounds/c3.mp3"
let c4 = Audio.create "sounds/c4.mp3"
let c5 = Audio.create "sounds/c5.mp3"
let playAudio (step : Step.state) =
match step.step with
| Step.Prepare when step.remaining == !Config.config.prepare ->
Audio.playOrReplay c3
| Step.Work when step.remaining == !Config.config.work ->
Audio.playOrReplay c5
| Step.Rest when step.remaining == !Config.config.rest ->
Audio.playOrReplay c3
| Step.End -> Audio.playOrReplay c3
| _ -> if step.remaining <= 3 then Audio.playOrReplay c4 else ()
(* Elements *)
let timerElt = Document.querySelectorUnsafe "#g-Timer"
let dialElt = Document.querySelectorUnsafe "#g-Timer__Dial"
let arcPathElt = Document.querySelectorUnsafe "#g-Timer__ArcProgress"
let stepElt = Document.querySelectorUnsafe "#g-Timer__Step"
let durationElt = Document.querySelectorUnsafe "#g-Timer__Duration"
let tabataCurrentElt = Document.querySelectorUnsafe "#g-Timer__TabataCurrent"
let tabataTotalElt = Document.querySelectorUnsafe "#g-Timer__TabataTotal"
let cycleCurrentElt = Document.querySelectorUnsafe "#g-Timer__CycleCurrent"
let cycleTotalElt = Document.querySelectorUnsafe "#g-Timer__CycleTotal"
let stopElt = Document.querySelectorUnsafe "#g-Timer__Stop"
(* State *)
let interval = ref None
let duration = ref 0
let elapsedTime = ref 0
let onStop : (unit -> unit) ref = ref (fun () -> ())
let isPlaying = ref false
(* Actions *)
let playPause _ = isPlaying := not !isPlaying
let stop _ =
let () = Belt.Option.forEach !interval Js.Global.clearInterval in
!onStop ()
(* View *)
let updateDom () =
let angle =
Js.Int.toFloat !elapsedTime /. Js.Int.toFloat !duration *. 360.0
in
let () =
Element.setAttribute arcPathElt "d" (Arc.describe 0.0 0.0 95.0 0.0 angle)
in
let step = Step.getAt !Config.config !elapsedTime in
let () = Element.setInnerText stepElt (Step.prettyPrint step.step) in
let () =
Element.setInnerText durationElt (Duration.prettyPrint step.remaining)
in
let () =
Element.setInnerText tabataCurrentElt (Js.Int.toString step.tabata)
in
let () = playAudio step in
Element.setInnerText cycleCurrentElt (Js.Int.toString step.cycle)
(* Update *)
let update () =
if !isPlaying then
let () = elapsedTime := !elapsedTime + 1 in
if !elapsedTime > !duration then stop () else updateDom ()
else ()
(* Init *)
let init () =
let () = duration := Config.getDuration () in
let () = elapsedTime := 0 in
let () =
Element.setInnerText tabataTotalElt (Js.Int.toString !Config.config.tabatas)
in
Element.setInnerText cycleTotalElt (Js.Int.toString !Config.config.cycles)
(* Setup and start *)
let setup onTimerStop = onStop := onTimerStop
let show () =
let () = updateDom () in
Element.setStyle timerElt "display: flex"
let hide () = Element.setStyle timerElt "display: none"
let start () =
let () = interval := Some (Js.Global.setInterval update 1000) in
isPlaying := true
let () =
let () = Element.addEventListener stopElt "click" stop in
Element.addEventListener dialElt "click" playPause
|