diff --git a/Cartfile b/Cartfile index 507d127d22..6a4cd16228 100644 --- a/Cartfile +++ b/Cartfile @@ -1,6 +1,6 @@ github "LoopKit/LoopKit" ~> 1.2.0 github "LoopKit/xDripG5" ~> 0.8.0 -github "i-schuetz/SwiftCharts" ~> 0.5.0 +github "bharat/SwiftCharts" "0.5.1-extension-api-safe" github "mddub/dexcom-share-client-swift" ~> 0.2.0 github "mddub/G4ShareSpy" ~> 0.3.1 github "ps2/rileylink_ios" ~> 1.0 diff --git a/Cartfile.resolved b/Cartfile.resolved index 7ba4700e45..9305615236 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,7 +1,7 @@ -github "amplitude/Amplitude-iOS" "v3.14.0" +github "amplitude/Amplitude-iOS" "v3.14.1" github "mddub/G4ShareSpy" "v0.3.1" github "LoopKit/LoopKit" "v1.2.0" -github "i-schuetz/SwiftCharts" "0.5.1" +github "bharat/SwiftCharts" "0.5.1-extension-api-safe" github "mddub/dexcom-share-client-swift" "v0.2.0" github "ps2/rileylink_ios" "v1.0" github "LoopKit/xDripG5" "v0.8.0" diff --git a/Carthage/Build/iOS/SwiftCharts.framework/Headers/SwiftCharts-Swift.h b/Carthage/Build/iOS/SwiftCharts.framework/Headers/SwiftCharts-Swift.h index 040ab82111..76871ca42c 100644 --- a/Carthage/Build/iOS/SwiftCharts.framework/Headers/SwiftCharts-Swift.h +++ b/Carthage/Build/iOS/SwiftCharts.framework/Headers/SwiftCharts-Swift.h @@ -136,6 +136,10 @@ SWIFT_CLASS("_TtC11SwiftCharts9ChartView") @interface ChartView : UIView - (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER; - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +/** + Initialization code shared between all initializers +*/ +- (void)sharedInit; @end @@ -152,15 +156,18 @@ SWIFT_CLASS("_TtC11SwiftCharts13ChartBaseView") SWIFT_CLASS("_TtC11SwiftCharts20ChartCandleStickView") @interface ChartCandleStickView : UIView +@property (nonatomic) BOOL highlighted; - (nonnull instancetype)initWithLineX:(CGFloat)lineX width:(CGFloat)width top:(CGFloat)top bottom:(CGFloat)bottom innerRectTop:(CGFloat)innerRectTop innerRectBottom:(CGFloat)innerRectBottom fillColor:(UIColor * _Nonnull)fillColor strokeColor:(UIColor * _Nonnull)strokeColor strokeWidth:(CGFloat)strokeWidth OBJC_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; - (void)drawRect:(CGRect)rect; - (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE; @end +@class UIBezierPath; SWIFT_CLASS("_TtC11SwiftCharts14ChartLinesView") @interface ChartLinesView : UIView +- (nonnull instancetype)initWithPath:(UIBezierPath * _Nonnull)path frame:(CGRect)frame lineColor:(UIColor * _Nonnull)lineColor lineWidth:(CGFloat)lineWidth animDuration:(float)animDuration animDelay:(float)animDelay dashPattern:(NSArray * _Nullable)dashPattern OBJC_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; - (nonnull instancetype)initWithFrame:(CGRect)frame SWIFT_UNAVAILABLE; @end diff --git a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm.swiftmodule b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm.swiftmodule index 572a60d9b8..fd0c8c2447 100644 Binary files a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm.swiftmodule and b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm.swiftmodule differ diff --git a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm64.swiftmodule b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm64.swiftmodule index b19cde5bc8..ffcba73167 100644 Binary files a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm64.swiftmodule and b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/arm64.swiftmodule differ diff --git a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/i386.swiftmodule b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/i386.swiftmodule index d56730e167..b41302f5c5 100644 Binary files a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/i386.swiftmodule and b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/i386.swiftmodule differ diff --git a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/x86_64.swiftmodule b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/x86_64.swiftmodule index d1c4246351..a734b261b9 100644 Binary files a/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/x86_64.swiftmodule and b/Carthage/Build/iOS/SwiftCharts.framework/Modules/SwiftCharts.swiftmodule/x86_64.swiftmodule differ diff --git a/Carthage/Build/iOS/SwiftCharts.framework/SwiftCharts b/Carthage/Build/iOS/SwiftCharts.framework/SwiftCharts index 6e2f4da09e..cbcd5b4088 100755 Binary files a/Carthage/Build/iOS/SwiftCharts.framework/SwiftCharts and b/Carthage/Build/iOS/SwiftCharts.framework/SwiftCharts differ diff --git a/Loop/Extensions/CGPoint.swift b/Common/Extensions/CGPoint.swift similarity index 100% rename from Loop/Extensions/CGPoint.swift rename to Common/Extensions/CGPoint.swift diff --git a/Loop/Extensions/ChartPoint.swift b/Common/Extensions/ChartPoint.swift similarity index 66% rename from Loop/Extensions/ChartPoint.swift rename to Common/Extensions/ChartPoint.swift index 850274c146..ba3d471bd2 100644 --- a/Loop/Extensions/ChartPoint.swift +++ b/Common/Extensions/ChartPoint.swift @@ -7,16 +7,11 @@ // import Foundation -import LoopKit import SwiftCharts extension ChartPoint { - static func pointsForGlucoseRangeSchedule(_ glucoseRangeSchedule: GlucoseRangeSchedule, xAxisValues: [ChartAxisValue]) -> [ChartPoint] { - let targetRanges = glucoseRangeSchedule.between( - start: ChartAxisValueDate.dateFromScalar(xAxisValues.first!.scalar), - end: ChartAxisValueDate.dateFromScalar(xAxisValues.last!.scalar) - ) + static func pointsForDatedRanges(_ targetRanges: [DatedRangeContext], xAxisValues: [ChartAxisValue]) -> [ChartPoint] { let dateFormatter = DateFormatter() var maxPoints: [ChartPoint] = [] @@ -36,8 +31,8 @@ extension ChartPoint { endDate = ChartAxisValueDate(date: targetRanges[index + 1].startDate, formatter: dateFormatter) } - let minValue = ChartAxisValueDouble(range.value.minValue) - let maxValue = ChartAxisValueDouble(range.value.maxValue) + let minValue = ChartAxisValueDouble(range.minValue) + let maxValue = ChartAxisValueDouble(range.maxValue) maxPoints += [ ChartPoint(x: startDate, y: maxValue), @@ -53,7 +48,7 @@ extension ChartPoint { return maxPoints + minPoints.reversed() } - static func pointsForGlucoseRangeScheduleOverrideDuration(_ override: AbsoluteScheduleValue, xAxisValues: [ChartAxisValue]) -> [ChartPoint] { + static func pointsForDatedRangeOverrideDuration(_ override: DatedRangeContext, xAxisValues: [ChartAxisValue]) -> [ChartPoint] { let startDate = Date() guard override.endDate.timeIntervalSince(startDate) > 0, @@ -65,8 +60,8 @@ extension ChartPoint { let dateFormatter = DateFormatter() let startDateAxisValue = ChartAxisValueDate(date: startDate, formatter: dateFormatter) let endDateAxisValue = ChartAxisValueDate(date: min(lastXAxisValue.date, override.endDate), formatter: dateFormatter) - let minValue = ChartAxisValueDouble(override.value.minValue) - let maxValue = ChartAxisValueDouble(override.value.maxValue) + let minValue = ChartAxisValueDouble(override.minValue) + let maxValue = ChartAxisValueDouble(override.maxValue) return [ ChartPoint(x: startDateAxisValue, y: maxValue), @@ -76,20 +71,20 @@ extension ChartPoint { ] } - static func pointsForGlucoseRangeScheduleOverride(_ override: AbsoluteScheduleValue, xAxisValues: [ChartAxisValue]) -> [ChartPoint] { + static func pointsForDatedRangeOverride(_ override: DatedRangeContext, xAxisValues: [ChartAxisValue]) -> [ChartPoint] { let startDate = Date() guard override.endDate.timeIntervalSince(startDate) > 0, let lastXAxisValue = xAxisValues.last as? ChartAxisValueDate - else { - return [] + else { + return [] } let dateFormatter = DateFormatter() let startDateAxisValue = ChartAxisValueDate(date: startDate, formatter: dateFormatter) let endDateAxisValue = ChartAxisValueDate(date: lastXAxisValue.date, formatter: dateFormatter) - let minValue = ChartAxisValueDouble(override.value.minValue) - let maxValue = ChartAxisValueDouble(override.value.maxValue) + let minValue = ChartAxisValueDouble(override.minValue) + let maxValue = ChartAxisValueDouble(override.maxValue) return [ ChartPoint(x: startDateAxisValue, y: maxValue), @@ -98,16 +93,5 @@ extension ChartPoint { ChartPoint(x: startDateAxisValue, y: minValue) ] } -} - -extension ChartPoint: TimelineValue { - public var startDate: Date { - if let dateValue = x as? ChartAxisValueDate { - return dateValue.date - } else { - return Date.distantPast - } - } } - diff --git a/Loop/Extensions/CollectionType.swift b/Common/Extensions/CollectionType.swift similarity index 75% rename from Loop/Extensions/CollectionType.swift rename to Common/Extensions/CollectionType.swift index 39359a1af4..cb0444941c 100644 --- a/Loop/Extensions/CollectionType.swift +++ b/Common/Extensions/CollectionType.swift @@ -7,7 +7,6 @@ // import Foundation -import LoopKit extension BidirectionalCollection where Index: Strideable, Iterator.Element: Comparable, Index.Stride == Int { @@ -72,24 +71,3 @@ extension BidirectionalCollection where Index: Strideable, Iterator.Element: Str } } - -public extension Sequence where Iterator.Element: TimelineValue { - /// Returns the closest element index in the sorted sequence prior to the specified date - /// - /// - parameter date: The date to use in the search - /// - /// - returns: The closest index, if any exist before the specified date - func closestIndexPriorToDate(_ date: Date) -> Int? { - var closestIndex: Int? - - for (index, value) in self.enumerated() { - if value.startDate <= date { - closestIndex = index - } else { - break - } - } - - return closestIndex - } -} diff --git a/Common/Extensions/HKUnit.swift b/Common/Extensions/HKUnit.swift index a4b7df21f6..b11c11a0dc 100644 --- a/Common/Extensions/HKUnit.swift +++ b/Common/Extensions/HKUnit.swift @@ -20,6 +20,10 @@ extension HKUnit { return 1 } } + + static func milligramsPerDeciliterUnit() -> HKUnit { + return HKUnit.gramUnit(with: .milli).unitDivided(by: HKUnit.literUnit(with: .deci)) + } static func millimolesPerLiterUnit() -> HKUnit { return HKUnit.moleUnit(with: .milli, molarMass: HKUnitMolarMassBloodGlucose).unitDivided(by: HKUnit.liter()) diff --git a/Common/Extensions/UIColor.swift b/Common/Extensions/UIColor.swift index 9087d2d41c..e0ea7248b3 100644 --- a/Common/Extensions/UIColor.swift +++ b/Common/Extensions/UIColor.swift @@ -16,8 +16,6 @@ extension UIColor { @nonobjc static let cellBackgroundColor = UIColor(white: 239 / 255, alpha: 1) - @nonobjc static let gridColor = UIColor(white: 193 / 255, alpha: 1) - @nonobjc static let IOBTintColor = UIColor.HIGOrangeColor() @nonobjc static let COBTintColor = UIColor(red: 99 / 255, green: 218 / 255, blue: 56 / 255, alpha: 1) diff --git a/Loop/Managers/StatusChartManager.swift b/Common/Managers/StatusChartsManager.swift similarity index 95% rename from Loop/Managers/StatusChartManager.swift rename to Common/Managers/StatusChartsManager.swift index b74bf2451f..bb001d6cf8 100644 --- a/Loop/Managers/StatusChartManager.swift +++ b/Common/Managers/StatusChartsManager.swift @@ -9,11 +9,15 @@ import Foundation import HealthKit -// TODO: Remove this dependency -import LoopKit - import SwiftCharts +protocol TargetPointsCalculator { + var glucosePoints: [ChartPoint] { get } + var overridePoints: [ChartPoint] { get } + var overrideDurationPoints: [ChartPoint] { get } + + func calculate(_ xAxisValues: [ChartAxisValue]?) +} final class StatusChartsManager { @@ -44,9 +48,9 @@ final class StatusChartsManager { return numberFormatter } - private lazy var axisLineColor = UIColor.clear + private lazy var axisLineColor = UIColor.axisLineColor - private lazy var axisLabelSettings: ChartLabelSettings = ChartLabelSettings(font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.caption1), fontColor: UIColor.secondaryLabelColor) + private lazy var axisLabelSettings: ChartLabelSettings = ChartLabelSettings(font: UIFont.preferredFont(forTextStyle: UIFontTextStyle.caption1), fontColor: UIColor.axisLabelColor) private lazy var guideLinesLayerSettings: ChartGuideLinesLayerSettings = ChartGuideLinesLayerSettings(linesColor: UIColor.gridColor) @@ -117,12 +121,6 @@ final class StatusChartsManager { } } - var glucoseTargetRangeSchedule: GlucoseRangeSchedule? { - didSet { - targetGlucosePoints = [] - } - } - var glucoseDisplayRange: (min: HKQuantity, max: HKQuantity)? { didSet { if let range = glucoseDisplayRange { @@ -168,6 +166,12 @@ final class StatusChartsManager { /// The chart points for alternate predicted glucose var alternatePredictedGlucosePoints: [ChartPoint]? + var targetPointsCalculator: TargetPointsCalculator? { + didSet { + targetGlucosePoints = [] + } + } + private var targetGlucosePoints: [ChartPoint] = [] { didSet { glucoseChart = nil @@ -238,7 +242,7 @@ final class StatusChartsManager { } } - private var xAxisValues: [ChartAxisValue]? { + internal var xAxisValues: [ChartAxisValue]? { didSet { if let xAxisValues = xAxisValues, xAxisValues.count > 1 { xAxisModel = ChartAxisModel(axisValues: xAxisValues, lineColor: axisLineColor) @@ -636,7 +640,7 @@ final class StatusChartsManager { return Chart(frame: frame, layers: layers.flatMap { $0 }) } - private func generateXAxisValues() { + internal func generateXAxisValues() { let timeFormatter = DateFormatter() timeFormatter.dateFormat = "h a" @@ -676,25 +680,16 @@ final class StatusChartsManager { generateXAxisValues() } - if let xAxisValues = xAxisValues, xAxisValues.count > 1, - targetGlucosePoints.count == 0, - let targets = glucoseTargetRangeSchedule - { - targetGlucosePoints = ChartPoint.pointsForGlucoseRangeSchedule(targets, xAxisValues: xAxisValues) - - if let override = targets.temporaryOverride { - targetOverridePoints = ChartPoint.pointsForGlucoseRangeScheduleOverride(override, xAxisValues: xAxisValues) - - targetOverrideDurationPoints = ChartPoint.pointsForGlucoseRangeScheduleOverrideDuration(override, xAxisValues: xAxisValues) - } else { - targetOverridePoints = [] - targetOverrideDurationPoints = [] - } + if let calculator = targetPointsCalculator, + targetGlucosePoints.count == 0 { + calculator.calculate(xAxisValues) + targetGlucosePoints = calculator.glucosePoints + targetOverridePoints = calculator.overridePoints + targetOverrideDurationPoints = calculator.overrideDurationPoints } } } - private extension HKUnit { var glucoseUnitYAxisSegmentSize: Double { if self == HKUnit.milligramsPerDeciliterUnit() { diff --git a/Loop/Models/ChartAxisValueDoubleLog.swift b/Common/Models/ChartAxisValueDoubleLog.swift similarity index 100% rename from Loop/Models/ChartAxisValueDoubleLog.swift rename to Common/Models/ChartAxisValueDoubleLog.swift diff --git a/Loop/Models/ChartAxisValueDoubleUnit.swift b/Common/Models/ChartAxisValueDoubleUnit.swift similarity index 100% rename from Loop/Models/ChartAxisValueDoubleUnit.swift rename to Common/Models/ChartAxisValueDoubleUnit.swift diff --git a/Common/Models/StatusExtensionContext.swift b/Common/Models/StatusExtensionContext.swift index 526517ae82..0e3c476db7 100644 --- a/Common/Models/StatusExtensionContext.swift +++ b/Common/Models/StatusExtensionContext.swift @@ -39,13 +39,34 @@ struct GlucoseContext { let value: Double let unit: HKUnit let startDate: Date - let sensor: SensorDisplayableContext? var quantity: HKQuantity { return HKQuantity(unit: unit, doubleValue: value) } } +struct PredictedGlucoseContext { + let values: [Double] + let unit: HKUnit + let startDate: Date + let interval: TimeInterval + + var samples: [GlucoseContext] { + var result: [GlucoseContext] = [] + for (i, v) in values.enumerated() { + result.append(GlucoseContext(value: v, unit: unit, startDate: startDate.addingTimeInterval(Double(i) * interval))) + } + return result + } +} + +struct DatedRangeContext { + let startDate: Date + let endDate: Date + let minValue: Double + let maxValue: Double +} + extension ReservoirContext: RawRepresentable { typealias RawValue = [String: Any] @@ -166,14 +187,11 @@ extension GlucoseContext: RawRepresentable { typealias RawValue = [String: Any] var rawValue: RawValue { - var raw: RawValue = [ + return [ "value": value, "unit": unit.unitString, "startDate": startDate ] - raw["sensor"] = sensor?.rawValue - - return raw } init?(rawValue: RawValue) { @@ -188,25 +206,80 @@ extension GlucoseContext: RawRepresentable { self.value = value self.unit = HKUnit(from: unitString) self.startDate = startDate + } +} - if let rawValue = rawValue["sensor"] as? SensorDisplayableContext.RawValue { - self.sensor = SensorDisplayableContext(rawValue: rawValue) - } else { - self.sensor = nil +extension PredictedGlucoseContext: RawRepresentable { + typealias RawValue = [String: Any] + + var rawValue: RawValue { + return [ + "values": values, + "unit": unit.unitString, + "startDate": startDate, + "interval": interval + ] + } + + init?(rawValue: RawValue) { + guard + let values = rawValue["values"] as? [Double], + let unitString = rawValue["unit"] as? String, + let startDate = rawValue["startDate"] as? Date, + let interval = rawValue["interval"] as? TimeInterval + else { + return nil + } + + self.values = values + self.unit = HKUnit(from: unitString) + self.startDate = startDate + self.interval = interval + } +} + +extension DatedRangeContext: RawRepresentable { + typealias RawValue = [String: Any] + + var rawValue: RawValue { + return [ + "startDate": startDate, + "endDate": endDate, + "minValue": minValue, + "maxValue": maxValue + ] + } + + init?(rawValue: RawValue) { + guard + let startDate = rawValue["startDate"] as? Date, + let endDate = rawValue["endDate"] as? Date, + let minValue = rawValue["minValue"] as? Double, + let maxValue = rawValue["maxValue"] as? Double + else { + return nil } + + self.startDate = startDate + self.endDate = endDate + self.minValue = minValue + self.maxValue = maxValue } } struct StatusExtensionContext: RawRepresentable { typealias RawValue = [String: Any] - private let version = 2 + private let version = 3 - var latestGlucose: GlucoseContext? + var glucose: [GlucoseContext]? + var predictedGlucose: PredictedGlucoseContext? var reservoir: ReservoirContext? var loop: LoopContext? var netBasal: NetBasalContext? var batteryPercentage: Double? - var eventualGlucose: GlucoseContext? + var targetRanges: [DatedRangeContext]? + var temporaryOverride: DatedRangeContext? + var sensor: SensorDisplayableContext? init() { } @@ -215,8 +288,12 @@ struct StatusExtensionContext: RawRepresentable { return nil } - if let rawValue = rawValue["latestGlucose"] as? GlucoseContext.RawValue { - latestGlucose = GlucoseContext(rawValue: rawValue) + if let rawValue = rawValue["glucose"] as? [GlucoseContext.RawValue] { + glucose = rawValue.flatMap({return GlucoseContext(rawValue: $0)}) + } + + if let rawValue = rawValue["predictedGlucose"] as? PredictedGlucoseContext.RawValue { + predictedGlucose = PredictedGlucoseContext(rawValue: rawValue) } if let rawValue = rawValue["reservoir"] as? ReservoirContext.RawValue { @@ -233,8 +310,16 @@ struct StatusExtensionContext: RawRepresentable { batteryPercentage = rawValue["batteryPercentage"] as? Double - if let rawValue = rawValue["eventualGlucose"] as? GlucoseContext.RawValue { - eventualGlucose = GlucoseContext(rawValue: rawValue) + if let rawValue = rawValue["targetRanges"] as? [DatedRangeContext.RawValue] { + targetRanges = rawValue.flatMap({return DatedRangeContext(rawValue: $0)}) + } + + if let rawValue = rawValue["temporaryOverride"] as? DatedRangeContext.RawValue { + temporaryOverride = DatedRangeContext(rawValue: rawValue) + } + + if let rawValue = rawValue["sensor"] as? SensorDisplayableContext.RawValue { + sensor = SensorDisplayableContext(rawValue: rawValue) } } @@ -242,12 +327,16 @@ struct StatusExtensionContext: RawRepresentable { var raw: RawValue = [ "version": version ] - raw["latestGlucose"] = latestGlucose?.rawValue + + raw["glucose"] = glucose?.map({return $0.rawValue}) + raw["predictedGlucose"] = predictedGlucose?.rawValue raw["reservoir"] = reservoir?.rawValue raw["loop"] = loop?.rawValue raw["netBasal"] = netBasal?.rawValue raw["batteryPercentage"] = batteryPercentage - raw["eventualGlucose"] = eventualGlucose?.rawValue + raw["targetRanges"] = targetRanges?.map({return $0.rawValue}) + raw["temporaryOverride"] = temporaryOverride?.rawValue + raw["sensor"] = sensor?.rawValue return raw } } diff --git a/Loop/Views/ChartPointsScatterDownTrianglesLayer.swift b/Common/Views/ChartPointsScatterDownTrianglesLayer.swift similarity index 100% rename from Loop/Views/ChartPointsScatterDownTrianglesLayer.swift rename to Common/Views/ChartPointsScatterDownTrianglesLayer.swift diff --git a/Loop/Views/ChartPointsTouchHighlightLayerViewCache.swift b/Common/Views/ChartPointsTouchHighlightLayerViewCache.swift similarity index 100% rename from Loop/Views/ChartPointsTouchHighlightLayerViewCache.swift rename to Common/Views/ChartPointsTouchHighlightLayerViewCache.swift diff --git a/Loop Status Extension/Base.lproj/MainInterface.storyboard b/Loop Status Extension/Base.lproj/MainInterface.storyboard index 2386d61a45..9904d79108 100644 --- a/Loop Status Extension/Base.lproj/MainInterface.storyboard +++ b/Loop Status Extension/Base.lproj/MainInterface.storyboard @@ -1,12 +1,11 @@ - - + + - @@ -19,29 +18,39 @@ - + - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + @@ -49,8 +58,9 @@ - + + diff --git a/Loop Status Extension/DatedRangedContextCalculator.swift b/Loop Status Extension/DatedRangedContextCalculator.swift new file mode 100644 index 0000000000..be43b4d68d --- /dev/null +++ b/Loop Status Extension/DatedRangedContextCalculator.swift @@ -0,0 +1,41 @@ +// +// DateRangedContextCalculator.swift +// Loop +// +// Created by Bharat Mediratta on 3/21/17. +// Copyright © 2017 LoopKit Authors. All rights reserved. +// + +import Foundation +import SwiftCharts + +class DatedRangeContextCalculator: TargetPointsCalculator { + + var targetRanges: [DatedRangeContext]? + var temporaryOverride: DatedRangeContext? + + var glucosePoints: [ChartPoint] = [] + var overridePoints: [ChartPoint] = [] + var overrideDurationPoints: [ChartPoint] = [] + + init(targetRanges: [DatedRangeContext]?, temporaryOverride: DatedRangeContext?) { + self.targetRanges = targetRanges + self.temporaryOverride = temporaryOverride + } + + func calculate(_ xAxisValues: [ChartAxisValue]?) { + if let xAxisValues = xAxisValues, xAxisValues.count > 1, + let targetRanges = targetRanges + { + glucosePoints = ChartPoint.pointsForDatedRanges(targetRanges, xAxisValues: xAxisValues) + + if let override = temporaryOverride { + overridePoints = ChartPoint.pointsForDatedRangeOverride(override, xAxisValues: xAxisValues) + overrideDurationPoints = ChartPoint.pointsForDatedRangeOverrideDuration(override, xAxisValues: xAxisValues) + } else { + overridePoints = [] + overrideDurationPoints = [] + } + } + } +} diff --git a/Loop Status Extension/StatusViewController.swift b/Loop Status Extension/StatusViewController.swift index d2ecf5a65f..b38922b9be 100644 --- a/Loop Status Extension/StatusViewController.swift +++ b/Loop Status Extension/StatusViewController.swift @@ -11,6 +11,7 @@ import HealthKit import LoopUI import NotificationCenter import UIKit +import SwiftCharts class StatusViewController: UIViewController, NCWidgetProviding { @@ -25,6 +26,18 @@ class StatusViewController: UIViewController, NCWidgetProviding { } } @IBOutlet weak var subtitleLabel: UILabel! + @IBOutlet weak var glucoseChartContentView: ChartContentView! + + private lazy var charts: StatusChartsManager = { + let charts = StatusChartsManager() + + charts.glucoseDisplayRange = ( + min: HKQuantity(unit: HKUnit.milligramsPerDeciliterUnit(), doubleValue: 100), + max: HKQuantity(unit: HKUnit.milligramsPerDeciliterUnit(), doubleValue: 175) + ) + + return charts + }() var statusExtensionContext: StatusExtensionContext? var defaults: UserDefaults? @@ -77,14 +90,43 @@ class StatusViewController: UIViewController, NCWidgetProviding { context: &observationContext ) } + + self.charts.prerender() + glucoseChartContentView.chartGenerator = { [unowned self] (frame) in + return self.charts.glucoseChartWithFrame(frame)?.view + } + + self.extensionContext?.widgetLargestAvailableDisplayMode = NCWidgetDisplayMode.expanded + glucoseChartContentView.alpha = self.extensionContext?.widgetActiveDisplayMode == NCWidgetDisplayMode.compact ? 0 : 1 } - + deinit { if let defaults = defaults { defaults.removeObserver(self, forKeyPath: defaults.statusExtensionContextObservableKey, context: &observationContext) } } + func widgetActiveDisplayModeDidChange(_ activeDisplayMode: NCWidgetDisplayMode, withMaximumSize maxSize: CGSize) { + if (activeDisplayMode == NCWidgetDisplayMode.compact) { + self.preferredContentSize = maxSize + } else { + self.preferredContentSize = CGSize(width: maxSize.width, height: 210) + } + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + + coordinator.animate(alongsideTransition: { + (UIViewControllerTransitionCoordinatorContext) -> Void in + if self.extensionContext?.widgetActiveDisplayMode == .compact { + self.glucoseChartContentView.alpha = 0 + } else { + self.glucoseChartContentView.alpha = 1 + } + }) + } + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard context == &observationContext else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) @@ -110,12 +152,11 @@ class StatusViewController: UIViewController, NCWidgetProviding { guard let context = defaults?.statusExtensionContext else { return NCUpdateResult.failed } - - if let glucose = context.latestGlucose { - glucoseHUD.setGlucoseQuantity(glucose.value, - at: glucose.startDate, - unit: glucose.unit, - sensor: glucose.sensor + if let lastGlucose = context.glucose?.last { + glucoseHUD.setGlucoseQuantity(lastGlucose.value, + at: lastGlucose.startDate, + unit: lastGlucose.unit, + sensor: context.sensor ) } @@ -139,21 +180,65 @@ class StatusViewController: UIViewController, NCWidgetProviding { subtitleLabel.alpha = 0 - if let eventualGlucose = context.eventualGlucose { - let formatter = NumberFormatter.glucoseFormatter(for: eventualGlucose.unit) + let dateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .none + dateFormatter.timeStyle = .short + + return dateFormatter + }() + - if let eventualGlucoseNumberString = formatter.string(from: NSNumber(value: eventualGlucose.value)) { - subtitleLabel.text = String( - format: NSLocalizedString( - "Eventually %1$@ %2$@", - comment: "The subtitle format describing eventual glucose. (1: localized glucose value description) (2: localized glucose units description)"), - eventualGlucoseNumberString, - eventualGlucose.unit.glucoseUnitDisplayString + if let glucose = context.glucose, + glucose.count > 0 { + let unit = glucose[0].unit + let glucoseFormatter = NumberFormatter.glucoseFormatter(for: unit) + + charts.glucosePoints = glucose.map { + ChartPoint( + x: ChartAxisValueDate(date: $0.startDate, formatter: dateFormatter), + y: ChartAxisValueDoubleUnit($0.value, unitString: unit.unitString, formatter: glucoseFormatter) ) - subtitleLabel.alpha = 1 } + + // Anchor the start date of the chart to the earliest date we have in our historical glucose + if let first = glucose.first { + charts.startDate = first.startDate + } + + if let predictedGlucose = context.predictedGlucose?.samples { + charts.predictedGlucosePoints = predictedGlucose.map { + ChartPoint( + x: ChartAxisValueDate(date: $0.startDate, formatter: dateFormatter), + y: ChartAxisValueDoubleUnit($0.value, unitString: unit.unitString, formatter: glucoseFormatter) + ) + } + + if let eventualGlucose = predictedGlucose.last { + let formatter = NumberFormatter.glucoseFormatter(for: eventualGlucose.unit) + + if let eventualGlucoseNumberString = formatter.string(from: NSNumber(value: eventualGlucose.value)) { + subtitleLabel.text = String( + format: NSLocalizedString( + "Eventually %1$@ %2$@", + comment: "The subtitle format describing eventual glucose. (1: localized glucose value description) (2: localized glucose units description)"), + eventualGlucoseNumberString, + eventualGlucose.unit.glucoseUnitDisplayString + ) + subtitleLabel.alpha = 1 + } + + charts.endDate = eventualGlucose.startDate + } + + } + + charts.targetPointsCalculator = DatedRangeContextCalculator(targetRanges: context.targetRanges, temporaryOverride: context.temporaryOverride) + + charts.prerender() + glucoseChartContentView.reloadChart() } - + // Right now we always act as if there's new data. // TODO: keep track of data changes and return .noData if necessary return NCUpdateResult.newData diff --git a/Loop Status Extension/UIColor+Widget.swift b/Loop Status Extension/UIColor+Widget.swift index f0e9109222..331fcdb95a 100644 --- a/Loop Status Extension/UIColor+Widget.swift +++ b/Loop Status Extension/UIColor+Widget.swift @@ -9,15 +9,19 @@ import UIKit extension UIColor { + @nonobjc static let axisLabelColor = subtitleLabelColor + + @nonobjc static let axisLineColor = subtitleLabelColor + @nonobjc static let doseTintColor = UIColor(red: 255 / 255, green: 109 / 255, blue: 0, alpha: 1) + @nonobjc static let freshColor = UIColor(red: 64 / 255, green: 219 / 255, blue: 89 / 255, alpha: 1) + @nonobjc static let glucoseTintColor = UIColor(red: 0 / 255, green: 122 / 255, blue: 244 / 255, alpha: 1) + @nonobjc static let gridColor = subtitleLabelColor + @nonobjc static let pumpStatusNormal = UIColor(red: 100 / 255, green: 101 / 255, blue: 105 / 255, alpha: 1) @nonobjc static let subtitleLabelColor = UIColor(white: 0, alpha: 0.4) } - -extension UIColor { - @nonobjc static let freshColor = UIColor(red: 64 / 255, green: 219 / 255, blue: 89 / 255, alpha: 1) -} diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 8bb5ba5df2..b0e633917b 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -14,10 +14,8 @@ 43076BF31DFDBC4B0012A723 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 43076BF21DFDBC4B0012A723 /* it.lproj */; }; 4309786C1E73D2F500BEBC82 /* it.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 4309786B1E73D2F500BEBC82 /* it.lproj */; }; 4309786E1E73DAD100BEBC82 /* CGM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4309786D1E73DAD100BEBC82 /* CGM.swift */; }; - 430C1ABD1E5568A80067F1AE /* StatusChartManager+LoopKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C1ABC1E5568A80067F1AE /* StatusChartManager+LoopKit.swift */; }; 430DA58E1D4AEC230097D1CA /* NSBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430DA58D1D4AEC230097D1CA /* NSBundle.swift */; }; 430DA5901D4B0E4C0097D1CA /* MySentryPumpStatusMessageBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430DA58F1D4B0E4C0097D1CA /* MySentryPumpStatusMessageBody.swift */; }; - 4313EDE01D8A6BF90060FA79 /* ChartContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4313EDDF1D8A6BF90060FA79 /* ChartContentView.swift */; }; 4315D2871CA5CC3B00589052 /* CarbEntryEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4315D2861CA5CC3B00589052 /* CarbEntryEditTableViewController.swift */; }; 4315D28A1CA5F45E00589052 /* DiagnosticLogger+LoopKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4315D2891CA5F45E00589052 /* DiagnosticLogger+LoopKit.swift */; }; 4328E01A1CFBE1DA00E199AA /* StatusInterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0151CFBE1DA00E199AA /* StatusInterfaceController.swift */; }; @@ -32,13 +30,10 @@ 4328E0331CFC091100E199AA /* WatchContext+LoopKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0311CFC068900E199AA /* WatchContext+LoopKit.swift */; }; 4328E0351CFC0AE100E199AA /* WatchDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0341CFC0AE100E199AA /* WatchDataManager.swift */; }; 432E73CB1D24B3D6009AD15D /* RemoteDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 432E73CA1D24B3D6009AD15D /* RemoteDataManager.swift */; }; - 4331E0781C85302200FBE832 /* CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4331E0771C85302200FBE832 /* CGPoint.swift */; }; - 4331E07A1C85650D00FBE832 /* ChartAxisValueDoubleLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4331E0791C85650D00FBE832 /* ChartAxisValueDoubleLog.swift */; }; 433EA4C21D9F39C900CD78FB /* PumpIDTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433EA4C11D9F39C900CD78FB /* PumpIDTableViewController.swift */; }; 433EA4C41D9F71C800CD78FB /* CommandResponseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433EA4C31D9F71C800CD78FB /* CommandResponseViewController.swift */; }; 4346D1E71C77F5FE00ABAFE3 /* ChartTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4346D1E61C77F5FE00ABAFE3 /* ChartTableViewCell.swift */; }; - 4346D1F01C781BEA00ABAFE3 /* SwiftCharts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4346D1EF1C781BEA00ABAFE3 /* SwiftCharts.framework */; }; - 4346D1F61C78501000ABAFE3 /* ChartPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4346D1F51C78501000ABAFE3 /* ChartPoint.swift */; }; + 4346D1F61C78501000ABAFE3 /* ChartPoint+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4346D1F51C78501000ABAFE3 /* ChartPoint+Loop.swift */; }; 434F54571D287FDB002A9274 /* NibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434F54561D287FDB002A9274 /* NibLoadable.swift */; }; 434F54591D28805E002A9274 /* ButtonTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 434F54581D28805E002A9274 /* ButtonTableViewCell.xib */; }; 434F545B1D2880D4002A9274 /* AuthenticationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 434F545A1D2880D4002A9274 /* AuthenticationTableViewCell.xib */; }; @@ -67,7 +62,6 @@ 437D9BA31D7BC977007245E8 /* PredictionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437D9BA21D7BC977007245E8 /* PredictionTableViewController.swift */; }; 43846AD51D8FA67800799272 /* Base.lproj in Resources */ = {isa = PBXBuildFile; fileRef = 43846AD41D8FA67800799272 /* Base.lproj */; }; 43846ADB1D91057000799272 /* ContextUpdatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846ADA1D91057000799272 /* ContextUpdatable.swift */; }; - 43880F951D9CD54A009061A8 /* ChartPointsScatterDownTrianglesLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43880F941D9CD54A009061A8 /* ChartPointsScatterDownTrianglesLayer.swift */; }; 438849EA1D297CB6003B3F23 /* NightscoutService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438849E91D297CB6003B3F23 /* NightscoutService.swift */; }; 438849EC1D29EC34003B3F23 /* AmplitudeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438849EB1D29EC34003B3F23 /* AmplitudeService.swift */; }; 438849EE1D2A1EBB003B3F23 /* MLabService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438849ED1D2A1EBB003B3F23 /* MLabService.swift */; }; @@ -142,9 +136,6 @@ 43E93FB51E4675E800EAB8DB /* NumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0B31E45C1BE00FF19A9 /* NumberFormatter.swift */; }; 43E93FB61E469A4000EAB8DB /* NumberFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43BFF0B31E45C1BE00FF19A9 /* NumberFormatter.swift */; }; 43E93FB71E469A5100EAB8DB /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; - 43EB40861C82646A00472A8C /* StatusChartManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EB40851C82646A00472A8C /* StatusChartManager.swift */; }; - 43F41C331D3A17AA00C11ED6 /* ChartAxisValueDoubleUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F41C321D3A17AA00C11ED6 /* ChartAxisValueDoubleUnit.swift */; }; - 43F41C351D3B623800C11ED6 /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F41C341D3B623800C11ED6 /* ChartPointsTouchHighlightLayerViewCache.swift */; }; 43F41C371D3BF32400C11ED6 /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F41C361D3BF32400C11ED6 /* UIAlertController.swift */; }; 43F4EF1D1BA2A57600526CE1 /* DiagnosticLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F4EF1C1BA2A57600526CE1 /* DiagnosticLogger.swift */; }; 43F5173D1D713DB0000FA422 /* RadioSelectionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F5173C1D713DB0000FA422 /* RadioSelectionTableViewController.swift */; }; @@ -158,6 +149,27 @@ 43FCBBC21E51710B00343C1B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 43776F9A1B8022E90074EA36 /* LaunchScreen.storyboard */; }; 4D3B40041D4A9E1A00BC6334 /* G4ShareSpy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D3B40021D4A9DFE00BC6334 /* G4ShareSpy.framework */; }; 4D5B7A4B1D457CCA00796CA9 /* GlucoseG4.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D5B7A4A1D457CCA00796CA9 /* GlucoseG4.swift */; }; + 4F08DE6D1E799EC7006741EA /* StatusChartsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE6C1E799EC7006741EA /* StatusChartsManager.swift */; }; + 4F08DE6E1E799ED1006741EA /* StatusChartsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE6C1E799EC7006741EA /* StatusChartsManager.swift */; }; + 4F08DE771E7B31C0006741EA /* ChartPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE751E7B3113006741EA /* ChartPoint.swift */; }; + 4F08DE791E7B57C9006741EA /* ChartPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE751E7B3113006741EA /* ChartPoint.swift */; }; + 4F08DE7E1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE7C1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift */; }; + 4F08DE7F1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */; }; + 4F08DE811E7BB6F1006741EA /* CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE801E7BB6F1006741EA /* CGPoint.swift */; }; + 4F08DE851E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE831E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift */; }; + 4F08DE861E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE841E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift */; }; + 4F08DE871E7BB726006741EA /* ChartPointsScatterDownTrianglesLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE831E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift */; }; + 4F08DE881E7BB726006741EA /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE841E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift */; }; + 4F08DE891E7BB729006741EA /* ChartAxisValueDoubleLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE7C1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift */; }; + 4F08DE8A1E7BB729006741EA /* ChartAxisValueDoubleUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */; }; + 4F08DE8B1E7BB72C006741EA /* CGPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE801E7BB6F1006741EA /* CGPoint.swift */; }; + 4F08DE8F1E7BB871006741EA /* CollectionType+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DE8E1E7BB871006741EA /* CollectionType+Loop.swift */; }; + 4F08DE9B1E7BC4ED006741EA /* SwiftCharts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4346D1EF1C781BEA00ABAFE3 /* SwiftCharts.framework */; }; + 4F08DE9D1E81D0E9006741EA /* StatusChartsManager+LoopKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430C1ABC1E5568A80067F1AE /* StatusChartsManager+LoopKit.swift */; }; + 4F08DEA11E81D90F006741EA /* GlucoseRangeScheduleCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DEA01E81D90F006741EA /* GlucoseRangeScheduleCalculator.swift */; }; + 4F08DEA31E81E12D006741EA /* DatedRangedContextCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F08DEA21E81E12D006741EA /* DatedRangedContextCalculator.swift */; }; + 4F20AE621E6B879C00D07A06 /* ReservoirVolumeHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEC71CD84CBB003C8C80 /* ReservoirVolumeHUDView.swift */; }; + 4F20AE631E6B87B100D07A06 /* ChartContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4313EDDF1D8A6BF90060FA79 /* ChartContentView.swift */; }; 4F2C15741E0209F500E160D4 /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; }; 4F2C15751E0209FA00E160D4 /* GlucoseTrend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EA285E1D50ED3D001BC233 /* GlucoseTrend.swift */; }; 4F2C15811E0495B200E160D4 /* WatchContext+WatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F2C15801E0495B200E160D4 /* WatchContext+WatchApp.swift */; }; @@ -186,7 +198,6 @@ 4F75289C1DFE1F6000C322D6 /* GlucoseHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4337615E1D52F487004A3647 /* GlucoseHUDView.swift */; }; 4F75289D1DFE1F6000C322D6 /* BaseHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEBB1CD6DE6A003C8C80 /* BaseHUDView.swift */; }; 4F75289E1DFE1F6000C322D6 /* LoopCompletionHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEBD1CD6E0CB003C8C80 /* LoopCompletionHUDView.swift */; }; - 4F75289F1DFE1F6000C322D6 /* ReservoirVolumeHUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437CEEC71CD84CBB003C8C80 /* ReservoirVolumeHUDView.swift */; }; 4F7528A01DFE1F9D00C322D6 /* LoopStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438DADC71CDE8F8B007697A5 /* LoopStateView.swift */; }; 4F7528A11DFE200B00C322D6 /* BasalStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43B371851CE583890013C5A6 /* BasalStateView.swift */; }; 4F7528A21DFE200B00C322D6 /* LevelMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */; }; @@ -194,6 +205,8 @@ 4F7528A71DFE20CE00C322D6 /* SensorDisplayable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EA28611D517E42001BC233 /* SensorDisplayable.swift */; }; 4F7528A91DFE212600C322D6 /* GlucoseTrend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EA285E1D50ED3D001BC233 /* GlucoseTrend.swift */; }; 4F7528AA1DFE215100C322D6 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; + 4FAC02531E22F6360087A773 /* CollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43649A621C7A347F00523D7F /* CollectionType.swift */; }; + 4FAC02541E22F6B20087A773 /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; }; 4FC8C8011DEB93E400A1452E /* NSUserDefaults+StatusExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FC8C8001DEB93E400A1452E /* NSUserDefaults+StatusExtension.swift */; }; 4FC8C8021DEB943800A1452E /* NSUserDefaults+StatusExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FC8C8001DEB93E400A1452E /* NSUserDefaults+StatusExtension.swift */; }; 4FF4D0F81E1725B000846527 /* NibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434F54561D287FDB002A9274 /* NibLoadable.swift */; }; @@ -340,7 +353,7 @@ 43076BF21DFDBC4B0012A723 /* it.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; path = it.lproj; sourceTree = ""; }; 4309786B1E73D2F500BEBC82 /* it.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; path = it.lproj; sourceTree = ""; }; 4309786D1E73DAD100BEBC82 /* CGM.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGM.swift; sourceTree = ""; }; - 430C1ABC1E5568A80067F1AE /* StatusChartManager+LoopKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StatusChartManager+LoopKit.swift"; sourceTree = ""; }; + 430C1ABC1E5568A80067F1AE /* StatusChartsManager+LoopKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StatusChartsManager+LoopKit.swift"; sourceTree = ""; }; 430DA58D1D4AEC230097D1CA /* NSBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSBundle.swift; sourceTree = ""; }; 430DA58F1D4B0E4C0097D1CA /* MySentryPumpStatusMessageBody.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MySentryPumpStatusMessageBody.swift; sourceTree = ""; }; 4313EDDF1D8A6BF90060FA79 /* ChartContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartContentView.swift; sourceTree = ""; }; @@ -358,14 +371,12 @@ 4328E0311CFC068900E199AA /* WatchContext+LoopKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WatchContext+LoopKit.swift"; sourceTree = ""; }; 4328E0341CFC0AE100E199AA /* WatchDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = WatchDataManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 432E73CA1D24B3D6009AD15D /* RemoteDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemoteDataManager.swift; sourceTree = ""; }; - 4331E0771C85302200FBE832 /* CGPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPoint.swift; sourceTree = ""; }; - 4331E0791C85650D00FBE832 /* ChartAxisValueDoubleLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleLog.swift; sourceTree = ""; }; 4337615E1D52F487004A3647 /* GlucoseHUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseHUDView.swift; sourceTree = ""; }; 433EA4C11D9F39C900CD78FB /* PumpIDTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PumpIDTableViewController.swift; sourceTree = ""; }; 433EA4C31D9F71C800CD78FB /* CommandResponseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandResponseViewController.swift; sourceTree = ""; }; 4346D1E61C77F5FE00ABAFE3 /* ChartTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTableViewCell.swift; sourceTree = ""; }; 4346D1EF1C781BEA00ABAFE3 /* SwiftCharts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftCharts.framework; path = Carthage/Build/iOS/SwiftCharts.framework; sourceTree = ""; }; - 4346D1F51C78501000ABAFE3 /* ChartPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPoint.swift; sourceTree = ""; }; + 4346D1F51C78501000ABAFE3 /* ChartPoint+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ChartPoint+Loop.swift"; sourceTree = ""; }; 434AB0B11CBB4C3300422F4A /* RileyLinkBLEKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RileyLinkBLEKit.framework; path = Carthage/Build/iOS/RileyLinkBLEKit.framework; sourceTree = ""; }; 434F54561D287FDB002A9274 /* NibLoadable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NibLoadable.swift; sourceTree = ""; }; 434F54581D28805E002A9274 /* ButtonTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ButtonTableViewCell.xib; sourceTree = ""; }; @@ -401,7 +412,6 @@ 437D9BA21D7BC977007245E8 /* PredictionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictionTableViewController.swift; sourceTree = ""; }; 43846AD41D8FA67800799272 /* Base.lproj */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base.lproj; sourceTree = ""; }; 43846ADA1D91057000799272 /* ContextUpdatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextUpdatable.swift; sourceTree = ""; }; - 43880F941D9CD54A009061A8 /* ChartPointsScatterDownTrianglesLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPointsScatterDownTrianglesLayer.swift; sourceTree = ""; }; 438849E91D297CB6003B3F23 /* NightscoutService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NightscoutService.swift; sourceTree = ""; }; 438849EB1D29EC34003B3F23 /* AmplitudeService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AmplitudeService.swift; sourceTree = ""; }; 438849ED1D2A1EBB003B3F23 /* MLabService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MLabService.swift; sourceTree = ""; }; @@ -476,10 +486,7 @@ 43E397A21D56B9E40028E321 /* Glucose.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Glucose.swift; sourceTree = ""; }; 43EA285E1D50ED3D001BC233 /* GlucoseTrend.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseTrend.swift; sourceTree = ""; }; 43EA28611D517E42001BC233 /* SensorDisplayable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SensorDisplayable.swift; sourceTree = ""; }; - 43EB40851C82646A00472A8C /* StatusChartManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusChartManager.swift; sourceTree = ""; }; 43EDEE6B1CF2E12A00393BE3 /* Loop.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Loop.entitlements; sourceTree = ""; }; - 43F41C321D3A17AA00C11ED6 /* ChartAxisValueDoubleUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleUnit.swift; sourceTree = ""; }; - 43F41C341D3B623800C11ED6 /* ChartPointsTouchHighlightLayerViewCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPointsTouchHighlightLayerViewCache.swift; sourceTree = ""; }; 43F41C361D3BF32400C11ED6 /* UIAlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = ""; }; 43F4EF1C1BA2A57600526CE1 /* DiagnosticLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiagnosticLogger.swift; sourceTree = ""; }; 43F5173C1D713DB0000FA422 /* RadioSelectionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioSelectionTableViewController.swift; sourceTree = ""; }; @@ -495,6 +502,16 @@ 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LevelMaskView.swift; sourceTree = ""; }; 4D3B40021D4A9DFE00BC6334 /* G4ShareSpy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = G4ShareSpy.framework; path = Carthage/Build/iOS/G4ShareSpy.framework; sourceTree = ""; }; 4D5B7A4A1D457CCA00796CA9 /* GlucoseG4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GlucoseG4.swift; path = Loop/Models/GlucoseG4.swift; sourceTree = SOURCE_ROOT; }; + 4F08DE6C1E799EC7006741EA /* StatusChartsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StatusChartsManager.swift; path = Managers/StatusChartsManager.swift; sourceTree = ""; }; + 4F08DE751E7B3113006741EA /* ChartPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartPoint.swift; sourceTree = ""; }; + 4F08DE7C1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleLog.swift; sourceTree = ""; }; + 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartAxisValueDoubleUnit.swift; sourceTree = ""; }; + 4F08DE801E7BB6F1006741EA /* CGPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPoint.swift; sourceTree = ""; }; + 4F08DE831E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartPointsScatterDownTrianglesLayer.swift; path = Views/ChartPointsScatterDownTrianglesLayer.swift; sourceTree = ""; }; + 4F08DE841E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartPointsTouchHighlightLayerViewCache.swift; path = Views/ChartPointsTouchHighlightLayerViewCache.swift; sourceTree = ""; }; + 4F08DE8E1E7BB871006741EA /* CollectionType+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CollectionType+Loop.swift"; sourceTree = ""; }; + 4F08DEA01E81D90F006741EA /* GlucoseRangeScheduleCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseRangeScheduleCalculator.swift; sourceTree = ""; }; + 4F08DEA21E81E12D006741EA /* DatedRangedContextCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatedRangedContextCalculator.swift; sourceTree = ""; }; 4F2C15801E0495B200E160D4 /* WatchContext+WatchApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WatchContext+WatchApp.swift"; sourceTree = ""; }; 4F2C15921E09BF2C00E160D4 /* HUDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HUDView.swift; sourceTree = ""; }; 4F2C15941E09BF3C00E160D4 /* HUDView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HUDView.xib; sourceTree = ""; }; @@ -556,7 +573,7 @@ 43CA93371CB98079000026B5 /* MinimedKit.framework in Frameworks */, 43523EDB1CC35083001850F1 /* RileyLinkKit.framework in Frameworks */, 43B371881CE597D10013C5A6 /* ShareClient.framework in Frameworks */, - 4346D1F01C781BEA00ABAFE3 /* SwiftCharts.framework in Frameworks */, + 4F08DE9B1E7BC4ED006741EA /* SwiftCharts.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -635,8 +652,6 @@ 43DE92601C555C26001FFDE1 /* AbsorptionTimeType+CarbKit.swift */, C17824A41E1AD4D100D9D25C /* BolusRecommendation.swift */, 4309786D1E73DAD100BEBC82 /* CGM.swift */, - 4331E0791C85650D00FBE832 /* ChartAxisValueDoubleLog.swift */, - 43F41C321D3A17AA00C11ED6 /* ChartAxisValueDoubleUnit.swift */, 540DED961E14C75F002B2491 /* EnliteSensorDisplayable.swift */, 43E397A21D56B9E40028E321 /* Glucose.swift */, 4D5B7A4A1D457CCA00796CA9 /* GlucoseG4.swift */, @@ -797,9 +812,8 @@ isa = PBXGroup; children = ( C17884621D51A7A400405663 /* BatteryIndicator.swift */, - 4331E0771C85302200FBE832 /* CGPoint.swift */, - 4346D1F51C78501000ABAFE3 /* ChartPoint.swift */, - 43649A621C7A347F00523D7F /* CollectionType.swift */, + 4346D1F51C78501000ABAFE3 /* ChartPoint+Loop.swift */, + 4F08DE8E1E7BB871006741EA /* CollectionType+Loop.swift */, 43CE7CDD1CA8B63E003CC1B0 /* Data.swift */, 4302F4E41D4EA75100F0FCAF /* DoseStore.swift */, C15713811DAC6983005BC4D2 /* MealBolusNightscoutTreatment.swift */, @@ -843,9 +857,6 @@ 434F545A1D2880D4002A9274 /* AuthenticationTableViewCell.xib */, 437CCADB1D284B830075D2C3 /* ButtonTableViewCell.swift */, 434F54581D28805E002A9274 /* ButtonTableViewCell.xib */, - 4313EDDF1D8A6BF90060FA79 /* ChartContentView.swift */, - 43880F941D9CD54A009061A8 /* ChartPointsScatterDownTrianglesLayer.swift */, - 43F41C341D3B623800C11ED6 /* ChartPointsTouchHighlightLayerViewCache.swift */, 4346D1E61C77F5FE00ABAFE3 /* ChartTableViewCell.swift */, 438D42FA1D7D11A4003244B0 /* PredictionInputEffectTableViewCell.swift */, 43A5676A1C96155700334FAC /* SwitchTableViewCell.swift */, @@ -870,10 +881,10 @@ C18C8C501D5A351900E043FB /* NightscoutDataManager.swift */, 43C094491CACCC73001F6403 /* NotificationManager.swift */, 432E73CA1D24B3D6009AD15D /* RemoteDataManager.swift */, - 43EB40851C82646A00472A8C /* StatusChartManager.swift */, - 430C1ABC1E5568A80067F1AE /* StatusChartManager+LoopKit.swift */, + 430C1ABC1E5568A80067F1AE /* StatusChartsManager+LoopKit.swift */, 4F70C20F1DE8FAC5006380B7 /* StatusExtensionDataManager.swift */, 4328E0341CFC0AE100E199AA /* WatchDataManager.swift */, + 4F08DEA01E81D90F006741EA /* GlucoseRangeScheduleCalculator.swift */, ); path = Managers; sourceTree = ""; @@ -887,6 +898,23 @@ path = LoopTests; sourceTree = ""; }; + 4F08DE6B1E799EBE006741EA /* Managers */ = { + isa = PBXGroup; + children = ( + 4F08DE6C1E799EC7006741EA /* StatusChartsManager.swift */, + ); + name = Managers; + sourceTree = ""; + }; + 4F08DE821E7BB6FE006741EA /* Views */ = { + isa = PBXGroup; + children = ( + 4F08DE831E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift */, + 4F08DE841E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift */, + ); + name = Views; + sourceTree = ""; + }; 4F70C1DF1DE8DCA7006380B7 /* Loop Status Extension */ = { isa = PBXGroup; children = ( @@ -896,6 +924,7 @@ 4F70C1E01DE8DCA7006380B7 /* StatusViewController.swift */, 43BFF0BE1E45C8EA00FF19A9 /* UIColor+Widget.swift */, 4F70C1E21DE8DCA7006380B7 /* MainInterface.storyboard */, + 4F08DEA21E81E12D006741EA /* DatedRangedContextCalculator.swift */, ); path = "Loop Status Extension"; sourceTree = ""; @@ -920,6 +949,7 @@ 43B371851CE583890013C5A6 /* BasalStateView.swift */, 437CEEBB1CD6DE6A003C8C80 /* BaseHUDView.swift */, 437CEEC91CD84DB7003C8C80 /* BatteryLevelHUDView.swift */, + 4313EDDF1D8A6BF90060FA79 /* ChartContentView.swift */, 4337615E1D52F487004A3647 /* GlucoseHUDView.swift */, 4F2C15921E09BF2C00E160D4 /* HUDView.swift */, 43FBEDD71D73843700B21F22 /* LevelMaskView.swift */, @@ -944,7 +974,9 @@ isa = PBXGroup; children = ( 4FF4D0FC1E1834CC00846527 /* Extensions */, + 4F08DE6B1E799EBE006741EA /* Managers */, 4FF4D0FB1E1834C400846527 /* Models */, + 4F08DE821E7BB6FE006741EA /* Views */, ); path = Common; sourceTree = ""; @@ -952,6 +984,8 @@ 4FF4D0FB1E1834C400846527 /* Models */ = { isa = PBXGroup; children = ( + 4F08DE7C1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift */, + 4F08DE7D1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift */, 435400301C9F744E00D5819C /* BolusSuggestionUserInfo.swift */, 43DE92581C5479E4001FFDE1 /* CarbEntryUserInfo.swift */, 43EA285E1D50ED3D001BC233 /* GlucoseTrend.swift */, @@ -965,6 +999,9 @@ 4FF4D0FC1E1834CC00846527 /* Extensions */ = { isa = PBXGroup; children = ( + 4F08DE801E7BB6F1006741EA /* CGPoint.swift */, + 4F08DE751E7B3113006741EA /* ChartPoint.swift */, + 43649A621C7A347F00523D7F /* CollectionType.swift */, 4F526D5E1DF2459000A04910 /* HKUnit.swift */, 434FF1E91CF26C29000DB779 /* IdentifiableClass.swift */, 434F54561D287FDB002A9274 /* NibLoadable.swift */, @@ -1373,6 +1410,8 @@ 434F54571D287FDB002A9274 /* NibLoadable.swift in Sources */, 4FF4D1001E18374700846527 /* WatchContext.swift in Sources */, 4315D28A1CA5F45E00589052 /* DiagnosticLogger+LoopKit.swift in Sources */, + 4F08DE851E7BB70B006741EA /* ChartPointsScatterDownTrianglesLayer.swift in Sources */, + 4F08DE7F1E7BB6E5006741EA /* ChartAxisValueDoubleUnit.swift in Sources */, 43C418B51CE0575200405B6A /* ShareGlucose+GlucoseKit.swift in Sources */, 4F2C15821E074FC600E160D4 /* NSTimeInterval.swift in Sources */, 430DA58E1D4AEC230097D1CA /* NSBundle.swift in Sources */, @@ -1381,16 +1420,15 @@ 439BED2E1E760BC600B0AED5 /* EnliteCGMManager.swift in Sources */, 43CE7CDE1CA8B63E003CC1B0 /* Data.swift in Sources */, 43BFF0CB1E466C0900FF19A9 /* StateColorPalette.swift in Sources */, - 43F41C331D3A17AA00C11ED6 /* ChartAxisValueDoubleUnit.swift in Sources */, 43F5C2DB1B92A5E1003EB13D /* SettingsTableViewController.swift in Sources */, C11C87DD1E21E53500BB71D3 /* GlucoseThreshold.swift in Sources */, - 4313EDE01D8A6BF90060FA79 /* ChartContentView.swift in Sources */, 434FF1EA1CF26C29000DB779 /* IdentifiableClass.swift in Sources */, 437CCADE1D2858FD0075D2C3 /* AuthenticationViewController.swift in Sources */, 43A5676B1C96155700334FAC /* SwitchTableViewCell.swift in Sources */, 43A567691C94880B00334FAC /* LoopDataManager.swift in Sources */, 43E397A31D56B9E40028E321 /* Glucose.swift in Sources */, 4302F4E11D4E9C8900F0FCAF /* TextFieldTableViewController.swift in Sources */, + 4F08DE7E1E7BB6E5006741EA /* ChartAxisValueDoubleLog.swift in Sources */, 43E344A41B9E1B1C00C85C07 /* NSUserDefaults.swift in Sources */, 43649A631C7A347F00523D7F /* CollectionType.swift in Sources */, 43F64DD91D9C92C900D24DC6 /* TitleSubtitleTableViewCell.swift in Sources */, @@ -1403,12 +1441,13 @@ 4346D1E71C77F5FE00ABAFE3 /* ChartTableViewCell.swift in Sources */, 437CEEE41CDE5C0A003C8C80 /* UIImage.swift in Sources */, 43DBF0591C93F73800B3C386 /* CarbEntryTableViewController.swift in Sources */, - 43F41C351D3B623800C11ED6 /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */, 43E93FB71E469A5100EAB8DB /* HKUnit.swift in Sources */, - 43EB40861C82646A00472A8C /* StatusChartManager.swift in Sources */, C17884631D51A7A400405663 /* BatteryIndicator.swift in Sources */, + 4F08DE811E7BB6F1006741EA /* CGPoint.swift in Sources */, 43BFF0BC1E45C80600FF19A9 /* UIColor+Loop.swift in Sources */, + 4F08DE771E7B31C0006741EA /* ChartPoint.swift in Sources */, 43C0944A1CACCC73001F6403 /* NotificationManager.swift in Sources */, + 4F08DE9D1E81D0E9006741EA /* StatusChartsManager+LoopKit.swift in Sources */, 434FF1EE1CF27EEF000DB779 /* UITableViewCell.swift in Sources */, 439BED2A1E76093C00B0AED5 /* CGMManager.swift in Sources */, C18C8C511D5A351900E043FB /* NightscoutDataManager.swift in Sources */, @@ -1417,8 +1456,8 @@ 4315D2871CA5CC3B00589052 /* CarbEntryEditTableViewController.swift in Sources */, 4309786E1E73DAD100BEBC82 /* CGM.swift in Sources */, 43F5173D1D713DB0000FA422 /* RadioSelectionTableViewController.swift in Sources */, - 4331E0781C85302200FBE832 /* CGPoint.swift in Sources */, C178249A1E1999FA00D9D25C /* CaseCountable.swift in Sources */, + 4F08DEA11E81D90F006741EA /* GlucoseRangeScheduleCalculator.swift in Sources */, 43DBF04C1C93B8D700B3C386 /* BolusViewController.swift in Sources */, 4328E0351CFC0AE100E199AA /* WatchDataManager.swift in Sources */, 43BFF0C51E465A2D00FF19A9 /* UIColor+HIG.swift in Sources */, @@ -1430,10 +1469,10 @@ 4D5B7A4B1D457CCA00796CA9 /* GlucoseG4.swift in Sources */, 438849EC1D29EC34003B3F23 /* AmplitudeService.swift in Sources */, 43E93FB61E469A4000EAB8DB /* NumberFormatter.swift in Sources */, + 4F08DE8F1E7BB871006741EA /* CollectionType+Loop.swift in Sources */, 435400341C9F878D00D5819C /* SetBolusUserInfo.swift in Sources */, 437D9BA31D7BC977007245E8 /* PredictionTableViewController.swift in Sources */, 43F41C371D3BF32400C11ED6 /* UIAlertController.swift in Sources */, - 430C1ABD1E5568A80067F1AE /* StatusChartManager+LoopKit.swift in Sources */, 433EA4C41D9F71C800CD78FB /* CommandResponseViewController.swift in Sources */, 434F545F1D288345002A9274 /* ShareService.swift in Sources */, 43CEE6E61E56AFD400CB9116 /* NightscoutUploader.swift in Sources */, @@ -1448,19 +1487,19 @@ 43BFF0B21E45C18400FF19A9 /* UIColor.swift in Sources */, 43F78D261C8FC000002152D1 /* DoseMath.swift in Sources */, 438D42F91D7C88BC003244B0 /* PredictionInputEffect.swift in Sources */, - 4331E07A1C85650D00FBE832 /* ChartAxisValueDoubleLog.swift in Sources */, 434F54611D28859B002A9274 /* ServiceCredential.swift in Sources */, 4F70C2101DE8FAC5006380B7 /* StatusExtensionDataManager.swift in Sources */, 436FACEE1D0BA636004E2427 /* InsulinDataSource.swift in Sources */, 439897371CD2F80600223065 /* AnalyticsManager.swift in Sources */, - 4346D1F61C78501000ABAFE3 /* ChartPoint.swift in Sources */, + 4346D1F61C78501000ABAFE3 /* ChartPoint+Loop.swift in Sources */, 438849EE1D2A1EBB003B3F23 /* MLabService.swift in Sources */, 438D42FB1D7D11A4003244B0 /* PredictionInputEffectTableViewCell.swift in Sources */, - 43880F951D9CD54A009061A8 /* ChartPointsScatterDownTrianglesLayer.swift in Sources */, 43F4EF1D1BA2A57600526CE1 /* DiagnosticLogger.swift in Sources */, 432E73CB1D24B3D6009AD15D /* RemoteDataManager.swift in Sources */, + 4F08DE6D1E799EC7006741EA /* StatusChartsManager.swift in Sources */, 43DE92591C5479E4001FFDE1 /* CarbEntryUserInfo.swift in Sources */, 434F54631D28DD80002A9274 /* ValidatingIndicatorView.swift in Sources */, + 4F08DE861E7BB70B006741EA /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */, 43DE92611C555C26001FFDE1 /* AbsorptionTimeType+CarbKit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1521,13 +1560,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4FAC02541E22F6B20087A773 /* NSTimeInterval.swift in Sources */, + 4FAC02531E22F6360087A773 /* CollectionType.swift in Sources */, + 4F08DE881E7BB726006741EA /* ChartPointsTouchHighlightLayerViewCache.swift in Sources */, 4F2C15831E0757E600E160D4 /* HKUnit.swift in Sources */, 43E93FB51E4675E800EAB8DB /* NumberFormatter.swift in Sources */, + 4F08DE8A1E7BB729006741EA /* ChartAxisValueDoubleUnit.swift in Sources */, + 4F08DE891E7BB729006741EA /* ChartAxisValueDoubleLog.swift in Sources */, 43BFF0CD1E466C8400FF19A9 /* StateColorPalette.swift in Sources */, + 4F08DEA31E81E12D006741EA /* DatedRangedContextCalculator.swift in Sources */, + 4F08DE8B1E7BB72C006741EA /* CGPoint.swift in Sources */, 43BFF0C21E464ACB00FF19A9 /* UIColor.swift in Sources */, 4F526D621DF9D95200A04910 /* NSBundle.swift in Sources */, + 4F08DE871E7BB726006741EA /* ChartPointsScatterDownTrianglesLayer.swift in Sources */, 4FC8C8021DEB943800A1452E /* NSUserDefaults+StatusExtension.swift in Sources */, 43BFF0C71E465A4F00FF19A9 /* UIColor+HIG.swift in Sources */, + 4F08DE6E1E799ED1006741EA /* StatusChartsManager.swift in Sources */, + 4F08DE791E7B57C9006741EA /* ChartPoint.swift in Sources */, 43BFF0BF1E45C8EA00FF19A9 /* UIColor+Widget.swift in Sources */, 4F70C2121DE900EA006380B7 /* StatusExtensionContext.swift in Sources */, 4F70C1E11DE8DCA7006380B7 /* StatusViewController.swift in Sources */, @@ -1538,6 +1587,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4F20AE621E6B879C00D07A06 /* ReservoirVolumeHUDView.swift in Sources */, 4FF4D0F91E17268800846527 /* IdentifiableClass.swift in Sources */, 4FF4D0F81E1725B000846527 /* NibLoadable.swift in Sources */, 4F7528AA1DFE215100C322D6 /* HKUnit.swift in Sources */, @@ -1547,6 +1597,7 @@ 43BFF0B71E45C20C00FF19A9 /* NumberFormatter.swift in Sources */, 4F7528A51DFE208C00C322D6 /* NSTimeInterval.swift in Sources */, 4F7528A11DFE200B00C322D6 /* BasalStateView.swift in Sources */, + 4F20AE631E6B87B100D07A06 /* ChartContentView.swift in Sources */, 4F7528A21DFE200B00C322D6 /* LevelMaskView.swift in Sources */, 43BFF0C61E465A4400FF19A9 /* UIColor+HIG.swift in Sources */, 4F7528A01DFE1F9D00C322D6 /* LoopStateView.swift in Sources */, @@ -1557,7 +1608,6 @@ 43BFF0C91E465B0A00FF19A9 /* StateColorPalette.swift in Sources */, 43E0F0A51E46D1670064F7CE /* LevelHUDView.swift in Sources */, 4F75289E1DFE1F6000C322D6 /* LoopCompletionHUDView.swift in Sources */, - 4F75289F1DFE1F6000C322D6 /* ReservoirVolumeHUDView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Loop/Base.lproj/Main.storyboard b/Loop/Base.lproj/Main.storyboard index 042725e30c..352e33d1d5 100644 --- a/Loop/Base.lproj/Main.storyboard +++ b/Loop/Base.lproj/Main.storyboard @@ -23,17 +23,17 @@ - + - + @@ -54,18 +54,18 @@ - +