From d5c482f033f6e9054467e5a15b9dceb935846aa9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 11 Sep 2018 16:44:38 -0500 Subject: [PATCH 01/12] Implement CGMManager protocol --- .gitignore | 37 ++ Cartfile | 1 + Cartfile.resolved | 1 + Common/LocalizedString.swift | 21 + ShareClient.xcodeproj/project.pbxproj | 431 +++++++++++++++++- .../xcschemes/ShareClient.xcscheme | 4 +- .../xcschemes/ShareClientUI.xcscheme | 80 ++++ ShareClient/Base.lproj/Localizable.strings | Bin 0 -> 548 bytes ShareClient/HKUnit.swift | 16 + ShareClient/ShareClient.swift | 2 +- ShareClient/ShareClientManager.swift | 100 ++++ ShareClient/ShareGlucose+GlucoseKit.swift | 47 ++ ShareClient/ShareService.swift | 140 ++++++ ShareClient/TimeInterval.swift | 61 +++ ShareClient/de.lproj/Localizable.strings | Bin 0 -> 566 bytes ShareClient/es.lproj/Localizable.strings | Bin 0 -> 552 bytes ShareClient/fr.lproj/Localizable.strings | Bin 0 -> 552 bytes ShareClient/it.lproj/Localizable.strings | Bin 0 -> 546 bytes ShareClient/nb.lproj/Localizable.strings | Bin 0 -> 546 bytes ShareClient/nl.lproj/Localizable.strings | Bin 0 -> 550 bytes ShareClient/pl.lproj/Localizable.strings | Bin 0 -> 550 bytes ShareClient/ru.lproj/Localizable.strings | Bin 0 -> 550 bytes ShareClient/zh-Hans.lproj/Localizable.strings | Bin 0 -> 506 bytes ShareClientTests/ShareClientTests.swift | 2 +- ShareClientUI/Base.lproj/Localizable.strings | Bin 0 -> 2062 bytes ShareClientUI/IdentifiableClass.swift | 24 + ShareClientUI/Info.plist | 24 + ShareClientUI/ShareClientManager+UI.swift | 25 + .../ShareClientSettingsViewController.swift | 205 +++++++++ .../ShareClientSetupViewController.swift | 47 ++ ShareClientUI/ShareClientUI.h | 19 + ShareClientUI/ShareService+UI.swift | 38 ++ ShareClientUI/UIColor.swift | 22 + ShareClientUI/de.lproj/Localizable.strings | Bin 0 -> 1002 bytes ShareClientUI/es.lproj/Localizable.strings | Bin 0 -> 996 bytes ShareClientUI/fr.lproj/Localizable.strings | Bin 0 -> 1042 bytes ShareClientUI/it.lproj/Localizable.strings | Bin 0 -> 988 bytes ShareClientUI/nb.lproj/Localizable.strings | Bin 0 -> 982 bytes ShareClientUI/nl.lproj/Localizable.strings | Bin 0 -> 1304 bytes ShareClientUI/pl.lproj/Localizable.strings | Bin 0 -> 996 bytes ShareClientUI/ru.lproj/Localizable.strings | Bin 0 -> 1004 bytes .../zh-Hans.lproj/Localizable.strings | Bin 0 -> 920 bytes 42 files changed, 1339 insertions(+), 8 deletions(-) create mode 100644 .gitignore create mode 100644 Cartfile create mode 100644 Cartfile.resolved create mode 100644 Common/LocalizedString.swift create mode 100644 ShareClient.xcodeproj/xcshareddata/xcschemes/ShareClientUI.xcscheme create mode 100644 ShareClient/Base.lproj/Localizable.strings create mode 100644 ShareClient/HKUnit.swift create mode 100644 ShareClient/ShareClientManager.swift create mode 100644 ShareClient/ShareGlucose+GlucoseKit.swift create mode 100644 ShareClient/ShareService.swift create mode 100644 ShareClient/TimeInterval.swift create mode 100644 ShareClient/de.lproj/Localizable.strings create mode 100644 ShareClient/es.lproj/Localizable.strings create mode 100644 ShareClient/fr.lproj/Localizable.strings create mode 100644 ShareClient/it.lproj/Localizable.strings create mode 100644 ShareClient/nb.lproj/Localizable.strings create mode 100644 ShareClient/nl.lproj/Localizable.strings create mode 100644 ShareClient/pl.lproj/Localizable.strings create mode 100644 ShareClient/ru.lproj/Localizable.strings create mode 100644 ShareClient/zh-Hans.lproj/Localizable.strings create mode 100644 ShareClientUI/Base.lproj/Localizable.strings create mode 100644 ShareClientUI/IdentifiableClass.swift create mode 100644 ShareClientUI/Info.plist create mode 100644 ShareClientUI/ShareClientManager+UI.swift create mode 100644 ShareClientUI/ShareClientSettingsViewController.swift create mode 100644 ShareClientUI/ShareClientSetupViewController.swift create mode 100644 ShareClientUI/ShareClientUI.h create mode 100644 ShareClientUI/ShareService+UI.swift create mode 100644 ShareClientUI/UIColor.swift create mode 100644 ShareClientUI/de.lproj/Localizable.strings create mode 100644 ShareClientUI/es.lproj/Localizable.strings create mode 100644 ShareClientUI/fr.lproj/Localizable.strings create mode 100644 ShareClientUI/it.lproj/Localizable.strings create mode 100644 ShareClientUI/nb.lproj/Localizable.strings create mode 100644 ShareClientUI/nl.lproj/Localizable.strings create mode 100644 ShareClientUI/pl.lproj/Localizable.strings create mode 100644 ShareClientUI/ru.lproj/Localizable.strings create mode 100644 ShareClientUI/zh-Hans.lproj/Localizable.strings diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61f9ecb --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# OS X +.DS_Store + +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +profile +*.moved-aside +DerivedData +*.hmap +*.ipa +project.xcworkspace + +# Bundler +.bundle + +Carthage +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# +# Note: if you ignore the Pods directory, make sure to uncomment +# `pod install` in .travis.yml +# + +Pods/ +Carthage/ +.gitmodules diff --git a/Cartfile b/Cartfile new file mode 100644 index 0000000..05195c5 --- /dev/null +++ b/Cartfile @@ -0,0 +1 @@ +github "LoopKit/LoopKit" "dev" diff --git a/Cartfile.resolved b/Cartfile.resolved new file mode 100644 index 0000000..1d52afe --- /dev/null +++ b/Cartfile.resolved @@ -0,0 +1 @@ +github "LoopKit/LoopKit" "0cc099726d4148db37d22c14475a97c2575afeaa" diff --git a/Common/LocalizedString.swift b/Common/LocalizedString.swift new file mode 100644 index 0000000..b0e5401 --- /dev/null +++ b/Common/LocalizedString.swift @@ -0,0 +1,21 @@ +// +// LocalizedString.swift +// LoopKit +// +// Created by Retina15 on 8/6/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import Foundation + +internal class FrameworkBundle { + static let main = Bundle(for: FrameworkBundle.self) +} + +func LocalizedString(_ key: String, tableName: String? = nil, value: String? = nil, comment: String) -> String { + if let value = value { + return NSLocalizedString(key, tableName: tableName, bundle: FrameworkBundle.main, value: value, comment: comment) + } else { + return NSLocalizedString(key, tableName: tableName, bundle: FrameworkBundle.main, comment: comment) + } +} diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index b1e0661..536d256 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -6,14 +6,63 @@ objectVersion = 46; objects = { +/* Begin PBXAggregateTarget section */ + 43A8EC75210E653B00A81379 /* Cartfile */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 43A8EC76210E653C00A81379 /* Build configuration list for PBXAggregateTarget "Cartfile" */; + buildPhases = ( + 43A8EC79210E654300A81379 /* Build Carthage Dependencies */, + ); + dependencies = ( + ); + name = Cartfile; + productName = Cartfile; + }; +/* End PBXAggregateTarget section */ + /* Begin PBXBuildFile section */ + 4325E9CF210E6A0A00969CE5 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4325E9CE210E6A0A00969CE5 /* HKUnit.swift */; }; + 4325E9D1210E6A3D00969CE5 /* TimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4325E9D0210E6A3D00969CE5 /* TimeInterval.swift */; }; + 4325E9D3210E6ADA00969CE5 /* IdentifiableClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4325E9D2210E6ADA00969CE5 /* IdentifiableClass.swift */; }; + 4325E9D5210E6B4400969CE5 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4325E9D4210E6B4300969CE5 /* UIColor.swift */; }; 432B0E8C1CDFC3C50045347B /* ShareClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 432B0E8B1CDFC3C50045347B /* ShareClient.h */; settings = {ATTRIBUTES = (Public, ); }; }; 432B0E931CDFC3C50045347B /* ShareClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432B0E881CDFC3C50045347B /* ShareClient.framework */; }; 432B0E981CDFC3C50045347B /* ShareClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432B0E971CDFC3C50045347B /* ShareClientTests.swift */; }; + 43A8EC7C210E661400A81379 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A8EC7B210E661400A81379 /* LoopKit.framework */; }; + 43A8EC86210E664300A81379 /* ShareClientUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 43A8EC84210E664300A81379 /* ShareClientUI.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 43A8EC8A210E664C00A81379 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A8EC7B210E661400A81379 /* LoopKit.framework */; }; + 43A8EC8C210E665700A81379 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A8EC8B210E665600A81379 /* LoopKitUI.framework */; }; + 43A8EC90210E676500A81379 /* ShareClientSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC8D210E676500A81379 /* ShareClientSetupViewController.swift */; }; + 43A8EC91210E676500A81379 /* ShareClientManager+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC8E210E676500A81379 /* ShareClientManager+UI.swift */; }; + 43A8EC92210E676500A81379 /* ShareClientSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC8F210E676500A81379 /* ShareClientSettingsViewController.swift */; }; + 43A8EC93210E679B00A81379 /* ShareClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 432B0E881CDFC3C50045347B /* ShareClient.framework */; }; + 43A8EC95210E67B000A81379 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A8EC94210E67B000A81379 /* HealthKit.framework */; }; + 43A8EC97210E680100A81379 /* ShareService+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC96210E680100A81379 /* ShareService+UI.swift */; }; + 43A8EC99210E682A00A81379 /* ShareService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC98210E682A00A81379 /* ShareService.swift */; }; + 43A8EC9B210E68BA00A81379 /* ShareGlucose+GlucoseKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC9A210E68BA00A81379 /* ShareGlucose+GlucoseKit.swift */; }; + 43A8EC9D210E68CE00A81379 /* ShareClientManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43A8EC9C210E68CE00A81379 /* ShareClientManager.swift */; }; + 43AB511B21330D1400B3D58D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43AB511921330D1400B3D58D /* Localizable.strings */; }; + 43AB5127213315D300B3D58D /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43AB5125213315D300B3D58D /* Localizable.strings */; }; + 43AB51362133177800B3D58D /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AB51352133177800B3D58D /* LocalizedString.swift */; }; + 43AB51372133177800B3D58D /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AB51352133177800B3D58D /* LocalizedString.swift */; }; 43C418AF1CE0488900405B6A /* ShareClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C418AE1CE0488900405B6A /* ShareClient.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 4325E9D6210E714B00969CE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 432B0E7F1CDFC3C50045347B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 43A8EC75210E653B00A81379; + remoteInfo = Cartfile; + }; + 4325E9D8210E715200969CE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 432B0E7F1CDFC3C50045347B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 43A8EC75210E653B00A81379; + remoteInfo = Cartfile; + }; 432B0E941CDFC3C50045347B /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 432B0E7F1CDFC3C50045347B /* Project object */; @@ -24,12 +73,50 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 4325E9CE210E6A0A00969CE5 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; + 4325E9D0210E6A3D00969CE5 /* TimeInterval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; + 4325E9D2210E6ADA00969CE5 /* IdentifiableClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IdentifiableClass.swift; sourceTree = ""; }; + 4325E9D4210E6B4300969CE5 /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; 432B0E881CDFC3C50045347B /* ShareClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ShareClient.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 432B0E8B1CDFC3C50045347B /* ShareClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareClient.h; sourceTree = ""; }; 432B0E8D1CDFC3C50045347B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 432B0E921CDFC3C50045347B /* ShareClientTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShareClientTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 432B0E971CDFC3C50045347B /* ShareClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareClientTests.swift; sourceTree = ""; }; 432B0E991CDFC3C50045347B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 43A8EC7B210E661400A81379 /* LoopKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LoopKit.framework; path = Carthage/Build/iOS/LoopKit.framework; sourceTree = ""; }; + 43A8EC82210E664300A81379 /* ShareClientUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ShareClientUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 43A8EC84210E664300A81379 /* ShareClientUI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShareClientUI.h; sourceTree = ""; }; + 43A8EC85210E664300A81379 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 43A8EC8B210E665600A81379 /* LoopKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LoopKitUI.framework; path = Carthage/Build/iOS/LoopKitUI.framework; sourceTree = ""; }; + 43A8EC8D210E676500A81379 /* ShareClientSetupViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareClientSetupViewController.swift; sourceTree = ""; }; + 43A8EC8E210E676500A81379 /* ShareClientManager+UI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ShareClientManager+UI.swift"; sourceTree = ""; }; + 43A8EC8F210E676500A81379 /* ShareClientSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareClientSettingsViewController.swift; sourceTree = ""; }; + 43A8EC94210E67B000A81379 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; + 43A8EC96210E680100A81379 /* ShareService+UI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ShareService+UI.swift"; sourceTree = ""; }; + 43A8EC98210E682A00A81379 /* ShareService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareService.swift; sourceTree = ""; }; + 43A8EC9A210E68BA00A81379 /* ShareGlucose+GlucoseKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ShareGlucose+GlucoseKit.swift"; sourceTree = ""; }; + 43A8EC9C210E68CE00A81379 /* ShareClientManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareClientManager.swift; sourceTree = ""; }; + 43AB511A21330D1400B3D58D /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 43AB511C21330D6800B3D58D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + 43AB511D21330D6B00B3D58D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + 43AB511E21330D7000B3D58D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 43AB511F21330D7800B3D58D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512021330D7E00B3D58D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512121330D8600B3D58D /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512221330D8A00B3D58D /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512321330D8E00B3D58D /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512421330D9400B3D58D /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + 43AB5126213315D300B3D58D /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 43AB51282133161100B3D58D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + 43AB51292133161200B3D58D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512A2133161300B3D58D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 43AB512B2133161600B3D58D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512C2133161700B3D58D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512D2133161800B3D58D /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512E2133161900B3D58D /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; + 43AB512F2133161A00B3D58D /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + 43AB51302133161A00B3D58D /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + 43AB51352133177800B3D58D /* LocalizedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; 43C418AE1CE0488900405B6A /* ShareClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareClient.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -38,6 +125,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 43A8EC95210E67B000A81379 /* HealthKit.framework in Frameworks */, + 43A8EC7C210E661400A81379 /* LoopKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -49,15 +138,28 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 43A8EC7E210E664300A81379 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 43A8EC93210E679B00A81379 /* ShareClient.framework in Frameworks */, + 43A8EC8C210E665700A81379 /* LoopKitUI.framework in Frameworks */, + 43A8EC8A210E664C00A81379 /* LoopKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 432B0E7E1CDFC3C50045347B = { isa = PBXGroup; children = ( + 43AB51342133176B00B3D58D /* Common */, 432B0E8A1CDFC3C50045347B /* ShareClient */, 432B0E961CDFC3C50045347B /* ShareClientTests */, + 43A8EC83210E664300A81379 /* ShareClientUI */, 432B0E891CDFC3C50045347B /* Products */, + 43A8EC7A210E661300A81379 /* Frameworks */, ); sourceTree = ""; }; @@ -66,6 +168,7 @@ children = ( 432B0E881CDFC3C50045347B /* ShareClient.framework */, 432B0E921CDFC3C50045347B /* ShareClientTests.xctest */, + 43A8EC82210E664300A81379 /* ShareClientUI.framework */, ); name = Products; sourceTree = ""; @@ -73,7 +176,13 @@ 432B0E8A1CDFC3C50045347B /* ShareClient */ = { isa = PBXGroup; children = ( + 43AB5125213315D300B3D58D /* Localizable.strings */, + 4325E9CE210E6A0A00969CE5 /* HKUnit.swift */, 43C418AE1CE0488900405B6A /* ShareClient.swift */, + 43A8EC9C210E68CE00A81379 /* ShareClientManager.swift */, + 43A8EC9A210E68BA00A81379 /* ShareGlucose+GlucoseKit.swift */, + 43A8EC98210E682A00A81379 /* ShareService.swift */, + 4325E9D0210E6A3D00969CE5 /* TimeInterval.swift */, 432B0E8B1CDFC3C50045347B /* ShareClient.h */, 432B0E8D1CDFC3C50045347B /* Info.plist */, ); @@ -89,6 +198,40 @@ path = ShareClientTests; sourceTree = ""; }; + 43A8EC7A210E661300A81379 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 43A8EC94210E67B000A81379 /* HealthKit.framework */, + 43A8EC8B210E665600A81379 /* LoopKitUI.framework */, + 43A8EC7B210E661400A81379 /* LoopKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 43A8EC83210E664300A81379 /* ShareClientUI */ = { + isa = PBXGroup; + children = ( + 43AB511921330D1400B3D58D /* Localizable.strings */, + 4325E9D2210E6ADA00969CE5 /* IdentifiableClass.swift */, + 43A8EC84210E664300A81379 /* ShareClientUI.h */, + 43A8EC8E210E676500A81379 /* ShareClientManager+UI.swift */, + 43A8EC8F210E676500A81379 /* ShareClientSettingsViewController.swift */, + 43A8EC8D210E676500A81379 /* ShareClientSetupViewController.swift */, + 43A8EC96210E680100A81379 /* ShareService+UI.swift */, + 4325E9D4210E6B4300969CE5 /* UIColor.swift */, + 43A8EC85210E664300A81379 /* Info.plist */, + ); + path = ShareClientUI; + sourceTree = ""; + }; + 43AB51342133176B00B3D58D /* Common */ = { + isa = PBXGroup; + children = ( + 43AB51352133177800B3D58D /* LocalizedString.swift */, + ); + path = Common; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -100,6 +243,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 43A8EC7F210E664300A81379 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 43A8EC86210E664300A81379 /* ShareClientUI.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -115,6 +266,7 @@ buildRules = ( ); dependencies = ( + 4325E9D7210E714B00969CE5 /* PBXTargetDependency */, ); name = ShareClient; productName = ShareClient; @@ -139,6 +291,25 @@ productReference = 432B0E921CDFC3C50045347B /* ShareClientTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 43A8EC81210E664300A81379 /* ShareClientUI */ = { + isa = PBXNativeTarget; + buildConfigurationList = 43A8EC87210E664300A81379 /* Build configuration list for PBXNativeTarget "ShareClientUI" */; + buildPhases = ( + 43A8EC7D210E664300A81379 /* Sources */, + 43A8EC7E210E664300A81379 /* Frameworks */, + 43A8EC7F210E664300A81379 /* Headers */, + 43A8EC80210E664300A81379 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4325E9D9210E715200969CE5 /* PBXTargetDependency */, + ); + name = ShareClientUI; + productName = ShareClientUI; + productReference = 43A8EC82210E664300A81379 /* ShareClientUI.framework */; + productType = "com.apple.product-type.framework"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -146,7 +317,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = "Mark Wilson"; TargetAttributes = { 432B0E871CDFC3C50045347B = { @@ -157,6 +328,14 @@ CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 0900; }; + 43A8EC75210E653B00A81379 = { + CreatedOnToolsVersion = 9.4.1; + ProvisioningStyle = Automatic; + }; + 43A8EC81210E664300A81379 = { + CreatedOnToolsVersion = 9.4.1; + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = 432B0E821CDFC3C50045347B /* Build configuration list for PBXProject "ShareClient" */; @@ -165,6 +344,16 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, + fr, + de, + "zh-Hans", + es, + it, + nl, + nb, + ru, + pl, ); mainGroup = 432B0E7E1CDFC3C50045347B; productRefGroup = 432B0E891CDFC3C50045347B /* Products */; @@ -173,6 +362,8 @@ targets = ( 432B0E871CDFC3C50045347B /* ShareClient */, 432B0E911CDFC3C50045347B /* ShareClientTests */, + 43A8EC81210E664300A81379 /* ShareClientUI */, + 43A8EC75210E653B00A81379 /* Cartfile */, ); }; /* End PBXProject section */ @@ -182,6 +373,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43AB5127213315D300B3D58D /* Localizable.strings in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -192,14 +384,45 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 43A8EC80210E664300A81379 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 43AB511B21330D1400B3D58D /* Localizable.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 43A8EC79210E654300A81379 /* Build Carthage Dependencies */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Build Carthage Dependencies"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 432B0E831CDFC3C50045347B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4325E9CF210E6A0A00969CE5 /* HKUnit.swift in Sources */, + 4325E9D1210E6A3D00969CE5 /* TimeInterval.swift in Sources */, + 43A8EC9D210E68CE00A81379 /* ShareClientManager.swift in Sources */, + 43AB51362133177800B3D58D /* LocalizedString.swift in Sources */, + 43A8EC9B210E68BA00A81379 /* ShareGlucose+GlucoseKit.swift in Sources */, 43C418AF1CE0488900405B6A /* ShareClient.swift in Sources */, + 43A8EC99210E682A00A81379 /* ShareService.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -211,9 +434,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 43A8EC7D210E664300A81379 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 43A8EC92210E676500A81379 /* ShareClientSettingsViewController.swift in Sources */, + 4325E9D5210E6B4400969CE5 /* UIColor.swift in Sources */, + 43A8EC97210E680100A81379 /* ShareService+UI.swift in Sources */, + 43AB51372133177800B3D58D /* LocalizedString.swift in Sources */, + 4325E9D3210E6ADA00969CE5 /* IdentifiableClass.swift in Sources */, + 43A8EC91210E676500A81379 /* ShareClientManager+UI.swift in Sources */, + 43A8EC90210E676500A81379 /* ShareClientSetupViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 4325E9D7210E714B00969CE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 43A8EC75210E653B00A81379 /* Cartfile */; + targetProxy = 4325E9D6210E714B00969CE5 /* PBXContainerItemProxy */; + }; + 4325E9D9210E715200969CE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 43A8EC75210E653B00A81379 /* Cartfile */; + targetProxy = 4325E9D8210E715200969CE5 /* PBXContainerItemProxy */; + }; 432B0E951CDFC3C50045347B /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 432B0E871CDFC3C50045347B /* ShareClient */; @@ -221,11 +468,53 @@ }; /* End PBXTargetDependency section */ +/* Begin PBXVariantGroup section */ + 43AB511921330D1400B3D58D /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 43AB511A21330D1400B3D58D /* Base */, + 43AB511C21330D6800B3D58D /* fr */, + 43AB511D21330D6B00B3D58D /* de */, + 43AB511E21330D7000B3D58D /* zh-Hans */, + 43AB511F21330D7800B3D58D /* es */, + 43AB512021330D7E00B3D58D /* it */, + 43AB512121330D8600B3D58D /* nl */, + 43AB512221330D8A00B3D58D /* nb */, + 43AB512321330D8E00B3D58D /* ru */, + 43AB512421330D9400B3D58D /* pl */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + 43AB5125213315D300B3D58D /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 43AB5126213315D300B3D58D /* Base */, + 43AB51282133161100B3D58D /* fr */, + 43AB51292133161200B3D58D /* de */, + 43AB512A2133161300B3D58D /* zh-Hans */, + 43AB512B2133161600B3D58D /* es */, + 43AB512C2133161700B3D58D /* it */, + 43AB512D2133161800B3D58D /* nl */, + 43AB512E2133161900B3D58D /* nb */, + 43AB512F2133161A00B3D58D /* ru */, + 43AB51302133161A00B3D58D /* pl */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ 432B0E9A1CDFC3C50045347B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CARTHAGE_PLATFORM_PATH_iphoneos = iOS; + CARTHAGE_PLATFORM_PATH_iphonesimulator = iOS; + CARTHAGE_PLATFORM_PATH_watchos = watchOS; + CARTHAGE_PLATFORM_PATH_watchsimulator = watchOS; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -235,12 +524,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -268,7 +559,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.1; + LOCALIZED_STRING_MACRO_NAMES = ( + NSLocalizedString, + CFLocalizedString, + LocalizedString, + ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -276,6 +572,7 @@ TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; }; name = Debug; }; @@ -283,6 +580,11 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CARTHAGE_PLATFORM_PATH_iphoneos = iOS; + CARTHAGE_PLATFORM_PATH_iphonesimulator = iOS; + CARTHAGE_PLATFORM_PATH_watchos = watchOS; + CARTHAGE_PLATFORM_PATH_watchsimulator = watchOS; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -292,12 +594,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -319,7 +623,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.1; + LOCALIZED_STRING_MACRO_NAMES = ( + NSLocalizedString, + CFLocalizedString, + LocalizedString, + ); MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -327,45 +636,60 @@ VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 4.0; }; name = Release; }; 432B0E9D1CDFC3C50045347B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 2; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/$(CARTHAGE_PLATFORM_PATH_$(PLATFORM_NAME))", + ); INFOPLIST_FILE = ShareClient/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mddub.ShareClient; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Debug; }; 432B0E9E1CDFC3C50045347B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 2; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/$(CARTHAGE_PLATFORM_PATH_$(PLATFORM_NAME))", + ); INFOPLIST_FILE = ShareClient/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mddub.ShareClient; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos watchsimulator"; SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Release; }; @@ -391,6 +715,89 @@ }; name = Release; }; + 43A8EC77210E653C00A81379 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 43A8EC78210E653C00A81379 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 43A8EC88210E664300A81379 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ShareClientUI/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.loopkit.ShareClientUI; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 43A8EC89210E664300A81379 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ShareClientUI/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.loopkit.ShareClientUI; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -421,6 +828,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 43A8EC76210E653C00A81379 /* Build configuration list for PBXAggregateTarget "Cartfile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 43A8EC77210E653C00A81379 /* Debug */, + 43A8EC78210E653C00A81379 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 43A8EC87210E664300A81379 /* Build configuration list for PBXNativeTarget "ShareClientUI" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 43A8EC88210E664300A81379 /* Debug */, + 43A8EC89210E664300A81379 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 432B0E7F1CDFC3C50045347B /* Project object */; diff --git a/ShareClient.xcodeproj/xcshareddata/xcschemes/ShareClient.xcscheme b/ShareClient.xcodeproj/xcshareddata/xcschemes/ShareClient.xcscheme index 0d2c14e..13e3884 100644 --- a/ShareClient.xcodeproj/xcshareddata/xcschemes/ShareClient.xcscheme +++ b/ShareClient.xcodeproj/xcshareddata/xcschemes/ShareClient.xcscheme @@ -1,6 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ShareClient/Base.lproj/Localizable.strings b/ShareClient/Base.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..0c5ccd94084ab6aaf45c6347f27fdf9f52ab1d4f GIT binary patch literal 548 zcmb`DK?{OF5QX2_Um+fY@CQVPDCiK?LH~f5mQZWB68-w>b5)d}y2LW$I`iI}H~V~q zn#fnIlQO=w3gYbUrE*tkJ1c5;r7Cry8i7w#Ih-X|y1`7jd32i-kCbv)6}7sXvea5z zP9j4b9p49Yb@NNAKCVKv0)3hrfSD8D5Hl1!beat#rWo1IiDgnkG&>*27Vi~~#}3|I z8@NVOHcfb;0-g_V(CHoT(97sr`V0Ea6hkf?fAIYa_h0wFT<^8vE&DfZ|5^txe~wyq literal 0 HcmV?d00001 diff --git a/ShareClient/HKUnit.swift b/ShareClient/HKUnit.swift new file mode 100644 index 0000000..e3f0dde --- /dev/null +++ b/ShareClient/HKUnit.swift @@ -0,0 +1,16 @@ +// +// HKUnit.swift +// xDripG5 +// +// Created by Nate Racklyeft on 8/6/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import HealthKit + + +extension HKUnit { + static let milligramsPerDeciliter: HKUnit = { + return HKUnit.gramUnit(with: .milli).unitDivided(by: HKUnit.literUnit(with: .deci)) + }() +} diff --git a/ShareClient/ShareClient.swift b/ShareClient/ShareClient.swift index 5f23358..70d869c 100644 --- a/ShareClient/ShareClient.swift +++ b/ShareClient/ShareClient.swift @@ -207,7 +207,7 @@ public class ShareClient { private func parseDate(_ wt: String) throws -> Date { // wt looks like "/Date(1462404576000)/" let re = try NSRegularExpression(pattern: "\\((.*)\\)") - if let match = re.firstMatch(in: wt, range: NSMakeRange(0, wt.characters.count)) { + if let match = re.firstMatch(in: wt, range: NSMakeRange(0, wt.count)) { #if swift(>=4) let matchRange = match.range(at: 1) #else diff --git a/ShareClient/ShareClientManager.swift b/ShareClient/ShareClientManager.swift new file mode 100644 index 0000000..60917e2 --- /dev/null +++ b/ShareClient/ShareClientManager.swift @@ -0,0 +1,100 @@ +// +// ShareClientManager.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import LoopKit +import HealthKit + + +public class ShareClientManager: CGMManager { + public static var managerIdentifier = "DexShareClient" + + public init() { + shareService = ShareService(keychainManager: keychain) + } + + required convenience public init?(rawState: CGMManager.RawStateValue) { + self.init() + } + + public var rawState: CGMManager.RawStateValue { + return [:] + } + + private let keychain = KeychainManager() + + public var shareService: ShareService { + didSet { + try! keychain.setDexcomShareUsername(shareService.username, password: shareService.password, url: shareService.url) + } + } + + public static let localizedTitle = LocalizedString("Dexcom Share", comment: "Title for the CGMManager option") + + public let appURL: URL? = nil + + weak public var cgmManagerDelegate: CGMManagerDelegate? + + public let providesBLEHeartbeat = false + + public let shouldSyncToRemoteService = false + + public var sensorState: SensorDisplayable? { + return latestBackfill + } + + public let managedDataInterval: TimeInterval? = nil + + public private(set) var latestBackfill: ShareGlucose? + + public func fetchNewDataIfNeeded(_ completion: @escaping (CGMResult) -> Void) { + guard let shareClient = shareService.client else { + completion(.noData) + return + } + + // If our last glucose was less than 4.5 minutes ago, don't fetch. + if let latestGlucose = latestBackfill, latestGlucose.startDate.timeIntervalSinceNow > -TimeInterval(minutes: 4.5) { + completion(.noData) + return + } + + shareClient.fetchLast(6) { (error, glucose) in + if let error = error { + completion(.error(error)) + return + } + guard let glucose = glucose else { + completion(.noData) + return + } + + // Ignore glucose values that are up to a minute newer than our previous value, to account for possible time shifting in Share data + let startDate = self.cgmManagerDelegate?.startDateToFilterNewData(for: self)?.addingTimeInterval(TimeInterval(minutes: 1)) + let newGlucose = glucose.filterDateRange(startDate, nil).filter({ $0.isStateValid }).map { + return NewGlucoseSample(date: $0.startDate, quantity: $0.quantity, isDisplayOnly: false, syncIdentifier: "\(Int($0.startDate.timeIntervalSince1970))", device: self.device) + } + + self.latestBackfill = glucose.first + + if newGlucose.count > 0 { + completion(.newData(newGlucose)) + } else { + completion(.noData) + } + } + } + + public var device: HKDevice? = nil + + public var debugDescription: String { + return [ + "## ShareClientManager", + "latestBackfill: \(String(describing: latestBackfill))", + "" + ].joined(separator: "\n") + } +} diff --git a/ShareClient/ShareGlucose+GlucoseKit.swift b/ShareClient/ShareGlucose+GlucoseKit.swift new file mode 100644 index 0000000..b40c86f --- /dev/null +++ b/ShareClient/ShareGlucose+GlucoseKit.swift @@ -0,0 +1,47 @@ +// +// ShareGlucose+GlucoseKit.swift +// Naterade +// +// Created by Nathan Racklyeft on 5/8/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation +import HealthKit +import LoopKit + + +extension ShareGlucose: GlucoseValue { + public var startDate: Date { + return timestamp + } + + public var quantity: HKQuantity { + return HKQuantity(unit: .milligramsPerDeciliter, doubleValue: Double(glucose)) + } +} + + +extension ShareGlucose: SensorDisplayable { + public var isStateValid: Bool { + return glucose >= 39 + } + + public var trendType: GlucoseTrend? { + return GlucoseTrend(rawValue: Int(trend)) + } + + public var isLocal: Bool { + return false + } +} + +extension SensorDisplayable { + public var stateDescription: String { + if isStateValid { + return LocalizedString("OK", comment: "Sensor state description for the valid state") + } else { + return LocalizedString("Needs Attention", comment: "Sensor state description for the non-valid state") + } + } +} diff --git a/ShareClient/ShareService.swift b/ShareClient/ShareService.swift new file mode 100644 index 0000000..8c7cdc2 --- /dev/null +++ b/ShareClient/ShareService.swift @@ -0,0 +1,140 @@ +// +// ShareService.swift +// Loop +// +// Created by Nate Racklyeft on 7/2/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation +import LoopKit + + +// Encapsulates the Dexcom Share client service and its authentication +public class ShareService: ServiceAuthentication { + public var credentialValues: [String?] + + public let title: String = LocalizedString("Dexcom Share", comment: "The title of the Dexcom Share service") + + public init(username: String?, password: String?, url: URL?) { + credentialValues = [ + username, + password, + url?.absoluteString + ] + + /* + To enable Loop to use a custom share server, change the value of customServer + and remove the comment markers on line 55 and 62. + + You can find installation instructions for one such custom share server at + https://github.com/dabear/NightscoutShareServer + */ + + /* + let customServer = "https://REPLACEME" + let customServerTitle = "Custom" + + credentials[2].options?.append( + (title: LocalizedString(customServerTitle, comment: "Custom share server option title"), + value: customServer)) + */ + + if let username = username, let password = password, let url = url { + isAuthorized = true + client = ShareClient(username: username, password: password, shareServer: url.absoluteString) + } + } + + // The share client, if credentials are present + private(set) var client: ShareClient? + + public var username: String? { + return credentialValues[0] + } + + var password: String? { + return credentialValues[1] + } + + var url: URL? { + guard let urlString = credentialValues[2] else { + return nil + } + + return URL(string: urlString) + } + + public var isAuthorized: Bool = false + + public func verify(_ completion: @escaping (_ success: Bool, _ error: Error?) -> Void) { + guard let username = username, let password = password, let url = url else { + completion(false, nil) + return + } + + let client = ShareClient(username: username, password: password, shareServer: url.absoluteString) + client.fetchLast(1) { (error, _) in + completion(true, error) + + } + self.client = client + } + + public func reset() { + isAuthorized = false + client = nil + } +} + + +private let DexcomShareURL = URL(string: KnownShareServers.US.rawValue)! +private let DexcomShareServiceLabel = "DexcomShare1" + + +extension KeychainManager { + func setDexcomShareUsername(_ username: String?, password: String?, url: URL?) throws { + let credentials: InternetCredentials? + + if let username = username, let password = password, let url = url { + credentials = InternetCredentials(username: username, password: password, url: url) + } else { + credentials = nil + } + + // Replace the legacy URL-keyed credentials + try replaceInternetCredentials(nil, forURL: DexcomShareURL) + + try replaceInternetCredentials(credentials, forLabel: DexcomShareServiceLabel) + } + + func getDexcomShareCredentials() -> (username: String, password: String, url: URL)? { + do { // Silence all errors and return nil + do { + let credentials = try getInternetCredentials(label: DexcomShareServiceLabel) + + return (username: credentials.username, password: credentials.password, url: credentials.url) + } catch KeychainManagerError.copy { + // Fetch and replace the legacy URL-keyed credentials + let credentials = try getInternetCredentials(url: DexcomShareURL) + + try setDexcomShareUsername(credentials.username, password: credentials.password, url: credentials.url) + + return (username: credentials.username, password: credentials.password, url: credentials.url) + } + } catch { + return nil + } + } +} + + +extension ShareService { + public convenience init(keychainManager: KeychainManager = KeychainManager()) { + if let (username, password, url) = keychainManager.getDexcomShareCredentials() { + self.init(username: username, password: password, url: url) + } else { + self.init(username: nil, password: nil, url: nil) + } + } +} diff --git a/ShareClient/TimeInterval.swift b/ShareClient/TimeInterval.swift new file mode 100644 index 0000000..5a8046a --- /dev/null +++ b/ShareClient/TimeInterval.swift @@ -0,0 +1,61 @@ +// +// NSTimeInterval.swift +// Naterade +// +// Created by Nathan Racklyeft on 1/9/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +extension TimeInterval { + static func hours(_ hours: Double) -> TimeInterval { + return self.init(hours: hours) + } + + static func minutes(_ minutes: Int) -> TimeInterval { + return self.init(minutes: Double(minutes)) + } + + static func minutes(_ minutes: Double) -> TimeInterval { + return self.init(minutes: minutes) + } + + static func seconds(_ seconds: Double) -> TimeInterval { + return self.init(seconds) + } + + static func milliseconds(_ milliseconds: Double) -> TimeInterval { + return self.init(milliseconds / 1000) + } + + init(minutes: Double) { + self.init(minutes * 60) + } + + init(hours: Double) { + self.init(minutes: hours * 60) + } + + init(seconds: Double) { + self.init(seconds) + } + + init(milliseconds: Double) { + self.init(milliseconds / 1000) + } + + var milliseconds: Double { + return self * 1000 + } + + var minutes: Double { + return self / 60.0 + } + + var hours: Double { + return minutes / 60.0 + } + +} diff --git a/ShareClient/de.lproj/Localizable.strings b/ShareClient/de.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..861ce5cf6f2f9310ff79a1b3f83f728591856150 GIT binary patch literal 566 zcmb`EOA5j;5QhJ?rzl+t;sL~ksJIYyp%(}~i<(MO#nY=_Ql&*uHxedIX6AoPdcU>R zRHB7;TJtTG5r=rrwTYRsG9Y)=Qn`*~=ky!7*yq`uE+Chj8dSqt)R;D)9J%7D($`26 zmXRg45uea=iuyU(1XpdiQhm}*>FE;RIyx{k;0Y7XQL*w*Cmtn3gqc_D9`6pvbqDXR zEm*4-lNw$q1DAlScwUaD@U5wO>OJZ~#jV){0GEAUHvj+t literal 0 HcmV?d00001 diff --git a/ShareClient/es.lproj/Localizable.strings b/ShareClient/es.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..a2dbc8a0730193842df4ca16551050c2fdb1e2ef GIT binary patch literal 552 zcmb`D!3x4K5JczfSCk$F@dLzzD0mR{(EdQERtuU+Q^f!FuD+xdi=bYlY?AKI?9A@{ zHdJ4cQth?nu2m3+@Gg~yOjDVWyC_qsBiRJJQ5A5Gv(g!6#;Zrwe`%*v4yz(pw<=T3 zwd6Ch#4hk7FsGnjl8taRq*ts@x-pnB@eMJeLytaw!UPp7*E(@18N$!J;dFSfaNKq9 z?%Kk&8ZfD0Lj}AD-mA~k@rr(1s*d`Ex>vEBMc}`Ddz{~x3!5@6+G8^^SMFHP5nC)7_b!*<8+v z8Zt_?(wy&J1+fnIQj1WjJ3VSA=Z;dh>q9o{P(KRbAJ zZQ)uq*)-#Y3U~(IW6s_2h@G4SqQvYk=nc JUF*Nv!4)7BTV((M literal 0 HcmV?d00001 diff --git a/ShareClient/it.lproj/Localizable.strings b/ShareClient/it.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..43e410b24afd8fecbeb3b9246cbe3bc23d8bb57c GIT binary patch literal 546 zcmb`DOA5j;5QhJ?rzkE3@c`mN6kUkAXfF_I)q#(6)}mXUKumwF~+tN(ic<$0+Yn$3$= Hf0ctfvqxG2 literal 0 HcmV?d00001 diff --git a/ShareClient/nb.lproj/Localizable.strings b/ShareClient/nb.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..31d3169481a8507f9ac4ad59432dbf0ea8f8bb5b GIT binary patch literal 546 zcmb`D!3x4K5JczPuP8kV;s=NaQScz@!Tvx|tA(0MQ$&AWeMze=f_jm#+jMtkXEyiS zKs|+ub7Vevc-FedR=Yy|#QCS>h1ymC9J@I#X(A6{>Wknt{(%N1P|uYGD@KdUV5CzbKWkYHH1W%0x3Q zIJq3Li+ls-6z5k|4X#qO5`CJRfEf|r5JMDt=!6$$OmXseC!R?;5#GEZd%V{;es%Ef z+QD@i@Y0+OS$GECQ|IA$iQbm3r$442rZ}>V{HO16eE)`Au$KmO3o`7~M%_gJ_5aKF ON^`dP*lPFJIk*8z0b1t( literal 0 HcmV?d00001 diff --git a/ShareClient/pl.lproj/Localizable.strings b/ShareClient/pl.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..aacca8fe6c3071395ff5f4ffcd465b71b6da5cd9 GIT binary patch literal 550 zcmb`DO$x$5429p?Qw%Nz=>f!rD7X-RKrc|WYDK5gsXusl_3N}!5!8(gNoJC~yqCG( z0yShb(?$_7Q;hBWJ<-Z%ib{{%MGGa`lbzBZD)oI1pXvm1!L3F$KeLxfD^Mx9tYqn` zuOTOt#nv8g=s9@)gseeTz^uAH@z&{SW8XSjOsFv@-*5_xl`EAvm_jVyd5L#uPf`4; z;9a!^Yt>}akROV{8F1B{r{WRwBC3vhhkDLp@v+BOx+lCdSg+LQI%-Qa#IygCn9csH Q|CjEu25>%qwRjZ@9&FEB7ytkO literal 0 HcmV?d00001 diff --git a/ShareClient/ru.lproj/Localizable.strings b/ShareClient/ru.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..74085abfa17b203d7f0754a564e2b046834ff579 GIT binary patch literal 550 zcmb`D&1wQc5QOW{C(n6+VNM|+nt%`z4N(IgBzn*nSd2dl$!ypW$1)XwmS0@ zrWL4?*mmD#sF7YdnF6*>ct_1=>R%9bsA|FG^;cg{O%L6BsB%y0OJ_7cUX3eHsrut7~G&Dc;5&Vf7f928IBTau0B`{b)G q0iP%QQMX59$8K$iAE5irdUnqQ?Q~BsuKz#XQ;pf?VXO78-rz4m5mtl% literal 0 HcmV?d00001 diff --git a/ShareClient/zh-Hans.lproj/Localizable.strings b/ShareClient/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..871bf95468fd5161ec5a9bb0ec43f77da1a837ef GIT binary patch literal 506 zcmb`DPfEi;6vn@GTzG|$r64(gxDbUd#JWf}Zj>RW8i~bfjiq@ z#)K9@x+%k(8Qy!}pZ7LDsm>HD*Q-k2Ruxf)f1_E*{8nzrEmf$|8`+G0BNzHSx6=Y- z!7rlPpL~yL2Fj6Z2bF70bjLBW#7n@(^vr{PLpH`$3Rj~4bQ5|miA3E~_xSm7@}B4d zLU2-IEAmI>ZxB*?^P^! c74SQs-|MgX)EwL8A$Rw>Wk=(#Ru7~87LD3h+W-In literal 0 HcmV?d00001 diff --git a/ShareClientTests/ShareClientTests.swift b/ShareClientTests/ShareClientTests.swift index dabd268..f3c6475 100644 --- a/ShareClientTests/ShareClientTests.swift +++ b/ShareClientTests/ShareClientTests.swift @@ -7,7 +7,7 @@ // import XCTest -@testable import ShareClient + class ShareClientTests: XCTestCase { diff --git a/ShareClientUI/Base.lproj/Localizable.strings b/ShareClientUI/Base.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..da3f31f8f54f81b548a52b8cb7a855854a5c5b5a GIT binary patch literal 2062 zcmcIl+fD*85S?efqT$g8_yA*!LgI@?gYW^%RTA7a?gIMr>NzcCrpqcMYRK-k)9K8a zGpFVAqbq0Pq$h>sGMA;i%ClrrVML3=Y$hdsnJh4J@G0QqWQy4e4?T0NIe0M6jojgT zCS7SsTdv^CUGLbn#<#>fwQR93M-+#rz+2;TUnNh7Ut$y@Um~WH3q1c5`y8lSz)ntv z$Q>{&frGU=Ae`e(RGdvb_6f!-%reZCH?l%oc-xiI?}IDmr#`T+2XJl7naD+<44Z>2s_V zSaWiVZy_%jX-)Bru;zfp*4MOZYqfY!<8|ZvyH1$BNx0Yib-T^{hzM4*mgjf_tacqM zJ&W}Yld%kaj<-YPkpNFMR#8OwavIG$m|&hg%2hgi*_ zej>uAh>EOv)gn56Z}frX&7TJ9#$tT|YTmY6;Cn?y&F5DY_E7UzoQErag)!xGBm*e_ z7*6Ub_CPVF))b$f>(i89AwKUoauz!|+}kv#wb_g#=|DN1T0hcSk86kO(_CR@v;0OI Z>z$Hw^ql|7$2cF={4K6fSBw;I^DoALO6dRq literal 0 HcmV?d00001 diff --git a/ShareClientUI/IdentifiableClass.swift b/ShareClientUI/IdentifiableClass.swift new file mode 100644 index 0000000..29095b5 --- /dev/null +++ b/ShareClientUI/IdentifiableClass.swift @@ -0,0 +1,24 @@ +// +// IdentifiableClass.swift +// Naterade +// +// Created by Nathan Racklyeft on 5/22/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +protocol IdentifiableClass: class { + static var className: String { get } +} + + +extension IdentifiableClass { + static var className: String { + return NSStringFromClass(self).components(separatedBy: ".").last! + } +} + + +extension UITableViewCell: IdentifiableClass { } diff --git a/ShareClientUI/Info.plist b/ShareClientUI/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/ShareClientUI/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/ShareClientUI/ShareClientManager+UI.swift b/ShareClientUI/ShareClientManager+UI.swift new file mode 100644 index 0000000..e16b503 --- /dev/null +++ b/ShareClientUI/ShareClientManager+UI.swift @@ -0,0 +1,25 @@ +// +// ShareClientManager+UI.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import LoopKitUI +import HealthKit +import ShareClient + + +extension ShareClientManager: CGMManagerUI { + public static func setupViewController() -> (UIViewController & CGMManagerSetupViewController)? { + return ShareClientSetupViewController() + } + + public func settingsViewController(for glucoseUnit: HKUnit) -> UIViewController { + return ShareClientSettingsViewController(cgmManager: self, glucoseUnit: glucoseUnit, allowsDeletion: true) + } + + public var smallImage: UIImage? { + return nil + } +} diff --git a/ShareClientUI/ShareClientSettingsViewController.swift b/ShareClientUI/ShareClientSettingsViewController.swift new file mode 100644 index 0000000..ed9e440 --- /dev/null +++ b/ShareClientUI/ShareClientSettingsViewController.swift @@ -0,0 +1,205 @@ +// +// ShareClientSettingsViewController.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import UIKit +import HealthKit +import LoopKit +import LoopKitUI +import ShareClient + + +public class ShareClientSettingsViewController: UITableViewController { + + public let cgmManager: ShareClientManager + + public let glucoseUnit: HKUnit + + public let allowsDeletion: Bool + + public init(cgmManager: ShareClientManager, glucoseUnit: HKUnit, allowsDeletion: Bool) { + self.cgmManager = cgmManager + self.glucoseUnit = glucoseUnit + self.allowsDeletion = allowsDeletion + + super.init(style: .grouped) + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func viewDidLoad() { + super.viewDidLoad() + + title = cgmManager.localizedTitle + + tableView.rowHeight = UITableViewAutomaticDimension + tableView.estimatedRowHeight = 44 + + tableView.sectionHeaderHeight = UITableViewAutomaticDimension + tableView.estimatedSectionHeaderHeight = 55 + + tableView.register(SettingsTableViewCell.self, forCellReuseIdentifier: SettingsTableViewCell.className) + tableView.register(TextButtonTableViewCell.self, forCellReuseIdentifier: TextButtonTableViewCell.className) + } + + // MARK: - UITableViewDataSource + + private enum Section: Int { + case authentication + case latestReading + case delete + + static let count = 3 + } + + override public func numberOfSections(in tableView: UITableView) -> Int { + return allowsDeletion ? Section.count : Section.count - 1 + } + + private enum LatestReadingRow: Int { + case glucose + case date + case trend + + static let count = 3 + } + + override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch Section(rawValue: section)! { + case .authentication: + return 1 + case .latestReading: + return LatestReadingRow.count + case .delete: + return 1 + } + } + + private lazy var glucoseFormatter: QuantityFormatter = { + let formatter = QuantityFormatter() + formatter.setPreferredNumberFormatter(for: glucoseUnit) + return formatter + }() + + private lazy var dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .long + formatter.timeStyle = .long + formatter.doesRelativeDateFormatting = true + return formatter + }() + + public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + switch Section(rawValue: indexPath.section)! { + case .authentication: + let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath) as! SettingsTableViewCell + + let service = cgmManager.shareService + + cell.textLabel?.text = LocalizedString("Credentials", comment: "Title of cell to set credentials") + cell.detailTextLabel?.text = service.username ?? SettingsTableViewCell.TapToSetString + cell.accessoryType = .disclosureIndicator + + return cell + case .latestReading: + let cell = tableView.dequeueReusableCell(withIdentifier: SettingsTableViewCell.className, for: indexPath) as! SettingsTableViewCell + let glucose = cgmManager.latestBackfill + + switch LatestReadingRow(rawValue: indexPath.row)! { + case .glucose: + cell.textLabel?.text = LocalizedString("Glucose", comment: "Title describing glucose value") + + if let quantity = glucose?.quantity, let formatted = glucoseFormatter.string(from: quantity, for: glucoseUnit) { + cell.detailTextLabel?.text = formatted + } else { + cell.detailTextLabel?.text = SettingsTableViewCell.NoValueString + } + case .date: + cell.textLabel?.text = LocalizedString("Date", comment: "Title describing glucose date") + + if let date = glucose?.timestamp { + cell.detailTextLabel?.text = dateFormatter.string(from: date) + } else { + cell.detailTextLabel?.text = SettingsTableViewCell.NoValueString + } + case .trend: + cell.textLabel?.text = LocalizedString("Trend", comment: "Title describing glucose trend") + + cell.detailTextLabel?.text = glucose?.trendType?.localizedDescription ?? SettingsTableViewCell.NoValueString + } + + return cell + case .delete: + let cell = tableView.dequeueReusableCell(withIdentifier: TextButtonTableViewCell.className, for: indexPath) as! TextButtonTableViewCell + + cell.textLabel?.text = LocalizedString("Delete CGM", comment: "Title text for the button to remove a CGM from Loop") + cell.textLabel?.textAlignment = .center + cell.tintColor = .delete + cell.isEnabled = true + return cell + } + } + + public override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + switch Section(rawValue: section)! { + case .authentication: + return nil + case .latestReading: + return LocalizedString("Latest Reading", comment: "Section title for latest glucose reading") + case .delete: + return nil + } + } + + public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + switch Section(rawValue: indexPath.section)! { + case .authentication: + let vc = AuthenticationViewController(authentication: cgmManager.shareService) + vc.authenticationObserver = { [weak self] (service) in + self?.cgmManager.shareService = service + + self?.tableView.reloadRows(at: [indexPath], with: .none) + } + + show(vc, sender: nil) + case .latestReading: + tableView.deselectRow(at: indexPath, animated: true) + case .delete: + let confirmVC = UIAlertController(cgmDeletionHandler: { + self.cgmManager.cgmManagerDelegate?.cgmManagerWantsDeletion(self.cgmManager) + self.navigationController?.popViewController(animated: true) + }) + + present(confirmVC, animated: true) { + tableView.deselectRow(at: indexPath, animated: true) + } + } + } +} + + +private extension UIAlertController { + convenience init(cgmDeletionHandler handler: @escaping () -> Void) { + self.init( + title: nil, + message: LocalizedString("Are you sure you want to delete this CGM?", comment: "Confirmation message for deleting a CGM"), + preferredStyle: .actionSheet + ) + + addAction(UIAlertAction( + title: LocalizedString("Delete CGM", comment: "Button title to delete CGM"), + style: .destructive, + handler: { (_) in + handler() + } + )) + + let cancel = LocalizedString("Cancel", comment: "The title of the cancel action in an action sheet") + addAction(UIAlertAction(title: cancel, style: .cancel, handler: nil)) + } +} diff --git a/ShareClientUI/ShareClientSetupViewController.swift b/ShareClientUI/ShareClientSetupViewController.swift new file mode 100644 index 0000000..79ee2fa --- /dev/null +++ b/ShareClientUI/ShareClientSetupViewController.swift @@ -0,0 +1,47 @@ +// +// ShareClientSetupViewController.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import UIKit +import LoopKit +import LoopKitUI +import ShareClient + + +class ShareClientSetupViewController: UINavigationController, CGMManagerSetupViewController { + var setupDelegate: CGMManagerSetupViewControllerDelegate? + + let cgmManager = ShareClientManager() + + init() { + let authVC = AuthenticationViewController(authentication: cgmManager.shareService) + + super.init(rootViewController: authVC) + + authVC.authenticationObserver = { [weak self] (service) in + self?.cgmManager.shareService = service + } + authVC.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancel)) + authVC.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(save)) + } + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func cancel() { + setupDelegate?.cgmManagerSetupViewControllerDidCancel(self) + } + + @objc private func save() { + setupDelegate?.cgmManagerSetupViewController(self, didSetUpCGMManager: cgmManager) + } + +} diff --git a/ShareClientUI/ShareClientUI.h b/ShareClientUI/ShareClientUI.h new file mode 100644 index 0000000..12a7a32 --- /dev/null +++ b/ShareClientUI/ShareClientUI.h @@ -0,0 +1,19 @@ +// +// ShareClientUI.h +// ShareClientUI +// +// Created by Nathan Racklyeft on 7/29/18. +// Copyright © 2018 Mark Wilson. All rights reserved. +// + +#import + +//! Project version number for ShareClientUI. +FOUNDATION_EXPORT double ShareClientUIVersionNumber; + +//! Project version string for ShareClientUI. +FOUNDATION_EXPORT const unsigned char ShareClientUIVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/ShareClientUI/ShareService+UI.swift b/ShareClientUI/ShareService+UI.swift new file mode 100644 index 0000000..1fc86e2 --- /dev/null +++ b/ShareClientUI/ShareService+UI.swift @@ -0,0 +1,38 @@ +// +// ShareService+UI.swift +// Loop +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import LoopKitUI +import ShareClient + + +extension ShareService: ServiceAuthenticationUI { + public var credentialFormFields: [ServiceCredential] { + return [ + ServiceCredential( + title: LocalizedString("Username", comment: "The title of the Dexcom share username credential"), + isSecret: false, + keyboardType: .asciiCapable + ), + ServiceCredential( + title: LocalizedString("Password", comment: "The title of the Dexcom share password credential"), + isSecret: true, + keyboardType: .asciiCapable + ), + ServiceCredential( + title: LocalizedString("Server", comment: "The title of the Dexcom share server URL credential"), + isSecret: false, + options: [ + (title: LocalizedString("US", comment: "U.S. share server option title"), + value: KnownShareServers.US.rawValue), + (title: LocalizedString("Outside US", comment: "Outside US share server option title"), + value: KnownShareServers.NON_US.rawValue) + + ] + ) + ] + } +} diff --git a/ShareClientUI/UIColor.swift b/ShareClientUI/UIColor.swift new file mode 100644 index 0000000..0095c6b --- /dev/null +++ b/ShareClientUI/UIColor.swift @@ -0,0 +1,22 @@ +// +// UIColor.swift +// LoopKitUI +// +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import UIKit + + +extension UIColor { + static let delete = UIColor.higRed() +} + + +// MARK: - HIG colors +// See: https://developer.apple.com/ios/human-interface-guidelines/visual-design/color/ +extension UIColor { + private static func higRed() -> UIColor { + return UIColor(red: 1, green: 59 / 255, blue: 48 / 255, alpha: 1) + } +} diff --git a/ShareClientUI/de.lproj/Localizable.strings b/ShareClientUI/de.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..b674fae543759a1fabba388c1cb824faff4073eb GIT binary patch literal 1002 zcmb_bNlwE+5Uew=82QK{c>v16!iWn3l;8&#V?>0P$O|Ao%TIvno+Psf$s8hU7Ijxw zS9gzpzLz+M!2@1U@f@+`s`cLCSuNI6qCkt1o|@KzH^Fwa8J@C>KlTjDTM=uRXNfZ; zxb&D3+E-i&QatkO$zN(rOWOtU5|J@tq{pGHWkTbjuBmKdbcZ3pTKntKZdq;JcZ?W` z-{Ofe201p|MRlQC&a2z+)}gw;7@h8v`M#7(GSsZtXy$&OJ3ZF(-??OD z`_QVJNcoN#27d2U-7||JO8P66wpxWKaC5nj@J@B;8BeG&>~4-VZf13Ew10LYPGe~G zXPjffsV<`Kgqi2(Dlfxj%W!qVE=>DZ)^Y+3tDBot9^sv?TYb-;+MxrR{f~YDFjJt4 literal 0 HcmV?d00001 diff --git a/ShareClientUI/es.lproj/Localizable.strings b/ShareClientUI/es.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..269261402fd36c79ca6b8a6eae75ab24098920af GIT binary patch literal 996 zcmb_b%WlFj5S(+r!s6Hid_dJxd0Z-iO8o&=3IYidln3}*+A)<+bkw)`w$Th4p!5v0; zN-~XzKl1LQ4mFVnvV}h-zh&LXo%5|=W|y!Q)YTEK(Db+|9{IlOCBJCN-{Xzn7+9>i zie^zDh~%nq*3~fgDd{?$Rp{-vjH&KUGdX7V6=#^Ss{QHXuWn44=Uux!W{OYL-tf9m zZOtl%Ea^q+m8#yUgF*2s<43jE5%0+D8v9eVc)|0a&b3a?I}tSoR2-Ck!>REaEyi?o poK2`-eb`eu6|v&~JJx-lvXV|5+2xR9HseQa66y5p%AXl#@dbHuo&5j+ literal 0 HcmV?d00001 diff --git a/ShareClientUI/fr.lproj/Localizable.strings b/ShareClientUI/fr.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..22f3090cefe4ca478a015e96da710894668a236f GIT binary patch literal 1042 zcmcJOT}s116ot>Ts~GYk2(}9lAH;$${$cC_LR&G=Bqcxo?9Nx0(oLw}ofsw^ggz80 z^V56JoH_TN$@kY(Cvtk!vsSFFa>m;4D?Ry0pIInVsRfxe(Tts8D`Jk-X3NK!#`CVg zI_{b3NQo{-ObPLGMxqN&m+Ji8HUH1R8hQr0<<@`TjLJ>061-@#{d8T literal 0 HcmV?d00001 diff --git a/ShareClientUI/it.lproj/Localizable.strings b/ShareClientUI/it.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..0d0428a3d8b6834204a83ba03f1bee401222de33 GIT binary patch literal 988 zcmb_bNp8YG5Ug`vG4e47cmT>F3L=*XP{=&MG9WB@LD-PIK1p>C)+`|TkjR?F)#dK$ zsqxSE6pt|YzyUk1JxY#B_bv8{xJZE<4GKmoqB(cMZHXDKGD|#-beeZZu3?=i9+2TB z$dnO(;)v0Tj0`ifg+J$8&$^!LkdX6ARcC5y(M3$bOI2NSl^ias>w3j+dVW!2%b0=1 zhO=nSaZ*IGop90FF#9p+Iy|ePw|g1A?gi_$%vWA(Jtum`U6@nJm-bmFN{`gs@%hvW zTSg1*K{{(xb*|10O4kYBtGtbbXZ9D3@o8GT<84&uCUC%OjL}e^#e^;F|McoipX6RO^q}T$%qyGly|N|Ub{VYxBjWUM%YOlEb)4A% literal 0 HcmV?d00001 diff --git a/ShareClientUI/nb.lproj/Localizable.strings b/ShareClientUI/nb.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..3b6f0f3d3eb115e9121d39b6e9c6b2312fdceefb GIT binary patch literal 982 zcmb_aNp8YG5Ug`vVfmN?JRr(}1SuD!M1gsLu|cdJgl&?1KB2mYVeAo-b3m3Cb(gzq znZMs59+6;%6&8HgSo7ZLx5ZK`u9G7}iJYAss~NupYgtS9mZ$XNPNj1f#3tM`!~;^i zwkD;lKl4s8!U=O6@k4BiCn5zqCbs6zfO8ew!n~1DLp~N&2kGkDYu(Lsdf)j+P5c^# zYBiXWg|N-YL7b3TM{<&9!WjqRz23Gdc&oY@@@guVw6{yKYx_A{l!K&s&d}ZBkh?hhj_^q+yDX1`GwscOp zq!XTsdPRa`(J9T<(vgNUtjvuKJ8f9MBU&@2c@NZ4h|YnDfEup2>%bGs|8kEVpYNSW@)x#jak zmJR1|rea}}RmNJHMZKN}`H`iMsE)66IgWibGrVw{&hcC%4n&T9H1#yYn7WP!>hwFG s_tAS3{?V6ps{7ljiVl>V?wkVIAU~=w=j|2U)>eI*PAxYpx4OZ#U+v=0=l}o! literal 0 HcmV?d00001 diff --git a/ShareClientUI/pl.lproj/Localizable.strings b/ShareClientUI/pl.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..99edf0d9642bf81aef76c28c8b476a4ab124d7e6 GIT binary patch literal 996 zcmb_a%TB{E5FD<2g_R?R_5&&oRV#5pP*L&$RtO@{CRH8{RQxnQ0L-q599u{^fTG0C z?s#@~$6udwT)^NSPsq8pDERJlU*S`6gKMbVu$E&-_~uDcCi!Eo*w5i`Wt7N>63f(ga8se_{MYmVwjtd&@d4 z@dX~V*A!c-5VaPyMue-zQNM;9hf%-dDGgoy#^_aVepDDprDddMdirbXc;(D1>?55A zDsK4n%+>715G5T*U!`ic>e!%j6XCta6&d72t%w{ST*ImTMQ1qA6nD6u)VkH_I}f~0 z7wt6{>Ps=>bZ60o!phT5ibKBIfBV(ZE4f)Er@QBF%C9uSdu2CdIMH`Yjt=iE}lW=Wuw$3+6mCEV!2ToZ#6ic_&7MHDY#_tVVoNY{Hu3sk`>;osG?% z6YKb$4i4bqzB0*Uz0c+0R7TR1Yw62{c<_l-?3mb$-z;&*?2mRZ6EfP8PlC-3@<@ES zkz3B}@eIDF=86NplktrOo=k0s8F?t*2&q+cT8cN@9jCum6j$%5(Dl>Al6RM!9qwdE zK37~me=9GCmYm69ja{=JWAb`8)vLX{Lp)$gL~N>5>)Lcg=3~KqR?%8=Zjt9uE^RM7 z`E6eQgWoReJTp1J5N-O|-g`66j%p^VxAC_=Z7r`U{fMyQ{Wp0O*6<~>6DBFJbPbrR QsdQyP*Ytm)IV+O?1s4pJ*8l(j literal 0 HcmV?d00001 diff --git a/ShareClientUI/zh-Hans.lproj/Localizable.strings b/ShareClientUI/zh-Hans.lproj/Localizable.strings new file mode 100644 index 0000000000000000000000000000000000000000..e444031ec27a98a264a8bdd5072d813c278fc8aa GIT binary patch literal 920 zcmb`F&q~8U5XL{jlh9{y$w@r4-UP*y1uufqH1!||vBtL0Bqe{e2f<4Zp1gYYWqgFb zfsdi}n+;*Ji;#m7l3iv#W_~kYHs3w$Lt%(1BAx|ieCPU};$BCp%orgOjG37;8uBLE zlrhCqzLIw{xvm>gtJtT99e6lxRPq=<;p<`Tzr-GnsSr({nu5Jd{xjO0nEV+jN;0I# zEmgSMUag;MT{YVUl?8P(-08Uj`0OZTAu=728W|q+SFz@zFp9D)iRqPNh$eQzcBwfZi6jj156D689)V|b&myX`heOzxX|BuVwTz~=2 zTiJZQ=W5%At222YOh-0ZfG)l2I=irYw!0;Mn?B-=-Q_R7l=MXYorL?2d290}aP)?2 LuROf%3~RC<5s;c5 literal 0 HcmV?d00001 From f0125aed8960586a9473dca02d17b3e5969558ac Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 15 Sep 2018 13:25:14 -0500 Subject: [PATCH 02/12] Prevent recursive building --- ShareClient.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index 536d256..c383e45 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -407,7 +407,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi"; + shellScript = "if [ \"$CARTHAGE\" = \"YES\" ]; then\n echo \"Skipping carthage build because we're already in one\"\nelif [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ From 0d3a8886bd9b55da2054c9114f46c402c712915f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 19 Sep 2018 16:39:03 -0500 Subject: [PATCH 03/12] Update loopkit dev version --- Cartfile.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 1d52afe..cf1a185 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "LoopKit/LoopKit" "0cc099726d4148db37d22c14475a97c2575afeaa" +github "LoopKit/LoopKit" "8c553f7bd03c2032b146e4a52d58d527a4285c15" From 7af726cb6c24a25abc9c056294578cff6cd9c245 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 25 Sep 2018 16:32:06 -0500 Subject: [PATCH 04/12] Update to LoopKit dev --- Cartfile.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index cf1a185..0110def 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "LoopKit/LoopKit" "8c553f7bd03c2032b146e4a52d58d527a4285c15" +github "LoopKit/LoopKit" "f130260f76d5e58a5984045484331a363e1b7080" From d5102258f279546f5fb1401814795b0575c9c443 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 28 Sep 2018 16:48:23 -0500 Subject: [PATCH 05/12] Avoid carthage build when using workspace setup --- ShareClient.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index c383e45..04e6047 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -407,7 +407,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ \"$CARTHAGE\" = \"YES\" ]; then\n echo \"Skipping carthage build because we're already in one\"\nelif [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; + shellScript = "if [ \"$CARTHAGE\" = \"YES\" ]; then\n echo \"Skipping carthage build because we're already in one\"\nelif [ -d $PROJECT_DIR/../../../Loop.xcworkspace ]; then\n echo \"Skipping carthage build because we're in a workspace\"\nelif [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ From 3e408f4a3c572e355aeb297f903b6a974a35f223 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 29 Sep 2018 12:03:21 -0500 Subject: [PATCH 06/12] verify() should fail if authentication returns error --- ShareClient/ShareService.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ShareClient/ShareService.swift b/ShareClient/ShareService.swift index 8c7cdc2..9cb7a2c 100644 --- a/ShareClient/ShareService.swift +++ b/ShareClient/ShareService.swift @@ -75,8 +75,7 @@ public class ShareService: ServiceAuthentication { let client = ShareClient(username: username, password: password, shareServer: url.absoluteString) client.fetchLast(1) { (error, _) in - completion(true, error) - + completion(error == nil, error) } self.client = client } From 03ba730824f4ad92680423356fe31c34f0d933fa Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 1 Oct 2018 19:49:46 -0500 Subject: [PATCH 07/12] Update LoopKit rev --- Cartfile.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 0110def..7f915e9 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "LoopKit/LoopKit" "f130260f76d5e58a5984045484331a363e1b7080" +github "LoopKit/LoopKit" "1c23bb5fd54c0b0aaa81dbabcb35f2d4c9c2e8cf" From 81f6539a0e66fa9bcf34cfb92f60720741536f8a Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 26 Oct 2018 16:59:35 -0500 Subject: [PATCH 08/12] Migrate to Swift 4.2 --- ShareClient.xcodeproj/project.pbxproj | 11 ++++++----- ShareClient/ShareClientManager.swift | 9 +++++---- .../ShareClientSettingsViewController.swift | 16 ++++++---------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index 04e6047..8304af0 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -322,7 +322,7 @@ TargetAttributes = { 432B0E871CDFC3C50045347B = { CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 0900; + LastSwiftMigration = 1000; }; 432B0E911CDFC3C50045347B = { CreatedOnToolsVersion = 7.3.1; @@ -334,6 +334,7 @@ }; 43A8EC81210E664300A81379 = { CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 1000; ProvisioningStyle = Automatic; }; }; @@ -662,7 +663,7 @@ SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos watchsimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Debug; @@ -688,7 +689,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "iphonesimulator iphoneos watchos watchsimulator"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2,4"; }; name = Release; @@ -760,7 +761,7 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -793,7 +794,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.loopkit.ShareClientUI; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/ShareClient/ShareClientManager.swift b/ShareClient/ShareClientManager.swift index 60917e2..d62b30f 100644 --- a/ShareClient/ShareClientManager.swift +++ b/ShareClient/ShareClientManager.swift @@ -74,14 +74,15 @@ public class ShareClientManager: CGMManager { // Ignore glucose values that are up to a minute newer than our previous value, to account for possible time shifting in Share data let startDate = self.cgmManagerDelegate?.startDateToFilterNewData(for: self)?.addingTimeInterval(TimeInterval(minutes: 1)) - let newGlucose = glucose.filterDateRange(startDate, nil).filter({ $0.isStateValid }).map { + let newGlucose = glucose.filterDateRange(startDate, nil) + let newSamples = newGlucose.filter({ $0.isStateValid }).map { return NewGlucoseSample(date: $0.startDate, quantity: $0.quantity, isDisplayOnly: false, syncIdentifier: "\(Int($0.startDate.timeIntervalSince1970))", device: self.device) } - self.latestBackfill = glucose.first + self.latestBackfill = newGlucose.first - if newGlucose.count > 0 { - completion(.newData(newGlucose)) + if newSamples.count > 0 { + completion(.newData(newSamples)) } else { completion(.noData) } diff --git a/ShareClientUI/ShareClientSettingsViewController.swift b/ShareClientUI/ShareClientSettingsViewController.swift index ed9e440..9181c0b 100644 --- a/ShareClientUI/ShareClientSettingsViewController.swift +++ b/ShareClientUI/ShareClientSettingsViewController.swift @@ -37,10 +37,10 @@ public class ShareClientSettingsViewController: UITableViewController { title = cgmManager.localizedTitle - tableView.rowHeight = UITableViewAutomaticDimension + tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 44 - tableView.sectionHeaderHeight = UITableViewAutomaticDimension + tableView.sectionHeaderHeight = UITableView.automaticDimension tableView.estimatedSectionHeaderHeight = 55 tableView.register(SettingsTableViewCell.self, forCellReuseIdentifier: SettingsTableViewCell.className) @@ -49,24 +49,20 @@ public class ShareClientSettingsViewController: UITableViewController { // MARK: - UITableViewDataSource - private enum Section: Int { + private enum Section: Int, CaseIterable { case authentication case latestReading case delete - - static let count = 3 } override public func numberOfSections(in tableView: UITableView) -> Int { - return allowsDeletion ? Section.count : Section.count - 1 + return allowsDeletion ? Section.allCases.count : Section.allCases.count - 1 } - private enum LatestReadingRow: Int { + private enum LatestReadingRow: Int, CaseIterable { case glucose case date case trend - - static let count = 3 } override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -74,7 +70,7 @@ public class ShareClientSettingsViewController: UITableViewController { case .authentication: return 1 case .latestReading: - return LatestReadingRow.count + return LatestReadingRow.allCases.count case .delete: return 1 } From c53d44a13beaac4c1fde71ba48a767039aca0033 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 27 Oct 2018 11:43:37 -0500 Subject: [PATCH 09/12] Fix tests --- Cartfile.resolved | 2 +- ShareClient.xcodeproj/project.pbxproj | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 7f915e9..f2175a9 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "LoopKit/LoopKit" "1c23bb5fd54c0b0aaa81dbabcb35f2d4c9c2e8cf" +github "LoopKit/LoopKit" "0f12e7a973625be59ea617166fea7bd2e0f6d729" diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index 8304af0..afbfec4 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -46,6 +46,8 @@ 43AB51362133177800B3D58D /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AB51352133177800B3D58D /* LocalizedString.swift */; }; 43AB51372133177800B3D58D /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AB51352133177800B3D58D /* LocalizedString.swift */; }; 43C418AF1CE0488900405B6A /* ShareClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C418AE1CE0488900405B6A /* ShareClient.swift */; }; + C17D3CC52184CBCD003458C8 /* LoopKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 43A8EC7B210E661400A81379 /* LoopKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + C17D3CC62184CC26003458C8 /* LoopKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43A8EC7B210E661400A81379 /* LoopKit.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -72,6 +74,19 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + C17D3CC42184CBB7003458C8 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + C17D3CC52184CBCD003458C8 /* LoopKit.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 4325E9CE210E6A0A00969CE5 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HKUnit.swift; sourceTree = ""; }; 4325E9D0210E6A3D00969CE5 /* TimeInterval.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeInterval.swift; sourceTree = ""; }; @@ -135,6 +150,7 @@ buildActionMask = 2147483647; files = ( 432B0E931CDFC3C50045347B /* ShareClient.framework in Frameworks */, + C17D3CC62184CC26003458C8 /* LoopKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -280,6 +296,7 @@ 432B0E8E1CDFC3C50045347B /* Sources */, 432B0E8F1CDFC3C50045347B /* Frameworks */, 432B0E901CDFC3C50045347B /* Resources */, + C17D3CC42184CBB7003458C8 /* CopyFiles */, ); buildRules = ( ); @@ -408,7 +425,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ \"$CARTHAGE\" = \"YES\" ]; then\n echo \"Skipping carthage build because we're already in one\"\nelif [ -d $PROJECT_DIR/../../../Loop.xcworkspace ]; then\n echo \"Skipping carthage build because we're in a workspace\"\nelif [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; + shellScript = "if [ \"$CARTHAGE\" = \"YES\" ]; then\n echo \"Skipping carthage build because we're already in one\"\nelif [ -d $PROJECT_DIR/../../../Loop.xcworkspace ]; then\n echo \"Skipping carthage build because we're in a workspace\"\nelif [ -f $PROJECT_DIR/.gitmodules ]; then\n echo \"Skipping checkout due to presence of .gitmodules file\"\n if [ $ACTION = \"install\" ]; then\n echo \"You're installing: Make sure to keep all submodules up-to-date and run carthage build after changes.\"\n fi\nelse\n unset LLVM_TARGET_TRIPLE_SUFFIX\n echo \"Bootstrapping carthage dependencies\"\n /usr/local/bin/carthage bootstrap --project-directory \"$SRCROOT\" --cache-builds\nfi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -697,6 +714,10 @@ 432B0EA01CDFC3C50045347B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited),", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); INFOPLIST_FILE = ShareClientTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mddub.ShareClientTests; @@ -708,6 +729,10 @@ 432B0EA11CDFC3C50045347B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited),", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); INFOPLIST_FILE = ShareClientTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.mddub.ShareClientTests; From 9343c6f6fa459735b66d9e34c8af0076b53bde77 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 27 Oct 2018 11:45:24 -0500 Subject: [PATCH 10/12] Add travis config --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..08bf3da --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: objective-c +osx_image: xcode10 + +script: +# Build Travis project and run tests +- xcodebuild -project ShareClient.xcodeproj -scheme ShareClient build -destination name="iPhone SE" test From 13e0f5cfd98dd4bfdf5eff413ba3ed36617cbb08 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 27 Oct 2018 11:51:56 -0500 Subject: [PATCH 11/12] Trigger travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 08bf3da..6467470 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: objective-c osx_image: xcode10 + script: # Build Travis project and run tests - xcodebuild -project ShareClient.xcodeproj -scheme ShareClient build -destination name="iPhone SE" test From f0f8059941d20b4285c5b83bb4630f750130c565 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 25 Jan 2019 15:28:37 -0600 Subject: [PATCH 12/12] Bump version --- Cartfile | 2 +- Cartfile.resolved | 2 +- ShareClient.xcodeproj/project.pbxproj | 8 ++++---- ShareClient/Info.plist | 2 +- ShareClientTests/Info.plist | 2 +- ShareClientUI/Info.plist | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cartfile b/Cartfile index 05195c5..5abe0d1 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "LoopKit/LoopKit" "dev" +github "LoopKit/LoopKit" ~> 2.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index f2175a9..ea5e0dd 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "LoopKit/LoopKit" "0f12e7a973625be59ea617166fea7bd2e0f6d729" +github "LoopKit/LoopKit" "v2.2.1" diff --git a/ShareClient.xcodeproj/project.pbxproj b/ShareClient.xcodeproj/project.pbxproj index afbfec4..1d48918 100644 --- a/ShareClient.xcodeproj/project.pbxproj +++ b/ShareClient.xcodeproj/project.pbxproj @@ -769,10 +769,10 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; + DYLIB_CURRENT_VERSION = 2; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -803,10 +803,10 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; + DYLIB_CURRENT_VERSION = 2; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/ShareClient/Info.plist b/ShareClient/Info.plist index 2bb1ea9..a6f720e 100644 --- a/ShareClient/Info.plist +++ b/ShareClient/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.4.1 + 1.1 CFBundleSignature ???? CFBundleVersion diff --git a/ShareClientTests/Info.plist b/ShareClientTests/Info.plist index e7ba0f3..8a2d354 100644 --- a/ShareClientTests/Info.plist +++ b/ShareClientTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 0.4.1 + 1.1 CFBundleSignature ???? CFBundleVersion diff --git a/ShareClientUI/Info.plist b/ShareClientUI/Info.plist index 1007fd9..29dea2b 100644 --- a/ShareClientUI/Info.plist +++ b/ShareClientUI/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 1.1 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass