-
Notifications
You must be signed in to change notification settings - Fork 0
/
Alarm.fs
160 lines (132 loc) · 5.69 KB
/
Alarm.fs
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
namespace RadioClock
open System
open MonoTouch.Foundation
open MonoTouch.UIKit
/// Deal with two types of alarms: a sleep timer, which will turn the
/// radio off after a given time, and the actual alarm clock.
module Alarm =
let mutable timer: option<UILocalNotification> = None
let mutable alarm: option<UILocalNotification> = None
let sleepIco = Layout.icon Layout.SleepIcon
let alarmIco = Layout.icon Layout.AlarmIcon
let sleepLbl = Layout.label "" Layout.TinyFont
let alarmLbl = Layout.label "" Layout.TinyFont
let alarmRem = Layout.label "" Layout.TinyFont
let StatusBar : UIView =
let view = new UIView(TranslatesAutoresizingMaskIntoConstraints = false)
let views = [
"sleepIco", sleepIco :> UIView
"sleepLbl", sleepLbl :> UIView
"alarmIco", alarmIco :> UIView
"alarmLbl", alarmLbl :> UIView
"alarmRem", alarmRem :> UIView
]
let formats = [
"V:|[sleepIco]"
"V:|[sleepLbl]|"
"V:|[alarmIco]"
"V:|[alarmLbl][alarmRem]|"
"H:|[sleepIco]-[sleepLbl]-[alarmIco]-[alarmLbl]|"
"H:[alarmRem]|"
]
Layout.layout view formats views
view
let cancelNotification maybeNotification =
match maybeNotification with
| Some n -> UIApplication.SharedApplication.CancelLocalNotification(n)
| None -> ()
let cancelAlarm () =
cancelNotification alarm
alarmIco.Hidden <- true
alarmLbl.Hidden <- true
alarmRem.Hidden <- true
alarm <- None
let cancelTimer () =
cancelNotification timer
sleepIco.Hidden <- true
sleepLbl.Hidden <- true
timer <- None
let createNotification nsdate =
let notif = new UILocalNotification(FireDate = nsdate)
notif.AlertAction <- "Alarm Clock"
notif.AlertBody <- "A timer or an alarm went off. But alarm clock is in background."
notif.SoundName <- "Beacon"
UIApplication.SharedApplication.ScheduleLocalNotification(notif)
notif
let setAlarm2 alarmTime =
// TODO: split up in several functions, lock on alarm(needed?)
let time = System.DateTime.Now//.UtcNow
let span = TimeSpan(time.Hour, time.Minute, time.Second)
let alert = if (span.CompareTo(alarmTime)) < 0 then time.Date.AddTicks(alarmTime.Ticks) else time.Date.AddDays(1.0).AddTicks(alarmTime.Ticks)
let alert2 = DateTime.SpecifyKind(alert, DateTimeKind.Utc)
let reference = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc))
// let reference = new DateTime(2001, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
// TODO: find a better way, how do we deal with local time vs utc here??? need to subtract two hours for time zone and daylight savings
NSDate.FromTimeIntervalSinceReferenceDate((alert2 - reference).TotalSeconds).AddSeconds(-1.0*3600.0)
let remainingTime (n: UILocalNotification) =
let s = n.FireDate.SecondsSinceReferenceDate - (new NSDate()).SecondsSinceReferenceDate
TimeSpan(0, 0, int(s))
let updateRemaining (l: UILabel) n =
match n with
| Some(n) ->
l.InvokeOnMainThread(fun _ ->
l.Text <- (remainingTime n).ToString()
)
| None -> ()
let setAlarm alarmTime =
if (not (List.exists (fun (t: TimeSpan) -> alarmTime.Equals(t)) Config.alarmTimes)) then Config.alarmTimes <- Seq.take 3 (alarmTime :: Config.alarmTimes) |> Seq.toList
alarmIco.Hidden <- false
alarmLbl.Hidden <- false
alarmRem.Hidden <- false
alarmLbl.Text <- alarmTime.ToString()
alarm <- Some(createNotification (setAlarm2 alarmTime))
updateRemaining alarmRem alarm
let setTimer (timerTime: TimeSpan) =
sleepIco.Hidden <- false
sleepLbl.Hidden <- false
timer <- Some(createNotification ((new NSDate()).AddSeconds(timerTime.TotalSeconds)))
updateRemaining sleepLbl timer
// Handle incoming system notifications
let handleNotification (incoming: UILocalNotification) =
if (alarm.IsSome && alarm.Value.FireDate.IsEqual(incoming.FireDate)) then
cancelAlarm()
Radio.fadeIn()
UIScreen.MainScreen.Brightness <- 1.0f // reset original value!
if (timer.IsSome && timer.Value.FireDate.IsEqual(incoming.FireDate)) then
cancelTimer()
Radio.fadeOut()
UIScreen.MainScreen.Brightness <- 0.0f
do
// init: deactive/hide sleep and alarm UI elements
cancelAlarm()
cancelTimer()
// hide/show sleep state
Toolbar.timerButton.Add (fun maybeSpan ->
cancelTimer()
match maybeSpan with
| Some(span) -> setTimer span
| None -> ()
)
// hide/show alarm state
Toolbar.alarmButton.Add (fun maybeSpan ->
cancelAlarm()
match maybeSpan with
| Some(span) -> setAlarm span
| None -> ()
)
Toolbar.dayModeSelected.Add (fun _ ->
UIScreen.MainScreen.Brightness <- 1.0f
)
Toolbar.nightModeSelected.Add (fun _ ->
UIScreen.MainScreen.Brightness <- 0.0f
)
Radio.TurnOff.Publish.Add (fun _ ->
cancelTimer()
)
// install a timer that updates the remaining time labels
let ttt = new System.Timers.Timer(1000.0)
ttt.Elapsed.Add(fun _ ->
updateRemaining sleepLbl timer
updateRemaining alarmRem alarm
)
ttt.Start()