├── nightguard ├── de.lproj │ ├── LaunchScreen.strings │ ├── Localizable.strings │ ├── Duration.strings │ ├── Care.strings │ ├── Alarm.strings │ ├── Preferences.strings │ ├── Nightscout.strings │ ├── Bedside.strings │ └── Stats.strings ├── fi-FI.lproj │ ├── LaunchScreen.strings │ ├── Duration.strings │ ├── Care.strings │ ├── Alarm.strings │ ├── Preferences.strings │ ├── Nightscout.strings │ ├── Bedside.strings │ └── Stats.strings ├── .DS_Store ├── alarm.mp3 ├── alarm-notification.m4a ├── Media.xcassets │ ├── Contents.json │ ├── Care.imageset │ │ ├── hand.png │ │ └── Contents.json │ ├── close.imageset │ │ ├── close.png │ │ ├── close@2x.png │ │ ├── close@3x.png │ │ └── Contents.json │ ├── Alarm.imageset │ │ ├── Alarm@1x.png │ │ ├── Alarm@2x.png │ │ ├── Alarm@3x.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon.png │ │ ├── Icon-40.png │ │ ├── Icon-72.png │ │ ├── Icon-76.png │ │ ├── Icon@2x.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-40@3x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-72@2x.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-Small.png │ │ ├── Icon-83.5@2x.png │ │ ├── Icon-Small-50.png │ │ ├── Icon-Small@2x.png │ │ ├── Icon-Small@3x.png │ │ ├── Icon-Small-50@2x.png │ │ └── Nightscout1024NoAlpha.png │ ├── Main.imageset │ │ ├── Main@1x.png │ │ ├── Main@2x.png │ │ ├── Main@3x.png │ │ └── Contents.json │ ├── Prefs.imageset │ │ ├── Prefs@1x.png │ │ ├── Prefs@2x.png │ │ ├── Prefs@3x.png │ │ └── Contents.json │ ├── Stats.imageset │ │ ├── Stats@1x.png │ │ ├── Stats@2x.png │ │ ├── Stats@3x.png │ │ └── Contents.json │ ├── Action.imageset │ │ ├── Action@1x.png │ │ ├── Action@2x.png │ │ ├── Action@3x.png │ │ └── Contents.json │ ├── Fullscreen.imageset │ │ ├── Fullscreen@1x.png │ │ ├── Fullscreen@2x.png │ │ ├── Fullscreen@3x.png │ │ └── Contents.json │ ├── Nightscout.imageset │ │ ├── Nightscout@1x.png │ │ ├── Nightscout@2x.png │ │ ├── Nightscout@3x.png │ │ └── Contents.json │ ├── volume-low.imageset │ │ ├── volume-low@1x.png │ │ ├── volume-low@2x.png │ │ ├── volume-low@3x.png │ │ └── Contents.json │ ├── SlideArrow.imageset │ │ ├── slide-arrow-25.png │ │ ├── slide-arrow-50.png │ │ ├── slide-arrow-75.png │ │ └── Contents.json │ └── volume-high.imageset │ │ ├── volume-high@1x.png │ │ ├── volume-high@2x.png │ │ ├── volume-high@3x.png │ │ └── Contents.json ├── Base.lproj │ ├── Localizable.strings │ └── LaunchScreen.storyboard ├── KeepAwakeMessage.swift ├── RequestAlarmNotificationMessage.swift ├── DictionaryExtension.swift ├── Comparable+Extensions.swift ├── EmptyWatchMessage.swift ├── UIImageExtension.swift ├── UIViewControllerExtension.swift ├── Helpers.swift ├── external │ ├── regression │ │ ├── Matrix+Description.swift │ │ └── Matrix+Append.swift │ ├── model │ │ └── TemporaryTarget.swift │ └── WatchService.swift ├── UIView+Extensions.swift ├── ObservationToken.swift ├── scoutwatch.entitlements ├── XCUIElement.swift ├── PaddingLabel.swift ├── NightSafeMessage.swift ├── Units.swift ├── SnoozeMessage.swift ├── UserDefaultsSyncMessage.swift ├── MenuActionCell.swift ├── NightscoutDataMessage.swift ├── WatchSyncRequestMessage.swift ├── WatchMessage.swift ├── MPVolumeViewExtension.swift ├── DoubleExtension.swift ├── app │ ├── Colors.swift │ └── TimeService.swift ├── TabBarController.swift ├── UILabelExtension.swift ├── repository │ ├── StatisticsRepository.swift │ └── SharedUserDefaultsRepository.swift ├── UIScreen+AnimatedBrightness.swift ├── GenericWatchMessage.swift ├── FloatExtension.swift ├── BasicStatsPanelView.swift ├── ButtonRowWithDynamicDetails.swift ├── ArrayExtension.swift ├── StatsPrefsViewController.swift ├── StringExtension.swift ├── QuickSnoozeOption.swift ├── TimerExtension.swift ├── VolumeChangeDetector.swift ├── TouchReportingView.swift ├── XibLoadedView.swift ├── UIApplicationExtension.swift ├── GroupedLabelsView.swift ├── LowPredictionViewController.swift ├── SnoozeActionsViewController.swift └── CarbCorrectionTreatment.swift ├── fastlaneRelease.sh ├── .DS_Store ├── Gemfile ├── fastlaneScreenshots.sh ├── fastlaneAll.sh ├── images ├── watch.jpg ├── Nightscout.xcf ├── nightguard24.jpg ├── Nightscout1024.png ├── nightguardOnWatch.gif ├── complicationicon36.png ├── watch-complication.jpg ├── Nightscout1024NoAlpha.png └── NightscoutAppStoreIcon.jpg ├── fastlane ├── screenshots │ ├── .DS_Store │ ├── fi │ │ ├── .DS_Store │ │ ├── keyword.strings │ │ └── title.strings │ ├── background.jpg │ ├── fonts │ │ ├── Bosk.ttf │ │ └── FatCow.ttf │ ├── de-DE │ │ ├── .DS_Store │ │ ├── keyword.strings │ │ └── title.strings │ ├── en-US │ │ ├── .DS_Store │ │ ├── keyword.strings │ │ └── title.strings │ └── Framefile.json ├── Appfile ├── Snapfile ├── README.md └── Fastfile ├── nightguard Complication ├── Assets.xcassets │ ├── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── WidgetBackground.colorset │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── de.lproj │ └── nightguard_Complication.strings ├── fi-FI.lproj │ └── nightguard_Complication.strings ├── Info.plist ├── AccessoryCornerView.swift ├── AccessoryCornerGaugeView.swift └── Base.lproj │ └── nightguard_Complication.intentdefinition ├── nightguard WatchKit App ├── Media.xcassets │ ├── Contents.json │ ├── .DS_Store │ ├── AppIcon.appiconset │ │ ├── .DS_Store │ │ ├── Icon38mm@2x.png │ │ ├── Icon42mm@2x.png │ │ ├── Nightscout 1.png │ │ ├── Nightscout 2.png │ │ ├── Nightscout 3.png │ │ ├── Nightscout 4.png │ │ ├── Nightscout 5.png │ │ ├── Nightscout66.png │ │ ├── IconLauncher@2x.png │ │ ├── IconSettings@2x.png │ │ ├── IconSettings@3x.png │ │ ├── Nightscout100x2.png │ │ ├── Nightscout216x2.png │ │ ├── Nightscout88-x2.png │ │ ├── IconQuickLook38mm@2x.png │ │ ├── IconQuickLook42mm@2x.png │ │ ├── Nightscout.textClipping │ │ └── Nightscout1024NoAlpha.png │ ├── Activity1.imageset │ │ ├── Activity1.png │ │ ├── Activity1@2x.png │ │ ├── Activity1@3x.png │ │ └── Contents.json │ ├── Activity10.imageset │ │ ├── Activity10.png │ │ ├── Activity10@2x.png │ │ ├── Activity10@3x.png │ │ └── Contents.json │ ├── Activity11.imageset │ │ ├── Activity11.png │ │ ├── Activity11@2x.png │ │ ├── Activity11@3x.png │ │ └── Contents.json │ ├── Activity12.imageset │ │ ├── Activity12.png │ │ ├── Activity12@2x.png │ │ ├── Activity12@3x.png │ │ └── Contents.json │ ├── Activity13.imageset │ │ ├── Activity13.png │ │ ├── Activity13@2x.png │ │ ├── Activity13@3x.png │ │ └── Contents.json │ ├── Activity14.imageset │ │ ├── Activity14.png │ │ ├── Activity14@2x.png │ │ ├── Activity14@3x.png │ │ └── Contents.json │ ├── Activity15.imageset │ │ ├── Activity15.png │ │ ├── Activity15@2x.png │ │ ├── Activity15@3x.png │ │ └── Contents.json │ ├── Activity2.imageset │ │ ├── Activity2.png │ │ ├── Activity2@2x.png │ │ ├── Activity2@3x.png │ │ └── Contents.json │ ├── Activity3.imageset │ │ ├── Activity3.png │ │ ├── Activity3@2x.png │ │ ├── Activity3@3x.png │ │ └── Contents.json │ ├── Activity4.imageset │ │ ├── Activity4.png │ │ ├── Activity4@2x.png │ │ ├── Activity4@3x.png │ │ └── Contents.json │ ├── Activity5.imageset │ │ ├── Activity5.png │ │ ├── Activity5@2x.png │ │ ├── Activity5@3x.png │ │ └── Contents.json │ ├── Activity6.imageset │ │ ├── Activity6.png │ │ ├── Activity6@2x.png │ │ ├── Activity6@3x.png │ │ └── Contents.json │ ├── Activity7.imageset │ │ ├── Activity7.png │ │ ├── Activity7@2x.png │ │ ├── Activity7@3x.png │ │ └── Contents.json │ ├── Activity8.imageset │ │ ├── Activity8.png │ │ ├── Activity8@2x.png │ │ ├── Activity8@3x.png │ │ └── Contents.json │ ├── Activity9.imageset │ │ ├── Activity9.png │ │ ├── Activity9@2x.png │ │ ├── Activity9@3x.png │ │ └── Contents.json │ └── Complication.complicationset │ │ ├── .DS_Store │ │ ├── Circular.imageset │ │ ├── complicationicon32.png │ │ ├── complicationicon36.png │ │ ├── complicationicon40.png │ │ ├── complicationicon36-2.png │ │ └── Contents.json │ │ ├── Graphic Corner.imageset │ │ ├── Nightscout40.png │ │ ├── Nightscout44.png │ │ └── Contents.json │ │ ├── Modular.imageset │ │ ├── complicationicon58.png │ │ ├── complicationicon52-1.png │ │ └── Contents.json │ │ ├── Graphic Circular.imageset │ │ ├── Nightscout84.png │ │ ├── Nightscout94.png │ │ └── Contents.json │ │ ├── Utilitarian.imageset │ │ ├── complicationicon40.png │ │ ├── complicationicon44.png │ │ └── Contents.json │ │ ├── Extra Large.imageset │ │ └── Contents.json │ │ ├── Graphic Bezel.imageset │ │ └── Contents.json │ │ ├── Graphic Extra Large.imageset │ │ └── Contents.json │ │ ├── Graphic Large Rectangular.imageset │ │ └── Contents.json │ │ └── Contents.json ├── NotificationExtension.swift ├── nightguard.entitlements ├── AppConstants.swift ├── controllers │ ├── CarbsController.swift │ ├── TemporaryTargetController.swift │ ├── ActionButtonController.swift │ ├── MainController.swift │ ├── NotificationController.swift │ └── SnoozeInterfaceController.swift ├── app │ └── AppState.swift ├── external │ └── AppMessageService.swift ├── Supporting Files │ └── PushNotificationPayload.apns ├── ViewExtension.swift ├── Info.plist ├── views │ ├── AddCarbsPopupView.swift │ ├── CancelTemporaryTargetPopupView.swift │ └── ActivateTemporaryTargetPopupView.swift └── helper │ └── WKInterfaceLabel.swift ├── nightguard Widget Extension ├── Assets.xcassets │ ├── Contents.json │ ├── WidgetImageBlack.imageset │ │ ├── Icon-small-black@3x.png │ │ └── Contents.json │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── WidgetBackground.colorset │ │ └── Contents.json │ └── AppIcon.appiconset │ │ └── Contents.json ├── de.lproj │ ├── nightguard_Widget_Extension.strings │ └── nightguard_Widget_Extension.intentdefinition ├── fi-FI.lproj │ └── nightguard_Widget_Extension.strings ├── Info.plist ├── AccessoryInlineView.swift ├── AccessoryCircularView.swift ├── AccessoryCircularGaugeView.swift └── Base.lproj │ └── nightguard_Widget_Extension.intentdefinition ├── nightguardNotification.apns ├── nightguard.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── dirk.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── dirk.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── nightguard.xcworkspace ├── xcshareddata │ ├── WorkspaceSettings.xcsettings │ └── IDEWorkspaceChecks.plist └── contents.xcworkspacedata ├── nightguard ComplicationExtension.entitlements ├── nightguard Widget ExtensionExtension.entitlements ├── .gitignore ├── Podfile.lock ├── nightguardTests ├── TimeServiceTest.swift ├── Info.plist ├── TargetDataTest.swift └── UserDefaultsRepositoryTest.swift ├── nightguard.xctestplan ├── nightguardUITests └── Info.plist └── Podfile /nightguard/de.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlaneRelease.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bundle exec fastlane ios release 3 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/.DS_Store -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane", ">= 2.150.rc1" 4 | -------------------------------------------------------------------------------- /fastlaneScreenshots.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bundle exec fastlane ios screenshots 3 | -------------------------------------------------------------------------------- /fastlaneAll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ./fastlaneScreenshots.sh 3 | ./fastlaneRelease.sh 4 | -------------------------------------------------------------------------------- /images/watch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/watch.jpg -------------------------------------------------------------------------------- /nightguard/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/.DS_Store -------------------------------------------------------------------------------- /nightguard/alarm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/alarm.mp3 -------------------------------------------------------------------------------- /images/Nightscout.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/Nightscout.xcf -------------------------------------------------------------------------------- /images/nightguard24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/nightguard24.jpg -------------------------------------------------------------------------------- /images/Nightscout1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/Nightscout1024.png -------------------------------------------------------------------------------- /images/nightguardOnWatch.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/nightguardOnWatch.gif -------------------------------------------------------------------------------- /fastlane/screenshots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/.DS_Store -------------------------------------------------------------------------------- /images/complicationicon36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/complicationicon36.png -------------------------------------------------------------------------------- /images/watch-complication.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/watch-complication.jpg -------------------------------------------------------------------------------- /fastlane/screenshots/fi/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/fi/.DS_Store -------------------------------------------------------------------------------- /images/Nightscout1024NoAlpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/Nightscout1024NoAlpha.png -------------------------------------------------------------------------------- /images/NightscoutAppStoreIcon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/images/NightscoutAppStoreIcon.jpg -------------------------------------------------------------------------------- /nightguard/alarm-notification.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/alarm-notification.m4a -------------------------------------------------------------------------------- /fastlane/screenshots/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/background.jpg -------------------------------------------------------------------------------- /fastlane/screenshots/fonts/Bosk.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/fonts/Bosk.ttf -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /fastlane/screenshots/de-DE/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/de-DE/.DS_Store -------------------------------------------------------------------------------- /fastlane/screenshots/en-US/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/en-US/.DS_Store -------------------------------------------------------------------------------- /fastlane/screenshots/fonts/FatCow.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/fastlane/screenshots/fonts/FatCow.ttf -------------------------------------------------------------------------------- /nightguard/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/de.lproj/Localizable.strings -------------------------------------------------------------------------------- /nightguard Complication/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /nightguard/Base.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Base.lproj/Localizable.strings -------------------------------------------------------------------------------- /nightguard Complication/de.lproj/nightguard_Complication.strings: -------------------------------------------------------------------------------- 1 | "gpCwrM" = "Konfiguration"; 2 | 3 | "tVvJ9c" = "Complication Konfiguration"; 4 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /nightguard Complication/fi-FI.lproj/nightguard_Complication.strings: -------------------------------------------------------------------------------- 1 | "gpCwrM" = "Configuration"; 2 | 3 | "tVvJ9c" = "Complication Configuration"; 4 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/.DS_Store -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Care.imageset/hand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Care.imageset/hand.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/close.imageset/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/close.imageset/close.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Alarm.imageset/Alarm@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Alarm.imageset/Alarm@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Alarm.imageset/Alarm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Alarm.imageset/Alarm@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Alarm.imageset/Alarm@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Alarm.imageset/Alarm@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Main.imageset/Main@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Main.imageset/Main@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Main.imageset/Main@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Main.imageset/Main@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Main.imageset/Main@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Main.imageset/Main@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Prefs.imageset/Prefs@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Prefs.imageset/Prefs@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Prefs.imageset/Prefs@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Prefs.imageset/Prefs@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Prefs.imageset/Prefs@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Prefs.imageset/Prefs@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Stats.imageset/Stats@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Stats.imageset/Stats@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Stats.imageset/Stats@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Stats.imageset/Stats@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Stats.imageset/Stats@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Stats.imageset/Stats@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/close.imageset/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/close.imageset/close@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/close.imageset/close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/close.imageset/close@3x.png -------------------------------------------------------------------------------- /nightguard Widget Extension/de.lproj/nightguard_Widget_Extension.strings: -------------------------------------------------------------------------------- 1 | "gpCwrM" = "Configuration"; 2 | 3 | "tVvJ9c" = "Lockscreen Widget Konfiguration."; 4 | 5 | -------------------------------------------------------------------------------- /nightguard Widget Extension/fi-FI.lproj/nightguard_Widget_Extension.strings: -------------------------------------------------------------------------------- 1 | "gpCwrM" = "Configuration"; 2 | 3 | "tVvJ9c" = "Lockscreen Widget Configuration."; 4 | 5 | -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Action.imageset/Action@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Action.imageset/Action@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Action.imageset/Action@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Action.imageset/Action@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Action.imageset/Action@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Action.imageset/Action@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Fullscreen.imageset/Fullscreen@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Nightscout.imageset/Nightscout@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Nightscout.imageset/Nightscout@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Nightscout.imageset/Nightscout@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Nightscout.imageset/Nightscout@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Nightscout.imageset/Nightscout@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/Nightscout.imageset/Nightscout@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-low.imageset/volume-low@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-low.imageset/volume-low@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-low.imageset/volume-low@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-low.imageset/volume-low@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-low.imageset/volume-low@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-low.imageset/volume-low@3x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-25.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-50.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/SlideArrow.imageset/slide-arrow-75.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-high.imageset/volume-high@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-high.imageset/volume-high@1x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-high.imageset/volume-high@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-high.imageset/volume-high@2x.png -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-high.imageset/volume-high@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/volume-high.imageset/volume-high@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/.DS_Store -------------------------------------------------------------------------------- /nightguard/Media.xcassets/AppIcon.appiconset/Nightscout1024NoAlpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard/Media.xcassets/AppIcon.appiconset/Nightscout1024NoAlpha.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Icon38mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Icon38mm@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Icon42mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Icon42mm@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity1.imageset/Activity1@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity2.imageset/Activity2@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity3.imageset/Activity3@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity4.imageset/Activity4@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity5.imageset/Activity5@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity6.imageset/Activity6@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity7.imageset/Activity7@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity8.imageset/Activity8@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity9.imageset/Activity9@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 1.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 3.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 4.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout 5.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout66.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity10.imageset/Activity10@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity11.imageset/Activity11@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity12.imageset/Activity12@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity13.imageset/Activity13@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity14.imageset/Activity14@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Activity15.imageset/Activity15@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconLauncher@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconLauncher@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconSettings@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconSettings@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconSettings@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconSettings@3x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout100x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout100x2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout216x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout216x2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout88-x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout88-x2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/.DS_Store -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconQuickLook38mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconQuickLook38mm@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconQuickLook42mm@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/IconQuickLook42mm@2x.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout.textClipping: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout.textClipping -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout1024NoAlpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/AppIcon.appiconset/Nightscout1024NoAlpha.png -------------------------------------------------------------------------------- /nightguard/de.lproj/Duration.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Timer"; ObjectID = "WXX-3u-WfV"; */ 3 | "WXX-3u-WfV.title" = "Dauer"; 4 | 5 | "pQL-1y-5Wv.title" = "Dauer"; 6 | 7 | "eVw-6N-D8o.title" = "Dauer"; 8 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Duration.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Timer"; ObjectID = "WXX-3u-WfV"; */ 3 | "WXX-3u-WfV.title" = "Kesto"; 4 | 5 | "pQL-1y-5Wv.title" = "Kesto"; 6 | 7 | "eVw-6N-D8o.title" = "Kesto"; 8 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/WidgetImageBlack.imageset/Icon-small-black@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard Widget Extension/Assets.xcassets/WidgetImageBlack.imageset/Icon-small-black@3x.png -------------------------------------------------------------------------------- /nightguardNotification.apns: -------------------------------------------------------------------------------- 1 | { 2 | "Simulator Target Bundle": "de.my-wan.dhe.nightguard", 3 | "aps": { 4 | "alert": "Push Notifications Test", 5 | "sound": "default", 6 | "badge": 1 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /nightguard Complication/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nightguard Complication/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nightguard/de.lproj/Care.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Care"; ObjectID = "1MK-Nl-hRR"; */ 3 | "1MK-Nl-hRR.title" = "Aktion"; 4 | 5 | /* Class = "UINavigationItem"; title = "Care"; ObjectID = "xcV-xC-wUM"; */ 6 | "xcV-xC-wUM.title" = "Aktion"; 7 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon32.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon36.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon40.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Corner.imageset/Nightscout40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Corner.imageset/Nightscout40.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Corner.imageset/Nightscout44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Corner.imageset/Nightscout44.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Modular.imageset/complicationicon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Modular.imageset/complicationicon58.png -------------------------------------------------------------------------------- /nightguard/de.lproj/Alarm.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Alarms"; ObjectID = "5WR-Lr-3ax"; */ 3 | "5WR-Lr-3ax.title" = "Alarme"; 4 | 5 | /* Class = "UINavigationItem"; title = "Alarms"; ObjectID = "7i7-rr-MK5"; */ 6 | "7i7-rr-MK5.title" = "Alarme"; 7 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon36-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/complicationicon36-2.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Circular.imageset/Nightscout84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Circular.imageset/Nightscout84.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Circular.imageset/Nightscout94.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Circular.imageset/Nightscout94.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Modular.imageset/complicationicon52-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Modular.imageset/complicationicon52-1.png -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Care.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Care"; ObjectID = "1MK-Nl-hRR"; */ 3 | "1MK-Nl-hRR.title" = "Huolenpito"; 4 | 5 | /* Class = "UINavigationItem"; title = "Care"; ObjectID = "xcV-xC-wUM"; */ 6 | "xcV-xC-wUM.title" = "Huolenpito"; 7 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Utilitarian.imageset/complicationicon40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Utilitarian.imageset/complicationicon40.png -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Utilitarian.imageset/complicationicon44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nightscout/nightguard/HEAD/nightguard WatchKit App/Media.xcassets/Complication.complicationset/Utilitarian.imageset/complicationicon44.png -------------------------------------------------------------------------------- /nightguard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Alarm.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Alarms"; ObjectID = "5WR-Lr-3ax"; */ 3 | "5WR-Lr-3ax.title" = "Hälytykset"; 4 | 5 | /* Class = "UINavigationItem"; title = "Alarms"; ObjectID = "7i7-rr-MK5"; */ 6 | "7i7-rr-MK5.title" = "Hälytykset"; 7 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Preferences.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Preferences"; ObjectID = "Ll0-ak-LlN"; */ 3 | "Ll0-ak-LlN.title" = "Asetukset"; 4 | 5 | /* Class = "UINavigationItem"; title = "Preferences"; ObjectID = "pOZ-1z-Erq"; */ 6 | "pOZ-1z-Erq.title" = "Asetukset"; 7 | -------------------------------------------------------------------------------- /nightguard/KeepAwakeMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeepAwakeMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class KeepAwakeMessage: EmptyWatchMessage {} 12 | -------------------------------------------------------------------------------- /nightguard/de.lproj/Preferences.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Preferences"; ObjectID = "Ll0-ak-LlN"; */ 3 | "Ll0-ak-LlN.title" = "Einstellungen"; 4 | 5 | /* Class = "UINavigationItem"; title = "Preferences"; ObjectID = "pOZ-1z-Erq"; */ 6 | "pOZ-1z-Erq.title" = "Einstellungen"; 7 | -------------------------------------------------------------------------------- /fastlane/screenshots/en-US/keyword.strings: -------------------------------------------------------------------------------- 1 | "main" = "NIGHTGUARD"; 2 | 3 | "nightscout" = "NIGHTSCOUT"; 4 | 5 | "fullscreen" = "NIGHTMODE"; 6 | 7 | "care" = "CARE"; 8 | 9 | "duration" = "DURATION"; 10 | 11 | "alarms" = "ALARMS"; 12 | 13 | "stats" = "STATS"; 14 | 15 | "preferences" = "START"; 16 | -------------------------------------------------------------------------------- /fastlane/screenshots/de-DE/keyword.strings: -------------------------------------------------------------------------------- 1 | "main" = "NIGHTGUARD"; 2 | 3 | "nightscout" = "NIGHTSCOUT"; 4 | 5 | "fullscreen" = "NACHTMODUS"; 6 | 7 | "alarms" = "ALARME"; 8 | 9 | "care" = "AKTION"; 10 | 11 | "duration" = "Dauer"; 12 | 13 | "stats" = "STATISTIKEN"; 14 | 15 | "preferences" = "START"; 16 | -------------------------------------------------------------------------------- /fastlane/screenshots/fi/keyword.strings: -------------------------------------------------------------------------------- 1 | "main" = "NIGHTGUARD"; 2 | 3 | "nightscout" = "NIGHTSCOUT"; 4 | 5 | "fullscreen" = "YÖTILA"; 6 | 7 | "care" = "CARE"; 8 | 9 | "duration" = "KESTO"; 10 | 11 | "alarms" = "HÄLYTYKSET"; 12 | 13 | "stats" = "TILASTOT"; 14 | 15 | "preferences" = "ASETUKSET"; 16 | -------------------------------------------------------------------------------- /nightguard Complication/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "watchos", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | } 8 | ], 9 | "info" : { 10 | "author" : "xcode", 11 | "version" : 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nightguard.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /nightguard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /nightguard/RequestAlarmNotificationMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RequestNotificationMessage.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 06.02.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class RequestAlarmNotificationMessage: EmptyWatchMessage {} 12 | -------------------------------------------------------------------------------- /nightguard WatchKit App/NotificationExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationExtension.swift 3 | // nightguard WatchKit App 4 | // 5 | // Created by Philipp Pöml on 29.05.24. 6 | // 7 | 8 | import Foundation 9 | 10 | extension Notification.Name { 11 | static let refreshDataOnAppBecameActive = Notification.Name("Updates data on wrist raise") 12 | } 13 | -------------------------------------------------------------------------------- /nightguard ComplicationExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.de.my-wan.dhe.nightguard 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /nightguard Complication/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /nightguard WatchKit App/nightguard.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.de.my-wan.dhe.nightguard 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /nightguard Widget ExtensionExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.de.my-wan.dhe.nightguard 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.widgetkit-extension 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /nightguard.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Nightscout.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UIBarButtonItem"; title = "Close"; ObjectID = "3Bs-z4-DS6"; */ 3 | "3Bs-z4-DS6.title" = "Sulje"; 4 | 5 | /* Class = "UIBarButtonItem"; title = "Refresh"; ObjectID = "Ccu-t3-DVe"; */ 6 | "Ccu-t3-DVe.title" = "Päivitä"; 7 | 8 | /* Class = "UINavigationItem"; title = "Nightscout"; ObjectID = "YUj-LD-aQw"; */ 9 | "YUj-LD-aQw.title" = "Nightscout"; 10 | -------------------------------------------------------------------------------- /nightguard/de.lproj/Nightscout.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UIBarButtonItem"; title = "Close"; ObjectID = "3Bs-z4-DS6"; */ 3 | "3Bs-z4-DS6.title" = "Schließen"; 4 | 5 | /* Class = "UIBarButtonItem"; title = "Refresh"; ObjectID = "Ccu-t3-DVe"; */ 6 | "Ccu-t3-DVe.title" = "Aktualisieren"; 7 | 8 | /* Class = "UINavigationItem"; title = "Nightscout"; ObjectID = "YUj-LD-aQw"; */ 9 | "YUj-LD-aQw.title" = "Nightscout"; 10 | -------------------------------------------------------------------------------- /nightguard WatchKit App/AppConstants.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppConstants.swift 3 | // scoutwatch 4 | // 5 | // Created by Dirk Hermanns on 26.12.15. 6 | // Copyright © 2015 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // Class that contains general constants used in different classes 12 | class AppConstants { 13 | internal static let APP_GROUP_ID = "group.de.my-wan.dhe.nightguard" 14 | } 15 | -------------------------------------------------------------------------------- /nightguard/DictionaryExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DictionaryExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 12.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Dictionary where Value: Equatable { 12 | func key(from value: Value) -> Key? { 13 | return self.first(where: { $0.value == value })?.key 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nightguard/Comparable+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Comparable+Extensions.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 3/22/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Comparable { 12 | func clamped(to limits: ClosedRange) -> Self { 13 | return min(max(self, limits.lowerBound), limits.upperBound) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fastlane/screenshots/fi/title.strings: -------------------------------------------------------------------------------- 1 | 2 | "main" = "Arvot yhdellä silmäyksellä"; 3 | 4 | "nightscout" = "Nopea pääsy nightscout sivustollesi"; 5 | 6 | "fullscreen" = "Parempi luettavuus yötilassa"; 7 | 8 | "alarms" = "Säädä yksityiskohdat"; 9 | 10 | "care" = "Aseta väliaikaiset tavoitteet"; 11 | 12 | "duration" = "Seuraa kanyylin ikää"; 13 | 14 | "stats" = "Vertaa päiviä"; 15 | 16 | "preferences" = "Syötä Nightscout URL"; 17 | -------------------------------------------------------------------------------- /fastlane/screenshots/de-DE/title.strings: -------------------------------------------------------------------------------- 1 | 2 | "main" = "Alle Werte auf einen Blick"; 3 | 4 | "nightscout" = "Zugriff auf die Webseite"; 5 | 6 | "fullscreen" = "Extra groß im Dunkeln"; 7 | 8 | "care" = "Temporäre Ziele setzen"; 9 | 10 | "duration" = "Kathederalter im Blick behalten"; 11 | 12 | "alarms" = "Mit vielen Optionen"; 13 | 14 | "stats" = "Vergleiche verschiedene Tage"; 15 | 16 | "preferences" = "Gebe nur Deine Nightscout-URL ein"; 17 | -------------------------------------------------------------------------------- /fastlane/screenshots/en-US/title.strings: -------------------------------------------------------------------------------- 1 | 2 | "main" = "Your values at a glance"; 3 | 4 | "nightscout" = "Fast access to your nightscout site"; 5 | 6 | "fullscreen" = "Extra readability at night"; 7 | 8 | "care" = "Set temporary targets"; 9 | 10 | "duration" = "Keep track of cannula age"; 11 | 12 | "alarms" = "Tune all the details"; 13 | 14 | "stats" = "Compare every single day"; 15 | 16 | "preferences" = "By entering Nightscout-URL"; 17 | -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Care.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "hand.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/CarbsController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CarbsController.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 18.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | import SwiftUI 12 | 13 | class CarbsController: WKHostingController { 14 | override var body: CarbsView { 15 | return CarbsView() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /nightguard WatchKit App/app/AppState.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppState.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 09.02.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class AppState { 12 | 13 | // Flag for the watchos app to determine whether the UI is displayed or not. 14 | // This is used to decide whether an alarm should be played. 15 | static var isUIActive = false 16 | } 17 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Assets.xcassets/WidgetImageBlack.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "filename" : "Icon-small-black@3x.png", 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nightguard/EmptyWatchMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyWatchMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class EmptyWatchMessage: WatchMessage { 12 | 13 | var dictionary: [String : Any] { 14 | return [:] 15 | } 16 | 17 | init() { 18 | } 19 | 20 | required init?(dictionary: [String : Any]) { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nightguard.app.dSYM.zip 2 | nightguard.ipa 3 | nightguard.xcodeproj/xcshareddata/ 4 | Pods/ 5 | nightguard.xcodeproj/project.xcworkspace/xcshareddata/ 6 | nightguard.xcodeproj/project.xcworkspace/xcuserdata/ 7 | nightguard.xcodeproj/xcuserdata/ 8 | nightguard.xcworkspace/xcuserdata/ 9 | fastlane/Preview.html 10 | fastlane/report.xml 11 | fastlane/screenshots/en-US/*.png 12 | fastlane/screenshots/de-DE/*.png 13 | fastlane/screenshots/fi/*.png 14 | fastlane/screenshots/screenshots.html 15 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier("de.my-wan.dhe.nightguard") # The bundle identifier of your app 2 | apple_id("h3rmanns@gmail.com") # Your Apple email address 3 | 4 | # You can uncomment the lines below and add your own 5 | # team selection in case you're in multiple teams 6 | team_name "SPORTMEO LTD" 7 | team_id "127329692" 8 | 9 | itc_team_name "SPORTMEO LTD" 10 | itc_team_id "127329692" 11 | 12 | # For more information about the Appfile, see: 13 | # https://docs.fastlane.tools/advanced/#appfile 14 | -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/TemporaryTargetController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CareController.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 11.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | import SwiftUI 12 | 13 | class TemporaryTargetController: WKHostingController { 14 | override var body: TemporaryTargetView { 15 | return TemporaryTargetView() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Main.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Main@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Main@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Main@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "close.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "close@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "close@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Alarm.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Alarm@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Alarm@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Alarm@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Prefs.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Prefs@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Prefs@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Prefs@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Stats.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Stats@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Stats@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Stats@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Action.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Action@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Action@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Action@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/ActionButtonController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionController.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 05.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | import SwiftUI 12 | 13 | class ActionButtonController: WKHostingController { 14 | override var body: ActionButtonView { 15 | return ActionButtonView(mainViewModel: MainController.mainViewModel) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Fullscreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Fullscreen@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Fullscreen@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Fullscreen@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/Nightscout.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Nightscout@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Nightscout@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Nightscout@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/SlideArrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "slide-arrow-25.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "slide-arrow-50.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "slide-arrow-75.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-low.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "volume-low@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "volume-low@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "volume-low@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/UIImageExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 07.11.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIImage { 13 | 14 | static func emptyImage(with size: CGSize) -> UIImage? { 15 | UIGraphicsBeginImageContext(size) 16 | let image = UIGraphicsGetImageFromCurrentImageContext() 17 | UIGraphicsEndImageContext() 18 | return image 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity1@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity1@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity2@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity2@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity3.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity3@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity3@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity4.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity4@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity4@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity5.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity5@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity5@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity6.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity6@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity6@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity7.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity7@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity7@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity8.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity8@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity8@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity9.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity9@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity9@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard/Media.xcassets/volume-high.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "volume-high@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "volume-high@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "volume-high@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity10.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity10@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity10@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity11.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity11@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity11@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity12.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity12@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity12@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity13.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity13@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity13@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity14.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity14@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity14@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Activity15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Activity15.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Activity15@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Activity15@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Eureka (5.3.3) 3 | - XLActionController (5.1.0): 4 | - XLActionController/Core (= 5.1.0) 5 | - XLActionController/Core (5.1.0) 6 | 7 | DEPENDENCIES: 8 | - Eureka 9 | - XLActionController 10 | 11 | SPEC REPOS: 12 | trunk: 13 | - Eureka 14 | - XLActionController 15 | 16 | SPEC CHECKSUMS: 17 | Eureka: e6d720290c56bb23333ad1a0e020b2a98a0e9a43 18 | XLActionController: 24140d835ab9e260270711afebc5efabebe9d392 19 | 20 | PODFILE CHECKSUM: dc0d10611d5c8069733cc7799527d08999ed32c2 21 | 22 | COCOAPODS: 1.16.2 23 | -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/MainController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HostingController.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 08.09.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | import SwiftUI 12 | 13 | class MainController: WKHostingController { 14 | 15 | static var mainViewModel = MainViewModel() 16 | 17 | override var body: MainView { 18 | return MainView(mainViewModel: MainController.mainViewModel) 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /nightguard/UIViewControllerExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewControllerExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 17.03.17. 6 | // Copyright © 2017 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIViewController { 13 | 14 | // The maximum Chart-Width is restricted to 4096 / Device-Scale pixels 15 | // So take care, that this is not exceeded. Otherwise we get nothing but a 16 | // black texture. 17 | func maximumDeviceTextureWidth() -> CGFloat { 18 | return 4096 / UIScreen.main.scale 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">161" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "scale" : "2x", 16 | "screen-width" : ">145" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "scale" : "2x", 21 | "screen-width" : ">183" 22 | } 23 | ], 24 | "info" : { 25 | "version" : 1, 26 | "author" : "xcode" 27 | } 28 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/external/AppMessageService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppPushService.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 27.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WatchKit 11 | import WatchConnectivity 12 | 13 | // This class handles values that are passed from the ios app. 14 | class AppMessageService { 15 | 16 | static let singleton = AppMessageService() 17 | 18 | // send a dummy message to keep the phone app awake (start the app if is not started) 19 | func keepAwakePhoneApp() { 20 | KeepAwakeMessage().send() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /nightguard.xcodeproj/project.xcworkspace/xcuserdata/dirk.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | IssueFilterStyle 12 | ShowActiveSchemeOnly 13 | LiveSourceIssuesEnabled 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /nightguard/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /nightguardTests/TimeServiceTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeServiceTest.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 07.07.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TimeServiceTest : XCTestCase { 12 | 13 | func testMinus29MinutesIsNotOlderThan30Minutes() { 14 | 15 | XCTAssertFalse(TimeService.isOlderThan30Minutes(Date.init().addingTimeInterval(-60 * 29))) 16 | } 17 | 18 | func testMinus31MinutesIsOlderThan30Minutes() { 19 | 20 | XCTAssertTrue(TimeService.isOlderThan30Minutes(Date.init().addingTimeInterval(-60 * 31))) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Extra Large.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">161" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "scale" : "2x", 16 | "screen-width" : ">145" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "scale" : "2x", 21 | "screen-width" : ">183" 22 | } 23 | ], 24 | "info" : { 25 | "author" : "xcode", 26 | "version" : 1 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "scale" : "2x", 11 | "screen-width" : ">161" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "scale" : "2x", 16 | "screen-width" : ">145" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "scale" : "2x", 21 | "screen-width" : ">183" 22 | } 23 | ], 24 | "info" : { 25 | "version" : 1, 26 | "author" : "xcode" 27 | } 28 | } -------------------------------------------------------------------------------- /nightguard/Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Helpers.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 11/14/18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | func dispatchOnMain(_ closure: @escaping () -> ()) { 12 | if Thread.isMainThread { 13 | closure() 14 | } else { 15 | DispatchQueue.main.async { 16 | closure() 17 | } 18 | } 19 | } 20 | 21 | func delay(_ delay:Double, closure: @escaping () -> ()) { 22 | DispatchQueue.main.asyncAfter( 23 | deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /nightguard/external/regression/Matrix+Description.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Matrix+Description.swift 3 | // Regression 4 | // 5 | // Created by Dominik Felber on 16.05.16. 6 | // Copyright © 2016 Dominik Felber. All rights reserved. 7 | // 8 | 9 | extension Matrix: CustomStringConvertible 10 | { 11 | var description: String { 12 | var desc = "*** Matrix(\(self.columns)x\(self.rows)) ***\n" 13 | 14 | for row in 0.. Void 15 | 16 | init(cancellationClosure: @escaping () -> Void) { 17 | self.cancellationClosure = cancellationClosure 18 | } 19 | 20 | func cancel() { 21 | cancellationClosure() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nightguard/scoutwatch.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.healthkit 6 | 7 | com.apple.developer.healthkit.access 8 | 9 | health-records 10 | 11 | com.apple.developer.healthkit.background-delivery 12 | 13 | com.apple.security.application-groups 14 | 15 | group.de.my-wan.dhe.nightguard 16 | 17 | com.apple.developer.usernotifications.critical-alerts 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "filename" : "Nightscout84.png", 11 | "screen-width" : ">161", 12 | "scale" : "2x" 13 | }, 14 | { 15 | "idiom" : "watch", 16 | "scale" : "2x", 17 | "screen-width" : ">145" 18 | }, 19 | { 20 | "idiom" : "watch", 21 | "filename" : "Nightscout94.png", 22 | "screen-width" : ">183", 23 | "scale" : "2x" 24 | } 25 | ], 26 | "info" : { 27 | "version" : 1, 28 | "author" : "xcode" 29 | } 30 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x", 6 | "screen-width" : "<=145" 7 | }, 8 | { 9 | "idiom" : "watch", 10 | "filename" : "Nightscout40.png", 11 | "screen-width" : ">161", 12 | "scale" : "2x" 13 | }, 14 | { 15 | "idiom" : "watch", 16 | "scale" : "2x", 17 | "screen-width" : ">145" 18 | }, 19 | { 20 | "idiom" : "watch", 21 | "filename" : "Nightscout44.png", 22 | "screen-width" : ">183", 23 | "scale" : "2x" 24 | } 25 | ], 26 | "info" : { 27 | "version" : 1, 28 | "author" : "xcode" 29 | } 30 | } -------------------------------------------------------------------------------- /nightguard.xctestplan: -------------------------------------------------------------------------------- 1 | { 2 | "configurations" : [ 3 | { 4 | "id" : "78ECACD6-8FC0-4475-B36E-80C6EE6B5044", 5 | "name" : "Test Scheme Action", 6 | "options" : { 7 | 8 | } 9 | } 10 | ], 11 | "defaultOptions" : { 12 | "codeCoverage" : false, 13 | "targetForVariableExpansion" : { 14 | "containerPath" : "container:nightguard.xcodeproj", 15 | "identifier" : "43647BC91BFF6435004389F9", 16 | "name" : "nightguard" 17 | } 18 | }, 19 | "testTargets" : [ 20 | { 21 | "target" : { 22 | "containerPath" : "container:nightguard.xcodeproj", 23 | "identifier" : "43647BDD1BFF6435004389F9", 24 | "name" : "nightguardTests" 25 | } 26 | } 27 | ], 28 | "version" : 1 29 | } 30 | -------------------------------------------------------------------------------- /nightguard/XCUIElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XCUIElement.swift 3 | // nightguardUITests 4 | // 5 | // Created by Dirk Hermanns on 15.04.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | import XCTest 9 | 10 | extension XCUIElement { 11 | 12 | func clearText(andReplaceWith newText:String? = nil) { 13 | 14 | let myValue = self.value 15 | guard let stringValue = myValue as? String else { 16 | XCTFail("Tried to clear and enter text into a non string value") 17 | return 18 | } 19 | //self.tap() 20 | let deleteString = String(repeating: XCUIKeyboardKey.delete.rawValue, count: stringValue.count) 21 | self.typeText(deleteString) 22 | 23 | if let newVal = newText { typeText(newVal) } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /nightguard/PaddingLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PaddingLabel.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 6/14/18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PaddingLabel: UILabel { 12 | 13 | var insets : UIEdgeInsets = UIEdgeInsets() { 14 | didSet { 15 | super.invalidateIntrinsicContentSize() 16 | } 17 | } 18 | 19 | override var intrinsicContentSize: CGSize { 20 | var size = super.intrinsicContentSize 21 | size.width += insets.left + insets.right 22 | size.height += insets.top + insets.bottom 23 | return size 24 | } 25 | 26 | override func drawText(in rect: CGRect) { 27 | return super.drawText(in: rect.inset(by: insets)) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Bedside.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "01:40"; ObjectID = "6GO-4B-bqb"; */ 3 | "6GO-4B-bqb.text" = "01:40"; 4 | 5 | /* Class = "UILabel"; text = "-"; ObjectID = "84s-NK-Vg0"; */ 6 | "84s-NK-Vg0.text" = "-"; 7 | 8 | /* Class = "UILabel"; text = "Persistent High BG"; ObjectID = "H7F-lV-LNq"; */ 9 | "H7F-lV-LNq.text" = "Jatkuva korkea VS"; 10 | 11 | /* Class = "UILabel"; text = "Snoozed for 5min"; ObjectID = "Jks-QJ-79F"; */ 12 | "Jks-QJ-79F.text" = "Torkkuu 5min"; 13 | 14 | /* Class = "UILabel"; text = "3min"; ObjectID = "Tor-n5-kS0"; */ 15 | "Tor-n5-kS0.text" = "3min"; 16 | 17 | /* Class = "UILabel"; text = "-3"; ObjectID = "bBh-xU-jo5"; */ 18 | "bBh-xU-jo5.text" = "-3"; 19 | 20 | /* Class = "UILabel"; text = "222"; ObjectID = "y0D-Zw-4uO"; */ 21 | "y0D-Zw-4uO.text" = "222"; 22 | -------------------------------------------------------------------------------- /nightguard/de.lproj/Bedside.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "01:40"; ObjectID = "6GO-4B-bqb"; */ 3 | "6GO-4B-bqb.text" = "01:40"; 4 | 5 | /* Class = "UILabel"; text = "-"; ObjectID = "84s-NK-Vg0"; */ 6 | "84s-NK-Vg0.text" = "-"; 7 | 8 | /* Class = "UILabel"; text = "Persistent High BG"; ObjectID = "H7F-lV-LNq"; */ 9 | "H7F-lV-LNq.text" = "Dauerhaft hohe Werte"; 10 | 11 | /* Class = "UILabel"; text = "Snoozed for 5min"; ObjectID = "Jks-QJ-79F"; */ 12 | "Jks-QJ-79F.text" = "Schlummern für 5min"; 13 | 14 | /* Class = "UILabel"; text = "3min"; ObjectID = "Tor-n5-kS0"; */ 15 | "Tor-n5-kS0.text" = "3min"; 16 | 17 | /* Class = "UILabel"; text = "-3"; ObjectID = "bBh-xU-jo5"; */ 18 | "bBh-xU-jo5.text" = "-3"; 19 | 20 | /* Class = "UILabel"; text = "222"; ObjectID = "y0D-Zw-4uO"; */ 21 | "y0D-Zw-4uO.text" = "222"; 22 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Modular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "filename" : "complicationicon52-1.png", 10 | "screen-width" : "<=145", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "scale" : "2x", 16 | "screen-width" : ">161" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "filename" : "complicationicon58.png", 21 | "screen-width" : ">145", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "idiom" : "watch", 26 | "scale" : "2x", 27 | "screen-width" : ">183" 28 | } 29 | ], 30 | "info" : { 31 | "version" : 1, 32 | "author" : "xcode" 33 | } 34 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "filename" : "complicationicon40.png", 10 | "screen-width" : "<=145", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "scale" : "2x", 16 | "screen-width" : ">161" 17 | }, 18 | { 19 | "idiom" : "watch", 20 | "filename" : "complicationicon44.png", 21 | "screen-width" : ">145", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "idiom" : "watch", 26 | "scale" : "2x", 27 | "screen-width" : ">183" 28 | } 29 | ], 30 | "info" : { 31 | "version" : 1, 32 | "author" : "xcode" 33 | } 34 | } -------------------------------------------------------------------------------- /nightguardTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 2.7.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 923 23 | 24 | 25 | -------------------------------------------------------------------------------- /nightguardUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 2.7.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 923 23 | 24 | 25 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Circular.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "watch", 5 | "scale" : "2x" 6 | }, 7 | { 8 | "idiom" : "watch", 9 | "filename" : "complicationicon32.png", 10 | "screen-width" : "<=145", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "watch", 15 | "filename" : "complicationicon36-2.png", 16 | "screen-width" : ">161", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "idiom" : "watch", 21 | "filename" : "complicationicon36.png", 22 | "screen-width" : ">145", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "idiom" : "watch", 27 | "filename" : "complicationicon40.png", 28 | "screen-width" : ">183", 29 | "scale" : "2x" 30 | } 31 | ], 32 | "info" : { 33 | "version" : 1, 34 | "author" : "xcode" 35 | } 36 | } -------------------------------------------------------------------------------- /nightguard WatchKit App/Supporting Files/PushNotificationPayload.apns: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert": { 4 | "body": "Test message", 5 | "title": "Optional title" 6 | }, 7 | "category": "myCategory" 8 | }, 9 | 10 | "WatchKit Simulator Actions": [ 11 | { 12 | "title": "First Button", 13 | "identifier": "firstButtonAction" 14 | } 15 | ], 16 | 17 | "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App." 18 | } 19 | -------------------------------------------------------------------------------- /nightguard/NightSafeMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NightSafeMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/23/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// request made by watch for collecting some "night safe" phone settings 12 | class RequestNightSafeMessage: EmptyWatchMessage {} 13 | 14 | 15 | /// Relevant phone settings for deciding if the alarms will be succesfully delivered (imagining a night scenario). 16 | struct PhoneNightSafeSettings: Codable { 17 | 18 | // is the phone in active state? 19 | var isPhoneActive: Bool 20 | 21 | // is the screen lock ON? 22 | var isScreenLockActive: Bool 23 | 24 | // what is the volume level (overriden or actual)? - values beween [0...1] 25 | var volumeLevel: Float 26 | } 27 | 28 | class ResponseNightSafeMessage: GenericWatchMessage {} 29 | -------------------------------------------------------------------------------- /nightguard/Units.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Units.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 14.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum Units : String { 12 | case mgdl = "mgdl" 13 | case mmol = "mmol" 14 | } 15 | 16 | extension Units: CustomStringConvertible { 17 | var description: String { 18 | 19 | switch self { 20 | case .mgdl: 21 | return "mg/dL" 22 | case .mmol: 23 | return "mmol/L" 24 | } 25 | } 26 | } 27 | 28 | extension Units: AnyConvertible { 29 | 30 | func toAny() -> Any { 31 | return rawValue 32 | } 33 | 34 | static func fromAny(_ anyValue: Any) -> Units? { 35 | guard let rawValue = anyValue as? String else { 36 | return nil 37 | } 38 | 39 | return Units(rawValue: rawValue) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /nightguard Complication/AccessoryCornerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessoryCircularView.swift 3 | // nightguard Widget Extension 4 | // 5 | // Created by Dirk Hermanns on 07.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import WidgetKit 12 | 13 | struct AccessoryCornerView : View { 14 | 15 | @State var entry: NightscoutDataEntry 16 | 17 | var body: some View { 18 | Text("\(calculateAgeInMinutes(from: entry.time))m") 19 | .font(.system(size: 20)) 20 | .foregroundColor( 21 | Color(entry.bgdeltaColor)) 22 | .widgetLabel { 23 | Text("\(entry.sgv)" + 24 | "\(entry.bgdeltaString)") 25 | .foregroundColor( 26 | Color(entry.sgvColor)) 27 | } 28 | .widgetAccentable(true) 29 | .unredacted() 30 | } 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /nightguard/SnoozeMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnoozeMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// The Snooze message definition, contains the timestamp while the alarm is snoozed. 12 | class SnoozeMessage: WatchMessage { 13 | 14 | // the snoozed until timestamp (if 0, snooze is off) 15 | let timestamp: TimeInterval 16 | 17 | var dictionary: [String : Any] { 18 | return ["snoozedUntilTimestamp": timestamp] 19 | } 20 | 21 | init(timestamp: TimeInterval) { 22 | self.timestamp = timestamp 23 | } 24 | 25 | required init?(dictionary: [String : Any]) { 26 | guard let timestamp = dictionary["snoozedUntilTimestamp"] as? TimeInterval else { 27 | return nil 28 | } 29 | 30 | self.timestamp = timestamp 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /fastlane/Snapfile: -------------------------------------------------------------------------------- 1 | # Uncomment the lines below you want to change by removing the # in the beginning 2 | 3 | # A list of devices you want to take the screenshots from 4 | devices([ 5 | "iPhone 8 Plus", 6 | "iPhone 11 Pro Max", 7 | "iPad Pro (12.9-inch) (3rd generation)", 8 | "Apple iPad Pro" 9 | ]) 10 | 11 | languages([ 12 | "en-US", 13 | "de-DE", 14 | "fi" 15 | ]) 16 | 17 | # The name of the scheme which contains the UI Tests 18 | # scheme("SchemeName") 19 | 20 | # Where should the resulting screenshots be stored? 21 | # output_directory("./screenshots") 22 | 23 | # remove the '#' to clear all previously generated screenshots before creating new ones 24 | clear_previous_screenshots(true) 25 | 26 | # Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments 27 | # launch_arguments(["-favColor red"]) 28 | 29 | # For more information about all available options run 30 | # fastlane action snapshot 31 | -------------------------------------------------------------------------------- /nightguard/UserDefaultsSyncMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsSyncMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class UserDefaultSyncMessage: WatchMessage { 12 | 13 | var dictionary: [String : Any] 14 | 15 | required init?(dictionary: [String : Any]) { 16 | self.dictionary = dictionary 17 | } 18 | 19 | init() { 20 | var dictionary = [String: Any]() 21 | UserDefaultsValueGroups.values(from: UserDefaultsValueGroups.GroupNames.watchSync)?.forEach { value in 22 | dictionary[value.key] = value.anyValue 23 | } 24 | 25 | // add the last watch sync update id also in the dictionary 26 | dictionary[UserDefaultsRepository.lastWatchSyncUpdateId.key] = UserDefaultsRepository.lastWatchSyncUpdateId.anyValue 27 | 28 | self.dictionary = dictionary 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ---- 3 | 4 | # Installation 5 | 6 | Make sure you have the latest version of the Xcode command line tools installed: 7 | 8 | ```sh 9 | xcode-select --install 10 | ``` 11 | 12 | For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) 13 | 14 | # Available Actions 15 | 16 | ## iOS 17 | 18 | ### ios screenshots 19 | 20 | ```sh 21 | [bundle exec] fastlane ios screenshots 22 | ``` 23 | 24 | Generate new localized screenshots 25 | 26 | ### ios release 27 | 28 | ```sh 29 | [bundle exec] fastlane ios release 30 | ``` 31 | 32 | Release the nightguard app 33 | 34 | ---- 35 | 36 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 37 | 38 | More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). 39 | 40 | The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 41 | -------------------------------------------------------------------------------- /nightguard/MenuActionCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuActionCell.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 4/22/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XLActionController 11 | 12 | class MenuActionCell: ActionCell { 13 | 14 | override init(frame: CGRect) { 15 | super.init(frame: frame) 16 | initialize() 17 | } 18 | 19 | required init?(coder aDecoder: NSCoder) { 20 | super.init(coder: aDecoder) 21 | } 22 | 23 | override func awakeFromNib() { 24 | super.awakeFromNib() 25 | initialize() 26 | } 27 | 28 | func initialize() { 29 | backgroundColor = .clear 30 | let backgroundView = UIView() 31 | backgroundView.backgroundColor = UIColor.darkGray.withAlphaComponent(0.3) 32 | selectedBackgroundView = backgroundView 33 | actionTitleLabel?.textColor = .white 34 | actionTitleLabel?.textAlignment = .left 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /nightguard/de.lproj/Stats.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "Day 2 activated"; ObjectID = "5s9-Ir-Y1w"; */ 3 | "5s9-Ir-Y1w.text" = "Tag 2 aktiviert"; 4 | 5 | /* Class = "UILabel"; text = "Day 4 activated"; ObjectID = "6w3-nX-GGA"; */ 6 | "6w3-nX-GGA.text" = "Tag 4 aktiviert"; 7 | 8 | /* Class = "UITabBarItem"; title = "Stats"; ObjectID = "Gq1-vb-adG"; */ 9 | "Gq1-vb-adG.title" = "Statistik"; 10 | 11 | /* Class = "UILabel"; text = "Day 1 activated"; ObjectID = "Z68-zn-H43"; */ 12 | "Z68-zn-H43.text" = "Tag 1 aktiviert"; 13 | 14 | /* Class = "UILabel"; text = "Day 3 activated"; ObjectID = "ZFw-0B-qy0"; */ 15 | "ZFw-0B-qy0.text" = "Tag 3 aktiviert"; 16 | 17 | /* Class = "UINavigationItem"; title = "Stats"; ObjectID = "jcp-sA-AVP"; */ 18 | "jcp-sA-AVP.title" = "Statistik"; 19 | 20 | /* Class = "UILabel"; text = "Day 5 activated"; ObjectID = "lPe-K1-SFm"; */ 21 | "lPe-K1-SFm.text" = "Tag 5 aktiviert"; 22 | 23 | /* Class = "UIButton"; normalTitle = "Edit"; ObjectID = "mfw-F5-wMB"; */ 24 | "mfw-F5-wMB.normalTitle" = "Editieren"; 25 | -------------------------------------------------------------------------------- /nightguard/fi-FI.lproj/Stats.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UILabel"; text = "Day 2 activated"; ObjectID = "5s9-Ir-Y1w"; */ 3 | "5s9-Ir-Y1w.text" = "Päivä 2 aktivoitu"; 4 | 5 | /* Class = "UILabel"; text = "Day 4 activated"; ObjectID = "6w3-nX-GGA"; */ 6 | "6w3-nX-GGA.text" = "Päivä 4 aktivoitu"; 7 | 8 | /* Class = "UITabBarItem"; title = "Stats"; ObjectID = "Gq1-vb-adG"; */ 9 | "Gq1-vb-adG.title" = "Tilastot"; 10 | 11 | /* Class = "UILabel"; text = "Day 1 activated"; ObjectID = "Z68-zn-H43"; */ 12 | "Z68-zn-H43.text" = "Päivä 1 aktivoitu"; 13 | 14 | /* Class = "UILabel"; text = "Day 3 activated"; ObjectID = "ZFw-0B-qy0"; */ 15 | "ZFw-0B-qy0.text" = "Päivä 3 aktivoitu"; 16 | 17 | /* Class = "UINavigationItem"; title = "Stats"; ObjectID = "jcp-sA-AVP"; */ 18 | "jcp-sA-AVP.title" = "Tilastot"; 19 | 20 | /* Class = "UILabel"; text = "Day 5 activated"; ObjectID = "lPe-K1-SFm"; */ 21 | "lPe-K1-SFm.text" = "Päivä 5 aktivoitu"; 22 | 23 | /* Class = "UIButton"; normalTitle = "Edit"; ObjectID = "mfw-F5-wMB"; */ 24 | "mfw-F5-wMB.normalTitle" = "Muuta"; 25 | -------------------------------------------------------------------------------- /nightguard/NightscoutDataMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NightscoutDataMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class NightscoutDataMessage: WatchMessage { 12 | 13 | let nightscoutData: NightscoutData 14 | 15 | var dictionary: [String : Any] { 16 | let encodedNightscoutData = try? JSONEncoder().encode(nightscoutData) 17 | return ["nightscoutData": encodedNightscoutData ?? Data()] 18 | } 19 | 20 | init() { 21 | self.nightscoutData = NightscoutCacheService.singleton.getCurrentNightscoutData() 22 | } 23 | 24 | required init?(dictionary: [String : Any]) { 25 | guard let data = dictionary["nightscoutData"] as? Data, let nightscoutData = try? JSONDecoder().decode(NightscoutData.self, from: data) else { 26 | print("Invalid nightscout data received!") 27 | return nil 28 | } 29 | 30 | self.nightscoutData = nightscoutData 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nightguard/WatchSyncRequestMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WatchSyncRequestMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/18/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Message sent by watch for requesting a sync from phone if its data is not actual; it contains the watch "last watch sync update id" and the snooze timestamp; the phone app will compare those values with his own ones and send the corresponding update messages if needed. 12 | class WatchSyncRequestMessage: WatchMessage { 13 | 14 | var dictionary: [String : Any] 15 | 16 | required init?(dictionary: [String : Any]) { 17 | self.dictionary = dictionary 18 | } 19 | 20 | init() { 21 | var dictionary = [String: Any]() 22 | dictionary[UserDefaultsRepository.lastWatchSyncUpdateId.key] = UserDefaultsRepository.lastWatchSyncUpdateId.anyValue 23 | dictionary["snoozedUntilTimestamp"] = AlarmRule.snoozedUntilTimestamp.value 24 | 25 | self.dictionary = dictionary 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # This file contains the fastlane.tools configuration 2 | # You can find the documentation at https://docs.fastlane.tools 3 | # 4 | # For a list of all available actions, check out 5 | # 6 | # https://docs.fastlane.tools/actions 7 | # 8 | # For a list of all available plugins, check out 9 | # 10 | # https://docs.fastlane.tools/plugins/available-plugins 11 | # 12 | 13 | # Uncomment the line if you want fastlane to automatically update itself 14 | # update_fastlane 15 | 16 | default_platform(:ios) 17 | 18 | platform :ios do 19 | desc "Generate new localized screenshots" 20 | lane :screenshots do 21 | capture_screenshots( 22 | workspace: "nightguard.xcworkspace", 23 | scheme: "nightguard") 24 | frame_screenshots 25 | end 26 | 27 | desc "Release the nightguard app" 28 | lane :release do 29 | increment_build_number 30 | build_app(scheme: "nightguard") 31 | upload_to_app_store( 32 | force: true, 33 | overwrite_screenshots: false, 34 | automatic_release: true, 35 | skip_screenshots: true) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /nightguard/WatchMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WatchMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/25/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WatchConnectivity 11 | 12 | 13 | /// An abstraction of an watch message, that can convert to or be created from a dictionary of values. The WatchMessageService class knows how to send or receive (create) intances of WatchMessage; communication between phone and watch is done exclusively by using custom WatchMessages. 14 | protocol WatchMessage { 15 | 16 | init?(dictionary: [String : Any]) 17 | var dictionary: [String : Any] { get } 18 | } 19 | 20 | extension WatchMessage { 21 | 22 | func send(replyHandler: (([String : Any]) -> Void)? = nil) { 23 | WatchMessageService.singleton.send(message: self, replyHandler: replyHandler) 24 | } 25 | 26 | func send(responseHandler: @escaping (T) -> Void) { 27 | WatchMessageService.singleton.send(request: self, responseHandler: responseHandler) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /nightguard Widget Extension/AccessoryInlineView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessoryInlineView.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 02.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import WidgetKit 12 | 13 | struct AccessoryInlineView : View { 14 | 15 | var entry: NightscoutDataEntry 16 | 17 | var body: some View { 18 | 19 | //AccessoryWidgetBackground() not supported in this Widget Family 20 | ZStack { 21 | let bgValue = entry.lastBGValues.first 22 | if let bgValue = bgValue { 23 | 24 | Text("\(String(bgValue.value)) \(bgValue.delta) \(bgValue.arrow) \(Date.now.addingTimeInterval(-(Date.now.timeIntervalSince1970 - (bgValue.timestamp / 1000))), style: .timer)") 25 | #if os(watchOS) 26 | .foregroundColor(Color(entry.sgvColor)) 27 | #endif 28 | } else { 29 | Text("--:-- --- -") 30 | } 31 | } 32 | .widgetAccentable(true) 33 | .unredacted() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nightguard/MPVolumeViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MPVolumeViewExtension.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/10/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AVFoundation 11 | import MediaPlayer 12 | 13 | /// MPVolumeView extension used for controlling the system output volume 14 | extension MPVolumeView { 15 | 16 | static var volume: Float { 17 | get { 18 | return AVAudioSession.sharedInstance().outputVolume 19 | // let volumeView = MPVolumeView() 20 | // let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider 21 | // return slider?.value ?? 0.5 22 | } 23 | set { 24 | let volumeView = MPVolumeView() 25 | let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider 26 | 27 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) { 28 | slider?.value = newValue 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nightguard/DoubleExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DoubleExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 26.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Double { 12 | 13 | // remove the decimal part of the float if it is ".0" and trim whitespaces 14 | var cleanValue: String { 15 | return self.truncatingRemainder(dividingBy: 1) == 0 16 | ? String(format: "%5.0f", self).trimmingCharacters(in: CharacterSet.whitespaces) 17 | : String(format: "%5.1f", self).trimmingCharacters(in: CharacterSet.whitespaces) 18 | } 19 | 20 | func string(fractionDigits:Int) -> String { 21 | let formatter = NumberFormatter() 22 | formatter.minimumFractionDigits = fractionDigits 23 | formatter.maximumFractionDigits = fractionDigits 24 | return formatter.string(from: NSNumber(value: self)) ?? "\(self)" 25 | } 26 | 27 | static func fromIsoString(isoTime: String) -> Double { 28 | 29 | return Date.fromIsoString(isoTime: isoTime).timeIntervalSince1970 * 1000 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nightguard/app/Colors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/1/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// Definition of all the colors used in the app 12 | extension UIColor { 13 | 14 | struct App { 15 | 16 | // Phone app colors 17 | #if os(iOS) 18 | 19 | // Preferences/Alarms screen colors 20 | struct Preferences { 21 | static let text = UIColor.white 22 | static let detailText = UIColor.lightGray 23 | static let placeholderText = UIColor.lightGray 24 | static let headerText = UIColor.gray 25 | static let footerText = UIColor.gray 26 | static let background = UIColor(netHex: 0x171717) 27 | static let rowBackground = UIColor(netHex: 0x1C1C1E) 28 | static let selectedRowBackground = UIColor(netHex: 0x313131) 29 | static let separator = UIColor(netHex: 0x3F3F3F) 30 | static let tint = UIColor.white //UIColor(netHex: 0xFE9500) 31 | } 32 | 33 | #endif 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nightguard WatchKit App/ViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 08.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | 12 | extension View { 13 | func calculateAgeInMinutes(from timestamp: NSNumber) -> String { 14 | let timestampAsDate = Date(timeIntervalSince1970: timestamp.doubleValue / 1000) 15 | let calendar = Calendar.current 16 | let components = calendar.dateComponents([.minute], from: timestampAsDate, to: Date()) 17 | if let ageInMinutes = components.minute { 18 | return "\(ageInMinutes)" 19 | } 20 | return "?" 21 | } 22 | 23 | func calculateAgeInMinutes(fromDouble timestamp: Double) -> String { 24 | let timestampAsDate = Date(timeIntervalSince1970: timestamp / 1000) 25 | let calendar = Calendar.current 26 | let components = calendar.dateComponents([.minute], from: timestampAsDate, to: Date()) 27 | if let ageInMinutes = components.minute { 28 | return "\(ageInMinutes)" 29 | } 30 | return "?" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nightguard/TabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITabBarController.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 23.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import AVFoundation 12 | 13 | class TabBarController: UITabBarController { 14 | 15 | override var supportedInterfaceOrientations : UIInterfaceOrientationMask { 16 | if let selectedViewController = (self.selectedViewController as? UINavigationController)?.viewControllers.first ?? self.selectedViewController { 17 | return selectedViewController.supportedInterfaceOrientations 18 | } 19 | return .allButUpsideDown 20 | } 21 | 22 | override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) { 23 | if motion == .motionShake { 24 | print("Device shaken") 25 | 26 | if !AlarmRule.isSnoozed() { 27 | DispatchQueue.main.async { [weak self] in 28 | self?.handleQuickSnooze(option: UserDefaultsRepository.shakingOnAlertSnoozeOption.value) 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /nightguard Widget Extension/AccessoryCircularView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessoryCircularView.swift 3 | // nightguard Widget Extension 4 | // 5 | // Created by Dirk Hermanns on 07.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import WidgetKit 12 | 13 | struct AccessoryCircularView : View { 14 | 15 | var entry: NightscoutDataEntry 16 | 17 | var body: some View { 18 | ZStack { 19 | AccessoryWidgetBackground() 20 | VStack { 21 | Text("\(calculateAgeInMinutes(fromDouble: entry.lastBGValues.first?.timestamp ?? Date.now.timeIntervalSinceNow-3600))m") 22 | Text("\(entry.lastBGValues.first?.value ?? "??")") 23 | .foregroundColor( 24 | Color.cyan) 25 | Text("\(entry.lastBGValues.first?.delta ?? "?")") 26 | .foregroundColor( 27 | Color(UIColorChanger.getDeltaLabelColor(Float(entry.lastBGValues.first?.delta ?? "99") ?? 99.0))) 28 | .widgetAccentable(true) 29 | .unredacted() 30 | } 31 | } 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /nightguard/UILabelExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UILabel.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 23.07.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UILabel { 13 | 14 | // forms a new string like so 15 | // prefix + ageOf(isoTime) 16 | // The color will be white/yellow/red depending on hoursUntilWarning and hoursUntilCritical. 17 | func convertToAge(prefix: String, time: Date, hoursUntilWarning: Int, hoursUntilCritical: Int) { 18 | 19 | let dateComponentsFormatter = DateComponentsFormatter() 20 | dateComponentsFormatter.allowedUnits = [.day,.hour] 21 | dateComponentsFormatter.maximumUnitCount = 2 22 | dateComponentsFormatter.unitsStyle = .abbreviated 23 | 24 | guard let differenceString = dateComponentsFormatter.string(from: time, to: Date()) else { 25 | self.text = prefix + "---" 26 | return 27 | } 28 | 29 | self.text = prefix + differenceString 30 | self.textColor = time.determineUIColorDependingOn(hoursUntilWarning: hoursUntilWarning, hoursUntilCritical: hoursUntilCritical) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nightguard Complication/AccessoryCornerGaugeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessoryCircularView.swift 3 | // nightguard Widget Extension 4 | // 5 | // Created by Dirk Hermanns on 07.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import WidgetKit 12 | 13 | struct AccessoryCornerGaugeView : View { 14 | 15 | var entry: NightscoutDataEntry 16 | 17 | var body: some View { 18 | 19 | Text("\(entry.lastBGValues.first?.value ?? "??")") 20 | .font(.system(size: 20)) 21 | .foregroundColor( 22 | Color(UIColorChanger.getBgColor(entry.lastBGValues.first?.value ?? "999"))) 23 | .widgetLabel { 24 | ProgressView(value: 25 | (Double(calculateAgeInMinutes(fromDouble: entry.lastBGValues.first?.timestamp ?? Date.now.timeIntervalSinceNow - 3600)) ?? 60) / 60) 26 | .tint( 27 | Color(UIColorChanger.getTimeLabelColor( 28 | fromDouble: entry.lastBGValues.first?.timestamp ?? Date().timeIntervalSinceNow - 3600))) 29 | } 30 | .widgetAccentable(true) 31 | .unredacted() 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /nightguardTests/TargetDataTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TargetDataTest.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 17.03.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | import XCTest 9 | 10 | class TargetDataTest : XCTestCase { 11 | 12 | func testParsingOfMmolTarget() { 13 | 14 | // Given 15 | let temporaryTargetDict = [ 16 | "units": "mmol", 17 | "targetTop": Float(10.0)] as [String : Any] 18 | 19 | // When 20 | let temporaryTarget = TemporaryTarget.parse(temporaryTargetDict: temporaryTargetDict) 21 | 22 | // Then 23 | XCTAssertEqual(temporaryTarget.targetTop, 180, "Mmol should have been converted to mgdl") 24 | } 25 | 26 | func testParsingOfMgdlTarget() { 27 | 28 | // Given 29 | let temporaryTargetDict = [ 30 | "targetTop": Int(180)] as [String : Any] 31 | 32 | // When 33 | let temporaryTarget = TemporaryTarget.parse(temporaryTargetDict: temporaryTargetDict) 34 | 35 | // Then 36 | XCTAssertEqual(temporaryTarget.targetTop, 180, "If no unit is available - it should treated as mgdl") 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /nightguard/external/regression/Matrix+Append.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Matrix+Append.swift 3 | // Regression 4 | // 5 | // Created by Dominik Felber on 16.05.16. 6 | // Copyright © 2016 Dominik Felber. All rights reserved. 7 | // 8 | 9 | extension Matrix 10 | { 11 | /// Appends a Matrix horizontally to the current Matrix. 12 | /// 13 | /// - parameter m: The Matrix that should be appended. 14 | /// - returns: A new Matrix based on the current Matrix and `m`. 15 | func appendHorizontal(_ m: Matrix) -> Matrix { 16 | let result = Matrix(columns: m.rows, rows: self.columns + m.columns) 17 | let a = self.transposed().values 18 | let b = m.transposed().values 19 | let values = concat(a, b) 20 | 21 | result.setValues(values) 22 | 23 | return result.transposed() 24 | } 25 | 26 | 27 | /// Appends a Matrix vertically to the current Matrix. 28 | /// 29 | /// - parameter m: The Matrix that should be appended. 30 | /// - returns: A new Matrix based on the current Matrix and `m`. 31 | func appendVertical(_ m: Matrix) -> Matrix { 32 | let result = Matrix(columns: m.rows, rows: self.columns + m.columns) 33 | let values = concat(self.values, m.values) 34 | result.setValues(values) 35 | 36 | return result 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /nightguard/repository/StatisticsRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StatisticsRepository.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 07.07.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class StatisticsRepository { 12 | 13 | static let singleton = StatisticsRepository() 14 | 15 | var lastSave : Date? 16 | 17 | var cachedDays : [[BloodSugar]?] = [nil, nil, nil, nil, nil, nil] 18 | 19 | 20 | // Reads the day starting with day 0 (current day). 21 | // If the day is not available or older than 30 Minutes, nil will be returned 22 | func readDay(_ nr : Int) -> [BloodSugar]? { 23 | 24 | if lastSave == nil || TimeService.isOlderThan30Minutes(lastSave ?? Date()) { 25 | return nil 26 | } 27 | 28 | if nr > cachedDays.count { 29 | return [] 30 | } 31 | 32 | if cachedDays[nr] == nil { 33 | // no values have been read so far => signal with nil that they have to be read once more 34 | return nil 35 | } 36 | return cachedDays[nr] 37 | } 38 | 39 | 40 | func saveDay(_ nr : Int, bloodSugarArray : [BloodSugar]) { 41 | 42 | lastSave = TimeService.getToday() 43 | 44 | cachedDays[nr] = bloodSugarArray 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /nightguard/UIScreen+AnimatedBrightness.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScreen+AnimatedBrightness.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/16/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIScreen { 12 | 13 | func setBrightness(_ value: CGFloat, animated: Bool) { 14 | if animated { 15 | _brightnessQueue.cancelAllOperations() 16 | let step: CGFloat = 0.04 * ((value > brightness) ? 1 : -1) 17 | _brightnessQueue.addOperations(stride(from: brightness, through: value, by: step).map({ [weak self] value -> Operation in 18 | let blockOperation = BlockOperation() 19 | unowned let _unownedOperation = blockOperation 20 | blockOperation.addExecutionBlock({ 21 | if !_unownedOperation.isCancelled { 22 | Thread.sleep(forTimeInterval: 1 / 60.0) 23 | self?.brightness = value 24 | } 25 | }) 26 | return blockOperation 27 | }), waitUntilFinished: false) 28 | } else { 29 | brightness = value 30 | } 31 | } 32 | 33 | } 34 | 35 | private let _brightnessQueue: OperationQueue = { 36 | let queue = OperationQueue() 37 | queue.maxConcurrentOperationCount = 1 38 | return queue 39 | }() 40 | -------------------------------------------------------------------------------- /nightguard WatchKit App/Media.xcassets/Complication.complicationset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "filename" : "Circular.imageset", 5 | "idiom" : "watch", 6 | "role" : "circular" 7 | }, 8 | { 9 | "filename" : "Extra Large.imageset", 10 | "idiom" : "watch", 11 | "role" : "extra-large" 12 | }, 13 | { 14 | "filename" : "Graphic Bezel.imageset", 15 | "idiom" : "watch", 16 | "role" : "graphic-bezel" 17 | }, 18 | { 19 | "filename" : "Graphic Circular.imageset", 20 | "idiom" : "watch", 21 | "role" : "graphic-circular" 22 | }, 23 | { 24 | "filename" : "Graphic Corner.imageset", 25 | "idiom" : "watch", 26 | "role" : "graphic-corner" 27 | }, 28 | { 29 | "filename" : "Graphic Extra Large.imageset", 30 | "idiom" : "watch", 31 | "role" : "graphic-extra-large" 32 | }, 33 | { 34 | "filename" : "Graphic Large Rectangular.imageset", 35 | "idiom" : "watch", 36 | "role" : "graphic-large-rectangular" 37 | }, 38 | { 39 | "filename" : "Modular.imageset", 40 | "idiom" : "watch", 41 | "role" : "modular" 42 | }, 43 | { 44 | "filename" : "Utilitarian.imageset", 45 | "idiom" : "watch", 46 | "role" : "utilitarian" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /nightguard/GenericWatchMessage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GenericWatchMessage.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/23/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// A message that wraps any codable struct/class 12 | class GenericWatchMessage: WatchMessage { 13 | 14 | typealias ValueType = T 15 | let value: ValueType 16 | 17 | var dictionary: [String : Any] { 18 | 19 | let jsonEncoder = JSONEncoder() 20 | if let jsonData = try? jsonEncoder.encode(value) { 21 | return ["data": jsonData] 22 | } else { 23 | print("GenericWatchMessage - failed to encode message!") 24 | return [:] 25 | } 26 | } 27 | 28 | init(_ value: ValueType) { 29 | self.value = value 30 | } 31 | 32 | required init?(dictionary: [String : Any]) { 33 | guard let data = dictionary["data"] as? Data else { 34 | print("GenericWatchMessage - failed to decode message!") 35 | return nil 36 | } 37 | 38 | let jsonDecoder = JSONDecoder() 39 | guard let value = try? jsonDecoder.decode(ValueType.self, from: data) else { 40 | print("GenericWatchMessage - failed to decode message!") 41 | return nil 42 | } 43 | 44 | self.value = value 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /nightguard/repository/SharedUserDefaultsRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SharedUserDefaultsRepository.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 18.09.22. 6 | // Copyright © 2022 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /* 13 | * UserDefaults that need access to a shared reference. 14 | * This is separated from the UserDefaultsRepository, since it can't be used 15 | * from a Widget. 16 | */ 17 | class SharedUserDefaultsRepository { 18 | 19 | static let showBGOnAppBadge = UserDefaultsValue( 20 | key: "showBGOnAppBadge", 21 | default: false, 22 | onChange: { show in 23 | // Should not be executed in Widgets or Complications: 24 | #if os(iOS) && MAIN_APP 25 | if show { 26 | UIApplication.shared.setCurrentBGValueOnAppBadge() 27 | } else { 28 | UIApplication.shared.clearAppBadge() 29 | } 30 | #endif 31 | }) 32 | 33 | // Should not be executed in Widgets or Complications: 34 | #if os(iOS) && MAIN_APP 35 | static let screenlockSwitchState = UserDefaultsValue( 36 | key: "screenlockSwitchState", 37 | default: UIApplication.shared.isIdleTimerDisabled, 38 | onChange: { screenlock in 39 | UIApplication.shared.isIdleTimerDisabled = screenlock 40 | }) 41 | #endif 42 | } 43 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | # platform :ios, '14.7' 3 | 4 | target 'nightguard' do 5 | platform :ios, '14.7' 6 | 7 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 8 | use_frameworks! 9 | 10 | # Pods for nightguard 11 | pod 'Eureka' 12 | pod 'XLActionController' 13 | 14 | target 'nightguardTests' do 15 | inherit! :search_paths 16 | # Pods for testing 17 | end 18 | 19 | target 'nightguardUITests' do 20 | inherit! :search_paths 21 | # Pods for testing 22 | pod 'Eureka' 23 | pod 'XLActionController' 24 | end 25 | 26 | end 27 | 28 | target 'nightguard WatchKit App' do 29 | platform :watchos, '9.1' 30 | 31 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 32 | use_frameworks! 33 | 34 | # Pods for nightguard WatchKit App 35 | end 36 | 37 | target 'nightguard Widget Extension' do 38 | platform :ios, '16.0' 39 | 40 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 41 | use_frameworks! 42 | 43 | # Pods for nightguard WatchKit Extension 44 | 45 | end 46 | 47 | target 'nightguard ComplicationExtension' do 48 | platform :watchos, '9.1' 49 | 50 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 51 | use_frameworks! 52 | 53 | # Pods for nightguard WatchKit App 54 | 55 | end 56 | -------------------------------------------------------------------------------- /nightguard/FloatExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FloatExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 18.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Float { 12 | 13 | // remove the decimal part of the float if it is ".0" and trim whitespaces 14 | var cleanValue: String { 15 | return self.truncatingRemainder(dividingBy: 1) == 0 16 | ? String(format: "%5.0f", self).trimmingCharacters(in: CharacterSet.whitespaces) 17 | : String(format: "%5.1f", self).trimmingCharacters(in: CharacterSet.whitespaces) 18 | } 19 | 20 | // remove the decimal part of the float if it is ".0" and trim whitespaces 21 | // add a sign "+" or "-" 22 | var cleanSignedValue: String { 23 | 24 | var sign = "" 25 | if self >= 0 { 26 | sign = "+" 27 | } 28 | 29 | return self.truncatingRemainder(dividingBy: 1) == 0 30 | ? sign + String(format: "%5.0f", self).trimmingCharacters(in: CharacterSet.whitespaces) 31 | : sign + String(format: "%5.1f", self).trimmingCharacters(in: CharacterSet.whitespaces) 32 | } 33 | 34 | var roundTo3f: Float { 35 | return round(to: 3) 36 | } 37 | 38 | func round(to places: Int) -> Float { 39 | let divisor = pow(10.0, Float(places)) 40 | return (divisor * self).rounded() / divisor 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /nightguard/BasicStatsPanelView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicStatsPanelView.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 3/10/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | The stats panel that contains all the rounded stats views. 13 | */ 14 | class BasicStatsPanelView: XibLoadedView { 15 | 16 | var model: BasicStats? { 17 | didSet { 18 | glucoseDistributionView.model = model 19 | a1cView.model = model 20 | readingsStatsView.model = model 21 | periodSelectorView.model = model 22 | } 23 | } 24 | 25 | @IBOutlet weak var glucoseDistributionView: GlucoseDistributionView! 26 | @IBOutlet weak var a1cView: A1cView! 27 | @IBOutlet weak var readingsStatsView: ReadingsStatsView! 28 | @IBOutlet weak var periodSelectorView: StatsPeriodSelectorView! 29 | 30 | override func commonInit() { 31 | super.commonInit() 32 | 33 | periodSelectorView.onPeriodChangeRequest = { period in 34 | self.model = BasicStats(period: period) 35 | } 36 | 37 | do { 38 | self.model = BasicStats(period: .last24h) 39 | } 40 | } 41 | 42 | func updateModel() { 43 | if let model = self.model, model.isUpToDate { 44 | 45 | // do nothing, the model contains already the most recent reading 46 | } else { 47 | 48 | // (re)create the model 49 | self.model = BasicStats(period: self.model?.period ?? .last24h) 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /nightguard Widget Extension/AccessoryCircularGaugeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AccessoryCircularView.swift 3 | // nightguard Widget Extension 4 | // 5 | // Created by Dirk Hermanns on 07.04.23. 6 | // Copyright © 2023 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftUI 11 | import WidgetKit 12 | 13 | struct AccessoryCircularGaugeView : View { 14 | 15 | var entry: NightscoutDataEntry 16 | 17 | var body: some View { 18 | ZStack { 19 | AccessoryWidgetBackground() 20 | Gauge(value: Double( 21 | calculateAgeInMinutes( 22 | fromDouble: entry.lastBGValues.first?.timestamp ?? Date.now.timeIntervalSinceNow - 3600)) ?? 60, 23 | in: 0...60) { 24 | Text("\(entry.lastBGValues.first?.delta ?? "?")") 25 | .foregroundColor( 26 | Color(UIColorChanger.getDeltaLabelColor( 27 | Float(entry.lastBGValues.first?.delta ?? "99") ?? 99))) 28 | } currentValueLabel: { 29 | Text(entry.lastBGValues.first?.value ?? "??") 30 | .foregroundColor( 31 | Color(UIColorChanger.getBgColor(entry.lastBGValues.first?.value ?? "999"))) 32 | } 33 | .tint( 34 | Color(UIColorChanger.getTimeLabelColor( 35 | fromDouble: entry.lastBGValues.first?.timestamp ?? Date().timeIntervalSinceNow - 3600))) 36 | 37 | .gaugeStyle(.accessoryCircular) 38 | .widgetAccentable(true) 39 | .unredacted() 40 | } 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /nightguard/ButtonRowWithDynamicDetails.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonRowWithDynamicDetails.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/7/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Eureka 11 | 12 | final class ButtonRowWithDynamicDetails: _ButtonRowOf, RowType { 13 | 14 | // the presented controller provider closure 15 | var controllerProvider: (() -> CustomFormViewController)? 16 | 17 | // subtitle text 18 | var detailTextProvider: (() -> String?)? 19 | 20 | required public init(tag: String?) { 21 | super.init(tag: tag) 22 | title = tag 23 | cellStyle = .subtitle 24 | } 25 | 26 | override func customDidSelect() { 27 | super.customDidSelect() 28 | guard !isDisabled else { return } 29 | 30 | guard let controllerProvider = self.controllerProvider else { return } 31 | 32 | let vc = controllerProvider() 33 | vc.title = title 34 | cell.formViewController()?.navigationController?.pushViewController(vc, animated: true) 35 | } 36 | 37 | override func customUpdateCell() { 38 | super.customUpdateCell() 39 | 40 | // always left! 41 | cell.textLabel?.textAlignment = .left 42 | cell.accessoryType = isDisabled ? .none : .disclosureIndicator 43 | 44 | // detail text can span on more than one line 45 | guard let detailTextProvider = self.detailTextProvider else { return } 46 | cell.detailTextLabel?.text = detailTextProvider() 47 | cell.detailTextLabel?.numberOfLines = 0 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nightguard/ArrayExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayExtension.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 12/14/18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Array { 12 | 13 | /// Returns the first N elements of the sequence that satisfies the given 14 | /// predicate. 15 | func prefix(_ maxLength: Int, where predicate: (Element) throws -> Bool) rethrows -> Array { 16 | 17 | var result = Array() 18 | 19 | var slice = self[...] 20 | while maxLength > result.count { 21 | guard let index = try slice.firstIndex(where: predicate) else { 22 | break 23 | } 24 | 25 | result.append(slice[index]) 26 | 27 | // move over 28 | slice = self[(index+1)...] 29 | } 30 | 31 | return result 32 | } 33 | 34 | /// Returns the last N elements of the sequence that satisfies the given 35 | /// predicate. 36 | func suffix(_ maxLength: Int, where predicate: (Element) throws -> Bool) rethrows -> Array { 37 | 38 | var result = Array() 39 | 40 | var slice = self[...] 41 | while maxLength > result.count { 42 | guard let index = try slice.lastIndex(where: predicate) else { 43 | break 44 | } 45 | 46 | result.append(slice[index]) 47 | 48 | // move over 49 | slice = self[.. 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Nightguard 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 923 25 | CLKComplicationPrincipalClass 26 | $(PRODUCT_MODULE_NAME).ComplicationController 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | 32 | NSUserActivityTypes 33 | 34 | ConfigurationIntent 35 | 36 | RemoteInterfacePrincipalClass 37 | $(PRODUCT_MODULE_NAME).InterfaceController 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | 43 | WKApplication 44 | 45 | WKCompanionAppBundleIdentifier 46 | de.my-wan.dhe.nightguard 47 | 48 | 49 | -------------------------------------------------------------------------------- /nightguard WatchKit App/views/AddCarbsPopupView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivateTemporaryTargetView.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 11.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import SpriteKit 11 | import Combine 12 | 13 | struct AddCarbsPopupView: View { 14 | 15 | @Environment(\.presentationMode) var presentationMode 16 | @Binding var isPresented: Bool 17 | 18 | var body: some View { 19 | VStack() { 20 | Text( 21 | String(format: NSLocalizedString("Do you want to add %dg of carbs?", comment: "Add carbs popup modal text"), UserDefaultsRepository.carbs.value)) 22 | HStack() { 23 | Button(action: { 24 | 25 | WKInterfaceDevice.current().play(.success) 26 | 27 | NightscoutService.singleton.createCarbsCorrection(carbs: UserDefaultsRepository.carbs.value, 28 | resultHandler: {(error: String?) in 29 | 30 | // TODO: Show the result 31 | }) 32 | isPresented = false 33 | }) { 34 | Text(NSLocalizedString("Accept", comment: "Popup Accept-Button")) 35 | .font(.system(size: 12)) 36 | } 37 | Button(action: { 38 | isPresented = false 39 | }) { 40 | Text(NSLocalizedString("Decline", comment: "Popup Decline-Button")) 41 | .font(.system(size: 12)) 42 | } 43 | } 44 | Spacer() 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /nightguard/StringExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringExtension.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 19.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension String { 12 | 13 | // remove the decimal part of the float if it is ".0" 14 | var floatValue: Float { 15 | return NSString(string: self).floatValue 16 | } 17 | 18 | // remove whitespaces from string 19 | func trim() -> String { 20 | return self.trimmingCharacters(in: CharacterSet.whitespaces) 21 | } 22 | 23 | // treat the String as float and round if regarding the first decimal. 24 | // If that doesn't work - return self 25 | var cleanFloatValue: String { 26 | 27 | guard let doubleValue = Double(self)?.cleanValue else { 28 | return self 29 | } 30 | return String(doubleValue) 31 | } 32 | 33 | // remove all characters in the middle of the String. 34 | // The new size of the string will be 35 | // keepPrefixCharacterCount + keepPostfixCharacterCount + 3 36 | func trimInfix(keepPrefixCharacterCount: Int, keepPostfixCharacterCount: Int) -> String { 37 | 38 | if self.count <= (keepPrefixCharacterCount + keepPostfixCharacterCount + 3) { 39 | // string is not too long => do nothing 40 | return self 41 | } 42 | 43 | return self.prefix(keepPrefixCharacterCount) + "..." + self.suffix(keepPostfixCharacterCount) 44 | } 45 | 46 | func removing(charactersOf string: String) -> String { 47 | let characterSet = CharacterSet(charactersIn: string) 48 | let components = self.components(separatedBy: characterSet) 49 | return components.joined(separator: "") 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /nightguard/external/model/TemporaryTarget.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TemporaryTarget.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 17.03.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TemporaryTarget { 12 | 13 | public var targetTop : Int 14 | public var targetBottom : Int 15 | public var createdAt : String? 16 | public var duration : Int? 17 | 18 | public init() { 19 | self.targetTop = 100 20 | self.targetBottom = 100 21 | } 22 | 23 | public static func parse(temporaryTargetDict : [String:Any]) -> TemporaryTarget { 24 | 25 | let temporaryTarget = TemporaryTarget.init() 26 | 27 | let units = temporaryTargetDict["units"] as? String ?? "mgdl" 28 | if units.contains("mol") { 29 | // Looks like targetTop is stored as mmol => convert to mgdl 30 | temporaryTarget.targetTop = 31 | Int(UnitsConverter.mmolToMgdl(temporaryTargetDict["targetTop"] as? Float ?? 5.0)) 32 | } else { 33 | temporaryTarget.targetTop = temporaryTargetDict["targetTop"] as? Int ?? 100 34 | } 35 | 36 | if units.contains("mol") { 37 | // looks like targetBottom is stored as mmol => convert to mgdl 38 | temporaryTarget.targetBottom = 39 | Int(UnitsConverter.mmolToMgdl(temporaryTargetDict["targetBottom"] as? Float ?? 5.0)) 40 | } else { 41 | temporaryTarget.targetBottom = temporaryTargetDict["targetBottom"] as? Int ?? 100 42 | } 43 | 44 | temporaryTarget.createdAt = temporaryTargetDict["created_at"] as? String 45 | temporaryTarget.duration = temporaryTargetDict["duration"] as? Int 46 | 47 | return temporaryTarget 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nightguard/QuickSnoozeOption.swift: -------------------------------------------------------------------------------- 1 | // 2 | // QuickSnoozingAction.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/10/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// Quick Snoozing options 12 | enum QuickSnoozeOption: Int { 13 | case doNothing = -1 14 | case showSnoozePopup = 0 15 | case snoozeOneMinute = 1 16 | case snoozeFiveMinutes = 5 17 | case snoozeTenMinutes = 10 18 | } 19 | 20 | extension QuickSnoozeOption: CustomStringConvertible { 21 | var description: String { 22 | 23 | switch self { 24 | case .doNothing: 25 | return NSLocalizedString("Will do Nothing", comment: "Will do Nothing Quick Snooze Option") 26 | case .showSnoozePopup: 27 | return NSLocalizedString("Will show the Snooze Dialog", comment: "Will show the Snooze Dialog Quick Snooze Option") 28 | case .snoozeOneMinute: 29 | return NSLocalizedString("Will snooze for 1 Minute", comment: "Will snooze for 1 Minute Dialog Quick Snooze Option") 30 | case .snoozeFiveMinutes: 31 | return NSLocalizedString("Will snooze for 5 Minutes", comment: "Will snooze for 5 Minutes Dialog Quick Snooze Option") 32 | case .snoozeTenMinutes: 33 | return NSLocalizedString("Will snooze for 10 Minutes", comment: "Will snooze for 10 Minutes Dialog Quick Snooze Option") 34 | } 35 | } 36 | } 37 | 38 | extension QuickSnoozeOption: AnyConvertible { 39 | 40 | func toAny() -> Any { 41 | return rawValue 42 | } 43 | 44 | static func fromAny(_ anyValue: Any) -> QuickSnoozeOption? { 45 | guard let rawValue = anyValue as? Int else { 46 | return nil 47 | } 48 | 49 | return QuickSnoozeOption(rawValue: rawValue) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /nightguard/TimerExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimerExtension.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 1/12/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // https://gist.github.com/natecook1000/b0285b518576b22c4dc8 12 | extension Timer { 13 | /** 14 | Creates and schedules a one-time `NSTimer` instance. 15 | 16 | - Parameters: 17 | - delay: The delay before execution. 18 | - handler: A closure to execute after `delay`. 19 | 20 | - Returns: The newly-created `NSTimer` instance. 21 | */ 22 | class func schedule(_ delay: TimeInterval, handler: ((Timer?) -> Void)!) -> Timer! { 23 | let fireDate = delay + CFAbsoluteTimeGetCurrent() 24 | let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, 0, 0, 0, handler) 25 | CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, .commonModes) 26 | return timer 27 | } 28 | 29 | /** 30 | Creates and schedules a repeating `NSTimer` instance. 31 | 32 | - Parameters: 33 | - repeatInterval: The interval (in seconds) between each execution of 34 | `handler`. Note that individual calls may be delayed; subsequent calls 35 | to `handler` will be based on the time the timer was created. 36 | - handler: A closure to execute at each `repeatInterval`. 37 | 38 | - Returns: The newly-created `NSTimer` instance. 39 | */ 40 | class func schedule(repeatInterval interval: TimeInterval, handler: ((Timer?) -> Void)!) -> Timer! { 41 | let fireDate = interval + CFAbsoluteTimeGetCurrent() 42 | let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, fireDate, interval, 0, 0, handler) 43 | CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, .commonModes) 44 | return timer 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /nightguard/VolumeChangeDetector.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VolumeChangeDetector.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/10/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AVFoundation 11 | 12 | /// System Output Volume listener class. 13 | class VolumeChangeDetector: NSObject { 14 | 15 | var onVolumeChange: (() -> ())? 16 | 17 | var isActive: Bool = false { 18 | didSet { 19 | guard isActive != oldValue else { 20 | return 21 | } 22 | 23 | if isActive { 24 | do { 25 | try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category(rawValue: convertFromAVAudioSessionCategory(AVAudioSession.Category.playback))) 26 | try AVAudioSession.sharedInstance().setActive(true) 27 | } catch { 28 | NSLog("VolumeChangeDetector - error activating audio session") 29 | } 30 | AVAudioSession.sharedInstance().addObserver(self, forKeyPath: "outputVolume", options: NSKeyValueObservingOptions.new, context: nil) 31 | } else { 32 | AVAudioSession.sharedInstance().removeObserver(self, forKeyPath: "outputVolume") 33 | } 34 | } 35 | } 36 | 37 | deinit { 38 | isActive = false 39 | } 40 | 41 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 42 | 43 | if keyPath == "outputVolume" { 44 | print("Volume changed!") 45 | onVolumeChange?() 46 | } 47 | } 48 | } 49 | 50 | // Helper function inserted by Swift 4.2 migrator. 51 | fileprivate func convertFromAVAudioSessionCategory(_ input: AVAudioSession.Category) -> String { 52 | return input.rawValue 53 | } 54 | -------------------------------------------------------------------------------- /nightguard Complication/Base.lproj/nightguard_Complication.intentdefinition: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INEnums 6 | 7 | INIntentDefinitionModelVersion 8 | 1.2 9 | INIntentDefinitionNamespace 10 | 88xZPY 11 | INIntentDefinitionSystemVersion 12 | 22D68 13 | INIntentDefinitionToolsBuildVersion 14 | 14C18 15 | INIntentDefinitionToolsVersion 16 | 14.2 17 | INIntents 18 | 19 | 20 | INIntentCategory 21 | information 22 | INIntentDescription 23 | Complication Configuration 24 | INIntentDescriptionID 25 | tVvJ9c 26 | INIntentEligibleForWidgets 27 | 28 | INIntentIneligibleForSuggestions 29 | 30 | INIntentName 31 | Configuration 32 | INIntentResponse 33 | 34 | INIntentResponseCodes 35 | 36 | 37 | INIntentResponseCodeName 38 | success 39 | INIntentResponseCodeSuccess 40 | 41 | 42 | 43 | INIntentResponseCodeName 44 | failure 45 | 46 | 47 | 48 | INIntentTitle 49 | Configuration 50 | INIntentTitleID 51 | gpCwrM 52 | INIntentType 53 | Custom 54 | INIntentVerb 55 | View 56 | 57 | 58 | INTypes 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /nightguard WatchKit App/helper/WKInterfaceLabel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WKInterfaceLabel.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 29.07.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WatchKit 11 | 12 | extension WKInterfaceLabel { 13 | 14 | // forms a new string like so 15 | // prefix + ageOf(isoTime) 16 | // The color will be white/yellow/red depending on hoursUntilWarning and hoursUntilCritical. 17 | func convertToAge(prefix: String, time: Date, hoursUntilWarning: Int, hoursUntilCritical: Int) { 18 | 19 | let dateComponentsFormatter = DateComponentsFormatter() 20 | dateComponentsFormatter.allowedUnits = [.day,.hour] 21 | dateComponentsFormatter.maximumUnitCount = 2 22 | dateComponentsFormatter.unitsStyle = .abbreviated 23 | 24 | guard let differenceString = dateComponentsFormatter.string(from: time, to: Date()) else { 25 | self.setText(prefix + "---") 26 | return 27 | } 28 | 29 | self.setText(prefix + differenceString) 30 | self.setTextColor(determineColorDependingOn(time: time, hoursUntilWarning: hoursUntilWarning, hoursUntilCritical: hoursUntilCritical)) 31 | } 32 | 33 | fileprivate func determineColorDependingOn(time: Date, hoursUntilWarning: Int, hoursUntilCritical: Int) -> UIColor { 34 | 35 | let diffComponents = Calendar.current.dateComponents([.hour], from: time, to: Date()) 36 | guard let hours = diffComponents.hour else { 37 | return UIColor.white 38 | } 39 | 40 | if hours > hoursUntilCritical { 41 | return UIColor.nightguardRed() 42 | } 43 | 44 | if hours > hoursUntilWarning { 45 | return UIColor.nightguardYellow() 46 | } 47 | 48 | return UIColor.white 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nightguard Widget Extension/de.lproj/nightguard_Widget_Extension.intentdefinition: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INEnums 6 | 7 | INIntentDefinitionModelVersion 8 | 1.2 9 | INIntentDefinitionNamespace 10 | 88xZPY 11 | INIntentDefinitionSystemVersion 12 | 21G115 13 | INIntentDefinitionToolsBuildVersion 14 | 14A400 15 | INIntentDefinitionToolsVersion 16 | 14.0.1 17 | INIntents 18 | 19 | 20 | INIntentCategory 21 | information 22 | INIntentDescription 23 | Lockscreen Widget Configuration. 24 | INIntentDescriptionID 25 | tVvJ9c 26 | INIntentEligibleForWidgets 27 | 28 | INIntentIneligibleForSuggestions 29 | 30 | INIntentName 31 | Configuration 32 | INIntentResponse 33 | 34 | INIntentResponseCodes 35 | 36 | 37 | INIntentResponseCodeName 38 | success 39 | INIntentResponseCodeSuccess 40 | 41 | 42 | 43 | INIntentResponseCodeName 44 | failure 45 | 46 | 47 | 48 | INIntentTitle 49 | Configuration 50 | INIntentTitleID 51 | gpCwrM 52 | INIntentType 53 | Custom 54 | INIntentVerb 55 | View 56 | 57 | 58 | INTypes 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /nightguard Widget Extension/Base.lproj/nightguard_Widget_Extension.intentdefinition: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INEnums 6 | 7 | INIntentDefinitionModelVersion 8 | 1.2 9 | INIntentDefinitionNamespace 10 | 88xZPY 11 | INIntentDefinitionSystemVersion 12 | 21G115 13 | INIntentDefinitionToolsBuildVersion 14 | 14A400 15 | INIntentDefinitionToolsVersion 16 | 14.0.1 17 | INIntents 18 | 19 | 20 | INIntentCategory 21 | information 22 | INIntentDescription 23 | Lockscreen Widget Configuration. 24 | INIntentDescriptionID 25 | tVvJ9c 26 | INIntentEligibleForWidgets 27 | 28 | INIntentIneligibleForSuggestions 29 | 30 | INIntentName 31 | Configuration 32 | INIntentResponse 33 | 34 | INIntentResponseCodes 35 | 36 | 37 | INIntentResponseCodeName 38 | success 39 | INIntentResponseCodeSuccess 40 | 41 | 42 | 43 | INIntentResponseCodeName 44 | failure 45 | 46 | 47 | 48 | INIntentTitle 49 | Configuration 50 | INIntentTitleID 51 | gpCwrM 52 | INIntentType 53 | Custom 54 | INIntentVerb 55 | View 56 | 57 | 58 | INTypes 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /nightguardTests/UserDefaultsRepositoryTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsRepositoryTest.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 15.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class UserDefaultsRepositoryTest : XCTestCase { 12 | 13 | func testSaveUnitsWithMgdl() { 14 | 15 | UserDefaultsRepository.units.value = Units.mgdl 16 | 17 | XCTAssertEqual(UserDefaultsRepository.units.value, Units.mgdl) 18 | } 19 | 20 | func testSaveUnitsWithMmoll() { 21 | 22 | UserDefaultsRepository.units.value = Units.mmol 23 | 24 | XCTAssertEqual(UserDefaultsRepository.units.value, Units.mmol) 25 | } 26 | 27 | func testScreenLockStateIsSaved() { 28 | 29 | // Given 30 | let initialPosition : Bool = false 31 | 32 | // When 33 | UserDefaultsRepository.screenlockSwitchState.value = initialPosition 34 | let retrievedPosition = UserDefaultsRepository.screenlockSwitchState.value 35 | 36 | // Then 37 | XCTAssertEqual(retrievedPosition, initialPosition) 38 | } 39 | 40 | func testSaveTreatments() { 41 | 42 | // Given 43 | var treatments : [Treatment] = [] 44 | treatments.append(Treatment.init(id: "id0", timestamp: 0)) 45 | treatments.append(Treatment.init(id: "id1", timestamp: 1)) 46 | 47 | // When 48 | UserDefaultsRepository.treatments.value = treatments 49 | let retrievedTreatments : [Treatment] = UserDefaultsRepository.treatments.value 50 | 51 | // Then 52 | XCTAssertEqual(retrievedTreatments.count, 2) 53 | 54 | XCTAssertEqual(retrievedTreatments[0].id, "id0") 55 | XCTAssertEqual(retrievedTreatments[0].timestamp, 0) 56 | 57 | XCTAssertEqual(retrievedTreatments[1].id, "id1") 58 | XCTAssertEqual(retrievedTreatments[1].timestamp, 1) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /nightguard WatchKit App/views/CancelTemporaryTargetPopupView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CancelTemporaryTargetPopupView.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 11.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import SpriteKit 11 | import Combine 12 | 13 | struct CancelTemporaryTargetPopupView: View { 14 | 15 | @Environment(\.presentationMode) var presentationMode 16 | 17 | @Binding var isPresented: Bool 18 | 19 | var body: some View { 20 | VStack() { 21 | Text( 22 | NSLocalizedString("Do you want to cancel an active temporary target?", comment: "Cancel Target Popup Text")) 23 | HStack() { 24 | Button(action: { 25 | 26 | WKInterfaceDevice.current().play(.success) 27 | 28 | NightscoutService.singleton.deleteTemporaryTarget( 29 | resultHandler: {(error: String?) in 30 | 31 | /* TODO show error message 32 | if (error != nil) { 33 | self.displayErrorMessagePopup(message: error!) 34 | } else { 35 | UIApplication.shared.showMain() 36 | }*/ 37 | }) 38 | isPresented = false 39 | }) { 40 | Text(NSLocalizedString("Accept", comment: "Popup Accept-Button")) 41 | .font(.system(size: 12)) 42 | } 43 | Button(action: { 44 | 45 | isPresented = false 46 | }) { 47 | Text(NSLocalizedString("Decline", comment: "Popup Decline-Button")) 48 | .font(.system(size: 12)) 49 | } 50 | } 51 | Spacer() 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /nightguard/TouchReportingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TouchReportingView.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 3/21/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// UIButton or UITableViewCell like touch & tap detection UIControl, useful for giving a button behavior to any view (highlighting on touch, execute action on tap). 12 | class TouchReportingView: UIControl { 13 | 14 | /// closure called when touch started (isHighlighted == true) 15 | var onTouchStarted: (() -> Void)? 16 | 17 | /// closure called when touch ended (isHighlighted == false) 18 | var onTouchEnded: (() -> Void)? 19 | 20 | /// closure called when a tap is detected 21 | var onTouchUpInside: (() -> Void)? 22 | 23 | override init(frame: CGRect) { 24 | super.init(frame: frame) 25 | commonInit() 26 | } 27 | 28 | required init?(coder aDecoder: NSCoder) { 29 | super.init(coder: aDecoder) 30 | commonInit() 31 | } 32 | 33 | func commonInit() { 34 | addTarget(self, action: #selector(touchedUp), for: .touchUpInside) 35 | addTarget(self, action: #selector(touchedDown), for: .touchDown) 36 | addTarget(self, action: #selector(exited), for: .touchCancel) 37 | addTarget(self, action: #selector(exited), for: .touchDragExit) 38 | addTarget(self, action: #selector(entered), for: .touchDragEnter) 39 | } 40 | 41 | @objc func touchedDown() { 42 | onTouchStarted?() 43 | } 44 | 45 | @objc func entered() { 46 | onTouchStarted?() 47 | } 48 | 49 | @objc func exited() { 50 | UIView.animate(withDuration: 0.4, animations: { [weak self] in 51 | self?.onTouchEnded?() 52 | }) 53 | } 54 | 55 | @objc func touchedUp() { 56 | UIView.animate(withDuration: 0.4, animations: { [weak self] in 57 | self?.onTouchEnded?() 58 | }) 59 | 60 | onTouchUpInside?() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /nightguard/XibLoadedView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XibLoadedView.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 3/12/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XibLoadedView: UIView { 12 | 13 | // the custom view from the XIB file 14 | var view: UIView! 15 | 16 | // the XIB file name (by default, the class name - override this property in subclasses if needed) 17 | var nibName: String { 18 | return NSStringFromClass(type(of: self)).components(separatedBy: ".").last! 19 | } 20 | 21 | override init(frame: CGRect) { 22 | super.init(frame: frame) 23 | commonInit() 24 | } 25 | 26 | required init?(coder aDecoder: NSCoder) { 27 | super.init(coder: aDecoder) 28 | commonInit() 29 | } 30 | 31 | func commonInit() { 32 | xibSetup() 33 | } 34 | 35 | fileprivate func xibSetup() { 36 | self.backgroundColor = .clear 37 | view = loadViewFromNib() 38 | 39 | addSubview(view) 40 | view.translatesAutoresizingMaskIntoConstraints = false 41 | NSLayoutConstraint.activate([ 42 | view.leadingAnchor.constraint(equalTo: self.leadingAnchor), 43 | view.trailingAnchor.constraint(equalTo: self.trailingAnchor), 44 | view.topAnchor.constraint(equalTo: self.topAnchor), 45 | view.bottomAnchor.constraint(equalTo: self.bottomAnchor) 46 | ]) 47 | } 48 | 49 | fileprivate func loadViewFromNib() -> UIView { 50 | let bundle = Bundle(for: type(of: self)) 51 | let nibName = self.nibName 52 | guard let _ = bundle.path(forResource: nibName, ofType: "nib") else { 53 | return UIView() 54 | } 55 | 56 | let nib = UINib(nibName: nibName, bundle: bundle) 57 | 58 | // Assumes UIView is top level and only object in CustomView.xib file 59 | let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView 60 | return view 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /nightguard/UIApplicationExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIApplicationExtension.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 12/10/18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UserNotifications 11 | 12 | #if os(iOS) && MAIN_APP 13 | extension UIApplication { 14 | 15 | /* 16 | * Updates app bagdge with the current BG value 17 | */ 18 | func setCurrentBGValueOnAppBadge() { 19 | 20 | let nightscoutData = NightscoutCacheService.singleton.getCurrentNightscoutData() 21 | guard let sgvAsDouble = Double(UnitsConverter.mgdlToDisplayUnits(nightscoutData.sgv)) else { 22 | return 23 | } 24 | let sgvAsInt = Int(sgvAsDouble.rounded()) 25 | 26 | UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .alert, .sound, .criticalAlert]) { (granted, error) in 27 | if granted && error == nil { 28 | 29 | // success! 30 | dispatchOnMain { 31 | 32 | UIApplication.shared.applicationIconBadgeNumber = sgvAsInt 33 | } 34 | } 35 | } 36 | 37 | } 38 | 39 | /* 40 | * Removes the current BG value from app badge 41 | */ 42 | func clearAppBadge() { 43 | UIApplication.shared.applicationIconBadgeNumber = 0 44 | } 45 | 46 | /* 47 | * function will return reference to tabbarcontroller 48 | */ 49 | func showMain() { 50 | // Use the modern approach for accessing the rootViewController in multi-scene environments 51 | let keyWindow = UIApplication.shared.connectedScenes 52 | .compactMap { $0 as? UIWindowScene } 53 | .flatMap { $0.windows } 54 | .first { $0.isKeyWindow } 55 | 56 | guard let vc = keyWindow?.rootViewController else { return } 57 | if let tabBarController = vc as? TabBarController { 58 | tabBarController.selectedIndex = 0 59 | } 60 | } 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/NotificationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationController.swift 3 | // scoutwatch WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 20.11.15. 6 | // Copyright © 2015 private. All rights reserved. 7 | // 8 | 9 | import WatchKit 10 | import Foundation 11 | 12 | class NotificationController: WKUserNotificationInterfaceController { 13 | 14 | override init() { 15 | // Initialize variables here. 16 | super.init() 17 | 18 | // Configure interface objects here. 19 | } 20 | 21 | override func willActivate() { 22 | // This method is called when watch view controller is about to be visible to user 23 | super.willActivate() 24 | } 25 | 26 | override func didDeactivate() { 27 | // This method is called when watch view controller is no longer visible 28 | super.didDeactivate() 29 | } 30 | 31 | /* 32 | override func didReceiveLocalNotification(localNotification: UILocalNotification, withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) { 33 | // This method is called when a local notification needs to be presented. 34 | // Implement it if you use a dynamic notification interface. 35 | // Populate your dynamic notification interface as quickly as possible. 36 | // 37 | // After populating your dynamic notification interface call the completion block. 38 | completionHandler(.Custom) 39 | } 40 | */ 41 | 42 | /* 43 | override func didReceiveRemoteNotification(remoteNotification: [NSObject : AnyObject], withCompletion completionHandler: ((WKUserNotificationInterfaceType) -> Void)) { 44 | // This method is called when a remote notification needs to be presented. 45 | // Implement it if you use a dynamic notification interface. 46 | // Populate your dynamic notification interface as quickly as possible. 47 | // 48 | // After populating your dynamic notification interface call the completion block. 49 | completionHandler(.Custom) 50 | } 51 | */ 52 | } 53 | -------------------------------------------------------------------------------- /nightguard/GroupedLabelsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GroupedLabelsView.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 6/14/18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class GroupedLabelsView: UIStackView { 12 | 13 | private lazy var backgroundView: UIView = { 14 | let view = UIView() 15 | view.backgroundColor = UIColor.white.withAlphaComponent(0.5) 16 | view.layer.cornerRadius = 2 17 | return view 18 | }() 19 | 20 | lazy var label: UILabel = { 21 | let label = PaddingLabel() 22 | label.textAlignment = .center 23 | label.insets = UIEdgeInsets(top: 1, left: 2, bottom: 1, right: 2) 24 | label.font = UIFont.systemFont(ofSize: 9) 25 | label.clipsToBounds = true 26 | return label 27 | }() 28 | 29 | lazy var highlightedLabel: UILabel = { 30 | let label = PaddingLabel() 31 | label.textAlignment = .center 32 | label.insets = UIEdgeInsets(top: 1, left: 2, bottom: 1, right: 2) 33 | label.font = UIFont.systemFont(ofSize: 11) 34 | label.textColor = .white 35 | label.backgroundColor = UIColor.black.withAlphaComponent(0.8) 36 | label.clipsToBounds = true 37 | label.layer.cornerRadius = 2 38 | return label 39 | }() 40 | 41 | override init(frame: CGRect) { 42 | super.init(frame: frame) 43 | commonInit() 44 | } 45 | 46 | required init(coder: NSCoder) { 47 | super.init(coder: coder) 48 | commonInit() 49 | } 50 | 51 | private func commonInit() { 52 | 53 | layoutMargins = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) 54 | isLayoutMarginsRelativeArrangement = true 55 | 56 | pinBackground() 57 | addArrangedSubview(highlightedLabel) 58 | addArrangedSubview(label) 59 | } 60 | 61 | private func pinBackground() { 62 | backgroundView.translatesAutoresizingMaskIntoConstraints = false 63 | insertSubview(backgroundView, at: 0) 64 | backgroundView.pin(to: self) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /nightguard WatchKit App/views/ActivateTemporaryTargetPopupView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActivateTemporaryTargetView.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 11.10.20. 6 | // Copyright © 2020 private. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import SpriteKit 11 | import Combine 12 | 13 | struct ActivateTemporaryTargetPopupView: View { 14 | 15 | @Environment(\.presentationMode) var presentationMode 16 | @Binding var isPresented: Bool 17 | 18 | var body: some View { 19 | VStack() { 20 | Text( 21 | String(format: NSLocalizedString("Do you want to set a temporary target for %d minutes?", comment: "Set Target Message Text"), UserDefaultsRepository.temporaryTargetDuration.value) + 22 | "\n (\(UnitsConverter.mgdlToDisplayUnits(Float(UserDefaultsRepository.temporaryTargetAmount.value))) \(UserDefaultsRepository.units.value.description))") 23 | HStack() { 24 | Button(action: { 25 | 26 | WKInterfaceDevice.current().play(.success) 27 | 28 | NightscoutService.singleton.createTemporaryTarget( 29 | reason: UserDefaultsRepository.temporaryTargetReason.value, 30 | target: UserDefaultsRepository.temporaryTargetAmount.value, 31 | durationInMinutes: UserDefaultsRepository.temporaryTargetDuration.value, 32 | resultHandler: {(error: String?) in 33 | 34 | // TODO: Show the result 35 | }) 36 | isPresented = false 37 | }) { 38 | Text(NSLocalizedString("Accept", comment: "Popup Accept-Button")) 39 | .font(.system(size: 12)) 40 | } 41 | Button(action: { 42 | isPresented = false 43 | }) { 44 | Text(NSLocalizedString("Decline", comment: "Popup Decline-Button")) 45 | .font(.system(size: 12)) 46 | } 47 | } 48 | Spacer() 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /nightguard.xcodeproj/xcuserdata/dirk.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | nightguard ComplicationExtension.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 11 11 | 12 | nightguard WatchKit App (Complication).xcscheme 13 | 14 | orderHint 15 | 2 16 | 17 | nightguard WatchKit App (Notification).xcscheme 18 | 19 | orderHint 20 | 1 21 | 22 | nightguard WatchKit App.xcscheme 23 | 24 | orderHint 25 | 0 26 | 27 | nightguard Widget Extension.xcscheme_^#shared#^_ 28 | 29 | orderHint 30 | 12 31 | 32 | nightguard Widget ExtensionExtension.xcscheme_^#shared#^_ 33 | 34 | orderHint 35 | 11 36 | 37 | nightguard.xcscheme_^#shared#^_ 38 | 39 | orderHint 40 | 13 41 | 42 | nightguardTests.xcscheme_^#shared#^_ 43 | 44 | orderHint 45 | 11 46 | 47 | 48 | SuppressBuildableAutocreation 49 | 50 | 43647BC91BFF6435004389F9 51 | 52 | primary 53 | 54 | 55 | 43647BDD1BFF6435004389F9 56 | 57 | primary 58 | 59 | 60 | 43647BE81BFF6435004389F9 61 | 62 | primary 63 | 64 | 65 | 43647BF11BFF6435004389F9 66 | 67 | primary 68 | 69 | 70 | 438DAC7A28D2356800FBF520 71 | 72 | primary 73 | 74 | 75 | 43D005CE29DC9BFA003BCE92 76 | 77 | primary 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /nightguard WatchKit App/controllers/SnoozeInterfaceController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnoozeInterfaceController.swift 3 | // nightguard WatchKit Extension 4 | // 5 | // Created by Dirk Hermanns on 10.02.18. 6 | // Copyright © 2018 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WatchKit 11 | 12 | class SnoozeInterfaceController : WKInterfaceController { 13 | 14 | @IBOutlet var stopSnoozingButton: WKInterfaceButton! 15 | 16 | override public init() { 17 | super.init() 18 | 19 | setTitle(NSLocalizedString("Cancel", comment: "Watch Interface Controller Cancel Label")) 20 | } 21 | 22 | override func awake(withContext context: Any?) { 23 | super.awake(withContext: context) 24 | 25 | if !AlarmRule.isSnoozed() { 26 | stopSnoozingButton.setHidden(true) 27 | } 28 | } 29 | 30 | @IBAction func doSnooze5Minutes() { 31 | AlarmRule.snooze(5) 32 | self.dismiss() 33 | } 34 | 35 | @IBAction func doSnooze10Minutes() { 36 | AlarmRule.snooze(10) 37 | self.dismiss() 38 | } 39 | 40 | @IBAction func doSnooze15Minutes() { 41 | AlarmRule.snooze(15) 42 | self.dismiss() 43 | } 44 | 45 | @IBAction func doSnooze20Minutes() { 46 | AlarmRule.snooze(20) 47 | self.dismiss() 48 | } 49 | 50 | @IBAction func doSnooze30Minutes() { 51 | AlarmRule.snooze(30) 52 | self.dismiss() 53 | } 54 | 55 | @IBAction func doSnooze45Minutes() { 56 | AlarmRule.snooze(45) 57 | self.dismiss() 58 | } 59 | 60 | @IBAction func doSnooze1Hour() { 61 | AlarmRule.snooze(60) 62 | self.dismiss() 63 | } 64 | 65 | @IBAction func doSnooze2Hours() { 66 | AlarmRule.snooze(120) 67 | self.dismiss() 68 | } 69 | 70 | @IBAction func doSnooze3Hours() { 71 | AlarmRule.snooze(180) 72 | self.dismiss() 73 | } 74 | 75 | @IBAction func doSnooze6Hours() { 76 | AlarmRule.snooze(60 * 6) 77 | self.dismiss() 78 | } 79 | 80 | @IBAction func doSnooze1Day() { 81 | AlarmRule.snooze(60 * 24) 82 | self.dismiss() 83 | } 84 | 85 | @IBAction func doCancelSnoozeAction() { 86 | AlarmRule.disableSnooze() 87 | self.dismiss() 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /nightguard/LowPredictionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LowPredictionViewController.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/7/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Eureka 11 | 12 | class LowPredictionViewController: CustomFormViewController { 13 | 14 | private let lowPredictionAlarmOptions = [5, 10, 15, 20, 25, 30] 15 | private var selectableSection: SelectableSection>! 16 | 17 | override func constructForm() { 18 | 19 | selectableSection = SelectableSection>(NSLocalizedString("Prediction interval", comment: "Label for prediction interval options"), selectionType: .singleSelection(enableDeselection: true)) 20 | selectableSection.onSelectSelectableRow = { cell, row in 21 | guard let value = row.value else { return } 22 | AlarmRule.minutesToPredictLow.value = value 23 | } 24 | selectableSection.hidden = .function(["Low Prediction"], { form -> Bool in 25 | let row: RowOf! = form.rowBy(tag: "Low Prediction") 26 | return row.value ?? false == false 27 | }) 28 | 29 | for option in lowPredictionAlarmOptions { 30 | let optionString = String(format: NSLocalizedString("%d Minutes", comment: "Option in low predicion alert settings"), option) 31 | 32 | selectableSection <<< ListCheckRow(optionString) { lrow in 33 | lrow.title = optionString 34 | lrow.selectableValue = option 35 | lrow.value = (option == AlarmRule.minutesToPredictLow.value) ? option : nil 36 | } 37 | } 38 | 39 | form +++ Section(header: "", footer: NSLocalizedString("Alerts when a low BG value is predicted in the near future (if the current trend is continued).", comment: "Footer in low predicion alert settings")) 40 | <<< SwitchRow("Low Prediction") { row in 41 | row.title = NSLocalizedString("Low Prediction2", comment: "Title in low predicion alert settings") 42 | row.value = AlarmRule.isLowPredictionEnabled.value 43 | }.onChange { row in 44 | guard let value = row.value else { return } 45 | AlarmRule.isLowPredictionEnabled.value = value 46 | } 47 | 48 | +++ selectableSection 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /nightguard/SnoozeActionsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SnoozeActionsViewController.swift 3 | // nightguard 4 | // 5 | // Created by Florian Preknya on 2/10/19. 6 | // Copyright © 2019 private. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Eureka 11 | 12 | class SnoozeActionsViewController: CustomFormViewController { 13 | 14 | private let quickActionCodes: [QuickSnoozeOption] = [ 15 | .doNothing, 16 | .showSnoozePopup, 17 | .snoozeOneMinute, 18 | .snoozeFiveMinutes, 19 | .snoozeTenMinutes 20 | ] 21 | 22 | override func constructForm() { 23 | 24 | form +++ Section(footer: NSLocalizedString("After an alert started, sometimes it is important to have a shortcut, a quick way to stop it for the moment.", comment: "SnoozeActionsViewController Quick Snooze Hint")) 25 | +++ Section(header: NSLocalizedString("Quick Snoozing", comment: "Quick Snoozing Label"), footer: NSLocalizedString("NOTE: snoozing with volume buttons is enabled only if the \"Override System Volume\" option is ON (Alert Volume screen)", comment: "Snoozing with volume button hint")) 26 | <<< makeQuickSnoozePickerRow(title: NSLocalizedString("Shaking the phone", comment: "Shaking the phone Label"), userDefaultsValue: UserDefaultsRepository.shakingOnAlertSnoozeOption) 27 | <<< makeQuickSnoozePickerRow(title: NSLocalizedString("Volume Buttons", comment: "Volume Buttons Label"), userDefaultsValue: UserDefaultsRepository.volumeKeysOnAlertSnoozeOption) 28 | } 29 | 30 | private func makeQuickSnoozePickerRow(title: String, userDefaultsValue: UserDefaultsValue) -> PickerInlineRow { 31 | 32 | return PickerInlineRow() { row in 33 | row.title = title 34 | row.cellStyle = .subtitle 35 | row.displayValueFor = { value in 36 | guard let value = value else { return nil } 37 | guard let quickSnoozeOption = QuickSnoozeOption(rawValue: value) else { return nil} 38 | 39 | return quickSnoozeOption.description 40 | } 41 | row.options = quickActionCodes.map { $0.rawValue } 42 | row.value = userDefaultsValue.value.rawValue 43 | }.onChange { row in 44 | guard let value = row.value else { return } 45 | guard let quickSnoozeOption = QuickSnoozeOption(rawValue: value) else { return } 46 | userDefaultsValue.value = quickSnoozeOption 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /nightguard/CarbCorrectionTreatment.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 17.02.21. 6 | // Copyright © 2021 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class CarbCorrectionTreatment : Treatment { 12 | 13 | public let carbs : Int 14 | 15 | public init(id : String, timestamp: Double, carbs : Int) { 16 | 17 | self.carbs = carbs 18 | 19 | super.init(id: id, timestamp: timestamp) 20 | } 21 | 22 | enum CodingKeys: String, CodingKey { 23 | case id 24 | case timestamp 25 | case carbs 26 | } 27 | 28 | /* 29 | Code to deserialize Treatment content. The error handling is needed in case that old serialized 30 | data leads to an error. 31 | */ 32 | required init(coder decoder: NSCoder) { 33 | 34 | self.carbs = decoder.decodeInteger(forKey: "carbs") 35 | 36 | super.init(coder: decoder) 37 | } 38 | 39 | /* 40 | Code to serialize the treatment to store them in UserDefaults. 41 | */ 42 | override func encode(with aCoder: NSCoder) { 43 | 44 | super.encode(with: aCoder) 45 | 46 | aCoder.encode(self.carbs, forKey: "carbs") 47 | } 48 | 49 | // MARK:- Codable interface implementation 50 | 51 | /// Creates a new instance by decoding from the given decoder. 52 | /// 53 | /// This initializer throws an error if reading from the decoder fails, or 54 | /// if the data read is corrupted or otherwise invalid. 55 | /// 56 | /// - Parameter decoder: The decoder to read data from. 57 | required init(from decoder: Decoder) throws { 58 | 59 | let container = try decoder.container(keyedBy: CodingKeys.self) 60 | self.carbs = try container.decode(Int.self, forKey: .carbs) 61 | 62 | try super.init(from: decoder) 63 | } 64 | 65 | /// Encodes this value into the given encoder. 66 | /// 67 | /// If the value fails to encode anything, `encoder` will encode an empty 68 | /// keyed container in its place. 69 | /// 70 | /// This function throws an error if any values are invalid for the given 71 | /// encoder's format. 72 | /// 73 | /// - Parameter encoder: The encoder to write data to. 74 | override func encode(to encoder: Encoder) throws { 75 | 76 | try super.encode(to: encoder) 77 | 78 | var container = encoder.container(keyedBy: CodingKeys.self) 79 | try container.encode(self.carbs, forKey: .carbs) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /nightguard/app/TimeService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimeService.swift 3 | // scoutwatch 4 | // 5 | // Created by Dirk Hermanns on 23.01.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TimeService { 12 | 13 | fileprivate static var testTime : Double? = nil 14 | fileprivate static var testMode : Bool = false 15 | 16 | static func getStartOfCurrentDay() -> Double { 17 | 18 | let date = Date() 19 | let cal = Calendar(identifier: .gregorian) 20 | let startOfCurrentDay = cal.startOfDay(for: date) 21 | 22 | return Double(startOfCurrentDay.timeIntervalSince1970 * 1000) 23 | } 24 | 25 | static func setTestTime(_ testTime : Double) { 26 | self.testTime = testTime; 27 | } 28 | 29 | static func getCurrentTime() -> Double { 30 | if testTime != nil { 31 | return testTime! 32 | } else { 33 | return Date().timeIntervalSince1970 34 | } 35 | } 36 | 37 | static func getToday() -> Date { 38 | if testTime != nil { 39 | return Date(timeIntervalSince1970: testTime!) 40 | } 41 | return Date() 42 | } 43 | 44 | static func get4DaysAgo() -> Date { 45 | return getToday().addingTimeInterval(4 * -24 * 60 * 60) 46 | } 47 | 48 | static func getNrOfDaysAgo(_ nrOfDaysAgo : Int) -> Date { 49 | return getToday().addingTimeInterval(Double(nrOfDaysAgo) * -24 * 60 * 60) 50 | } 51 | 52 | static func getYesterday() -> Date { 53 | let yesterday = getToday().addingTimeInterval(-24*60*60) 54 | 55 | return yesterday 56 | } 57 | 58 | static func getTomorrow() -> Date { 59 | let tomorrow = getToday().addingTimeInterval(24*60*60) 60 | 61 | return tomorrow 62 | } 63 | 64 | static func isYesterday(_ microsSince1970 : Double) -> Bool { 65 | let secondsSince1970 = microsSince1970 / 1000 66 | 67 | let calendar = Calendar.current 68 | let startOfYesterday = calendar.startOfDay(for: TimeService.getYesterday()).timeIntervalSince1970 69 | let endOfYesterday = calendar.startOfDay(for: TimeService.getToday()).timeIntervalSince1970 70 | 71 | return startOfYesterday <= secondsSince1970 && 72 | secondsSince1970 <= endOfYesterday 73 | 74 | } 75 | 76 | static func isOlderThan30Minutes(_ date : Date) -> Bool { 77 | return getToday().addingTimeInterval(-30 * 60).compare(date) == ComparisonResult.orderedDescending 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /nightguard/external/WatchService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WatchService.swift 3 | // nightguard 4 | // 5 | // Created by Dirk Hermanns on 05.06.16. 6 | // Copyright © 2016 private. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WatchConnectivity 11 | 12 | class WatchService { 13 | 14 | static let singleton = WatchService() 15 | 16 | private var lastSentNightscoutDataTime: NSNumber? 17 | private var lastWatchUpdateTime: Date? 18 | private var lastWatchComplicationUpdateTime: Date? 19 | 20 | func sendToWatchCurrentNightwatchData() { 21 | 22 | // send ONLY if the phone app has new nightscout data 23 | let nightscoutData = NightscoutCacheService.singleton.getCurrentNightscoutData() 24 | guard !nightscoutData.isOlderThanXMinutes(15) else { 25 | return 26 | } 27 | 28 | // the session must be active in order to send data 29 | guard WCSession.default.activationState == .activated else { 30 | return 31 | } 32 | 33 | // update watch 34 | if lastSentNightscoutDataTime != nightscoutData.time { 35 | // Assuring we are sending ONLY once a nightscout data... 36 | // ... and respecting the update rate! 37 | if let lastWatchUpdateTime = self.lastWatchUpdateTime, (Calendar.current.date(byAdding: .minute, value: 5, to: lastWatchUpdateTime) ?? Date()) >= Date() { 38 | 39 | // do nothing, last watch update was more recent than update rate, will skip updating it now! 40 | } else { 41 | 42 | // do update! 43 | NightscoutDataMessage().send() 44 | self.lastSentNightscoutDataTime = nightscoutData.time 45 | self.lastWatchUpdateTime = Date() 46 | } 47 | } 48 | } 49 | 50 | private func sendOrTransmitToWatch(_ message: [String : Any]) { 51 | 52 | // send message if watch is reachable 53 | if WCSession.default.isReachable { 54 | WCSession.default.sendMessage(message, replyHandler: { data in 55 | print("Received data: \(data)") 56 | }, errorHandler: { error in 57 | print(error) 58 | 59 | // transmit message on failure 60 | try? WCSession.default.updateApplicationContext(message) 61 | }) 62 | } else { 63 | 64 | // otherwise, transmit application context 65 | try? WCSession.default.updateApplicationContext(message) 66 | } 67 | } 68 | } 69 | --------------------------------------------------------------------------------