Browse Source

Write to calendar for Watch Complication

Jon Fawcett 6 years ago
parent
commit
f74c0ca521

+ 57 - 1
LoopFollow/Controllers/MainViewController.swift

@@ -8,6 +8,7 @@
 
 
 import UIKit
 import UIKit
 import Charts
 import Charts
+import EventKit
 
 
 
 
 class MainViewController: UIViewController, UITableViewDataSource, ChartViewDelegate {
 class MainViewController: UIViewController, UITableViewDataSource, ChartViewDelegate {
@@ -99,6 +100,9 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
     var basalData: [basalDataStruct] = []
     var basalData: [basalDataStruct] = []
     var predictionData: [Double] = []
     var predictionData: [Double] = []
     
     
+    // calendar setup
+    let store = EKEventStore()
+    
     var snoozeTabItem: UITabBarItem = UITabBarItem()
     var snoozeTabItem: UITabBarItem = UITabBarItem()
     
     
     override func viewDidLoad() {
     override func viewDidLoad() {
@@ -315,6 +319,9 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         self.updateBadge(entries: bgData)
         self.updateBadge(entries: bgData)
         self.updateBG(entries: bgData)
         self.updateBG(entries: bgData)
         self.createGraph(entries: bgData)
         self.createGraph(entries: bgData)
+        if UserDefaultsRepository.writeCalendarEvent.value {
+            self.writeCalendar()
+        }
        }
        }
     
     
     //update Min Ago Text. We need to call this separately because it updates between readings
     //update Min Ago Text. We need to call this separately because it updates between readings
@@ -987,7 +994,8 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         }
         }
     }
     }
     
     
-    func bgDirectionGraphic(_ value:String)->String {
+    func bgDirectionGraphic(_ value:String)->String
+    {
         let //graphics:[String:String]=["Flat":"\u{2192}","DoubleUp":"\u{21C8}","SingleUp":"\u{2191}","FortyFiveUp":"\u{2197}\u{FE0E}","FortyFiveDown":"\u{2198}\u{FE0E}","SingleDown":"\u{2193}","DoubleDown":"\u{21CA}","None":"-","NOT COMPUTABLE":"-","RATE OUT OF RANGE":"-"]
         let //graphics:[String:String]=["Flat":"\u{2192}","DoubleUp":"\u{21C8}","SingleUp":"\u{2191}","FortyFiveUp":"\u{2197}\u{FE0E}","FortyFiveDown":"\u{2198}\u{FE0E}","SingleDown":"\u{2193}","DoubleDown":"\u{21CA}","None":"-","NOT COMPUTABLE":"-","RATE OUT OF RANGE":"-"]
         graphics:[String:String]=["Flat":"→","DoubleUp":"↑↑","SingleUp":"↑","FortyFiveUp":"↗","FortyFiveDown":"↘︎","SingleDown":"↓","DoubleDown":"↓↓","None":"-","NOT COMPUTABLE":"-","RATE OUT OF RANGE":"-"]
         graphics:[String:String]=["Flat":"→","DoubleUp":"↑↑","SingleUp":"↑","FortyFiveUp":"↗","FortyFiveDown":"↘︎","SingleDown":"↓","DoubleDown":"↓↓","None":"-","NOT COMPUTABLE":"-","RATE OUT OF RANGE":"-"]
         
         
@@ -995,6 +1003,54 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         return graphics[value]!
         return graphics[value]!
     }
     }
     
     
+    // Write calendar. Not implemented yet
+    func writeCalendar() {
+        store.requestAccess(to: .event) {(granted, error) in
+        if !granted { return }
+            
+        // Create Event info
+           // eventTitle = BGText.text + " " + DirectionText.text + " " + DeltaText.text + "\nC:" + tableData[1].value + "g I:" + tableData[0].value + "u"
+            let deltaBG = self.bgData[self.bgData.count - 1].sgv -  self.bgData[self.bgData.count - 2].sgv as Int
+            var deltaString = ""
+            if deltaBG < 0 {
+                deltaString = String(deltaBG)
+            }
+            else
+            {
+                deltaString = "+" + String(deltaBG)
+            }
+            let direction = self.bgDirectionGraphic(self.bgData[self.bgData.count - 1].direction ?? "")
+            var eventTitle = String(self.bgData[self.bgData.count - 1].sgv) + " "
+            eventTitle += direction + " "
+            eventTitle += deltaString + "\n"
+            eventTitle += "C:" + self.tableData[1].value + "g "
+            eventTitle += "I: " + self.tableData[0].value + "u"
+            var eventStartDate = Date(timeIntervalSince1970: self.bgData[self.bgData.count - 1].date)
+            
+        // Delete Last Event
+            let eventToRemove = self.store.event(withIdentifier: UserDefaultsRepository.savedEventID.value)
+            if eventToRemove != nil {
+                do {
+                    try self.store.remove(eventToRemove!, span: .thisEvent, commit: true)
+                } catch {
+                    // Display error to user
+                }
+            }
+        // Write New Event
+            var event = EKEvent(eventStore: self.store)
+            event.title = eventTitle
+            event.startDate = eventStartDate
+            event.endDate = event.startDate.addingTimeInterval(60*10) //Add 10 minutes
+            event.calendar = self.store.calendar(withIdentifier: UserDefaultsRepository.calendarIdentifier.value)
+            do {
+                try self.store.save(event, span: .thisEvent, commit: true)
+                UserDefaultsRepository.savedEventID.value = event.eventIdentifier //save event id to access this particular event later
+            } catch {
+                // Display error to user
+            }
+        }
+    }
+    
     func checkAlarms(bgs: [sgvData]) {
     func checkAlarms(bgs: [sgvData]) {
         
         
         // Don't check or fire alarms within 1 minute of prior alarm
         // Don't check or fire alarms within 1 minute of prior alarm

+ 47 - 1
LoopFollow/Controllers/SettingsViewController.swift

@@ -8,9 +8,15 @@
 
 
 import UIKit
 import UIKit
 import Eureka
 import Eureka
+import EventKit
+import EventKitUI
 
 
 class SettingsViewController: FormViewController {
 class SettingsViewController: FormViewController {
 
 
+    struct cal {
+        var title: String
+        var identifier: String
+    }
 
 
     
     
     override func viewDidLoad() {
     override func viewDidLoad() {
@@ -19,7 +25,16 @@ class SettingsViewController: FormViewController {
             overrideUserInterfaceStyle = .dark
             overrideUserInterfaceStyle = .dark
         }
         }
         
         
-
+        //array of calendars
+        let store = EKEventStore()
+        let ekCalendars = store.calendars(for: EKEntityType.event)
+        var calendars: [cal] = []
+        for i in 0..<ekCalendars.count{
+            
+            let item = cal(title: ekCalendars[i].title, identifier: ekCalendars[i].calendarIdentifier)
+            calendars.append(item)
+        }
+      
         form +++ Section("Nightscout Settings")
         form +++ Section("Nightscout Settings")
             <<< TextRow(){ row in
             <<< TextRow(){ row in
                 row.title = "URL"
                 row.title = "URL"
@@ -161,6 +176,37 @@ class SettingsViewController: FormViewController {
                     UserDefaultsRepository.highLine.value = Int(value)
                     UserDefaultsRepository.highLine.value = Int(value)
             }
             }
         
         
+        
+            +++ Section(header: "Watch Settings", footer: "Add the Apple calendar complication to your watch face for BG, Trend, Delta, COB, and IOB updated every 5 minutes. It is recommended to create a new calendar called 'Loop' and modify the calendar settings in the iPhone Watch App to only display the Loop calendar on your watch")
+            <<< SwitchRow("writeCalendarEvent"){ row in
+                row.title = "BG to Calendar"
+                row.value = UserDefaultsRepository.writeCalendarEvent.value
+            }.onChange { [weak self] row in
+                        guard let value = row.value else { return }
+                        UserDefaultsRepository.writeCalendarEvent.value = value
+                }
+            <<< PickerInputRow<String>("calendarIdentifier") { row in
+                row.title = "Calendar"
+                row.options = calendars.map { $0.identifier }
+                row.hidden = "$writeCalendarEvent == false"
+                row.value = UserDefaultsRepository.calendarIdentifier.value
+                row.displayValueFor = { value in
+                guard let value = value else { return nil }
+                    let matching = calendars
+                    .flatMap { $0 }
+                        .filter { $0.identifier.range(of: value) != nil || $0.title.range(of: value) != nil }
+                    if matching.count > 0 {
+
+                        return "\(String(matching[0].title))"
+                    } else {
+                        return " - "
+                    }
+                }
+            }.onChange { [weak self] row in
+                    guard let value = row.value else { return }
+                    UserDefaultsRepository.calendarIdentifier.value = value
+            }
+        
          }
          }
         
         
         
         

+ 2 - 0
LoopFollow/Info.plist

@@ -4,6 +4,8 @@
 <dict>
 <dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 	<string>$(DEVELOPMENT_LANGUAGE)</string>
+	<key>NSCalendarsUsageDescription</key>
+	<string>Loop Follow would like to access your calendar to save BG readings</string>
 	<key>CFBundleExecutable</key>
 	<key>CFBundleExecutable</key>
 	<string>$(EXECUTABLE_NAME)</string>
 	<string>$(EXECUTABLE_NAME)</string>
 	<key>CFBundleIdentifier</key>
 	<key>CFBundleIdentifier</key>

+ 7 - 0
LoopFollow/repository/UserDefaults.swift

@@ -35,6 +35,13 @@ class UserDefaultsRepository {
             UIApplication.shared.isIdleTimerDisabled = screenlock
             UIApplication.shared.isIdleTimerDisabled = screenlock
     })
     })
     
     
+    
+    // Watch Calendar Settings
+    static let calendarIdentifier = UserDefaultsValue<String>(key: "calendarIdentifier", default: "")
+    static let savedEventID = UserDefaultsValue<String>(key: "savedEventID", default: "")
+    static let lastCalendarStartDate = UserDefaultsValue<Date?>(key: "lastCalendarStartDate", default: nil)
+    static let writeCalendarEvent = UserDefaultsValue<Bool>(key: "writeCalendarEvent", default: false)
+    
     // Alarm Settings
     // Alarm Settings
     static let systemOutputVolume = UserDefaultsValue<Float>(key: "systemOutputVolume", default: 0.5)
     static let systemOutputVolume = UserDefaultsValue<Float>(key: "systemOutputVolume", default: 0.5)
     static let fadeInTimeInterval = UserDefaultsValue<TimeInterval>(key: "fadeInTimeInterval", default: 0)
     static let fadeInTimeInterval = UserDefaultsValue<TimeInterval>(key: "fadeInTimeInterval", default: 0)