diff --git a/DoseMathTests/Info.plist b/DoseMathTests/Info.plist index 4507c55102..5963493d6a 100644 --- a/DoseMathTests/Info.plist +++ b/DoseMathTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleSignature ???? CFBundleVersion diff --git a/Loop Status Extension/Info.plist b/Loop Status Extension/Info.plist index 0e43389ef6..212d75db30 100644 --- a/Loop Status Extension/Info.plist +++ b/Loop Status Extension/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleVersion $(CURRENT_PROJECT_VERSION) AppGroupIdentifier diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 81db1cb41f..76c5aa72e9 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -290,6 +290,11 @@ 7D7076631FE06EE4004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076651FE06EE4004AC8EA /* Localizable.strings */; }; 7D7076681FE0702F004AC8EA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D70766A1FE0702F004AC8EA /* InfoPlist.strings */; }; 894F71E21FFEC4D8007D365C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 894F71E11FFEC4D8007D365C /* Assets.xcassets */; }; + 898ECA60218ABD17001E9D35 /* GlucoseChartScaler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA5E218ABD17001E9D35 /* GlucoseChartScaler.swift */; }; + 898ECA61218ABD17001E9D35 /* GlucoseChartData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA5F218ABD17001E9D35 /* GlucoseChartData.swift */; }; + 898ECA63218ABD21001E9D35 /* ComplicationChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA62218ABD21001E9D35 /* ComplicationChartManager.swift */; }; + 898ECA65218ABD9B001E9D35 /* CGRect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA64218ABD9A001E9D35 /* CGRect.swift */; }; + 898ECA69218ABDA9001E9D35 /* CLKTextProvider+Compound.m in Sources */ = {isa = PBXBuildFile; fileRef = 898ECA67218ABDA8001E9D35 /* CLKTextProvider+Compound.m */; }; C10428971D17BAD400DD539A /* NightscoutUploadKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */; }; C10B28461EA9BA5E006EA1FC /* far_future_high_bg_forecast.json in Resources */ = {isa = PBXBuildFile; fileRef = C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */; }; C11C87DE1E21EAAD00BB71D3 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; @@ -305,7 +310,6 @@ C18C8C511D5A351900E043FB /* NightscoutDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */; }; C1C6591C1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json in Resources */ = {isa = PBXBuildFile; fileRef = C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */; }; C1C73F0D1DE3D0270022FC89 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = C1C73F0F1DE3D0270022FC89 /* InfoPlist.strings */; }; - C9886AE51E5B2FAD00473BB8 /* gallery.ckcomplication in Resources */ = {isa = PBXBuildFile; fileRef = C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -824,6 +828,13 @@ 7DD382781F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/MainInterface.strings; sourceTree = ""; }; 7DD382791F8DBFC60071272B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Interface.strings; sourceTree = ""; }; 894F71E11FFEC4D8007D365C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 898ECA5E218ABD17001E9D35 /* GlucoseChartScaler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseChartScaler.swift; sourceTree = ""; }; + 898ECA5F218ABD17001E9D35 /* GlucoseChartData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseChartData.swift; sourceTree = ""; }; + 898ECA62218ABD21001E9D35 /* ComplicationChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComplicationChartManager.swift; sourceTree = ""; }; + 898ECA64218ABD9A001E9D35 /* CGRect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGRect.swift; sourceTree = ""; }; + 898ECA66218ABDA8001E9D35 /* WatchApp Extension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WatchApp Extension-Bridging-Header.h"; sourceTree = ""; }; + 898ECA67218ABDA8001E9D35 /* CLKTextProvider+Compound.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CLKTextProvider+Compound.m"; sourceTree = ""; }; + 898ECA68218ABDA9001E9D35 /* CLKTextProvider+Compound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CLKTextProvider+Compound.h"; sourceTree = ""; }; C10428961D17BAD400DD539A /* NightscoutUploadKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NightscoutUploadKit.framework; path = Carthage/Build/iOS/NightscoutUploadKit.framework; sourceTree = SOURCE_ROOT; }; C10B28451EA9BA5E006EA1FC /* far_future_high_bg_forecast.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = far_future_high_bg_forecast.json; sourceTree = ""; }; C12F21A61DFA79CB00748193 /* recommend_temp_basal_very_low_end_in_range.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_very_low_end_in_range.json; sourceTree = ""; }; @@ -835,7 +846,6 @@ C18852E12082AB1A00BECC8C /* RileyLinkKitUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RileyLinkKitUI.framework; path = Carthage/Build/iOS/RileyLinkKitUI.framework; sourceTree = ""; }; C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutDataManager.swift; sourceTree = ""; }; C1C6591B1E1B1FDA0025CC58 /* recommend_temp_basal_dropping_then_rising.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = recommend_temp_basal_dropping_then_rising.json; sourceTree = ""; }; - C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */ = {isa = PBXFileReference; lastKnownFileType = folder; path = gallery.ckcomplication; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -935,7 +945,10 @@ isa = PBXGroup; children = ( 4344629120A7C19800C4BE6F /* ButtonGroup.swift */, + 898ECA64218ABD9A001E9D35 /* CGRect.swift */, 4328E0221CFBE2C500E199AA /* CLKComplicationTemplate.swift */, + 898ECA68218ABDA9001E9D35 /* CLKTextProvider+Compound.h */, + 898ECA67218ABDA8001E9D35 /* CLKTextProvider+Compound.m */, 4F7E8AC420E2AB9600AEA65E /* Date.swift */, 4F73F5FB20E2E7FA00E8D82C /* GlucoseStore.swift */, 4328E0201CFBE2C500E199AA /* IdentifiableClass.swift */, @@ -946,6 +959,7 @@ 43CB2B2A1D924D450079823D /* WCSession.swift */, 4328E0251CFBE2C500E199AA /* WKAlertAction.swift */, 4328E02E1CFBF81800E199AA /* WKInterfaceImage.swift */, + 898ECA66218ABDA8001E9D35 /* WatchApp Extension-Bridging-Header.h */, ); path = Extensions; sourceTree = ""; @@ -1015,7 +1029,6 @@ children = ( 7D7076651FE06EE4004AC8EA /* Localizable.strings */, 7D7076511FE06EE1004AC8EA /* InfoPlist.strings */, - C9886AE41E5B2FAD00473BB8 /* gallery.ckcomplication */, 43EDEE6B1CF2E12A00393BE3 /* Loop.entitlements */, 43F5C2D41B92A4A6003EB13D /* Info.plist */, 43776F8F1B8022E90074EA36 /* AppDelegate.swift */, @@ -1068,6 +1081,7 @@ 4328E01F1CFBE2B100E199AA /* Extensions */, 4FE3475F20D5D7FA00A86D03 /* Managers */, 4F75F0052100146B00B5570E /* Scenes */, + 898ECA5D218ABD17001E9D35 /* Models */, 43A943831B926B7B0051FA24 /* Supporting Files */, ); path = "WatchApp Extension"; @@ -1307,6 +1321,7 @@ isa = PBXGroup; children = ( 4FDDD23620DC51DF00D04B16 /* LoopDataManager.swift */, + 898ECA62218ABD21001E9D35 /* ComplicationChartManager.swift */, ); path = Managers; sourceTree = ""; @@ -1373,6 +1388,15 @@ path = Common; sourceTree = ""; }; + 898ECA5D218ABD17001E9D35 /* Models */ = { + isa = PBXGroup; + children = ( + 898ECA5E218ABD17001E9D35 /* GlucoseChartScaler.swift */, + 898ECA5F218ABD17001E9D35 /* GlucoseChartData.swift */, + ); + path = Models; + sourceTree = ""; + }; 968DCD53F724DE56FFE51920 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -1601,7 +1625,7 @@ }; 43A9437D1B926B7B0051FA24 = { CreatedOnToolsVersion = 7.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 1000; SystemCapabilities = { com.apple.ApplicationGroups.iOS = { enabled = 0; @@ -1687,7 +1711,6 @@ 43776F991B8022E90074EA36 /* Assets.xcassets in Resources */, 7D7076631FE06EE4004AC8EA /* Localizable.strings in Resources */, 43776F971B8022E90074EA36 /* Main.storyboard in Resources */, - C9886AE51E5B2FAD00473BB8 /* gallery.ckcomplication in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1825,7 +1848,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks"; + shellScript = "carthage_frameworks_dir=${SRCROOT}/Carthage/Build/iOS\nif [ -f $PROJECT_DIR/.gitmodules && [ $ACTION != \"install\" ]; then\nfor varname in ${!SCRIPT_INPUT_FILE_*}\ndo\nexport ${varname}=${!varname/$carthage_frameworks_dir/$BUILT_PRODUCTS_DIR}\ndone\nfi\n/usr/local/bin/carthage copy-frameworks\n"; }; 43FF3DF620A8EFE800F8E62C /* Copy Frameworks with Carthage */ = { isa = PBXShellScriptBuildPhase; @@ -1970,6 +1993,7 @@ 4FF4D1011E18375000846527 /* WatchContext.swift in Sources */, 435400311C9F744E00D5819C /* BolusSuggestionUserInfo.swift in Sources */, 4372E49A213F7A830068E043 /* WalshInsulinModel.swift in Sources */, + 898ECA63218ABD21001E9D35 /* ComplicationChartManager.swift in Sources */, 43A9438A1B926B7B0051FA24 /* NotificationController.swift in Sources */, 439A7945211FE23A0041B75F /* NSUserActivity.swift in Sources */, 43A943881B926B7B0051FA24 /* ExtensionDelegate.swift in Sources */, @@ -1978,10 +2002,12 @@ 4328E02F1CFBF81800E199AA /* WKInterfaceImage.swift in Sources */, 4F2C15811E0495B200E160D4 /* WatchContext+WatchApp.swift in Sources */, 4372E496213DCDD30068E043 /* GlucoseChartValueHashable.swift in Sources */, + 898ECA61218ABD17001E9D35 /* GlucoseChartData.swift in Sources */, 4344629820A8B2D700C4BE6F /* OSLog.swift in Sources */, 4328E02A1CFBE2C500E199AA /* UIColor.swift in Sources */, 4372E484213A63FB0068E043 /* ChartHUDController.swift in Sources */, 4FDDD23720DC51DF00D04B16 /* LoopDataManager.swift in Sources */, + 898ECA60218ABD17001E9D35 /* GlucoseChartScaler.swift in Sources */, 4328E01B1CFBE1DA00E199AA /* BolusInterfaceController.swift in Sources */, 4F82655020E69F9A0031A8F5 /* HUDInterfaceController.swift in Sources */, 4372E492213D956C0068E043 /* GlucoseRangeSchedule.swift in Sources */, @@ -1998,9 +2024,11 @@ 432CF87520D8AC950066B889 /* NSUserDefaults+WatchApp.swift in Sources */, 43027F0F1DFE0EC900C51989 /* HKUnit.swift in Sources */, 4344629220A7C19800C4BE6F /* ButtonGroup.swift in Sources */, + 898ECA69218ABDA9001E9D35 /* CLKTextProvider+Compound.m in Sources */, 4372E48C213CB6750068E043 /* Double.swift in Sources */, 43785E972120E4500057DED1 /* INRelevantShortcutStore+Loop.swift in Sources */, 4372E48E213CF8AD0068E043 /* LoopSettings.swift in Sources */, + 898ECA65218ABD9B001E9D35 /* CGRect.swift in Sources */, 4372E49B213F7B340068E043 /* NSBundle.swift in Sources */, 43CB2B2B1D924D450079823D /* WCSession.swift in Sources */, 4372E497213F79F90068E043 /* NSUserDefaults.swift in Sources */, @@ -2506,7 +2534,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer: loudnate@gmail.com (XZN842LDLT)"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -2578,7 +2606,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer: loudnate@gmail.com (XZN842LDLT)"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -2619,7 +2647,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; "OTHER_SWIFT_FLAGS[sdk=iphonesimulator*]" = "-D IOS_SIMULATOR"; @@ -2636,7 +2664,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = Loop/Loop.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; INFOPLIST_FILE = Loop/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER)"; @@ -2649,10 +2677,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2661,6 +2690,9 @@ PROVISIONING_PROFILE = ""; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "WatchApp Extension/Extensions/WatchApp Extension-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 4; }; name = Debug; @@ -2669,10 +2701,11 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "WatchApp Extension/WatchApp Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/watchOS"; INFOPLIST_FILE = "WatchApp Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; @@ -2681,6 +2714,8 @@ PROVISIONING_PROFILE = ""; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "WatchApp Extension/Extensions/WatchApp Extension-Bridging-Header.h"; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 4; }; name = Release; @@ -2692,7 +2727,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2713,7 +2748,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=watchos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; FRAMEWORK_SEARCH_PATHS = ""; IBSC_MODULE = WatchApp_Extension; INFOPLIST_FILE = WatchApp/Info.plist; @@ -2792,7 +2827,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2811,7 +2846,7 @@ CODE_SIGN_ENTITLEMENTS = "Loop Status Extension/Loop Status Extension.entitlements"; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 5Q5Q8W9ATZ; INFOPLIST_FILE = "Loop Status Extension/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "$(MAIN_APP_BUNDLE_IDENTIFIER).statuswidget"; @@ -2829,11 +2864,11 @@ CLANG_WARN_SUSPICIOUS_MOVES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 53; + DYLIB_CURRENT_VERSION = 54; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = LoopUI/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -2856,11 +2891,11 @@ CLANG_WARN_SUSPICIOUS_MOVES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - CURRENT_PROJECT_VERSION = 53; + CURRENT_PROJECT_VERSION = 54; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 53; + DYLIB_CURRENT_VERSION = 54; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = LoopUI/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/Loop/Info.plist b/Loop/Info.plist index 8d8b8ce20c..d9c870279f 100644 --- a/Loop/Info.plist +++ b/Loop/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleSignature ???? CFBundleURLTypes diff --git a/Loop/gallery.ckcomplication/11076976-F7D6-460C-845C-10C8A7003F0D.json b/Loop/gallery.ckcomplication/11076976-F7D6-460C-845C-10C8A7003F0D.json deleted file mode 100644 index 846670445e..0000000000 --- a/Loop/gallery.ckcomplication/11076976-F7D6-460C-845C-10C8A7003F0D.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateUtilitarianLargeFlat", - "textProvider" : { - "textProviders" : [ - { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - }, - { - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "75" - }, - { - "class" : "CLKTimeTextProvider", - "date" : 510206747.733748 - } - ], - "class" : "CLKLocalizableCompoundTextProvider", - "formatKey" : "UtilitarianLargeFlat" - }, - "version" : 30000 -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/28C71A33-1C97-4A92-8677-4FE8644380DF.json b/Loop/gallery.ckcomplication/28C71A33-1C97-4A92-8677-4FE8644380DF.json deleted file mode 100644 index 9bf1460c74..0000000000 --- a/Loop/gallery.ckcomplication/28C71A33-1C97-4A92-8677-4FE8644380DF.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateModularLargeTallBody", - "bodyTextProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - }, - "version" : 30000, - "headerTextProvider" : { - "class" : "CLKRelativeDateTextProvider", - "relativeDateStyle" : 0, - "calendarUnits" : 64, - "date" : 510206747.738849 - } -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/2E750127-9918-4653-8B91-FC0AB09DF91F.json b/Loop/gallery.ckcomplication/2E750127-9918-4653-8B91-FC0AB09DF91F.json deleted file mode 100644 index 15d5f951fb..0000000000 --- a/Loop/gallery.ckcomplication/2E750127-9918-4653-8B91-FC0AB09DF91F.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateModularSmallStackText", - "highlightLine2" : false, - "line2TextProvider" : { - "class" : "CLKRelativeDateTextProvider", - "relativeDateStyle" : 0, - "calendarUnits" : 64, - "date" : 510206747.724802 - }, - "version" : 30000, - "line1TextProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - } -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/38411872-4973-48F3-AC34-504D40170A49.json b/Loop/gallery.ckcomplication/38411872-4973-48F3-AC34-504D40170A49.json deleted file mode 100644 index b4e7818ff9..0000000000 --- a/Loop/gallery.ckcomplication/38411872-4973-48F3-AC34-504D40170A49.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateCircularSmallSimpleText", - "textProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - }, - "version" : 30000 -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/59939B64-2F84-4438-8860-91BB63BE827B.json b/Loop/gallery.ckcomplication/59939B64-2F84-4438-8860-91BB63BE827B.json deleted file mode 100644 index 55fc7c648c..0000000000 --- a/Loop/gallery.ckcomplication/59939B64-2F84-4438-8860-91BB63BE827B.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateUtilitarianSmallFlat", - "textProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - }, - "version" : 30000 -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/688917AC-E1E4-4B66-9B44-6EE17F1D19DB.json b/Loop/gallery.ckcomplication/688917AC-E1E4-4B66-9B44-6EE17F1D19DB.json deleted file mode 100644 index 55fc7c648c..0000000000 --- a/Loop/gallery.ckcomplication/688917AC-E1E4-4B66-9B44-6EE17F1D19DB.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateUtilitarianSmallFlat", - "textProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - }, - "version" : 30000 -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/AF8DC7FB-6148-4322-BE40-6D6DD3C963A9.json b/Loop/gallery.ckcomplication/AF8DC7FB-6148-4322-BE40-6D6DD3C963A9.json deleted file mode 100644 index e2f54551fe..0000000000 --- a/Loop/gallery.ckcomplication/AF8DC7FB-6148-4322-BE40-6D6DD3C963A9.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "tintColor" : { - "green" : 0.5843138, - "red" : 1, - "alpha" : 1, - "blue" : 0 - }, - "class" : "CLKComplicationTemplateExtraLargeStackText", - "highlightLine2" : false, - "line2TextProvider" : { - "class" : "CLKRelativeDateTextProvider", - "relativeDateStyle" : 0, - "calendarUnits" : 64, - "date" : 510206747.748279 - }, - "version" : 30000, - "line1TextProvider" : { - "shortText" : "120", - "class" : "CLKLocalizableSimpleTextProvider", - "text" : "120↘︎" - } -} \ No newline at end of file diff --git a/Loop/gallery.ckcomplication/Base.lproj/ckcomplication.strings b/Loop/gallery.ckcomplication/Base.lproj/ckcomplication.strings deleted file mode 100644 index f05b483c67..0000000000 --- a/Loop/gallery.ckcomplication/Base.lproj/ckcomplication.strings +++ /dev/null @@ -1,13 +0,0 @@ -/* - ckcomplication.strings - Loop - - Created by Nate Racklyeft on 9/18/16. - Copyright © 2016 Nathan Racklyeft. All rights reserved. -*/ - -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - -/* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ -"UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/Loop/gallery.ckcomplication/complicationManifest.json b/Loop/gallery.ckcomplication/complicationManifest.json deleted file mode 100644 index 7c531785e5..0000000000 --- a/Loop/gallery.ckcomplication/complicationManifest.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "supported complication families" : { - "7" : "AF8DC7FB-6148-4322-BE40-6D6DD3C963A9.json", - "3" : "11076976-F7D6-460C-845C-10C8A7003F0D.json", - "4" : "38411872-4973-48F3-AC34-504D40170A49.json", - "0" : "2E750127-9918-4653-8B91-FC0AB09DF91F.json", - "1" : "28C71A33-1C97-4A92-8677-4FE8644380DF.json", - "6" : "688917AC-E1E4-4B66-9B44-6EE17F1D19DB.json", - "2" : "59939B64-2F84-4438-8860-91BB63BE827B.json" - }, - "client ID" : "com.loudnate.Loop.LoopWatch.watchkitextension" -} diff --git a/Loop/gallery.ckcomplication/it.lproj/ckcomplication.strings b/Loop/gallery.ckcomplication/it.lproj/ckcomplication.strings deleted file mode 100644 index 26493ed457..0000000000 --- a/Loop/gallery.ckcomplication/it.lproj/ckcomplication.strings +++ /dev/null @@ -1,13 +0,0 @@ -/* - ckcomplication.strings - Loop - - Created by Nate Racklyeft on 9/18/16. - Copyright © 2016 Nathan Racklyeft. All rights reserved. -*/ - -/* The complication template example glucose & trend */ -"120↘︎" = "6.7↘︎"; - -/* The complication template example eventual glucose */ -"75" = "3.0"; diff --git a/LoopTests/Info.plist b/LoopTests/Info.plist index 4507c55102..5963493d6a 100644 --- a/LoopTests/Info.plist +++ b/LoopTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleSignature ???? CFBundleVersion diff --git a/LoopUI/Info.plist b/LoopUI/Info.plist index ead3c07674..f1c2e1159e 100644 --- a/LoopUI/Info.plist +++ b/LoopUI/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json index f84499ba51..79979e083e 100644 --- a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Contents.json @@ -2,13 +2,25 @@ "images" : [ { "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" + "filename" : "Icon-Complication-16x16@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "Icon-Complication-18x18@2x.png", + "screen-width" : ">161", + "scale" : "2x" }, { "idiom" : "watch", "scale" : "2x", "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" } ], "info" : { diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-16x16@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-16x16@2x.png new file mode 100644 index 0000000000..ff4721e7b3 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-16x16@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-18x18@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-18x18@2x.png new file mode 100644 index 0000000000..9f97913e0d Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Circular.imageset/Icon-Complication-18x18@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Contents.json index c8ebf0675f..1571c7e531 100644 --- a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Contents.json +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Contents.json @@ -10,6 +10,26 @@ "filename" : "Extra Large.imageset", "role" : "extra-large" }, + { + "idiom" : "watch", + "filename" : "Graphic Bezel.imageset", + "role" : "graphic-bezel" + }, + { + "idiom" : "watch", + "filename" : "Graphic Circular.imageset", + "role" : "graphic-circular" + }, + { + "idiom" : "watch", + "filename" : "Graphic Corner.imageset", + "role" : "graphic-corner" + }, + { + "idiom" : "watch", + "filename" : "Graphic Large Rectangular.imageset", + "role" : "graphic-large-rectangular" + }, { "idiom" : "watch", "filename" : "Modular.imageset", diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json index f84499ba51..aefef2914e 100644 --- a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Extra Large.imageset/Contents.json @@ -5,10 +5,20 @@ "scale" : "2x", "screen-width" : "<=145" }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">161" + }, { "idiom" : "watch", "scale" : "2x", "screen-width" : ">145" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">183" } ], "info" : { diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json new file mode 100644 index 0000000000..fe9e93e854 --- /dev/null +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Contents.json @@ -0,0 +1,30 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-42x42@2x.png", + "screen-width" : ">161", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-47x47@2x.png", + "screen-width" : ">183", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-42x42@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-42x42@2x.png new file mode 100644 index 0000000000..815478c10a Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-42x42@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-47x47@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-47x47@2x.png new file mode 100644 index 0000000000..28afdee569 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Bezel.imageset/Icon-AppleWatch-47x47@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json new file mode 100644 index 0000000000..fe9e93e854 --- /dev/null +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Contents.json @@ -0,0 +1,30 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-42x42@2x.png", + "screen-width" : ">161", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-47x47@2x.png", + "screen-width" : ">183", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-42x42@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-42x42@2x.png new file mode 100644 index 0000000000..815478c10a Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-42x42@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-47x47@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-47x47@2x.png new file mode 100644 index 0000000000..28afdee569 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Circular.imageset/Icon-AppleWatch-47x47@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json new file mode 100644 index 0000000000..faf72e9052 --- /dev/null +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Contents.json @@ -0,0 +1,30 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-32x32@2x.png", + "screen-width" : ">161", + "scale" : "2x" + }, + { + "idiom" : "watch", + "scale" : "2x", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "filename" : "Icon-AppleWatch-36x36@2x.png", + "screen-width" : ">183", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-32x32@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-32x32@2x.png new file mode 100644 index 0000000000..e8eefb523c Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-32x32@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-36x36@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-36x36@2x.png new file mode 100644 index 0000000000..b3abdc0592 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Corner.imageset/Icon-AppleWatch-36x36@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json new file mode 100644 index 0000000000..e011e32711 --- /dev/null +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Graphic Large Rectangular.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "watch", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json index f84499ba51..df4e8550a6 100644 --- a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Contents.json @@ -2,13 +2,26 @@ "images" : [ { "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" + "filename" : "Icon-Complication-26x26@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "Icon-Complication-29x29@2x.png", + "screen-width" : ">161", + "scale" : "2x" }, { "idiom" : "watch", "scale" : "2x", "screen-width" : ">145" + }, + { + "idiom" : "watch", + "filename" : "Icon-Complication-32x32@2x.png", + "screen-width" : ">183", + "scale" : "2x" } ], "info" : { diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-26x26@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-26x26@2x.png new file mode 100644 index 0000000000..48e6ea7a29 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-26x26@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-29x29@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-29x29@2x.png new file mode 100644 index 0000000000..2a0fc8ffc0 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-29x29@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-32x32@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-32x32@2x.png new file mode 100644 index 0000000000..d929b5acc8 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Modular.imageset/Icon-Complication-32x32@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json index f84499ba51..be2006d7ea 100644 --- a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json +++ b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Contents.json @@ -2,13 +2,26 @@ "images" : [ { "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" + "filename" : "Icon-Complication-20x20@2x.png", + "screen-width" : "<=145", + "scale" : "2x" + }, + { + "idiom" : "watch", + "filename" : "Icon-Complication-22x22@2x.png", + "screen-width" : ">161", + "scale" : "2x" }, { "idiom" : "watch", "scale" : "2x", "screen-width" : ">145" + }, + { + "idiom" : "watch", + "filename" : "Icon-Complication-25x25@2x.png", + "screen-width" : ">183", + "scale" : "2x" } ], "info" : { diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-20x20@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-20x20@2x.png new file mode 100644 index 0000000000..3e64959cdc Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-20x20@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-22x22@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-22x22@2x.png new file mode 100644 index 0000000000..1593033216 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-22x22@2x.png differ diff --git a/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-25x25@2x.png b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-25x25@2x.png new file mode 100644 index 0000000000..2e5645d885 Binary files /dev/null and b/WatchApp Extension/Assets.xcassets/Complication.complicationset/Utilitarian.imageset/Icon-Complication-25x25@2x.png differ diff --git a/WatchApp Extension/Base.lproj/ckcomplication.strings b/WatchApp Extension/Base.lproj/ckcomplication.strings index f05b483c67..f4d1b4d52c 100644 --- a/WatchApp Extension/Base.lproj/ckcomplication.strings +++ b/WatchApp Extension/Base.lproj/ckcomplication.strings @@ -6,8 +6,11 @@ Copyright © 2016 Nathan Racklyeft. All rights reserved. */ -/* The complication template example unit string */ +/* The complication template example glucose and trend string */ "120↘︎" = "120↘︎"; +/* The complication template example glucose string */ +"120" = "120"; + /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/ComplicationController.swift b/WatchApp Extension/ComplicationController.swift index e889eeb229..ca41ba2b33 100644 --- a/WatchApp Extension/ComplicationController.swift +++ b/WatchApp Extension/ComplicationController.swift @@ -40,23 +40,61 @@ final class ComplicationController: NSObject, CLKComplicationDataSource { // MARK: - Timeline Population - private lazy var formatter = NumberFormatter() + private let chartManager = ComplicationChartManager() - func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: (@escaping (CLKComplicationTimelineEntry?) -> Void)) { - let entry: CLKComplicationTimelineEntry? - - if let context = ExtensionDelegate.shared().loopManager.activeContext, - let glucoseDate = context.glucoseDate, - glucoseDate.timeIntervalSinceNow.minutes >= -15, - let template = CLKComplicationTemplate.templateForFamily(complication.family, from: context) - { - template.tintColor = UIColor.tintColor - entry = CLKComplicationTimelineEntry(date: glucoseDate, complicationTemplate: template) - } else { - entry = nil + private func updateChartManagerIfNeeded(completion: @escaping () -> Void) { + if #available(watchOSApplicationExtension 5.0, *) { + guard + let activeComplications = CLKComplicationServer.sharedInstance().activeComplications, + activeComplications.contains(where: { $0.family == .graphicRectangular }) + else { + completion() + return + } + + ExtensionDelegate.shared().loopManager.generateChartData { chartData in + self.chartManager.data = chartData + completion() + } } + } + + var makeChart: () -> UIImage? { + // c.f. https://developer.apple.com/design/human-interface-guidelines/watchos/icons-and-images/complication-images/ + let size: CGSize = { + let scaleFactor = 1 / WKInterfaceDevice.current().screenScale + switch WKInterfaceDevice.current().screenBounds.width { + case 162: // 40mm + return CGSize(width: 150.0 * scaleFactor, height: 47.0 * scaleFactor) + default /* case 184 */: // 44mm + return CGSize(width: 171.0 * scaleFactor, height: 54.0 * scaleFactor) + } + }() + return { [chartManager] in chartManager.renderChartImage(size: size) } + } + + func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: (@escaping (CLKComplicationTimelineEntry?) -> Void)) { + updateChartManagerIfNeeded { + let entry: CLKComplicationTimelineEntry? + + if let context = ExtensionDelegate.shared().loopManager.activeContext, + let glucoseDate = context.glucoseDate, + glucoseDate.timeIntervalSinceNow.minutes >= -15, + let template = CLKComplicationTemplate.templateForFamily(complication.family, from: context, chartGenerator: self.makeChart) + { + switch complication.family { + case .graphicRectangular: + break + default: + template.tintColor = .tintColor + } + entry = CLKComplicationTimelineEntry(date: glucoseDate, complicationTemplate: template) + } else { + entry = nil + } - handler(entry) + handler(entry) + } } func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: (@escaping ([CLKComplicationTimelineEntry]?) -> Void)) { @@ -65,66 +103,107 @@ final class ComplicationController: NSObject, CLKComplicationDataSource { } func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: (@escaping ([CLKComplicationTimelineEntry]?) -> Void)) { - // Call the handler with the timeline entries after to the given date - let entries: [CLKComplicationTimelineEntry]? - - if let context = ExtensionDelegate.shared().loopManager.activeContext, - let glucoseDate = context.glucoseDate, - glucoseDate.timeIntervalSince(date) > 0, - let template = CLKComplicationTemplate.templateForFamily(complication.family, from: context) - { - template.tintColor = UIColor.tintColor - entries = [CLKComplicationTimelineEntry(date: glucoseDate, complicationTemplate: template)] - } else { - entries = nil - } + updateChartManagerIfNeeded { + let entries: [CLKComplicationTimelineEntry]? - handler(entries) + if let context = ExtensionDelegate.shared().loopManager.activeContext, + let glucoseDate = context.glucoseDate, + glucoseDate.timeIntervalSince(date) > 0, + let template = CLKComplicationTemplate.templateForFamily(complication.family, from: context, chartGenerator: self.makeChart) + { + template.tintColor = UIColor.tintColor + entries = [CLKComplicationTimelineEntry(date: glucoseDate, complicationTemplate: template)] + } else { + entries = nil + } + + handler(entries) + } } // MARK: - Placeholder Templates func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { + let template = getLocalizableSampleTemplate(for: complication.family) + handler(template) + } - let template: CLKComplicationTemplate? - - let glucoseText = CLKSimpleTextProvider.localizableTextProvider(withStringsFileTextKey: "120↘︎", shortTextKey: "120") + func getLocalizableSampleTemplate(for family: CLKComplicationFamily) -> CLKComplicationTemplate? { + let glucoseAndTrendText = CLKSimpleTextProvider.localizableTextProvider(withStringsFileTextKey: "120↘︎") + let glucoseText = CLKSimpleTextProvider.localizableTextProvider(withStringsFileTextKey: "120") let timeText = CLKRelativeDateTextProvider(date: Date(), style: .natural, units: .minute) - switch complication.family { - case .graphicCorner, .graphicCircular, .graphicRectangular, .graphicBezel: - template = nil + switch family { case .modularSmall: - let modularSmall = CLKComplicationTemplateModularSmallStackText() - modularSmall.line1TextProvider = glucoseText - modularSmall.line2TextProvider = timeText - template = modularSmall + let template = CLKComplicationTemplateModularSmallStackText() + template.line1TextProvider = glucoseAndTrendText + template.line2TextProvider = timeText + return template case .modularLarge: - let modularSmall = CLKComplicationTemplateModularLargeTallBody() - modularSmall.bodyTextProvider = glucoseText - modularSmall.headerTextProvider = timeText - template = modularSmall + let template = CLKComplicationTemplateModularLargeTallBody() + template.bodyTextProvider = glucoseAndTrendText + template.headerTextProvider = timeText + return template case .circularSmall: - let circularSmall = CLKComplicationTemplateCircularSmallSimpleText() - circularSmall.textProvider = glucoseText - template = circularSmall + let template = CLKComplicationTemplateCircularSmallSimpleText() + template.textProvider = glucoseAndTrendText + return template case .extraLarge: - let extraLarge = CLKComplicationTemplateExtraLargeStackText() - extraLarge.line1TextProvider = glucoseText - extraLarge.line2TextProvider = timeText - template = extraLarge + let template = CLKComplicationTemplateExtraLargeStackText() + template.line1TextProvider = glucoseAndTrendText + template.line2TextProvider = timeText + return template case .utilitarianSmall, .utilitarianSmallFlat: - let utilitarianSmallFlat = CLKComplicationTemplateUtilitarianSmallFlat() - utilitarianSmallFlat.textProvider = glucoseText - template = utilitarianSmallFlat + let template = CLKComplicationTemplateUtilitarianSmallFlat() + template.textProvider = glucoseAndTrendText + return template case .utilitarianLarge: - let utilitarianLarge = CLKComplicationTemplateUtilitarianLargeFlat() + let template = CLKComplicationTemplateUtilitarianLargeFlat() let eventualGlucoseText = CLKSimpleTextProvider.localizableTextProvider(withStringsFileTextKey: "75") - utilitarianLarge.textProvider = CLKSimpleTextProvider.localizableTextProvider(withStringsFileFormatKey: "UtilitarianLargeFlat", textProviders: [glucoseText, eventualGlucoseText, CLKTimeTextProvider(date: Date())]) - template = utilitarianLarge + template.textProvider = CLKSimpleTextProvider.localizableTextProvider(withStringsFileFormatKey: "UtilitarianLargeFlat", textProviders: [glucoseAndTrendText, eventualGlucoseText, CLKTimeTextProvider(date: Date())]) + return template + case .graphicCorner: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicCornerStackText() + timeText.tintColor = .tintColor + template.innerTextProvider = timeText + template.outerTextProvider = glucoseAndTrendText + return template + } else { + return nil + } + case .graphicCircular: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicCircularOpenGaugeSimpleText() + template.centerTextProvider = glucoseText + template.bottomTextProvider = CLKSimpleTextProvider(text: "↘︎") + template.gaugeProvider = CLKSimpleGaugeProvider(style: .fill, gaugeColor: .tintColor, fillFraction: 1) + return template + } else { + return nil + } + case .graphicBezel: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicBezelCircularText() + guard let circularTemplate = getLocalizableSampleTemplate(for: .graphicCircular) as? CLKComplicationTemplateGraphicCircular else { + fatalError("\(#function) invoked with .graphicCircular must return a subclass of CLKComplicationTemplateGraphicCircular") + } + template.circularTemplate = circularTemplate + template.textProvider = timeText + return template + } else { + return nil + } + case .graphicRectangular: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicRectangularLargeImage() + // TODO: Better placeholder image here + template.imageProvider = CLKFullColorImageProvider(fullColorImage: UIImage()) + template.textProvider = glucoseAndTrendText + return template + } else { + return nil + } } - - template?.tintColor = UIColor.tintColor - handler(template) } } diff --git a/WatchApp Extension/Controllers/ChartHUDController.swift b/WatchApp Extension/Controllers/ChartHUDController.swift index 1297a0ecc6..1b86733c00 100644 --- a/WatchApp Extension/Controllers/ChartHUDController.swift +++ b/WatchApp Extension/Controllers/ChartHUDController.swift @@ -187,17 +187,9 @@ final class ChartHUDController: HUDInterfaceController, WKCrownDelegate { } func updateGlucoseChart() { - guard let activeContext = loopManager.activeContext else { - return - } - - scene.predictedGlucose = activeContext.predictedGlucose?.values - scene.correctionRange = loopManager.settings.glucoseTargetRangeSchedule - scene.unit = activeContext.preferredGlucoseUnit - - loopManager.glucoseStore.getCachedGlucoseSamples(start: .earliestGlucoseCutoff) { (samples) in + loopManager.generateChartData { chartData in DispatchQueue.main.async { - self.scene.historicalGlucose = samples + self.scene.data = chartData self.scene.setNeedsUpdate() } } diff --git a/WatchApp Extension/Extensions/CGRect.swift b/WatchApp Extension/Extensions/CGRect.swift new file mode 100644 index 0000000000..56d6a82fba --- /dev/null +++ b/WatchApp Extension/Extensions/CGRect.swift @@ -0,0 +1,23 @@ +// +// CGRect.swift +// WatchApp Extension +// +// Created by Michael Pangburn on 10/17/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import CoreGraphics + + +extension CGRect { + func alignedToScreenScale(_ screenScale: CGFloat) -> CGRect { + let factor = 1 / screenScale + + return CGRect( + x: origin.x.floored(to: factor), + y: origin.y.floored(to: factor), + width: size.width.ceiled(to: factor), + height: size.height.ceiled(to: factor) + ) + } +} diff --git a/WatchApp Extension/Extensions/CLKComplicationTemplate.swift b/WatchApp Extension/Extensions/CLKComplicationTemplate.swift index 1a3e54331f..debd12c2c4 100644 --- a/WatchApp Extension/Extensions/CLKComplicationTemplate.swift +++ b/WatchApp Extension/Extensions/CLKComplicationTemplate.swift @@ -14,15 +14,23 @@ import Foundation extension CLKComplicationTemplate { - static func templateForFamily(_ family: CLKComplicationFamily, from context: WatchContext) -> CLKComplicationTemplate? { + static func templateForFamily(_ family: CLKComplicationFamily, from context: WatchContext, chartGenerator makeChart: () -> UIImage?) -> CLKComplicationTemplate? { guard let glucose = context.glucose, let unit = context.preferredGlucoseUnit else { return nil } - return templateForFamily(family, glucose: glucose, unit: unit, date: context.glucoseDate, trend: context.glucoseTrend, eventualGlucose: context.eventualGlucose) + return templateForFamily(family, glucose: glucose, unit: unit, date: context.glucoseDate, trend: context.glucoseTrend, eventualGlucose: context.eventualGlucose, chartGenerator: makeChart) } - static func templateForFamily(_ family: CLKComplicationFamily, glucose: HKQuantity, unit: HKUnit, date: Date?, trend: GlucoseTrend?, eventualGlucose: HKQuantity?) -> CLKComplicationTemplate? { + static func templateForFamily( + _ family: CLKComplicationFamily, + glucose: HKQuantity, + unit: HKUnit, + date: Date?, + trend: GlucoseTrend?, + eventualGlucose: HKQuantity?, + chartGenerator makeChart: () -> UIImage? + ) -> CLKComplicationTemplate? { let formatter = NumberFormatter.glucoseFormatter(for: unit) @@ -32,7 +40,8 @@ extension CLKComplicationTemplate { return nil } - let glucoseAndTrend = "\(glucoseString)\(trend?.symbol ?? " ")" + let trendString = trend?.symbol ?? " " + let glucoseAndTrend = "\(glucoseString)\(trendString)" var accessibilityStrings = [glucoseString] if let trend = trend { @@ -47,8 +56,6 @@ extension CLKComplicationTemplate { timeFormatter.timeStyle = .short switch family { - case .graphicCorner, .graphicCircular, .graphicRectangular, .graphicBezel: - return nil case .modularSmall: let template = CLKComplicationTemplateModularSmallStackText() template.line1TextProvider = glucoseAndTrendText @@ -71,7 +78,6 @@ extension CLKComplicationTemplate { case .utilitarianSmall, .utilitarianSmallFlat: let template = CLKComplicationTemplateUtilitarianSmallFlat() template.textProvider = CLKSimpleTextProvider(text: glucoseString) - return template case .utilitarianLarge: var eventualGlucoseText = "" @@ -91,6 +97,50 @@ extension CLKComplicationTemplate { ] )) return template + case .graphicCorner: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicCornerStackText() + timeText.tintColor = .tintColor + template.innerTextProvider = timeText + template.outerTextProvider = glucoseAndTrendText + return template + } else { + return nil + } + case .graphicCircular: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicCircularOpenGaugeSimpleText() + template.centerTextProvider = CLKSimpleTextProvider(text: glucoseString) + template.bottomTextProvider = CLKSimpleTextProvider(text: trendString) + template.gaugeProvider = CLKSimpleGaugeProvider(style: .fill, gaugeColor: .tintColor, fillFraction: 1) + return template + } else { + return nil + } + case .graphicBezel: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicBezelCircularText() + guard + let circularTemplate = templateForFamily(.graphicCircular, glucose: glucose, unit: unit, date: date, trend: trend, eventualGlucose: eventualGlucose, chartGenerator: makeChart) as? CLKComplicationTemplateGraphicCircular + else { + fatalError("\(#function) invoked with .graphicCircular must return a subclass of CLKComplicationTemplateGraphicCircular") + } + template.circularTemplate = circularTemplate + template.textProvider = timeText + return template + } else { + return nil + } + case .graphicRectangular: + if #available(watchOSApplicationExtension 5.0, *) { + let template = CLKComplicationTemplateGraphicRectangularLargeImage() + template.imageProvider = CLKFullColorImageProvider(fullColorImage: makeChart() ?? UIImage()) + timeText.tintColor = .tintColor + template.textProvider = CLKTextProvider(byJoining: [glucoseAndTrendText, timeText], separator: " ") + return template + } else { + return nil + } } } } diff --git a/WatchApp Extension/Extensions/CLKTextProvider+Compound.h b/WatchApp Extension/Extensions/CLKTextProvider+Compound.h new file mode 100644 index 0000000000..8da6380afd --- /dev/null +++ b/WatchApp Extension/Extensions/CLKTextProvider+Compound.h @@ -0,0 +1,20 @@ +// +// CLKTextProvider+Compound.h +// Loop +// +// Created by Michael Pangburn on 10/27/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +#ifndef CLKTextProvider_Compound_h +#define CLKTextProvider_Compound_h + +#import + +@interface CLKTextProvider (Compound) + ++ (CLKTextProvider *)textProviderByJoiningTextProviders: (nonnull NSArray *)textProviders separator:(nullable NSString *) separator; + +@end + +#endif /* CLKTextProvider_Compound_h */ diff --git a/WatchApp Extension/Extensions/CLKTextProvider+Compound.m b/WatchApp Extension/Extensions/CLKTextProvider+Compound.m new file mode 100644 index 0000000000..37d147361f --- /dev/null +++ b/WatchApp Extension/Extensions/CLKTextProvider+Compound.m @@ -0,0 +1,33 @@ +// +// CLKTextProvider+Compound.m +// WatchApp Extension +// +// Created by Michael Pangburn on 10/27/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +#import "CLKTextProvider+Compound.h" + +// CLKTextProvider.textProviderWithFormat (compound text provider creation) is unavailable in Swift. +// c.f. https://crunchybagel.com/using-multicolour-clktextprovider-in-swift-in-watchos-5/ +@implementation CLKTextProvider (Compound) + ++ (CLKTextProvider *)textProviderByJoiningTextProviders: (nonnull NSArray *)textProviders separator:(nullable NSString *) separator { + + NSString *formatString = @"%@%@"; + + if (separator.length > 0) { + formatString = [NSString stringWithFormat:@"%@%@%@", @"%@", separator, @"%@"]; + } + + CLKTextProvider *firstItem = textProviders.firstObject; + + for (int index = 1; index < textProviders.count; index++) { + CLKTextProvider *secondItem = [textProviders objectAtIndex: index]; + firstItem = [CLKTextProvider textProviderWithFormat:formatString, firstItem, secondItem]; + } + + return firstItem; +} + +@end diff --git a/WatchApp Extension/Extensions/WatchApp Extension-Bridging-Header.h b/WatchApp Extension/Extensions/WatchApp Extension-Bridging-Header.h new file mode 100644 index 0000000000..35a90b80f3 --- /dev/null +++ b/WatchApp Extension/Extensions/WatchApp Extension-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "CLKTextProvider+Compound.h" diff --git a/WatchApp Extension/Info.plist b/WatchApp Extension/Info.plist index 44c9ce1e78..926303a823 100644 --- a/WatchApp Extension/Info.plist +++ b/WatchApp Extension/Info.plist @@ -26,13 +26,17 @@ $(PRODUCT_MODULE_NAME).ComplicationController CLKComplicationSupportedFamilies - CLKComplicationFamilyModularSmall CLKComplicationFamilyCircularSmall CLKComplicationFamilyExtraLarge - CLKComplicationFamilyUtilitarianSmallFlat - CLKComplicationFamilyUtilitarianLarge + CLKComplicationFamilyGraphicBezel + CLKComplicationFamilyGraphicCircular + CLKComplicationFamilyGraphicCorner + CLKComplicationFamilyGraphicRectangular CLKComplicationFamilyModularLarge + CLKComplicationFamilyModularSmall + CLKComplicationFamilyUtilitarianLarge CLKComplicationFamilyUtilitarianSmall + CLKComplicationFamilyUtilitarianSmallFlat NSExtension diff --git a/WatchApp Extension/Managers/ComplicationChartManager.swift b/WatchApp Extension/Managers/ComplicationChartManager.swift new file mode 100644 index 0000000000..54619f6bb9 --- /dev/null +++ b/WatchApp Extension/Managers/ComplicationChartManager.swift @@ -0,0 +1,130 @@ +// +// ComplicationChartManager.swift +// WatchApp Extension +// +// Created by Michael Pangburn on 10/17/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import Foundation +import UIKit +import HealthKit +import WatchKit + + +private enum ComplicationChartConstants { + static let textInsets = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) + static let glucoseSize = CGSize(width: 1, height: 1) + static let glucoseLabelAttributes: [NSAttributedString.Key: Any] = [ + .font: UIFont(name: "HelveticaNeue", size: 5)!, + .foregroundColor: UIColor.chartLabel + ] +} + +private enum GlucoseLabelPosition { + case high + case low +} + +final class ComplicationChartManager { + var data: GlucoseChartData? + var lastRenderDate: Date? + var renderedChartImage: UIImage? + var visibleInterval: TimeInterval = .hours(4) + + private var unit: HKUnit { + return data?.unit ?? .milligramsPerDeciliter + } + + func renderChartImage(size: CGSize) -> UIImage? { + UIGraphicsBeginImageContextWithOptions(size, false, 0.0) + defer { UIGraphicsEndImageContext() } + + let context = UIGraphicsGetCurrentContext()! + drawChart(in: context, size: size) + let image = context.makeImage().map(UIImage.init(cgImage:)) + renderedChartImage = image + return image + } + + private func drawChart(in context: CGContext, size: CGSize) { + guard let data = data else { + // TODO: handle empty data case + return + } + + let now = Date() + lastRenderDate = now + let spannedInterval = DateInterval(start: now - visibleInterval / 2, duration: visibleInterval) + let glucoseRange = data.chartableGlucoseRange(from: spannedInterval) + let scaler = GlucoseChartScaler(size: size, dateInterval: spannedInterval, glucoseRange: glucoseRange, unit: unit) + + let drawingSteps = [drawTargetRange, drawOverridesIfNeeded, drawHistoricalGlucose, drawPredictedGlucose, drawGlucoseLabels] + drawingSteps.forEach { drawIn in drawIn(context, scaler) } + } + + private func drawGlucoseLabels(in context: CGContext, using scaler: GlucoseChartScaler) { + let formatter = NumberFormatter.glucoseFormatter(for: unit) + drawGlucoseLabelText(formatter.string(from: scaler.glucoseMax)!, position: .high, scaler: scaler) + drawGlucoseLabelText(formatter.string(from: scaler.glucoseMin)!, position: .low, scaler: scaler) + } + + private func drawGlucoseLabelText(_ text: String, position: GlucoseLabelPosition, scaler: GlucoseChartScaler) { + let attributedText = NSAttributedString(string: text, attributes: ComplicationChartConstants.glucoseLabelAttributes) + let size = attributedText.size() + let x = scaler.xCoordinate(for: scaler.dates.end) - size.width - ComplicationChartConstants.textInsets.right + let y: CGFloat = { + switch position { + case .high: + return scaler.yCoordinate(for: scaler.glucoseMax) + ComplicationChartConstants.textInsets.top + case .low: + return scaler.yCoordinate(for: scaler.glucoseMin) - size.height - ComplicationChartConstants.textInsets.bottom + } + }() + let rect = CGRect(origin: CGPoint(x: x, y: y), size: size).alignedToScreenScale(WKInterfaceDevice.current().screenScale) + attributedText.draw(with: rect, options: .usesLineFragmentOrigin, context: nil) + } + + private func drawTargetRange(in context: CGContext, using scaler: GlucoseChartScaler) { + let activeOverride = data?.correctionRange?.activeOverride + let targetRangeAlpha: CGFloat = activeOverride != nil ? 0.2 : 0.3 + context.setFillColor(UIColor.glucose.withAlphaComponent(targetRangeAlpha).cgColor) + data?.correctionRange?.quantityBetween(start: scaler.dates.start, end: scaler.dates.end).forEach { range in + let rangeRect = scaler.rect(for: range, unit: unit) + context.fill(rangeRect) + } + } + + private func drawOverridesIfNeeded(in context: CGContext, using scaler: GlucoseChartScaler) { + guard let override = data?.correctionRange?.activeOverride else { + return + } + context.setFillColor(UIColor.glucose.withAlphaComponent(0.4).cgColor) + let overrideRect = scaler.rect(for: override, unit: unit) + context.fill(overrideRect) + } + + private func drawHistoricalGlucose(in context: CGContext, using scaler: GlucoseChartScaler) { + context.setFillColor(UIColor.glucose.cgColor) + data?.historicalGlucose?.lazy + .filter { scaler.dates.contains($0.startDate) } + .forEach { glucose in + let origin = scaler.point(for: glucose, unit: unit) + let glucoseRect = CGRect(origin: origin, size: ComplicationChartConstants.glucoseSize).alignedToScreenScale(WKInterfaceDevice.current().screenScale) + context.fill(glucoseRect) + } + } + + private func drawPredictedGlucose(in context: CGContext, using scaler: GlucoseChartScaler) { + guard let predictedGlucose = data?.predictedGlucose, predictedGlucose.count > 2 else { + return + } + let predictedPath = CGMutablePath() + let glucosePoints = predictedGlucose.map { scaler.point(for: $0, unit: unit) } + predictedPath.addLines(between: glucosePoints) + let dashedPath = predictedPath.copy(dashingWithPhase: 6.5, lengths: [2.5, 1.5]) + context.setStrokeColor(UIColor.white.cgColor) + context.addPath(dashedPath) + context.strokePath() + } +} diff --git a/WatchApp Extension/Managers/LoopDataManager.swift b/WatchApp Extension/Managers/LoopDataManager.swift index 7f2b5f9e70..4191ced26f 100644 --- a/WatchApp Extension/Managers/LoopDataManager.swift +++ b/WatchApp Extension/Managers/LoopDataManager.swift @@ -124,3 +124,22 @@ extension LoopDataManager { return true } } + +extension LoopDataManager { + func generateChartData(completion: @escaping (GlucoseChartData?) -> Void) { + guard let activeContext = activeContext else { + completion(nil) + return + } + + glucoseStore.getCachedGlucoseSamples(start: .earliestGlucoseCutoff) { samples in + let chartData = GlucoseChartData( + unit: activeContext.preferredGlucoseUnit, + correctionRange: self.settings.glucoseTargetRangeSchedule, + historicalGlucose: samples, + predictedGlucose: activeContext.predictedGlucose?.values + ) + completion(chartData) + } + } +} diff --git a/WatchApp Extension/Models/GlucoseChartData.swift b/WatchApp Extension/Models/GlucoseChartData.swift new file mode 100644 index 0000000000..6bf47c3670 --- /dev/null +++ b/WatchApp Extension/Models/GlucoseChartData.swift @@ -0,0 +1,101 @@ +// +// GlucoseChartData.swift +// WatchApp Extension +// +// Created by Michael Pangburn on 10/17/18. +// Copyright © 2018 LoopKit Authors. All rights reserved. +// + +import Foundation +import HealthKit +import LoopKit + + +struct GlucoseChartData { + var unit: HKUnit? + + var correctionRange: GlucoseRangeSchedule? + + var historicalGlucose: [SampleValue]? { + didSet { + historicalGlucoseRange = historicalGlucose?.quantityRange + } + } + + private(set) var historicalGlucoseRange: Range? + + var predictedGlucose: [SampleValue]? { + didSet { + predictedGlucoseRange = predictedGlucose?.quantityRange + } + } + + private(set) var predictedGlucoseRange: Range? + + init(unit: HKUnit?, correctionRange: GlucoseRangeSchedule?, historicalGlucose: [SampleValue]?, predictedGlucose: [SampleValue]?) { + self.unit = unit + self.correctionRange = correctionRange + self.historicalGlucose = historicalGlucose + self.historicalGlucoseRange = historicalGlucose?.quantityRange + self.predictedGlucose = predictedGlucose + self.predictedGlucoseRange = predictedGlucose?.quantityRange + } + + func chartableGlucoseRange(from interval: DateInterval) -> Range { + let unit = self.unit ?? .milligramsPerDeciliter + + // Defaults + var min = unit.lowWatermark + var max = unit.highWatermark + + for correction in correctionRange?.quantityBetween(start: interval.start, end: interval.end) ?? [] { + min = Swift.min(min, correction.value.lowerBound.doubleValue(for: unit)) + max = Swift.max(max, correction.value.upperBound.doubleValue(for: unit)) + } + + if let override = correctionRange?.activeOverrideQuantityRange { + min = Swift.min(min, override.lowerBound.doubleValue(for: unit)) + max = Swift.max(max, override.upperBound.doubleValue(for: unit)) + } + + if let historicalGlucoseRange = historicalGlucoseRange { + min = Swift.min(min, historicalGlucoseRange.lowerBound.doubleValue(for: unit)) + max = Swift.max(max, historicalGlucoseRange.upperBound.doubleValue(for: unit)) + } + + if let predictedGlucoseRange = predictedGlucoseRange { + min = Swift.min(min, predictedGlucoseRange.lowerBound.doubleValue(for: unit)) + max = Swift.max(max, predictedGlucoseRange.upperBound.doubleValue(for: unit)) + } + + min = min.floored(to: unit.axisIncrement) + max = max.ceiled(to: unit.axisIncrement) + + let lowerBound = HKQuantity(unit: unit, doubleValue: min) + let upperBound = HKQuantity(unit: unit, doubleValue: max) + + return lowerBound.. CGFloat { + return CGFloat(date.timeIntervalSince(dates.start)) * xScale + } + + func yCoordinate(for glucose: Double) -> CGFloat { + switch coordinateSystem { + case .standard: + return CGFloat(glucoseMax - glucose) * yScale + case .inverted: + return CGFloat(glucose - glucoseMin) * yScale + } + } + + func point(_ date: Date, _ glucose: Double) -> CGPoint { + return CGPoint(x: xCoordinate(for: date), y: yCoordinate(for: glucose)) + } + + func point(for glucose: SampleValue, unit: HKUnit) -> CGPoint { + return point(glucose.startDate, glucose.quantity.doubleValue(for: unit)) + } + + // By default enforce a minimum height so that the range is visible + func rect( + for range: GlucoseChartValueHashable, + unit: HKUnit, + minHeight: CGFloat = 2, + alignedToScreenScale screenScale: CGFloat = WKInterfaceDevice.current().screenScale + ) -> CGRect { + let minY: Double + let maxY: Double + + if unit != .milligramsPerDeciliter { + minY = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: range.min).doubleValue(for: unit) + maxY = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: range.max).doubleValue(for: unit) + } else { + minY = range.min + maxY = range.max + } + + let bottomLeft = point(max(dates.start, range.start), minY) + let topRight = point(min(dates.end, range.end), maxY) + let size = CGSize(width: topRight.x - bottomLeft.x, height: max(topRight.y - bottomLeft.y, minHeight)) + return CGRect(origin: bottomLeft, size: size).alignedToScreenScale(screenScale) + } +} + +extension GlucoseChartScaler { + init(size: CGSize, dateInterval: DateInterval, glucoseRange: Range, unit: HKUnit, coordinateSystem: CoordinateSystem = .standard) { + self.dates = dateInterval + self.glucoseMin = glucoseRange.lowerBound.doubleValue(for: unit) + self.glucoseMax = glucoseRange.upperBound.doubleValue(for: unit) + self.xScale = size.width / CGFloat(dateInterval.duration) + self.yScale = size.height / CGFloat(glucoseRange.span(with: unit)) + self.coordinateSystem = coordinateSystem + } +} + +extension Range where Bound == HKQuantity { + func span(with unit: HKUnit) -> Double { + return upperBound.doubleValue(for: unit) - lowerBound.doubleValue(for: unit) + } +} diff --git a/WatchApp Extension/Scenes/GlucoseChartScene.swift b/WatchApp Extension/Scenes/GlucoseChartScene.swift index b5a11687ee..32eb582763 100644 --- a/WatchApp Extension/Scenes/GlucoseChartScene.swift +++ b/WatchApp Extension/Scenes/GlucoseChartScene.swift @@ -55,138 +55,27 @@ private extension SKSpriteNode { } } -extension CGRect { - fileprivate func alignedToScreenScale(_ screenScale: CGFloat) -> CGRect { - let factor = 1 / screenScale - - return CGRect( - x: origin.x.floored(to: factor), - y: origin.y.floored(to: factor), - width: size.width.ceiled(to: factor), - height: size.height.ceiled(to: factor) - ) - } -} - -private struct Scaler { - let dates: DateInterval - let glucoseMin: Double - let xScale: CGFloat - let yScale: CGFloat - - func point(_ x: Date, _ y: Double) -> CGPoint { - return CGPoint(x: CGFloat(x.timeIntervalSince(dates.start)) * xScale, y: CGFloat(y - glucoseMin) * yScale) - } - - // By default enforce a minimum height so that the range is visible - func rect(for range: GlucoseChartValueHashable, unit: HKUnit, minHeight: CGFloat = 2) -> CGRect { - let minY: Double - let maxY: Double - - if unit != .milligramsPerDeciliter { - minY = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: range.min).doubleValue(for: unit) - maxY = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: range.max).doubleValue(for: unit) - } else { - minY = range.min - maxY = range.max - } - - let a = point(max(dates.start, range.start), minY) - let b = point(min(dates.end, range.end), maxY) - let size = CGSize(width: b.x - a.x, height: max(b.y - a.y, minHeight)) - return CGRect(origin: CGPoint(x: a.x + size.width / 2, y: a.y + size.height / 2), size: size).alignedToScreenScale(WKInterfaceDevice.current().screenScale) - } -} - -private extension HKUnit { - var axisIncrement: Double { - return chartableIncrement * 25 - } - - var highWatermark: Double { - if self == .milligramsPerDeciliter { - return 150 - } else { - return 8 - } - } - - var lowWatermark: Double { - if self == .milligramsPerDeciliter { - return 50.0 - } else { - return 3.0 - } - } -} - class GlucoseChartScene: SKScene { let log = OSLog(category: "GlucoseChartScene") var textInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) - var unit: HKUnit? - var correctionRange: GlucoseRangeSchedule? - var historicalGlucose: [SampleValue]? { + var data: GlucoseChartData? { didSet { - historicalGlucoseRange = historicalGlucose?.quantityRange - } - } - private(set) var historicalGlucoseRange: Range? - var predictedGlucose: [SampleValue]? { - didSet { - predictedGlucoseRange = predictedGlucose?.quantityRange - - if let firstNewValue = predictedGlucose?.first { - if oldValue?.first == nil || oldValue?.first!.startDate != firstNewValue.startDate { + if let firstNewValue = data?.predictedGlucose?.first { + if oldValue?.predictedGlucose?.first == nil || oldValue?.predictedGlucose?.first!.startDate != firstNewValue.startDate { shouldAnimatePredictionPath = true } } } } - private(set) var predictedGlucoseRange: Range? - - private func chartableGlucoseRange(from start: Date, to end: Date) -> Range { - let unit = self.unit ?? .milligramsPerDeciliter - - // Defaults - var min = unit.lowWatermark - var max = unit.highWatermark - - for correction in correctionRange?.quantityBetween(start: start, end: end) ?? [] { - min = Swift.min(min, correction.value.lowerBound.doubleValue(for: unit)) - max = Swift.max(max, correction.value.upperBound.doubleValue(for: unit)) - } - - if let override = correctionRange?.activeOverrideQuantityRange { - min = Swift.min(min, override.lowerBound.doubleValue(for: unit)) - max = Swift.max(max, override.upperBound.doubleValue(for: unit)) - } - - if let historicalGlucoseRange = historicalGlucoseRange { - min = Swift.min(min, historicalGlucoseRange.lowerBound.doubleValue(for: unit)) - max = Swift.max(max, historicalGlucoseRange.upperBound.doubleValue(for: unit)) - } - - if let predictedGlucoseRange = predictedGlucoseRange { - min = Swift.min(min, predictedGlucoseRange.lowerBound.doubleValue(for: unit)) - max = Swift.max(max, predictedGlucoseRange.upperBound.doubleValue(for: unit)) - } - - min = min.floored(to: unit.axisIncrement) - max = max.ceiled(to: unit.axisIncrement) - - let lowerBound = HKQuantity(unit: unit, doubleValue: min) - let upperBound = HKQuantity(unit: unit, doubleValue: max) - - return lowerBound.. (sprite: SKSpriteNode, created: Bool) { - var created = false - if nodes[hashValue] == nil { - nodes[hashValue] = SKSpriteNode(color: .clear, size: CGSize(width: 0, height: 0)) - addChild(nodes[hashValue]!) - created = true + if let existingNode = nodes[hashValue] { + return (sprite: existingNode, created: false) + } else { + let newNode = SKSpriteNode(color: .clear, size: CGSize(width: 0, height: 0)) + newNode.anchorPoint = CGPoint(x: 0, y: 0) + nodes[hashValue] = newNode + addChild(newNode) + return (sprite: newNode, created: true) } - return (sprite: nodes[hashValue]!, created: created) } func setNeedsUpdate() { @@ -307,38 +189,31 @@ class GlucoseChartScene: SKScene { } private func performUpdate(animated: Bool) { - guard let unit = unit else { + guard let data = data, let unit = data.unit else { return } - let window = visibleDuration / 2 - let start = Date(timeIntervalSinceNow: -window) - let end = start.addingTimeInterval(visibleDuration) - let yRange = chartableGlucoseRange(from: start, to: end) - let scaler = Scaler( - dates: DateInterval(start: start, end: end), - glucoseMin: yRange.lowerBound.doubleValue(for: unit), - xScale: size.width / CGFloat(window * 2), - yScale: size.height / CGFloat(yRange.upperBound.doubleValue(for: unit) - yRange.lowerBound.doubleValue(for: unit)) - ) + let spannedInterval = DateInterval(start: Date() - visibleDuration / 2, duration: visibleDuration) + let glucoseRange = data.chartableGlucoseRange(from: spannedInterval) + let scaler = GlucoseChartScaler(size: size, dateInterval: spannedInterval, glucoseRange: glucoseRange, unit: unit, coordinateSystem: .inverted) let numberFormatter = NumberFormatter.glucoseFormatter(for: unit) - minBGLabel.text = numberFormatter.string(from: yRange.lowerBound.doubleValue(for: unit)) - maxBGLabel.text = numberFormatter.string(from: yRange.upperBound.doubleValue(for: unit)) + minBGLabel.text = numberFormatter.string(from: glucoseRange.lowerBound.doubleValue(for: unit)) + maxBGLabel.text = numberFormatter.string(from: glucoseRange.upperBound.doubleValue(for: unit)) hoursLabel.text = dateFormatter.string(from: visibleDuration) // Keep track of the nodes we started this pass with so we can expire obsolete nodes at the end var inactiveNodes = nodes - let activeOverride = correctionRange?.activeOverride + let activeOverride = data.correctionRange?.activeOverride - correctionRange?.quantityBetween(start: start, end: end).forEach({ (range) in + data.correctionRange?.quantityBetween(start: spannedInterval.start, end: spannedInterval.end).forEach { range in let (sprite, created) = getSprite(forHash: range.chartHashValue) sprite.color = UIColor.glucose.withAlphaComponent(activeOverride != nil ? 0.2 : 0.3) sprite.zPosition = NodePlane.ranges.zPosition sprite.move(to: scaler.rect(for: range, unit: unit), animated: !created) inactiveNodes.removeValue(forKey: range.chartHashValue) - }) + } // Make temporary overrides visually match what we do in the Loop app. This means that we have // one darker box which represents the duration of the override, but we have a second lighter box which @@ -350,8 +225,8 @@ class GlucoseChartScene: SKScene { sprite1.move(to: scaler.rect(for: range, unit: unit), animated: !created) inactiveNodes.removeValue(forKey: range.chartHashValue) - if range.end < end { - let extendedRange = GlucoseRangeSchedule.Override(context: range.context, start: range.start, end: end, value: range.value) + if range.end < spannedInterval.end { + let extendedRange = GlucoseRangeSchedule.Override(context: range.context, start: range.start, end: spannedInterval.end, value: range.value) let (sprite2, created) = getSprite(forHash: extendedRange.chartHashValue) sprite2.color = UIColor.glucose.withAlphaComponent(0.25) sprite2.zPosition = NodePlane.overrideRanges.zPosition @@ -360,9 +235,10 @@ class GlucoseChartScene: SKScene { } } - historicalGlucose?.filter { scaler.dates.contains($0.startDate) }.forEach { - let origin = scaler.point($0.startDate, $0.quantity.doubleValue(for: unit)) + data.historicalGlucose?.filter { scaler.dates.contains($0.startDate) }.forEach { + let center = scaler.point($0.startDate, $0.quantity.doubleValue(for: unit)) let size = CGSize(width: 2, height: 2) + let origin = CGPoint(x: center.x - size.width / 2, y: center.y - size.height / 2) let (sprite, created) = getSprite(forHash: $0.chartHashValue) sprite.color = .glucose sprite.zPosition = NodePlane.values.zPosition @@ -371,7 +247,7 @@ class GlucoseChartScene: SKScene { } predictedPathNode?.removeFromParent() - if let predictedGlucose = predictedGlucose, predictedGlucose.count > 2 { + if let predictedGlucose = data.predictedGlucose, predictedGlucose.count > 2 { let predictedPath = CGMutablePath() predictedPath.addLines(between: predictedGlucose.map { scaler.point($0.startDate, $0.quantity.doubleValue(for: unit)) diff --git a/WatchApp Extension/de.lproj/ckcomplication.strings b/WatchApp Extension/de.lproj/ckcomplication.strings index 57e3b0a8e6..6839fc3047 100644 --- a/WatchApp Extension/de.lproj/ckcomplication.strings +++ b/WatchApp Extension/de.lproj/ckcomplication.strings @@ -1,6 +1,3 @@ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/fr.lproj/ckcomplication.strings b/WatchApp Extension/fr.lproj/ckcomplication.strings index ba82abd915..346c8f6ec3 100644 --- a/WatchApp Extension/fr.lproj/ckcomplication.strings +++ b/WatchApp Extension/fr.lproj/ckcomplication.strings @@ -6,9 +6,6 @@ Copyright © 2016 Nathan Racklyeft. All rights reserved. */ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/it.lproj/ckcomplication.strings b/WatchApp Extension/it.lproj/ckcomplication.strings index 57e3b0a8e6..6839fc3047 100644 --- a/WatchApp Extension/it.lproj/ckcomplication.strings +++ b/WatchApp Extension/it.lproj/ckcomplication.strings @@ -1,6 +1,3 @@ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/nb.lproj/ckcomplication.strings b/WatchApp Extension/nb.lproj/ckcomplication.strings index f05b483c67..a859782678 100644 --- a/WatchApp Extension/nb.lproj/ckcomplication.strings +++ b/WatchApp Extension/nb.lproj/ckcomplication.strings @@ -6,8 +6,5 @@ Copyright © 2016 Nathan Racklyeft. All rights reserved. */ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/nl.lproj/ckcomplication.strings b/WatchApp Extension/nl.lproj/ckcomplication.strings index f05b483c67..a859782678 100644 --- a/WatchApp Extension/nl.lproj/ckcomplication.strings +++ b/WatchApp Extension/nl.lproj/ckcomplication.strings @@ -6,8 +6,5 @@ Copyright © 2016 Nathan Racklyeft. All rights reserved. */ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/pl.lproj/ckcomplication.strings b/WatchApp Extension/pl.lproj/ckcomplication.strings index f05b483c67..a859782678 100644 --- a/WatchApp Extension/pl.lproj/ckcomplication.strings +++ b/WatchApp Extension/pl.lproj/ckcomplication.strings @@ -6,8 +6,5 @@ Copyright © 2016 Nathan Racklyeft. All rights reserved. */ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp Extension/zh-Hans.lproj/ckcomplication.strings b/WatchApp Extension/zh-Hans.lproj/ckcomplication.strings index 57e3b0a8e6..6839fc3047 100644 --- a/WatchApp Extension/zh-Hans.lproj/ckcomplication.strings +++ b/WatchApp Extension/zh-Hans.lproj/ckcomplication.strings @@ -1,6 +1,3 @@ -/* The complication template example unit string */ -"120↘︎" = "120↘︎"; - /* Utilitarian large flat format string (1: Glucose & Trend symbol) (2: Eventual Glucose) (3: Time) */ "UtilitarianLargeFlat" = "%@%@ %@"; diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Home Screen.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Home Screen.png deleted file mode 100644 index b9b45b2865..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Home Screen.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Notification.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Notification.png deleted file mode 100644 index 5027b37e16..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Notification.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Short Look.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Short Look.png deleted file mode 100644 index 042d05fdc2..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/38mm Short Look.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Notification.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Notification.png deleted file mode 100644 index 651a4530db..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Notification.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Short Look.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Short Look.png deleted file mode 100644 index 9b7cd90921..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/42mm Short Look.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json index 736d59705c..81ddce690d 100644 --- a/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/WatchApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -3,7 +3,7 @@ { "size" : "24x24", "idiom" : "watch", - "filename" : "38mm Notification.png", + "filename" : "Icon-AppleWatch-24x24@2x.png", "scale" : "2x", "role" : "notificationCenter", "subtype" : "38mm" @@ -11,7 +11,7 @@ { "size" : "27.5x27.5", "idiom" : "watch", - "filename" : "42mm Notification.png", + "filename" : "Icon-AppleWatch-27.5x27.5@2x.png", "scale" : "2x", "role" : "notificationCenter", "subtype" : "42mm" @@ -19,21 +19,21 @@ { "size" : "29x29", "idiom" : "watch", - "filename" : "Icon-Small@2x.png", + "filename" : "Icon-AppleWatch-Companion-29x29@2x.png", "role" : "companionSettings", "scale" : "2x" }, { "size" : "29x29", "idiom" : "watch", - "filename" : "Icon-Small@3x.png", + "filename" : "Icon-AppleWatch-Companion-29x29@3x.png", "role" : "companionSettings", "scale" : "3x" }, { "size" : "40x40", "idiom" : "watch", - "filename" : "38mm Home Screen.png", + "filename" : "Icon-AppleWatch-40x40@2x.png", "scale" : "2x", "role" : "appLauncher", "subtype" : "38mm" @@ -41,6 +41,7 @@ { "size" : "44x44", "idiom" : "watch", + "filename" : "Icon-AppleWatch-44x44@2x.png", "scale" : "2x", "role" : "appLauncher", "subtype" : "40mm" @@ -48,6 +49,7 @@ { "size" : "50x50", "idiom" : "watch", + "filename" : "Icon-AppleWatch-100x100@2x.png", "scale" : "2x", "role" : "appLauncher", "subtype" : "44mm" @@ -55,7 +57,7 @@ { "size" : "86x86", "idiom" : "watch", - "filename" : "38mm Short Look.png", + "filename" : "Icon-AppleWatch-86x86@2x.png", "scale" : "2x", "role" : "quickLook", "subtype" : "38mm" @@ -63,7 +65,7 @@ { "size" : "98x98", "idiom" : "watch", - "filename" : "42mm Short Look.png", + "filename" : "Icon-AppleWatch-98x98@2x.png", "scale" : "2x", "role" : "quickLook", "subtype" : "42mm" @@ -71,6 +73,7 @@ { "size" : "108x108", "idiom" : "watch", + "filename" : "Icon-AppleWatch-216x216@2x.png", "scale" : "2x", "role" : "quickLook", "subtype" : "44mm" diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-100x100@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-100x100@2x.png new file mode 100644 index 0000000000..d243b294c8 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-100x100@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-216x216@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-216x216@2x.png new file mode 100644 index 0000000000..38e0d0e733 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-216x216@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-24x24@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-24x24@2x.png new file mode 100644 index 0000000000..82bdb41f42 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-24x24@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-27.5x27.5@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-27.5x27.5@2x.png new file mode 100644 index 0000000000..27d3087b55 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-27.5x27.5@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-40x40@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-40x40@2x.png new file mode 100644 index 0000000000..d9782e6983 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-40x40@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-44x44@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-44x44@2x.png new file mode 100644 index 0000000000..370b790d0e Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-44x44@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-86x86@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-86x86@2x.png new file mode 100644 index 0000000000..e98a9bbaf9 Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-86x86@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-98x98@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-98x98@2x.png new file mode 100644 index 0000000000..fc5e01e12e Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-98x98@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@2x.png new file mode 100644 index 0000000000..7df2e309fc Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@2x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@3x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@3x.png new file mode 100644 index 0000000000..77b33293cb Binary files /dev/null and b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-AppleWatch-Companion-29x29@3x.png differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png deleted file mode 100644 index 02e28324c5..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png b/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png deleted file mode 100644 index 3659954b6e..0000000000 Binary files a/WatchApp/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.pdf b/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.pdf new file mode 100644 index 0000000000..9b1f69cc2d Binary files /dev/null and b/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.pdf differ diff --git a/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.png b/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.png deleted file mode 100644 index 5228f51731..0000000000 Binary files a/WatchApp/Assets.xcassets/bolus.imageset/Bolus Icon 42mm.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/bolus.imageset/Contents.json b/WatchApp/Assets.xcassets/bolus.imageset/Contents.json index c2810020f3..e2504681a7 100644 --- a/WatchApp/Assets.xcassets/bolus.imageset/Contents.json +++ b/WatchApp/Assets.xcassets/bolus.imageset/Contents.json @@ -1,5 +1,29 @@ { "images" : [ + { + "idiom" : "watch", + "filename" : "Bolus Icon 42mm.pdf" + }, + { + "idiom" : "watch", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "screen-width" : ">183" + }, + { + "idiom" : "watch", + "scale" : "2x" + }, { "idiom" : "watch", "filename" : "Bolus icon 38mm.png", @@ -13,9 +37,8 @@ }, { "idiom" : "watch", - "filename" : "Bolus Icon 42mm.png", - "screen-width" : ">145", - "scale" : "2x" + "scale" : "2x", + "screen-width" : ">145" }, { "idiom" : "watch", @@ -28,6 +51,7 @@ "author" : "xcode" }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "template", + "auto-scaling" : "auto" } } \ No newline at end of file diff --git a/WatchApp/Assets.xcassets/carbs.imageset/Carb Icon 42mm.pdf b/WatchApp/Assets.xcassets/carbs.imageset/Carb Icon 42mm.pdf new file mode 100644 index 0000000000..a41b291aa7 Binary files /dev/null and b/WatchApp/Assets.xcassets/carbs.imageset/Carb Icon 42mm.pdf differ diff --git a/WatchApp/Assets.xcassets/carbs.imageset/Carbs Icon 42mm.png b/WatchApp/Assets.xcassets/carbs.imageset/Carbs Icon 42mm.png deleted file mode 100644 index f825624552..0000000000 Binary files a/WatchApp/Assets.xcassets/carbs.imageset/Carbs Icon 42mm.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/carbs.imageset/Contents.json b/WatchApp/Assets.xcassets/carbs.imageset/Contents.json index 5e0d2deaa5..2eb4ab27dc 100644 --- a/WatchApp/Assets.xcassets/carbs.imageset/Contents.json +++ b/WatchApp/Assets.xcassets/carbs.imageset/Contents.json @@ -1,5 +1,29 @@ { "images" : [ + { + "idiom" : "watch", + "filename" : "Carb Icon 42mm.pdf" + }, + { + "idiom" : "watch", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "screen-width" : ">183" + }, + { + "idiom" : "watch", + "scale" : "2x" + }, { "idiom" : "watch", "filename" : "Carbs icon 38mm.png", @@ -13,9 +37,8 @@ }, { "idiom" : "watch", - "filename" : "Carbs Icon 42mm.png", - "screen-width" : ">145", - "scale" : "2x" + "scale" : "2x", + "screen-width" : ">145" }, { "idiom" : "watch", @@ -28,6 +51,7 @@ "author" : "xcode" }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "template", + "auto-scaling" : "auto" } } \ No newline at end of file diff --git a/WatchApp/Assets.xcassets/pre-meal.imageset/Contents.json b/WatchApp/Assets.xcassets/pre-meal.imageset/Contents.json index 581fbb49aa..28da17b6b7 100644 --- a/WatchApp/Assets.xcassets/pre-meal.imageset/Contents.json +++ b/WatchApp/Assets.xcassets/pre-meal.imageset/Contents.json @@ -1,5 +1,29 @@ { "images" : [ + { + "idiom" : "watch", + "filename" : "Pre-Meal 42mm.pdf" + }, + { + "idiom" : "watch", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "screen-width" : ">183" + }, + { + "idiom" : "watch", + "scale" : "2x" + }, { "idiom" : "watch", "filename" : "Pre-Meal 38mm.png", @@ -13,9 +37,8 @@ }, { "idiom" : "watch", - "filename" : "Pre-Meal 42mm.png", - "screen-width" : ">145", - "scale" : "2x" + "scale" : "2x", + "screen-width" : ">145" }, { "idiom" : "watch", @@ -28,6 +51,7 @@ "author" : "xcode" }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "template", + "auto-scaling" : "auto" } } \ No newline at end of file diff --git a/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.pdf b/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.pdf new file mode 100644 index 0000000000..b502d5a664 Binary files /dev/null and b/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.pdf differ diff --git a/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.png b/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.png deleted file mode 100644 index f363b068f9..0000000000 Binary files a/WatchApp/Assets.xcassets/pre-meal.imageset/Pre-Meal 42mm.png and /dev/null differ diff --git a/WatchApp/Assets.xcassets/workout.imageset/Contents.json b/WatchApp/Assets.xcassets/workout.imageset/Contents.json index cc9ab23361..1e233ff059 100644 --- a/WatchApp/Assets.xcassets/workout.imageset/Contents.json +++ b/WatchApp/Assets.xcassets/workout.imageset/Contents.json @@ -1,5 +1,29 @@ { "images" : [ + { + "idiom" : "watch", + "filename" : "Workout 42mm.pdf" + }, + { + "idiom" : "watch", + "screen-width" : "<=145" + }, + { + "idiom" : "watch", + "screen-width" : ">161" + }, + { + "idiom" : "watch", + "screen-width" : ">145" + }, + { + "idiom" : "watch", + "screen-width" : ">183" + }, + { + "idiom" : "watch", + "scale" : "2x" + }, { "idiom" : "watch", "filename" : "Workout 38mm.png", @@ -13,9 +37,8 @@ }, { "idiom" : "watch", - "filename" : "Workout 42mm.png", - "screen-width" : ">145", - "scale" : "2x" + "scale" : "2x", + "screen-width" : ">145" }, { "idiom" : "watch", @@ -28,6 +51,7 @@ "author" : "xcode" }, "properties" : { - "template-rendering-intent" : "template" + "template-rendering-intent" : "template", + "auto-scaling" : "auto" } } \ No newline at end of file diff --git a/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.pdf b/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.pdf new file mode 100644 index 0000000000..d8db095e6c Binary files /dev/null and b/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.pdf differ diff --git a/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.png b/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.png deleted file mode 100644 index d43a70eea7..0000000000 Binary files a/WatchApp/Assets.xcassets/workout.imageset/Workout 42mm.png and /dev/null differ diff --git a/WatchApp/Info.plist b/WatchApp/Info.plist index 11079c1573..b9cfe59fb9 100644 --- a/WatchApp/Info.plist +++ b/WatchApp/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.9.2 + 1.9.4 dev CFBundleSignature ???? CFBundleVersion