├── 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 |
--------------------------------------------------------------------------------