diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index e94e7da8db..4d7dc14373 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 01414522FC033F2B7A9B223A /* Loop/Resources/Sounds/crying.caf in Resources */ = {isa = PBXBuildFile; fileRef = 85203550670F2E9BE92F27D8 /* Loop/Resources/Sounds/crying.caf */; }; + 0A02E77AD7536C322933D49B /* Loop/Resources/Sounds/minimal.caf in Resources */ = {isa = PBXBuildFile; fileRef = 74145BE3C46270883D295A1F /* Loop/Resources/Sounds/minimal.caf */; }; + 124B300527D84BE2A1233A91 /* Loop/Resources/Sounds/urgent_low.caf in Resources */ = {isa = PBXBuildFile; fileRef = C9EA3F48338B49BD9C6BD0F9 /* Loop/Resources/Sounds/urgent_low.caf */; }; 1419606928D9554E00BA86E0 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 437AFEE6203688CF008C4892 /* LoopKitUI.framework */; }; 1419606A28D955BC00BA86E0 /* MockKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C101947127DD473C004E7EB8 /* MockKitUI.framework */; }; 142CB7592A60BF2E0075748A /* EditMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 142CB7582A60BF2E0075748A /* EditMode.swift */; }; @@ -56,6 +59,7 @@ 14C970862C5C358C00E8A01B /* FavoriteFoodInsightsChartsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14C970852C5C358C00E8A01B /* FavoriteFoodInsightsChartsView.swift */; }; 14D906F42A846510006EB79A /* FavoriteFoodsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14D906F32A846510006EB79A /* FavoriteFoodsViewModel.swift */; }; 14ED83F62C6421F9008B4A5C /* FavoriteFoodInsightsCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14ED83F52C6421F9008B4A5C /* FavoriteFoodInsightsCardView.swift */; }; + 16E5A3BC4D931CE6AED18518 /* Loop/Resources/Sounds/trill.caf in Resources */ = {isa = PBXBuildFile; fileRef = 21F13EB666EBFDD03F99CB7E /* Loop/Resources/Sounds/trill.caf */; }; 1D05219B2469E9DF000EBBDE /* StoredAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D05219A2469E9DF000EBBDE /* StoredAlert.swift */; }; 1D05219D2469F1F5000EBBDE /* AlertStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D05219C2469F1F5000EBBDE /* AlertStore.swift */; }; 1D080CBD2473214A00356610 /* AlertStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1D080CBB2473214A00356610 /* AlertStore.xcdatamodeld */; }; @@ -76,38 +80,15 @@ 1DA7A84224476EAD008257F0 /* AlertManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA7A84124476EAD008257F0 /* AlertManagerTests.swift */; }; 1DA7A84424477698008257F0 /* InAppModalAlertSchedulerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA7A84324477698008257F0 /* InAppModalAlertSchedulerTests.swift */; }; 1DB1065124467E18005542BD /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1065024467E18005542BD /* AlertManager.swift */; }; - C9A47B0180AAB1FC572D3EFE /* CriticalAlertAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0175B13A9543390BC5 /* CriticalAlertAudioPlayer.swift */; }; - C1A1A00001000000000000A1 /* CriticalAlertAlarmScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A1A00001000000000000A2 /* CriticalAlertAlarmScheduler.swift */; }; - C9A47B0280AAB1FC572D3EFF /* GlucoseAlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0275B13A9543390BC6 /* GlucoseAlertManager.swift */; }; - C9A47B0380AAB1FC572D3F00 /* GlucoseAlertSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0375B13A9543390BC7 /* GlucoseAlertSettingsView.swift */; }; - C9A47B0480AAB1FC572D3F01 /* critical.caf in Resources */ = {isa = PBXBuildFile; fileRef = C9A47B0475B13A9543390BC8 /* critical.caf */; }; - DE965737FE2DAE9FE692769E /* alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = 0FC34B523FE5A50C920506D5 /* alarm.caf */; }; - A413B305CB4C4009DA09BE57 /* bloom.caf in Resources */ = {isa = PBXBuildFile; fileRef = 8FB2394478FF679F436E8EF1 /* bloom.caf */; }; - 230BE095719B8D8969B32A9C /* bloop.caf in Resources */ = {isa = PBXBuildFile; fileRef = AF16A5EDEB9DF756890E0C09 /* bloop.caf */; }; - 9B8FCBDD6E3A9E603C4AABAD /* bright_alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = 270F994CD56D566028B3CB25 /* bright_alarm.caf */; }; - 9960C6964DD51D81093FAD5D /* chime.caf in Resources */ = {isa = PBXBuildFile; fileRef = 3F7A1D72697082DC3A14587E /* chime.caf */; }; - 824A01CBE97A4F7A9D32F7D6 /* clear_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = 4A645E0E2DDA534A635C9201 /* clear_chimes.caf */; }; - 01414522FC033F2B7A9B223A /* crying.caf in Resources */ = {isa = PBXBuildFile; fileRef = 85203550670F2E9BE92F27D8 /* crying.caf */; }; - 2C694BFD5806E573AFAB5E2E /* dings.caf in Resources */ = {isa = PBXBuildFile; fileRef = 62F7CB5D5DC337E705032AC7 /* dings.caf */; }; - A4574F416AD62A1FCDE36D7D /* high_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = 491F8F0D89972E9D8903CFA7 /* high_chimes.caf */; }; - FA37F6EC10FF02D4F985D724 /* honk.caf in Resources */ = {isa = PBXBuildFile; fileRef = 6D5FCC7207E50ACC682E9E6E /* honk.caf */; }; - 0A02E77AD7536C322933D49B /* minimal.caf in Resources */ = {isa = PBXBuildFile; fileRef = 74145BE3C46270883D295A1F /* minimal.caf */; }; - 33644743F20B3706E3107FAC /* mood_synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = BEC0BA802BE613F144AC3A70 /* mood_synth.caf */; }; - A2779286E117BD3627DA0618 /* simple.caf in Resources */ = {isa = PBXBuildFile; fileRef = 5181B60CBF3CB2DA537F0475 /* simple.caf */; }; - D6E28676C2C7751C77C7F2FB /* spring.caf in Resources */ = {isa = PBXBuildFile; fileRef = 9471E156FC10D6D0FF219C77 /* spring.caf */; }; - CB1AF8155B1761A30ACA5591 /* synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = 83081FFB0497A4596F597830 /* synth.caf */; }; - 16E5A3BC4D931CE6AED18518 /* trill.caf in Resources */ = {isa = PBXBuildFile; fileRef = 21F13EB666EBFDD03F99CB7E /* trill.caf */; }; - 124B300527D84BE2A1233A91 /* urgent_low.caf in Resources */ = {isa = PBXBuildFile; fileRef = C9EA3F48338B49BD9C6BD0F9 /* urgent_low.caf */; }; 1DB1CA4D24A55F0000B3B94C /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1CA4C24A55F0000B3B94C /* Image.swift */; }; 1DB619AC270BAD3D006C9D07 /* VersionUpdateViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB619AB270BAD3D006C9D07 /* VersionUpdateViewModel.swift */; }; 1DDE273D24AEA4B000796622 /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB1CA4E24A56D7600B3B94C /* SettingsViewModel.swift */; }; - FEEDB0000000000000000001 /* StatisticsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000001 /* StatisticsViewModel.swift */; }; 1DDE273E24AEA4B000796622 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */; }; - FEEDB0000000000000000004 /* TimeInRangeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000004 /* TimeInRangeBar.swift */; }; - FEEDB0000000000000000003 /* AGPChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000003 /* AGPChartView.swift */; }; - FEEDB0000000000000000002 /* StatisticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000002 /* StatisticsView.swift */; }; 1DDE274024AEA4F200796622 /* NotificationsCriticalAlertPermissionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA46B5F2492E2E300D71A63 /* NotificationsCriticalAlertPermissionsView.swift */; }; 1DFE9E172447B6270082C280 /* UserNotificationAlertSchedulerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DFE9E162447B6270082C280 /* UserNotificationAlertSchedulerTests.swift */; }; + 230BE095719B8D8969B32A9C /* Loop/Resources/Sounds/bloop.caf in Resources */ = {isa = PBXBuildFile; fileRef = AF16A5EDEB9DF756890E0C09 /* Loop/Resources/Sounds/bloop.caf */; }; + 2C694BFD5806E573AFAB5E2E /* Loop/Resources/Sounds/dings.caf in Resources */ = {isa = PBXBuildFile; fileRef = 62F7CB5D5DC337E705032AC7 /* Loop/Resources/Sounds/dings.caf */; }; + 33644743F20B3706E3107FAC /* Loop/Resources/Sounds/mood_synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = BEC0BA802BE613F144AC3A70 /* Loop/Resources/Sounds/mood_synth.caf */; }; 3ED3198A2EB659E600820BCF /* GlucoseLiveActivityConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED319882EB659E600820BCF /* GlucoseLiveActivityConfiguration.swift */; }; 3ED3198B2EB659E600820BCF /* ChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED319872EB659E600820BCF /* ChartView.swift */; }; 3ED3198C2EB659E600820BCF /* BasalViewActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ED319862EB659E600820BCF /* BasalViewActivity.swift */; }; @@ -130,7 +111,6 @@ 430D85891F44037000AF2D4F /* HUDViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430D85881F44037000AF2D4F /* HUDViewTableViewCell.swift */; }; 4311FB9B1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4311FB9A1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift */; }; 431A8C401EC6E8AB00823B9C /* CircleMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 431A8C3F1EC6E8AB00823B9C /* CircleMaskView.swift */; }; - 4326BA641F3A44D9007CCAD4 /* ChartLineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4326BA631F3A44D9007CCAD4 /* ChartLineModel.swift */; }; 4328E0281CFBE2C500E199AA /* CLKComplicationTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0221CFBE2C500E199AA /* CLKComplicationTemplate.swift */; }; 4328E02A1CFBE2C500E199AA /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0241CFBE2C500E199AA /* UIColor.swift */; }; 4328E02B1CFBE2C500E199AA /* WKAlertAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4328E0251CFBE2C500E199AA /* WKAlertAction.swift */; }; @@ -252,6 +232,7 @@ 4FF4D0F81E1725B000846527 /* NibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434F54561D287FDB002A9274 /* NibLoadable.swift */; }; 7D23667D21250C7E0028B67D /* LocalizedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D23667C21250C7E0028B67D /* LocalizedString.swift */; }; 7E69CFFC2A16A77E00203CBD /* ResetLoopManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */; }; + 824A01CBE97A4F7A9D32F7D6 /* Loop/Resources/Sounds/clear_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = 4A645E0E2DDA534A635C9201 /* Loop/Resources/Sounds/clear_chimes.caf */; }; 841306BB2F7F0D9C00AF0320 /* ReferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841306BA2F7F0D9C00AF0320 /* ReferencesView.swift */; }; 84213C752D932F0F00642E78 /* InsulinDeliveryLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84213C742D932F0F00642E78 /* InsulinDeliveryLog.swift */; }; 84213C892D94941000642E78 /* InsulinDeliveryLogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84213C882D94941000642E78 /* InsulinDeliveryLogEvent.swift */; }; @@ -270,7 +251,6 @@ 8446319F2F5A2AB3003825AE /* PresetsPerformanceHistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8446319E2F5A2AA9003825AE /* PresetsPerformanceHistoryViewModel.swift */; }; 847F23432E4543140035C864 /* ActivePresetBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847F23422E4543140035C864 /* ActivePresetBanner.swift */; }; 8496F7312B5711C4003E672C /* ContentMargin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8496F7302B5711C4003E672C /* ContentMargin.swift */; }; - 84A7B5502D2D972C00B6D202 /* Image+Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */; }; 84AA81D32A4A27A3000B658B /* LoopWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D22A4A27A3000B658B /* LoopWidgets.swift */; }; 84AA81D62A4A28AF000B658B /* WidgetBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D52A4A28AF000B658B /* WidgetBackground.swift */; }; 84AA81D82A4A2910000B658B /* StatusWidgetTimelimeEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D72A4A2910000B658B /* StatusWidgetTimelimeEntry.swift */; }; @@ -348,6 +328,12 @@ 89F9119424358E4500ECCAF3 /* CarbAbsorptionTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F9119324358E4500ECCAF3 /* CarbAbsorptionTime.swift */; }; 89F9119624358E6900ECCAF3 /* BolusPickerValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F9119524358E6900ECCAF3 /* BolusPickerValues.swift */; }; 89FE21AD24AC57E30033F501 /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89FE21AC24AC57E30033F501 /* Collection.swift */; }; + 9960C6964DD51D81093FAD5D /* Loop/Resources/Sounds/chime.caf in Resources */ = {isa = PBXBuildFile; fileRef = 3F7A1D72697082DC3A14587E /* Loop/Resources/Sounds/chime.caf */; }; + 9B8FCBDD6E3A9E603C4AABAD /* Loop/Resources/Sounds/bright_alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = 270F994CD56D566028B3CB25 /* Loop/Resources/Sounds/bright_alarm.caf */; }; + A1B2C3D40000000000000002 /* GlucoseAlertManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D40000000000000001 /* GlucoseAlertManagerTests.swift */; }; + A2779286E117BD3627DA0618 /* Loop/Resources/Sounds/simple.caf in Resources */ = {isa = PBXBuildFile; fileRef = 5181B60CBF3CB2DA537F0475 /* Loop/Resources/Sounds/simple.caf */; }; + A413B305CB4C4009DA09BE57 /* Loop/Resources/Sounds/bloom.caf in Resources */ = {isa = PBXBuildFile; fileRef = 8FB2394478FF679F436E8EF1 /* Loop/Resources/Sounds/bloom.caf */; }; + A4574F416AD62A1FCDE36D7D /* Loop/Resources/Sounds/high_chimes.caf in Resources */ = {isa = PBXBuildFile; fileRef = 491F8F0D89972E9D8903CFA7 /* Loop/Resources/Sounds/high_chimes.caf */; }; A91D2A3F26CF0FF80023B075 /* IconTitleSubtitleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91D2A3E26CF0FF80023B075 /* IconTitleSubtitleTableViewCell.swift */; }; A91E4C2124F867A700BE9213 /* StoredAlertTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91E4C2024F867A700BE9213 /* StoredAlertTests.swift */; }; A91E4C2324F86F1000BE9213 /* CriticalEventLogExportManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A91E4C2224F86F1000BE9213 /* CriticalEventLogExportManagerTests.swift */; }; @@ -459,7 +445,6 @@ C10C57FE2E71E87D00A4825C /* ActiveOverrideView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10C57FD2E71E87400A4825C /* ActiveOverrideView.swift */; }; C110888D2A3913C600BA4898 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = C110888C2A3913C600BA4898 /* BuildDetails.swift */; }; C11445B22DA98A3400034864 /* CorrectionRangeInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11445B12DA98A2D00034864 /* CorrectionRangeInformationView.swift */; }; - C11B9D5B286778A800500CF8 /* SwiftCharts in Frameworks */ = {isa = PBXBuildFile; productRef = C11B9D5A286778A800500CF8 /* SwiftCharts */; }; C11B9D5E286778D000500CF8 /* LoopKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C11B9D5D286778D000500CF8 /* LoopKitUI.framework */; }; C11B9D62286779C000500CF8 /* MockKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C11B9D60286779C000500CF8 /* MockKit.framework */; }; C11B9D63286779C000500CF8 /* MockKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C11B9D60286779C000500CF8 /* MockKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -485,9 +470,7 @@ C151634E2FA2C9C800FEECE8 /* RequiredVersionUpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C151634D2FA2C9C800FEECE8 /* RequiredVersionUpdateView.swift */; }; C152B9F52C9C7D4A00ACBC06 /* AutomationHistoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = C152B9F42C9C7D4A00ACBC06 /* AutomationHistoryEntry.swift */; }; C152B9F72C9C7EF100ACBC06 /* AutomationHistoryEntryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C152B9F62C9C7EF100ACBC06 /* AutomationHistoryEntryTests.swift */; }; - FEEDB0000000000000000005 /* GlucoseStatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000005 /* GlucoseStatisticsTests.swift */; }; C1550B0C2E6F249A009369DC /* LoopCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1550B0B2E6F249A009369DC /* LoopCircleView.swift */; }; - C15A8C492A7305B1009D736B /* SwiftCharts in Frameworks */ = {isa = PBXBuildFile; productRef = C1E3DC4628595FAA00CA19FF /* SwiftCharts */; }; C165756F2534C468004AE16E /* SimpleBolusViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C165756E2534C468004AE16E /* SimpleBolusViewModelTests.swift */; }; C16575712538A36B004AE16E /* CGMStalenessMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16575702538A36B004AE16E /* CGMStalenessMonitor.swift */; }; C16575732538AFF6004AE16E /* CGMStalenessMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16575722538AFF6004AE16E /* CGMStalenessMonitorTests.swift */; }; @@ -533,6 +516,7 @@ C19E23B62E83513400C20D83 /* PresetActivateCrownConfirm.swift in Sources */ = {isa = PBXBuildFile; fileRef = C19E23B52E83512A00C20D83 /* PresetActivateCrownConfirm.swift */; }; C19E23B82E83566700C20D83 /* CircularProgressWithCheckmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = C19E23B72E83566300C20D83 /* CircularProgressWithCheckmark.swift */; }; C19F48742560ABFB003632D7 /* NSBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430DA58D1D4AEC230097D1CA /* NSBundle.swift */; }; + C1A1A00001000000000000A1 /* CriticalAlertAlarmScheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A1A00001000000000000A2 /* CriticalAlertAlarmScheduler.swift */; }; C1AD4200256D61E500164DDD /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AD41FF256D61E500164DDD /* Comparable.swift */; }; C1AF062329426300002C1B19 /* ManualGlucoseEntryRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF062229426300002C1B19 /* ManualGlucoseEntryRow.swift */; }; C1B80D632AF97D7200AB7705 /* LoopDataManager+CarbAbsorption.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B80D622AF97D7200AB7705 /* LoopDataManager+CarbAbsorption.swift */; }; @@ -554,7 +538,6 @@ C1DE5D23251BFC4D00439E49 /* SimpleBolusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1DE5D22251BFC4D00439E49 /* SimpleBolusView.swift */; }; C1E2773E224177C000354103 /* ClockKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1E2773D224177C000354103 /* ClockKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; C1E3862628247C6100F561A4 /* StoredLoopNotRunningNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E3862428247B7100F561A4 /* StoredLoopNotRunningNotification.swift */; }; - C1E3DC4928595FAA00CA19FF /* SwiftCharts in Embed Frameworks */ = {isa = PBXBuildFile; productRef = C1E3DC4628595FAA00CA19FF /* SwiftCharts */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; C1ED6C612E79BBA5002F91C2 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1ED6C602E79BB9C002F91C2 /* NotificationManager.swift */; }; C1ED6C622E79BBA5002F91C2 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1ED6C602E79BB9C002F91C2 /* NotificationManager.swift */; }; C1ED6C642E7C6DB9002F91C2 /* SettingsRequestUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C10C57E82E705CCB00A4825C /* SettingsRequestUserInfo.swift */; }; @@ -588,8 +571,6 @@ C1ED6C832E7D8E3D002F91C2 /* AcknowledgeAlertUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1ED6C812E7D8E36002F91C2 /* AcknowledgeAlertUserInfo.swift */; }; C1EE9E812A38D0FB0064784A /* BuildDetails.plist in Resources */ = {isa = PBXBuildFile; fileRef = C1EE9E802A38D0FB0064784A /* BuildDetails.plist */; }; C1EF747228D6A44A00C8C083 /* CrashRecoveryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1EF747128D6A44A00C8C083 /* CrashRecoveryManager.swift */; }; - C1F00C60285A802A006302C5 /* SwiftCharts in Frameworks */ = {isa = PBXBuildFile; productRef = C1F00C5F285A802A006302C5 /* SwiftCharts */; }; - C1F00C78285A8256006302C5 /* SwiftCharts in Embed Frameworks */ = {isa = PBXBuildFile; productRef = C1F00C5F285A802A006302C5 /* SwiftCharts */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; C1F2075C26D6F9B0007AB7EB /* AppExpirationAlerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F2075B26D6F9B0007AB7EB /* AppExpirationAlerter.swift */; }; C1F2CAAA2B76B3EE00D7F581 /* TempBasalRecommendation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F2CAA92B76B3EE00D7F581 /* TempBasalRecommendation.swift */; }; C1F2CAAC2B7A980600D7F581 /* BasalRelativeDose.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F2CAAB2B7A980600D7F581 /* BasalRelativeDose.swift */; }; @@ -598,13 +579,20 @@ C1FAD5192E7E0C3400F7FAD9 /* ChartPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FAD5182E7E0C3100F7FAD9 /* ChartPageView.swift */; }; C1FB428C217806A400FAB378 /* StateColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428B217806A300FAB378 /* StateColorPalette.swift */; }; C1FB428F217921D600FAB378 /* PumpManagerUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1FB428E217921D600FAB378 /* PumpManagerUI.swift */; }; + C9A47B0180AAB1FC572D3EFE /* CriticalAlertAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0175B13A9543390BC5 /* CriticalAlertAudioPlayer.swift */; }; + C9A47B0280AAB1FC572D3EFF /* GlucoseAlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0275B13A9543390BC6 /* GlucoseAlertManager.swift */; }; + C9A47B0380AAB1FC572D3F00 /* GlucoseAlertSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9A47B0375B13A9543390BC7 /* GlucoseAlertSettingsView.swift */; }; + C9A47B0480AAB1FC572D3F01 /* Loop/Resources/Sounds/critical.caf in Resources */ = {isa = PBXBuildFile; fileRef = C9A47B0475B13A9543390BC8 /* Loop/Resources/Sounds/critical.caf */; }; + C9SCENED0000000000000001 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9SCENED0000000000000002 /* SceneDelegate.swift */; }; + CB1AF8155B1761A30ACA5591 /* Loop/Resources/Sounds/synth.caf in Resources */ = {isa = PBXBuildFile; fileRef = 83081FFB0497A4596F597830 /* Loop/Resources/Sounds/synth.caf */; }; + D6E28676C2C7751C77C7F2FB /* Loop/Resources/Sounds/spring.caf in Resources */ = {isa = PBXBuildFile; fileRef = 9471E156FC10D6D0FF219C77 /* Loop/Resources/Sounds/spring.caf */; }; DD3DBD292A33AFE9000F8B5B /* IntegralRetrospectiveCorrectionSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3DBD282A33AFE9000F8B5B /* IntegralRetrospectiveCorrectionSelectionView.swift */; }; DDC389F62A2B61750066E2E8 /* ApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F52A2B61750066E2E8 /* ApplicationFactorStrategy.swift */; }; - FEEDB0000000000000000000 /* GlucoseStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000000 /* GlucoseStatistics.swift */; }; DDC389F82A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F72A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift */; }; DDC389FA2A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389F92A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift */; }; DDC389FC2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */; }; DDC389FE2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC389FD2A2C4C830066E2E8 /* GlucoseBasedApplicationFactorSelectionView.swift */; }; + DE965737FE2DAE9FE692769E /* Loop/Resources/Sounds/alarm.caf in Resources */ = {isa = PBXBuildFile; fileRef = 0FC34B523FE5A50C920506D5 /* Loop/Resources/Sounds/alarm.caf */; }; E93E865424DB6CBA00FF40C8 /* retrospective_output.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865324DB6CBA00FF40C8 /* retrospective_output.json */; }; E93E865624DB731900FF40C8 /* predicted_glucose_without_retrospective.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865524DB731900FF40C8 /* predicted_glucose_without_retrospective.json */; }; E93E865824DB75BE00FF40C8 /* predicted_glucose_very_negative.json in Resources */ = {isa = PBXBuildFile; fileRef = E93E865724DB75BD00FF40C8 /* predicted_glucose_very_negative.json */; }; @@ -644,13 +632,19 @@ E9C00EF324C6222400628F35 /* LoopSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C00EEF24C620EF00628F35 /* LoopSettings.swift */; }; E9C00EF524C623EF00628F35 /* LoopSettings+Loop.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C00EF424C623EF00628F35 /* LoopSettings+Loop.swift */; }; E9C58A7324DB4A2700487A17 /* LoopDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C58A7124DB489100487A17 /* LoopDataManagerTests.swift */; }; - A1B2C3D40000000000000002 /* GlucoseAlertManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D40000000000000001 /* GlucoseAlertManagerTests.swift */; }; E9C58A7C24DB529A00487A17 /* momentum_effect_bouncing.json in Resources */ = {isa = PBXBuildFile; fileRef = E9C58A7724DB529A00487A17 /* momentum_effect_bouncing.json */; }; E9C58A7D24DB529A00487A17 /* basal_profile.json in Resources */ = {isa = PBXBuildFile; fileRef = E9C58A7824DB529A00487A17 /* basal_profile.json */; }; E9C58A7E24DB529A00487A17 /* dynamic_glucose_effect_partially_observed.json in Resources */ = {isa = PBXBuildFile; fileRef = E9C58A7924DB529A00487A17 /* dynamic_glucose_effect_partially_observed.json */; }; E9C58A7F24DB529A00487A17 /* counteraction_effect_falling_glucose.json in Resources */ = {isa = PBXBuildFile; fileRef = E9C58A7A24DB529A00487A17 /* counteraction_effect_falling_glucose.json */; }; E9C58A8024DB529A00487A17 /* insulin_effect.json in Resources */ = {isa = PBXBuildFile; fileRef = E9C58A7B24DB529A00487A17 /* insulin_effect.json */; }; + FA37F6EC10FF02D4F985D724 /* Loop/Resources/Sounds/honk.caf in Resources */ = {isa = PBXBuildFile; fileRef = 6D5FCC7207E50ACC682E9E6E /* Loop/Resources/Sounds/honk.caf */; }; FADE0001000000000000DE02 /* DevelopmentBranchAlerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = FADE0001000000000000DE01 /* DevelopmentBranchAlerter.swift */; }; + FEEDB0000000000000000000 /* GlucoseStatistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000000 /* GlucoseStatistics.swift */; }; + FEEDB0000000000000000001 /* StatisticsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000001 /* StatisticsViewModel.swift */; }; + FEEDB0000000000000000002 /* Statistics/StatisticsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000002 /* Statistics/StatisticsView.swift */; }; + FEEDB0000000000000000003 /* Statistics/AGPChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000003 /* Statistics/AGPChartView.swift */; }; + FEEDB0000000000000000004 /* Statistics/TimeInRangeBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000004 /* Statistics/TimeInRangeBar.swift */; }; + FEEDB0000000000000000005 /* GlucoseStatisticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEEDF0000000000000000005 /* GlucoseStatisticsTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -743,7 +737,6 @@ C11B9D63286779C000500CF8 /* MockKit.framework in Embed Frameworks */, C19C8BBB28651DFB0056D5E4 /* TrueTime.framework in Embed Frameworks */, C11B9D65286779C000500CF8 /* MockKitUI.framework in Embed Frameworks */, - C1F00C78285A8256006302C5 /* SwiftCharts in Embed Frameworks */, C19C8BBF28651E3D0056D5E4 /* LoopKit.framework in Embed Frameworks */, 43D9FFD721EAE05D00AF44BF /* LoopCore.framework in Embed Frameworks */, ); @@ -780,7 +773,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - C1E3DC4928595FAA00CA19FF /* SwiftCharts in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -788,6 +780,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0FC34B523FE5A50C920506D5 /* Loop/Resources/Sounds/alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/alarm.caf; sourceTree = SOURCE_ROOT; }; 142CB7582A60BF2E0075748A /* EditMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditMode.swift; sourceTree = ""; }; 142CB75A2A60BFC30075748A /* FavoriteFoodsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FavoriteFoodsView.swift; sourceTree = ""; }; 1452F4A82A851C9400F8B9E4 /* FavoriteFoodAddEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteFoodAddEditViewModel.swift; sourceTree = ""; }; @@ -841,38 +834,14 @@ 1DA7A84124476EAD008257F0 /* AlertManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertManagerTests.swift; sourceTree = ""; }; 1DA7A84324477698008257F0 /* InAppModalAlertSchedulerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppModalAlertSchedulerTests.swift; sourceTree = ""; }; 1DB1065024467E18005542BD /* AlertManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertManager.swift; sourceTree = ""; }; - C9A47B0175B13A9543390BC5 /* CriticalAlertAudioPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CriticalAlertAudioPlayer.swift; sourceTree = ""; }; - C1A1A00001000000000000A2 /* CriticalAlertAlarmScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CriticalAlertAlarmScheduler.swift; sourceTree = ""; }; - C9A47B0275B13A9543390BC6 /* GlucoseAlertManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseAlertManager.swift; sourceTree = ""; }; - C9A47B0375B13A9543390BC7 /* GlucoseAlertSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseAlertSettingsView.swift; sourceTree = ""; }; - C9A47B0475B13A9543390BC8 /* critical.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/critical.caf"; sourceTree = SOURCE_ROOT; }; - 0FC34B523FE5A50C920506D5 /* alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/alarm.caf"; sourceTree = SOURCE_ROOT; }; - 8FB2394478FF679F436E8EF1 /* bloom.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/bloom.caf"; sourceTree = SOURCE_ROOT; }; - AF16A5EDEB9DF756890E0C09 /* bloop.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/bloop.caf"; sourceTree = SOURCE_ROOT; }; - 270F994CD56D566028B3CB25 /* bright_alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/bright_alarm.caf"; sourceTree = SOURCE_ROOT; }; - 3F7A1D72697082DC3A14587E /* chime.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/chime.caf"; sourceTree = SOURCE_ROOT; }; - 4A645E0E2DDA534A635C9201 /* clear_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/clear_chimes.caf"; sourceTree = SOURCE_ROOT; }; - 85203550670F2E9BE92F27D8 /* crying.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/crying.caf"; sourceTree = SOURCE_ROOT; }; - 62F7CB5D5DC337E705032AC7 /* dings.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/dings.caf"; sourceTree = SOURCE_ROOT; }; - 491F8F0D89972E9D8903CFA7 /* high_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/high_chimes.caf"; sourceTree = SOURCE_ROOT; }; - 6D5FCC7207E50ACC682E9E6E /* honk.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/honk.caf"; sourceTree = SOURCE_ROOT; }; - 74145BE3C46270883D295A1F /* minimal.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/minimal.caf"; sourceTree = SOURCE_ROOT; }; - BEC0BA802BE613F144AC3A70 /* mood_synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/mood_synth.caf"; sourceTree = SOURCE_ROOT; }; - 5181B60CBF3CB2DA537F0475 /* simple.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/simple.caf"; sourceTree = SOURCE_ROOT; }; - 9471E156FC10D6D0FF219C77 /* spring.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/spring.caf"; sourceTree = SOURCE_ROOT; }; - 83081FFB0497A4596F597830 /* synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/synth.caf"; sourceTree = SOURCE_ROOT; }; - 21F13EB666EBFDD03F99CB7E /* trill.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/trill.caf"; sourceTree = SOURCE_ROOT; }; - C9EA3F48338B49BD9C6BD0F9 /* urgent_low.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop/Resources/Sounds/urgent_low.caf"; sourceTree = SOURCE_ROOT; }; 1DB1CA4C24A55F0000B3B94C /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; 1DB1CA4E24A56D7600B3B94C /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = ""; }; - FEEDF0000000000000000001 /* StatisticsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatisticsViewModel.swift"; sourceTree = ""; }; 1DB619AB270BAD3D006C9D07 /* VersionUpdateViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionUpdateViewModel.swift; sourceTree = ""; }; 1DC63E7325351BDF004605DA /* TrueTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TrueTime.framework; path = Carthage/Build/iOS/TrueTime.framework; sourceTree = ""; }; 1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; - FEEDF0000000000000000004 /* TimeInRangeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Statistics/TimeInRangeBar.swift"; sourceTree = ""; }; - FEEDF0000000000000000003 /* AGPChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Statistics/AGPChartView.swift"; sourceTree = ""; }; - FEEDF0000000000000000002 /* StatisticsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Statistics/StatisticsView.swift"; sourceTree = ""; }; 1DFE9E162447B6270082C280 /* UserNotificationAlertSchedulerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNotificationAlertSchedulerTests.swift; sourceTree = ""; }; + 21F13EB666EBFDD03F99CB7E /* Loop/Resources/Sounds/trill.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/trill.caf; sourceTree = SOURCE_ROOT; }; + 270F994CD56D566028B3CB25 /* Loop/Resources/Sounds/bright_alarm.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/bright_alarm.caf; sourceTree = SOURCE_ROOT; }; 3ED319862EB659E600820BCF /* BasalViewActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasalViewActivity.swift; sourceTree = ""; }; 3ED319872EB659E600820BCF /* ChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartView.swift; sourceTree = ""; }; 3ED319882EB659E600820BCF /* GlucoseLiveActivityConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseLiveActivityConfiguration.swift; sourceTree = ""; }; @@ -886,6 +855,7 @@ 3ED3199E2EB65AFE00820BCF /* LocalizedString.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedString.swift; sourceTree = ""; }; 3ED319A02EB65B4100820BCF /* Bootstrap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bootstrap.swift; sourceTree = ""; }; 3ED319A22EB65DA300820BCF /* LiveActivityManagerProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveActivityManagerProxy.swift; sourceTree = ""; }; + 3F7A1D72697082DC3A14587E /* Loop/Resources/Sounds/chime.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/chime.caf; sourceTree = SOURCE_ROOT; }; 4302F4E01D4E9C8900F0FCAF /* TextFieldTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldTableViewController.swift; sourceTree = ""; }; 4302F4E21D4EA54200F0FCAF /* InsulinDeliveryTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InsulinDeliveryTableViewController.swift; sourceTree = ""; }; 430B29892041F54A00BA9F93 /* NSUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSUserDefaults.swift; sourceTree = ""; }; @@ -895,7 +865,6 @@ 4311FB9A1F37FE1B00D4C0A7 /* TitleSubtitleTextFieldTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleSubtitleTextFieldTableViewCell.swift; sourceTree = ""; }; 431A8C3F1EC6E8AB00823B9C /* CircleMaskView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircleMaskView.swift; sourceTree = ""; }; 431E73471FF95A900069B5F7 /* PersistenceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = ""; }; - 4326BA631F3A44D9007CCAD4 /* ChartLineModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartLineModel.swift; sourceTree = ""; }; 4328E0221CFBE2C500E199AA /* CLKComplicationTemplate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CLKComplicationTemplate.swift; sourceTree = ""; }; 4328E0231CFBE2C500E199AA /* NSUserDefaults+WatchApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSUserDefaults+WatchApp.swift"; sourceTree = ""; }; 4328E0241CFBE2C500E199AA /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; @@ -1020,6 +989,8 @@ 43F89CA222BDFBBC006BB54E /* UIActivityIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIActivityIndicatorView.swift; sourceTree = ""; }; 43FCEEA8221A615B0013DD30 /* StatusChartsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusChartsManager.swift; sourceTree = ""; }; 43FCEEAC221A66780013DD30 /* DateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateFormatter.swift; sourceTree = ""; }; + 491F8F0D89972E9D8903CFA7 /* Loop/Resources/Sounds/high_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/high_chimes.caf; sourceTree = SOURCE_ROOT; }; + 4A645E0E2DDA534A635C9201 /* Loop/Resources/Sounds/clear_chimes.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/clear_chimes.caf; sourceTree = SOURCE_ROOT; }; 4D3B40021D4A9DFE00BC6334 /* G4ShareSpy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = G4ShareSpy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4F08DE8E1E7BB871006741EA /* CollectionType+Loop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CollectionType+Loop.swift"; sourceTree = ""; }; 4F11D3BF20DCBEEC006E072C /* GlucoseBackfillRequestUserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBackfillRequestUserInfo.swift; sourceTree = ""; }; @@ -1043,6 +1014,10 @@ 4FC8C8001DEB93E400A1452E /* NSUserDefaults+StatusExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSUserDefaults+StatusExtension.swift"; sourceTree = ""; }; 4FDDD23620DC51DF00D04B16 /* LoopDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopDataManager.swift; sourceTree = ""; }; 4FF4D0FF1E18374700846527 /* WatchContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchContext.swift; sourceTree = ""; }; + 5181B60CBF3CB2DA537F0475 /* Loop/Resources/Sounds/simple.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/simple.caf; sourceTree = SOURCE_ROOT; }; + 62F7CB5D5DC337E705032AC7 /* Loop/Resources/Sounds/dings.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/dings.caf; sourceTree = SOURCE_ROOT; }; + 6D5FCC7207E50ACC682E9E6E /* Loop/Resources/Sounds/honk.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/honk.caf; sourceTree = SOURCE_ROOT; }; + 74145BE3C46270883D295A1F /* Loop/Resources/Sounds/minimal.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/minimal.caf; sourceTree = SOURCE_ROOT; }; 7D23667C21250C7E0028B67D /* LocalizedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LocalizedString.swift; path = LoopUI/Common/LocalizedString.swift; sourceTree = SOURCE_ROOT; }; 7D9BEF132335EC4B005DCFD6 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Intents.strings; sourceTree = ""; }; 7D9BEF292335EC58005DCFD6 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Intents.strings"; sourceTree = ""; }; @@ -1052,6 +1027,7 @@ 7D9BEF812335EC8B005DCFD6 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Intents.strings; sourceTree = ""; }; 7D9BF13A23370E8B005DCFD6 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Intents.strings; sourceTree = ""; }; 7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResetLoopManager.swift; sourceTree = ""; }; + 83081FFB0497A4596F597830 /* Loop/Resources/Sounds/synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/synth.caf; sourceTree = SOURCE_ROOT; }; 840A2F0D2C0F978E003D5E90 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 841306BA2F7F0D9C00AF0320 /* ReferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReferencesView.swift; sourceTree = ""; }; 84213C742D932F0F00642E78 /* InsulinDeliveryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinDeliveryLog.swift; sourceTree = ""; }; @@ -1071,7 +1047,6 @@ 8446319E2F5A2AA9003825AE /* PresetsPerformanceHistoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsPerformanceHistoryViewModel.swift; sourceTree = ""; }; 847F23422E4543140035C864 /* ActivePresetBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivePresetBanner.swift; sourceTree = ""; }; 8496F7302B5711C4003E672C /* ContentMargin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMargin.swift; sourceTree = ""; }; - 84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image+Optional.swift"; sourceTree = ""; }; 84AA81D22A4A27A3000B658B /* LoopWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopWidgets.swift; sourceTree = ""; }; 84AA81D52A4A28AF000B658B /* WidgetBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetBackground.swift; sourceTree = ""; }; 84AA81D72A4A2910000B658B /* StatusWidgetTimelimeEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusWidgetTimelimeEntry.swift; sourceTree = ""; }; @@ -1096,6 +1071,7 @@ 84EC162D2C9115CA00D220C5 /* DIYLoopUnitTestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DIYLoopUnitTestPlan.xctestplan; sourceTree = ""; }; 84F20DFC2D0B9C3A0089DF02 /* EditPresetDurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPresetDurationView.swift; sourceTree = ""; }; 84FA9D322CF7FD0D004162B4 /* PresetsHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsHistoryView.swift; sourceTree = ""; }; + 85203550670F2E9BE92F27D8 /* Loop/Resources/Sounds/crying.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/crying.caf; sourceTree = SOURCE_ROOT; }; 891B508424342BE1005DA578 /* CarbAndBolusFlowViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbAndBolusFlowViewModel.swift; sourceTree = ""; }; 892A5D29222EF60A008961AB /* MockKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = MockKit.framework; path = Carthage/Build/iOS/MockKit.framework; sourceTree = SOURCE_ROOT; }; 892A5D2B222EF60A008961AB /* MockKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = MockKitUI.framework; path = Carthage/Build/iOS/MockKitUI.framework; sourceTree = SOURCE_ROOT; }; @@ -1153,6 +1129,9 @@ 89F9119324358E4500ECCAF3 /* CarbAbsorptionTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbAbsorptionTime.swift; sourceTree = ""; }; 89F9119524358E6900ECCAF3 /* BolusPickerValues.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusPickerValues.swift; sourceTree = ""; }; 89FE21AC24AC57E30033F501 /* Collection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = ""; }; + 8FB2394478FF679F436E8EF1 /* Loop/Resources/Sounds/bloom.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/bloom.caf; sourceTree = SOURCE_ROOT; }; + 9471E156FC10D6D0FF219C77 /* Loop/Resources/Sounds/spring.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/spring.caf; sourceTree = SOURCE_ROOT; }; + A1B2C3D40000000000000001 /* GlucoseAlertManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertManagerTests.swift; sourceTree = ""; }; A900531A28D60862000BC15B /* Loop.shortcut */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop.shortcut; sourceTree = ""; }; A900531B28D608CA000BC15B /* Cancel Override.shortcut */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Cancel Override.shortcut"; sourceTree = ""; }; A900531C28D6090D000BC15B /* Loop Remote Overrides.shortcut */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Loop Remote Overrides.shortcut"; sourceTree = ""; }; @@ -1203,6 +1182,7 @@ A9F703742489C9A000C98AD8 /* GlucoseStore+SimulatedCoreData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GlucoseStore+SimulatedCoreData.swift"; sourceTree = ""; }; A9F703762489D8AA00C98AD8 /* PersistentDeviceLog+SimulatedCoreData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PersistentDeviceLog+SimulatedCoreData.swift"; sourceTree = ""; }; A9FB75F0252BE320004C7D3F /* BolusDosingDecision.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusDosingDecision.swift; sourceTree = ""; }; + AF16A5EDEB9DF756890E0C09 /* Loop/Resources/Sounds/bloop.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/bloop.caf; sourceTree = SOURCE_ROOT; }; B4001CED28CBBC82002FB414 /* AlertManagementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertManagementView.swift; sourceTree = ""; }; B40D07C6251A89D500C1C6D7 /* GlucoseDisplay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseDisplay.swift; sourceTree = ""; }; B429CAB22E97C7F300FA988E /* LoopStatusModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopStatusModalView.swift; sourceTree = ""; }; @@ -1260,6 +1240,7 @@ B66D1F422E6A5D6600471149 /* mul */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; name = mul; path = mul.lproj/Main.xcstrings; sourceTree = ""; }; B6F22EF72E95A03800CCA05F /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Intents.strings; sourceTree = ""; }; B6F22EF92E95A03C00CCA05F /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Intents.strings; sourceTree = ""; }; + BEC0BA802BE613F144AC3A70 /* Loop/Resources/Sounds/mood_synth.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/mood_synth.caf; sourceTree = SOURCE_ROOT; }; C1004DEF2981F5B700B8CF94 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/InfoPlist.strings; sourceTree = ""; }; C1004DFD2981F67A00B8CF94 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = ""; }; C1004E052981F6A100B8CF94 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1313,7 +1294,6 @@ C151634D2FA2C9C800FEECE8 /* RequiredVersionUpdateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequiredVersionUpdateView.swift; sourceTree = ""; }; C152B9F42C9C7D4A00ACBC06 /* AutomationHistoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutomationHistoryEntry.swift; sourceTree = ""; }; C152B9F62C9C7EF100ACBC06 /* AutomationHistoryEntryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutomationHistoryEntryTests.swift; sourceTree = ""; }; - FEEDF0000000000000000005 /* GlucoseStatisticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GlucoseStatisticsTests.swift"; sourceTree = ""; }; C1550B0B2E6F249A009369DC /* LoopCircleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopCircleView.swift; sourceTree = ""; }; C159C8192867857000A86EC0 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C159C8212867859800A86EC0 /* MockKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1361,6 +1341,7 @@ C19E23B72E83566300C20D83 /* CircularProgressWithCheckmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressWithCheckmark.swift; sourceTree = ""; }; C19E23B92E83607C00C20D83 /* DerivedAssetsBase.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = DerivedAssetsBase.xcassets; sourceTree = ""; }; C19F496225630504003632D7 /* Minizip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Minizip.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C1A1A00001000000000000A2 /* CriticalAlertAlarmScheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CriticalAlertAlarmScheduler.swift; sourceTree = ""; }; C1ABA1602E281D330049DF41 /* NotificationActionSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationActionSelection.swift; sourceTree = ""; }; C1AD41FF256D61E500164DDD /* Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; C1AF062229426300002C1B19 /* ManualGlucoseEntryRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualGlucoseEntryRow.swift; sourceTree = ""; }; @@ -1402,9 +1383,14 @@ C1FAD5182E7E0C3100F7FAD9 /* ChartPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartPageView.swift; sourceTree = ""; }; C1FB428B217806A300FAB378 /* StateColorPalette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateColorPalette.swift; sourceTree = ""; }; C1FB428E217921D600FAB378 /* PumpManagerUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpManagerUI.swift; sourceTree = ""; }; + C9A47B0175B13A9543390BC5 /* CriticalAlertAudioPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CriticalAlertAudioPlayer.swift; sourceTree = ""; }; + C9A47B0275B13A9543390BC6 /* GlucoseAlertManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseAlertManager.swift; sourceTree = ""; }; + C9A47B0375B13A9543390BC7 /* GlucoseAlertSettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseAlertSettingsView.swift; sourceTree = ""; }; + C9A47B0475B13A9543390BC8 /* Loop/Resources/Sounds/critical.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/critical.caf; sourceTree = SOURCE_ROOT; }; + C9EA3F48338B49BD9C6BD0F9 /* Loop/Resources/Sounds/urgent_low.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Loop/Resources/Sounds/urgent_low.caf; sourceTree = SOURCE_ROOT; }; + C9SCENED0000000000000002 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; DD3DBD282A33AFE9000F8B5B /* IntegralRetrospectiveCorrectionSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegralRetrospectiveCorrectionSelectionView.swift; sourceTree = ""; }; DDC389F52A2B61750066E2E8 /* ApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationFactorStrategy.swift; sourceTree = ""; }; - FEEDF0000000000000000000 /* GlucoseStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GlucoseStatistics.swift"; sourceTree = ""; }; DDC389F72A2B620B0066E2E8 /* GlucoseBasedApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseBasedApplicationFactorStrategy.swift; sourceTree = ""; }; DDC389F92A2B62470066E2E8 /* ConstantApplicationFactorStrategy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantApplicationFactorStrategy.swift; sourceTree = ""; }; DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SettingsView+algorithmExperimentsSection.swift"; sourceTree = ""; }; @@ -1446,7 +1432,6 @@ E9C00EEF24C620EF00628F35 /* LoopSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopSettings.swift; sourceTree = ""; }; E9C00EF424C623EF00628F35 /* LoopSettings+Loop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoopSettings+Loop.swift"; sourceTree = ""; }; E9C58A7124DB489100487A17 /* LoopDataManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopDataManagerTests.swift; sourceTree = ""; }; - A1B2C3D40000000000000001 /* GlucoseAlertManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseAlertManagerTests.swift; sourceTree = ""; }; E9C58A7724DB529A00487A17 /* momentum_effect_bouncing.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = momentum_effect_bouncing.json; sourceTree = ""; }; E9C58A7824DB529A00487A17 /* basal_profile.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = basal_profile.json; sourceTree = ""; }; E9C58A7924DB529A00487A17 /* dynamic_glucose_effect_partially_observed.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = dynamic_glucose_effect_partially_observed.json; sourceTree = ""; }; @@ -1455,6 +1440,12 @@ F5D9C01727DABBE0002E48F6 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Intents.strings; sourceTree = ""; }; F5E0BDD327E1D71C0033557E /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Intents.strings; sourceTree = ""; }; FADE0001000000000000DE01 /* DevelopmentBranchAlerter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevelopmentBranchAlerter.swift; sourceTree = ""; }; + FEEDF0000000000000000000 /* GlucoseStatistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseStatistics.swift; sourceTree = ""; }; + FEEDF0000000000000000001 /* StatisticsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatisticsViewModel.swift; sourceTree = ""; }; + FEEDF0000000000000000002 /* Statistics/StatisticsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Statistics/StatisticsView.swift; sourceTree = ""; }; + FEEDF0000000000000000003 /* Statistics/AGPChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Statistics/AGPChartView.swift; sourceTree = ""; }; + FEEDF0000000000000000004 /* Statistics/TimeInRangeBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Statistics/TimeInRangeBar.swift; sourceTree = ""; }; + FEEDF0000000000000000005 /* GlucoseStatisticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlucoseStatisticsTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1493,7 +1484,6 @@ C11B9D62286779C000500CF8 /* MockKit.framework in Frameworks */, C19C8BBE28651E3D0056D5E4 /* LoopKit.framework in Frameworks */, C19C8BBA28651DFB0056D5E4 /* TrueTime.framework in Frameworks */, - C1F00C60285A802A006302C5 /* SwiftCharts in Frameworks */, C19C8BC328651EAE0056D5E4 /* LoopTestingKit.framework in Frameworks */, C1735B1E2A0809830082BB8A /* ZIPFoundation in Frameworks */, C19C8BCE28651F520056D5E4 /* LoopKitUI.framework in Frameworks */, @@ -1521,7 +1511,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C15A8C492A7305B1009D736B /* SwiftCharts in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1530,7 +1519,6 @@ buildActionMask = 2147483647; files = ( C1CCF1122858FA900035389C /* LoopCore.framework in Frameworks */, - C11B9D5B286778A800500CF8 /* SwiftCharts in Frameworks */, C11B9D5E286778D000500CF8 /* LoopKitUI.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1744,6 +1732,7 @@ B4C6D2412EA7E38C006F5755 /* LocalizablePlural.xcstrings */, 437D9BA11D7B5203007245E8 /* Loop.xcconfig */, A951C5FF23E8AB51003E26DC /* Version.xcconfig */, + 84957A16300D5CDF0040E2EF /* Recovered References */, ); sourceTree = ""; }; @@ -1772,6 +1761,7 @@ 43F5C2D41B92A4A6003EB13D /* Info.plist */, C1EE9E802A38D0FB0064784A /* BuildDetails.plist */, 43776F8F1B8022E90074EA36 /* AppDelegate.swift */, + C9SCENED0000000000000002 /* SceneDelegate.swift */, 1D12D3B82548EFDD00B53E8B /* main.swift */, 43776F9A1B8022E90074EA36 /* LaunchScreen.storyboard */, 43776F951B8022E90074EA36 /* Main.storyboard */, @@ -1983,7 +1973,6 @@ C13DA2AF24F6C7690098BB29 /* UIViewController.swift */, 430B29922041F5B200BA9F93 /* UserDefaults+Loop.swift */, A9B607AF247F000F00792BE4 /* UserNotifications+Loop.swift */, - 84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */, ); path = Extensions; sourceTree = ""; @@ -2042,9 +2031,9 @@ B43B5C532EAFBF110096A6AE /* RecentGlucoseTableViewCell.xib */, C151634D2FA2C9C800FEECE8 /* RequiredVersionUpdateView.swift */, 1DE09BA824A3E23F009EE9F9 /* SettingsView.swift */, - FEEDF0000000000000000004 /* TimeInRangeBar.swift */, - FEEDF0000000000000000003 /* AGPChartView.swift */, - FEEDF0000000000000000002 /* StatisticsView.swift */, + FEEDF0000000000000000004 /* Statistics/TimeInRangeBar.swift */, + FEEDF0000000000000000003 /* Statistics/AGPChartView.swift */, + FEEDF0000000000000000002 /* Statistics/StatisticsView.swift */, E4854073AAE5C2CB97167F63 /* HealthAccessView.swift */, DDC389FB2A2BC6670066E2E8 /* SettingsView+algorithmExperimentsSection.swift */, C1DE5D22251BFC4D00439E49 /* SimpleBolusView.swift */, @@ -2130,7 +2119,6 @@ B66D1F3D2E6A5D6600471149 /* Localizable.xcstrings */, B66D1F202E6A5D6500471149 /* InfoPlist.xcstrings */, 4FB76FC41E8C576800B39636 /* Extensions */, - 4F7528A61DFE20AE00C322D6 /* Models */, B42C950F24A3C44F00857C73 /* ViewModel */, 4F7528931DFE1E1600C322D6 /* Views */, 4F75288D1DFE1DC600C322D6 /* LoopUI.h */, @@ -2164,14 +2152,6 @@ path = Views; sourceTree = ""; }; - 4F7528A61DFE20AE00C322D6 /* Models */ = { - isa = PBXGroup; - children = ( - 4326BA631F3A44D9007CCAD4 /* ChartLineModel.swift */, - ); - path = Models; - sourceTree = ""; - }; 4F75F0052100146B00B5570E /* Scenes */ = { isa = PBXGroup; children = ( @@ -2300,6 +2280,31 @@ path = Training; sourceTree = ""; }; + 84957A16300D5CDF0040E2EF /* Recovered References */ = { + isa = PBXGroup; + children = ( + C9A47B0475B13A9543390BC8 /* Loop/Resources/Sounds/critical.caf */, + 0FC34B523FE5A50C920506D5 /* Loop/Resources/Sounds/alarm.caf */, + 8FB2394478FF679F436E8EF1 /* Loop/Resources/Sounds/bloom.caf */, + AF16A5EDEB9DF756890E0C09 /* Loop/Resources/Sounds/bloop.caf */, + 270F994CD56D566028B3CB25 /* Loop/Resources/Sounds/bright_alarm.caf */, + 3F7A1D72697082DC3A14587E /* Loop/Resources/Sounds/chime.caf */, + 4A645E0E2DDA534A635C9201 /* Loop/Resources/Sounds/clear_chimes.caf */, + 85203550670F2E9BE92F27D8 /* Loop/Resources/Sounds/crying.caf */, + 62F7CB5D5DC337E705032AC7 /* Loop/Resources/Sounds/dings.caf */, + 491F8F0D89972E9D8903CFA7 /* Loop/Resources/Sounds/high_chimes.caf */, + 6D5FCC7207E50ACC682E9E6E /* Loop/Resources/Sounds/honk.caf */, + 74145BE3C46270883D295A1F /* Loop/Resources/Sounds/minimal.caf */, + BEC0BA802BE613F144AC3A70 /* Loop/Resources/Sounds/mood_synth.caf */, + 5181B60CBF3CB2DA537F0475 /* Loop/Resources/Sounds/simple.caf */, + 9471E156FC10D6D0FF219C77 /* Loop/Resources/Sounds/spring.caf */, + 83081FFB0497A4596F597830 /* Loop/Resources/Sounds/synth.caf */, + 21F13EB666EBFDD03F99CB7E /* Loop/Resources/Sounds/trill.caf */, + C9EA3F48338B49BD9C6BD0F9 /* Loop/Resources/Sounds/urgent_low.caf */, + ); + name = "Recovered References"; + sourceTree = ""; + }; 84AA81D12A4A2778000B658B /* Components */ = { isa = PBXGroup; children = ( @@ -2831,7 +2836,6 @@ ); name = Loop; packageProductDependencies = ( - C1F00C5F285A802A006302C5 /* SwiftCharts */, C1D6EE9F2A06C7270047DE5C /* MKRingProgressView */, C1735B1D2A0809830082BB8A /* ZIPFoundation */, ); @@ -2911,7 +2915,6 @@ ); name = LoopTests; packageProductDependencies = ( - C1E3DC4628595FAA00CA19FF /* SwiftCharts */, ); productName = LoopTests; productReference = 43E2D90B1D20C581004DA55F /* LoopTests.xctest */; @@ -2933,7 +2936,6 @@ ); name = LoopUI; packageProductDependencies = ( - C11B9D5A286778A800500CF8 /* SwiftCharts */, ); productName = LoopUI; productReference = 4F75288B1DFE1DC600C322D6 /* LoopUI.framework */; @@ -3058,7 +3060,6 @@ ); mainGroup = 43776F831B8022E90074EA36; packageReferences = ( - C1CCF10B2858F4F70035389C /* XCRemoteSwiftPackageReference "SwiftCharts" */, C1D6EE9E2A06C7270047DE5C /* XCRemoteSwiftPackageReference "MKRingProgressView" */, C1735B1C2A0809830082BB8A /* XCRemoteSwiftPackageReference "ZIPFoundation" */, ); @@ -3099,24 +3100,24 @@ C13255D6223E7BE2008AF50C /* BolusProgressTableViewCell.xib in Resources */, C1EE9E812A38D0FB0064784A /* BuildDetails.plist in Resources */, 43FCBBC21E51710B00343C1B /* LaunchScreen.storyboard in Resources */, - C9A47B0480AAB1FC572D3F01 /* critical.caf in Resources */, - DE965737FE2DAE9FE692769E /* alarm.caf in Resources */, - A413B305CB4C4009DA09BE57 /* bloom.caf in Resources */, - 230BE095719B8D8969B32A9C /* bloop.caf in Resources */, - 9B8FCBDD6E3A9E603C4AABAD /* bright_alarm.caf in Resources */, - 9960C6964DD51D81093FAD5D /* chime.caf in Resources */, - 824A01CBE97A4F7A9D32F7D6 /* clear_chimes.caf in Resources */, - 01414522FC033F2B7A9B223A /* crying.caf in Resources */, - 2C694BFD5806E573AFAB5E2E /* dings.caf in Resources */, - A4574F416AD62A1FCDE36D7D /* high_chimes.caf in Resources */, - FA37F6EC10FF02D4F985D724 /* honk.caf in Resources */, - 0A02E77AD7536C322933D49B /* minimal.caf in Resources */, - 33644743F20B3706E3107FAC /* mood_synth.caf in Resources */, - A2779286E117BD3627DA0618 /* simple.caf in Resources */, - D6E28676C2C7751C77C7F2FB /* spring.caf in Resources */, - CB1AF8155B1761A30ACA5591 /* synth.caf in Resources */, - 16E5A3BC4D931CE6AED18518 /* trill.caf in Resources */, - 124B300527D84BE2A1233A91 /* urgent_low.caf in Resources */, + C9A47B0480AAB1FC572D3F01 /* Loop/Resources/Sounds/critical.caf in Resources */, + DE965737FE2DAE9FE692769E /* Loop/Resources/Sounds/alarm.caf in Resources */, + A413B305CB4C4009DA09BE57 /* Loop/Resources/Sounds/bloom.caf in Resources */, + 230BE095719B8D8969B32A9C /* Loop/Resources/Sounds/bloop.caf in Resources */, + 9B8FCBDD6E3A9E603C4AABAD /* Loop/Resources/Sounds/bright_alarm.caf in Resources */, + 9960C6964DD51D81093FAD5D /* Loop/Resources/Sounds/chime.caf in Resources */, + 824A01CBE97A4F7A9D32F7D6 /* Loop/Resources/Sounds/clear_chimes.caf in Resources */, + 01414522FC033F2B7A9B223A /* Loop/Resources/Sounds/crying.caf in Resources */, + 2C694BFD5806E573AFAB5E2E /* Loop/Resources/Sounds/dings.caf in Resources */, + A4574F416AD62A1FCDE36D7D /* Loop/Resources/Sounds/high_chimes.caf in Resources */, + FA37F6EC10FF02D4F985D724 /* Loop/Resources/Sounds/honk.caf in Resources */, + 0A02E77AD7536C322933D49B /* Loop/Resources/Sounds/minimal.caf in Resources */, + 33644743F20B3706E3107FAC /* Loop/Resources/Sounds/mood_synth.caf in Resources */, + A2779286E117BD3627DA0618 /* Loop/Resources/Sounds/simple.caf in Resources */, + D6E28676C2C7751C77C7F2FB /* Loop/Resources/Sounds/spring.caf in Resources */, + CB1AF8155B1761A30ACA5591 /* Loop/Resources/Sounds/synth.caf in Resources */, + 16E5A3BC4D931CE6AED18518 /* Loop/Resources/Sounds/trill.caf in Resources */, + 124B300527D84BE2A1233A91 /* Loop/Resources/Sounds/urgent_low.caf in Resources */, B405E35A24D2B1A400DD058D /* HUDAssets.xcassets in Resources */, A966152623EA5A26005D8B29 /* DefaultAssets.xcassets in Resources */, A966152723EA5A26005D8B29 /* DerivedAssets.xcassets in Resources */, @@ -3390,6 +3391,7 @@ E9B355292935919E0076AB04 /* MissedMealSettings.swift in Sources */, 43A51E1F1EB6D62A000736CC /* CarbAbsorptionViewController.swift in Sources */, 43776F901B8022E90074EA36 /* AppDelegate.swift in Sources */, + C9SCENED0000000000000001 /* SceneDelegate.swift in Sources */, 4372E48B213CB5F00068E043 /* Double.swift in Sources */, 84DF48C12F6A0AED00BEDB40 /* Double+Closest.swift in Sources */, 430B29932041F5B300BA9F93 /* UserDefaults+Loop.swift in Sources */, @@ -3553,9 +3555,9 @@ 1D12D3B92548EFDD00B53E8B /* main.swift in Sources */, A9DCF32A25B0FABF00C89088 /* LoopUIColorPalette+Default.swift in Sources */, 1DDE273E24AEA4B000796622 /* SettingsView.swift in Sources */, - FEEDB0000000000000000004 /* TimeInRangeBar.swift in Sources */, - FEEDB0000000000000000003 /* AGPChartView.swift in Sources */, - FEEDB0000000000000000002 /* StatisticsView.swift in Sources */, + FEEDB0000000000000000004 /* Statistics/TimeInRangeBar.swift in Sources */, + FEEDB0000000000000000003 /* Statistics/AGPChartView.swift in Sources */, + FEEDB0000000000000000002 /* Statistics/StatisticsView.swift in Sources */, BAF043BF0BC70EC99AE79F71 /* HealthAccessView.swift in Sources */, A9B607B0247F000F00792BE4 /* UserNotifications+Loop.swift in Sources */, 43F89CA322BDFBBD006BB54E /* UIActivityIndicatorView.swift in Sources */, @@ -3612,7 +3614,6 @@ 439706E622D2E84900C81566 /* PredictionSettingTableViewCell.swift in Sources */, 430D85891F44037000AF2D4F /* HUDViewTableViewCell.swift in Sources */, 43A51E211EB6DBDD000736CC /* LoopChartsTableViewController.swift in Sources */, - 84A7B5502D2D972C00B6D202 /* Image+Optional.swift in Sources */, 8968B1122408B3520074BB48 /* UIFont.swift in Sources */, 1452F4A92A851C9400F8B9E4 /* FavoriteFoodAddEditViewModel.swift in Sources */, 438D42FB1D7D11A4003244B0 /* PredictionInputEffectTableViewCell.swift in Sources */, @@ -3856,7 +3857,6 @@ files = ( 7D23667D21250C7E0028B67D /* LocalizedString.swift in Sources */, 4FF4D0F81E1725B000846527 /* NibLoadable.swift in Sources */, - 4326BA641F3A44D9007CCAD4 /* ChartLineModel.swift in Sources */, 4374B5F0209D857E00D17AA8 /* OSLog.swift in Sources */, B4E96D4F248A6E20002DABAD /* CGMStatusHUDView.swift in Sources */, B4E96D4B248A6B6E002DABAD /* DeviceStatusHUDView.swift in Sources */, @@ -5187,14 +5187,6 @@ revision = c67b7509ec82ee2b4b0ab3f97742b94ed9692494; }; }; - C1CCF10B2858F4F70035389C /* XCRemoteSwiftPackageReference "SwiftCharts" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/ivanschuetz/SwiftCharts"; - requirement = { - branch = master; - kind = branch; - }; - }; C1D6EE9E2A06C7270047DE5C /* XCRemoteSwiftPackageReference "MKRingProgressView" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/maxkonovalov/MKRingProgressView.git"; @@ -5206,11 +5198,6 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - C11B9D5A286778A800500CF8 /* SwiftCharts */ = { - isa = XCSwiftPackageProductDependency; - package = C1CCF10B2858F4F70035389C /* XCRemoteSwiftPackageReference "SwiftCharts" */; - productName = SwiftCharts; - }; C1735B1D2A0809830082BB8A /* ZIPFoundation */ = { isa = XCSwiftPackageProductDependency; package = C1735B1C2A0809830082BB8A /* XCRemoteSwiftPackageReference "ZIPFoundation" */; @@ -5221,16 +5208,6 @@ package = C1D6EE9E2A06C7270047DE5C /* XCRemoteSwiftPackageReference "MKRingProgressView" */; productName = MKRingProgressView; }; - C1E3DC4628595FAA00CA19FF /* SwiftCharts */ = { - isa = XCSwiftPackageProductDependency; - package = C1CCF10B2858F4F70035389C /* XCRemoteSwiftPackageReference "SwiftCharts" */; - productName = SwiftCharts; - }; - C1F00C5F285A802A006302C5 /* SwiftCharts */ = { - isa = XCSwiftPackageProductDependency; - package = C1CCF10B2858F4F70035389C /* XCRemoteSwiftPackageReference "SwiftCharts" */; - productName = SwiftCharts; - }; /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ diff --git a/Loop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Loop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9cb3736d66..bbc0c86c20 100644 --- a/Loop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Loop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,32 +1,23 @@ { - "originHash" : "c4cada90348e9cd61ccdc1fdd95d021f037913f127c30ed5678702f19c1b75db", - "pins" : [ + "originHash": "c4cada90348e9cd61ccdc1fdd95d021f037913f127c30ed5678702f19c1b75db", + "pins": [ { - "identity" : "mkringprogressview", - "kind" : "remoteSourceControl", - "location" : "https://github.com/maxkonovalov/MKRingProgressView.git", - "state" : { - "branch" : "master", - "revision" : "660888aab1d2ab0ed7eb9eb53caec12af4955fa7" + "identity": "mkringprogressview", + "kind": "remoteSourceControl", + "location": "https://github.com/maxkonovalov/MKRingProgressView.git", + "state": { + "branch": "master", + "revision": "660888aab1d2ab0ed7eb9eb53caec12af4955fa7" } }, { - "identity" : "swiftcharts", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ivanschuetz/SwiftCharts", - "state" : { - "branch" : "master", - "revision" : "c354c1945bb35a1f01b665b22474f6db28cba4a2" - } - }, - { - "identity" : "zipfoundation", - "kind" : "remoteSourceControl", - "location" : "https://github.com/LoopKit/ZIPFoundation.git", - "state" : { - "revision" : "c67b7509ec82ee2b4b0ab3f97742b94ed9692494" + "identity": "zipfoundation", + "kind": "remoteSourceControl", + "location": "https://github.com/LoopKit/ZIPFoundation.git", + "state": { + "revision": "c67b7509ec82ee2b4b0ab3f97742b94ed9692494" } } ], - "version" : 3 -} + "version": 3 +} \ No newline at end of file diff --git a/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme b/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme index 4d7e977e53..d36ffa7ea7 100644 --- a/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme +++ b/Loop.xcodeproj/xcshareddata/xcschemes/WatchApp.xcscheme @@ -84,7 +84,6 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "43A943711B926B7B0051FA24" BuildableName = "WatchApp.app" - BlueprintName = "WatchApp" ReferencedContainer = "container:Loop.xcodeproj"> @@ -102,7 +101,6 @@ BuildableIdentifier = "primary" BlueprintIdentifier = "43A943711B926B7B0051FA24" BuildableName = "WatchApp.app" - BlueprintName = "WatchApp" ReferencedContainer = "container:Loop.xcodeproj"> diff --git a/Loop/AppDelegate.swift b/Loop/AppDelegate.swift index 0e0eeb1222..33af2f4ae0 100644 --- a/Loop/AppDelegate.swift +++ b/Loop/AppDelegate.swift @@ -9,10 +9,12 @@ import UIKit import LoopKit -final class AppDelegate: UIResponder, UIApplicationDelegate, WindowProvider { - var window: UIWindow? +final class AppDelegate: UIResponder, UIApplicationDelegate { + + let loopAppManager = LoopAppManager() + + private(set) var launchOptions: [UIApplication.LaunchOptionsKey: Any]? - private let loopAppManager = LoopAppManager() private let log = DiagnosticLog(category: "AppDelegate") // MARK: - UIApplicationDelegate - Initialization @@ -22,45 +24,9 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, WindowProvider { setenv("CFNETWORK_DIAGNOSTICS", "3", 1) - log.default("lastPathComponent = %{public}@", String(describing: Bundle.main.appStoreReceiptURL?.lastPathComponent)) - - loopAppManager.initialize(windowProvider: self, launchOptions: launchOptions) - loopAppManager.launch() - return loopAppManager.isLaunchComplete - // Avoid doing full initialization when running tests - if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] == nil { - loopAppManager.initialize(windowProvider: self, launchOptions: launchOptions) - loopAppManager.launch() - return loopAppManager.isLaunchComplete - } else { - return true - } - } - - // MARK: - UIApplicationDelegate - Life Cycle - - func applicationDidBecomeActive(_ application: UIApplication) { - log.default(#function) + self.launchOptions = launchOptions - loopAppManager.didBecomeActive() - } - - func applicationWillResignActive(_ application: UIApplication) { - log.default(#function) - } - - func applicationDidEnterBackground(_ application: UIApplication) { - log.default(#function) - } - - func applicationWillEnterForeground(_ application: UIApplication) { - log.default(#function) - - loopAppManager.askUserToConfirmLoopReset() - } - - func applicationWillTerminate(_ application: UIApplication) { - log.default(#function) + return true } // MARK: - UIApplicationDelegate - Environment @@ -91,20 +57,6 @@ final class AppDelegate: UIResponder, UIApplicationDelegate, WindowProvider { completionHandler(loopAppManager.handleRemoteNotification(userInfo as? [String: AnyObject]) ? .noData : .failed) } - - // MARK: - UIApplicationDelegate - Deeplinking - - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - loopAppManager.handle(url) - } - - // MARK: - UIApplicationDelegate - Continuity - - func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { - log.default(#function) - - return loopAppManager.userActivity(userActivity, restorationHandler: restorationHandler) - } // MARK: - UIApplicationDelegate - Interface diff --git a/Loop/Extensions/ChartSettings+Loop.swift b/Loop/Extensions/ChartSettings+Loop.swift index 731a67f126..348d9120c0 100644 --- a/Loop/Extensions/ChartSettings+Loop.swift +++ b/Loop/Extensions/ChartSettings+Loop.swift @@ -5,7 +5,7 @@ // Copyright © 2017 LoopKit Authors. All rights reserved. // -import SwiftCharts +import LoopKitUI extension ChartSettings { static var `default`: ChartSettings { diff --git a/Loop/Extensions/Image+Optional.swift b/Loop/Extensions/Image+Optional.swift deleted file mode 100644 index 775196265e..0000000000 --- a/Loop/Extensions/Image+Optional.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Image+Optional.swift -// Loop -// -// Created by Cameron Ingham on 1/7/25. -// Copyright © 2025 LoopKit Authors. All rights reserved. -// - -import SwiftUI - -// Since this `Image` initializer provides a view even if the asset is not found in the bundle, it can double the spacing between adjacent elements in a `VStack`, `HStack`, etc. -extension Image { - init?(_ name: String, bundle: Bundle? = nil) { - if let _ = UIImage(named: name, in: bundle, with: nil) { - self = Image(name, bundle: bundle) - } else { - return nil - } - } -} diff --git a/Loop/Extensions/UIAlertController.swift b/Loop/Extensions/UIAlertController.swift index e483d7d2fd..bce885b56c 100644 --- a/Loop/Extensions/UIAlertController.swift +++ b/Loop/Extensions/UIAlertController.swift @@ -43,7 +43,7 @@ extension UIAlertController { self.init( title: NSLocalizedString("Add Pump", comment: "Action sheet title selecting Pump"), message: nil, - preferredStyle: .actionSheet + preferredStyle: .alert ) for availablePumpManager in availablePumpManagers { @@ -55,6 +55,8 @@ extension UIAlertController { } )) } + + addCancelAction() } /// Initializes an action sheet-styled controller for selecting a CGMManager @@ -67,7 +69,7 @@ extension UIAlertController { self.init( title: NSLocalizedString("Add CGM", comment: "Action sheet title selecting CGM"), message: nil, - preferredStyle: .actionSheet + preferredStyle: .alert ) for availableCGMManager in availableCGMManagers.sorted(by: {$0.localizedTitle < $1.localizedTitle}) { @@ -79,6 +81,8 @@ extension UIAlertController { } )) } + + addCancelAction() } internal convenience init(deleteCGMManagerHandler handler: @escaping (_ isDeleted: Bool) -> Void) { diff --git a/Loop/Info.plist b/Loop/Info.plist index f99682f82b..f68e6a0d89 100644 --- a/Loop/Info.plist +++ b/Loop/Info.plist @@ -84,6 +84,25 @@ NewCarbEntryIntent ViewLoopStatus + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + UIBackgroundModes bluetooth-central @@ -91,12 +110,8 @@ remote-notification audio - UIDesignRequiresCompatibility - UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 diff --git a/Loop/Localizable.xcstrings b/Loop/Localizable.xcstrings index 2b0f3d58b4..713c6d896b 100644 --- a/Loop/Localizable.xcstrings +++ b/Loop/Localizable.xcstrings @@ -3277,10 +3277,6 @@ "comment" : "A label displaying the playback speed. The argument is the playback speed.", "isCommentAutoGenerated" : true }, - "%lld mg/dL" : { - "comment" : "A label displaying the current glucose level, formatted as a monospaced digit with a secondary foreground color.", - "isCommentAutoGenerated" : true - }, "%lld min" : { "comment" : "A picker row that lets the user select a snooze interval. The argument is the number of minutes in the interval.", "isCommentAutoGenerated" : true @@ -3288,6 +3284,12 @@ "%lld." : { "comment" : "A number followed by a period, used to number a list of references.", "isCommentAutoGenerated" : true + }, + "%lld%%" : { + + }, + "%lldd" : { + }, "%lldx" : { "comment" : "A label that shows the playback speed of the audio. The argument is the playback speed.", @@ -4438,6 +4440,9 @@ } } }, + "Above range (>180): %d%% · goal <25%%" : { + "comment" : "TIR above-range summary" + }, "Absorption Time" : { "comment" : "Label for food absorption entry on add favorite food screen", "localizations" : { @@ -5443,9 +5448,6 @@ } } } - }, - "Add Carbs" : { - }, "Add CGM" : { "comment" : "Action sheet title selecting CGM\nThe title of the CGM chooser in settings\nTitle text for button to add CGM device\nTitle text for button to set up a CGM", @@ -6067,6 +6069,9 @@ }, "Afternoon Exercise" : { + }, + "Alert Identifier" : { + }, "Alert Management" : { "comment" : "Alert Permissions button text\nTitle of alert management screen", @@ -8856,6 +8861,9 @@ "Automation was unsuccessful" : { "comment" : "title for when automation was unsuccessful" }, + "Average" : { + "comment" : "Average glucose metric title" + }, "Average Glucose" : { }, @@ -9216,6 +9224,9 @@ }, "Before" : { + }, + "Below range (<70): %d%% · goal <4%%" : { + "comment" : "TIR below-range summary" }, "Bluetooth\nOff" : { "comment" : "Message to the user to that the bluetooth is off", @@ -11640,6 +11651,9 @@ }, "CAUTION - Investigational device. Limited by Federal (or United States) law to investigational use." : { + }, + "CGM Active" : { + "comment" : "Percent of time CGM data present metric title" }, "Change the pump battery immediately" : { "comment" : "The notification alert describing a low pump battery", @@ -15000,6 +15014,12 @@ } } }, + "Daily glucose pattern" : { + "comment" : "Accessibility label for the daily glucose pattern (AGP) chart" + }, + "Daily Glucose Pattern" : { + "comment" : "Daily glucose pattern (AGP) section header" + }, "Date" : { "comment" : "Date picker label", "localizations" : { @@ -15256,6 +15276,15 @@ }, "Decreased Delivery" : { + }, + "Delay 1st Alert" : { + + }, + "Delay for" : { + + }, + "Delay the first alert until your reading stays out of range for this long." : { + }, "Delete" : { "localizations" : { @@ -17355,6 +17384,12 @@ }, "During this kind of hard exercise, your body may release hormones that raise glucose. This is more common in the morning before eating." : { + }, + "Each 1% time in range ≈ 15 minutes." : { + "comment" : "TIR helper" + }, + "Each 5% increase in range is clinically beneficial." : { + "comment" : "TIR suggestion" }, "Easy breath. Can carry on a conversation." : { @@ -21168,6 +21203,9 @@ } } }, + "Glucose Metrics" : { + "comment" : "Glucose metrics section header" + }, "Glucose Momentum" : { "comment" : "Title of the prediction input effect for glucose momentum", "localizations" : { @@ -21287,6 +21325,9 @@ } } }, + "Glucose overview and ambulatory glucose profile" : { + "comment" : "Statistics settings descriptive text" + }, "Glucose Summary" : { }, @@ -21364,9 +21405,30 @@ "Glucose, Insulin, and Carb Data Access" : { "comment" : "Apple Health settings descriptive text" }, + "GMI" : { + "comment" : "Glucose Management Indicator metric title" + }, "Go to Settings > Focus." : { "comment" : "Focus modes step 1" }, + "Goal: <%@" : { + "comment" : "Average glucose goal" + }, + "Goal: <1%" : { + "comment" : "TIR goal for very low" + }, + "Goal: <5%" : { + "comment" : "TIR goal for very high" + }, + "Goal: <7%" : { + "comment" : "GMI goal" + }, + "Goal: >70%" : { + "comment" : "CGM active goal\nTIR goal for target range" + }, + "Goal: ≤36%" : { + "comment" : "Glucose variability goal" + }, "grams" : { }, @@ -21430,7 +21492,7 @@ }, "High" : { - + "comment" : "Time-in-range band label (181–250 mg/dL)" }, "High Glucose" : { "localizations" : { @@ -21988,6 +22050,9 @@ } } }, + "In Range" : { + "comment" : "Time-in-range band label (70–180 mg/dL)" + }, "Includes basal and automated boluses" : { }, @@ -26000,7 +26065,7 @@ } }, "Low" : { - + "comment" : "Time-in-range band label (54–69 mg/dL)" }, "Low Glucose" : { "comment" : "Title for bolus screen warning when glucose is below glucose warning limit.\nTitle for bolus screen warning when glucose is below suspend threshold, but a bolus is recommended", @@ -26177,6 +26242,9 @@ } } } + }, + "Manager Identifier" : { + }, "Managing Alerts" : { "comment" : "View title for how mute alerts work", @@ -26709,6 +26777,9 @@ }, "Meal Timing" : { + }, + "Median (line) with 25–75% and 5–95% bands, by time of day." : { + "comment" : "AGP chart explanation" }, "Medium Intensity (Aerobic)" : { @@ -28423,6 +28494,9 @@ }, "No Delivery" : { + }, + "No glucose data for this period." : { + "comment" : "Statistics empty state" }, "No Maximum Bolus Configured" : { "comment" : "Alert title for a missing maximum bolus setting error", @@ -29119,6 +29193,9 @@ }, "None in last 24 hours" : { + }, + "Not enough data to plot a profile." : { + "comment" : "AGP empty state" }, "Not Set" : { "comment" : "Health sharing status: not determined" @@ -32888,6 +32965,9 @@ } } }, + "Range" : { + "comment" : "Statistics date-range picker label" + }, "Rapid-Acting – Adults" : { "comment" : "Title of insulin model preset", "extractionState" : "manual", @@ -34061,6 +34141,15 @@ } } } + }, + "Reset Alert Settings" : { + + }, + "Reset all glucose alert settings to defaults?" : { + + }, + "Restores all glucose alert thresholds, schedules, and sounds to their defaults, and removes any extra profiles." : { + }, "Resume insulin if you wish for the app to restart insulin delivery.\n\nIf you wish for the app to automate your insulin, go to Settings and toggle Closed Loop to on." : { "comment" : "message when automation is off and insulin delivery is suspended" @@ -35103,6 +35192,9 @@ }, "She can do this by raising her **Overall Insulin** setting. This tells %@ to deliver more than her usual amount, making her insulin settings stronger." : { + }, + "Showing %1$d days of data — not enough for the full %2$d-day period yet." : { + "comment" : "Notice when the selected statistics range has incomplete data" }, "Shows last loop error" : { "comment" : "Loop Completion HUD accessibility hint", @@ -35759,6 +35851,9 @@ }, "Sort By" : { + }, + "Sound" : { + }, "Stable Glucose" : { @@ -36095,9 +36190,18 @@ }, "Starting your exercise with high active insulin" : { + }, + "Statistics" : { + "comment" : "Statistics screen title\nStatistics settings button text" }, "Stay hydrated" : { + }, + "Stop" : { + "comment" : "Stop button on the AlarmKit critical alarm" + }, + "Stop Glucose Alarm" : { + }, "Stop Time" : { "comment" : "A label displayed below the \"Stop Time\" text in the \"Scheduling\" section of an alert profile detail view.", @@ -38212,6 +38316,9 @@ } } } + }, + "The sound played when this alarm fires." : { + }, "Therapy Settings" : { "comment" : "Title text for button to Therapy Settings", @@ -38313,6 +38420,9 @@ }, "These recommendations should be used as a starting point. Checking your glucose during exercise will help you find the settings that work best for you." : { + }, + "This device keeps %d days of glucose. Increase the cache duration and rebuild to review the full period." : { + "comment" : "Notice when the local cache limits the statistics history" }, "This dose still has active insulin. Deleting it may cause Loop to make up for the reduced active insulin by dosing more." : { "comment" : "Warning when deleting a Loop-recorded dose that still has active insulin" @@ -38401,6 +38511,9 @@ }, "Time in\nAutomation" : { + }, + "Time in Range" : { + "comment" : "Time-in-range section header" }, "Time of Day" : { @@ -40867,6 +40980,9 @@ } } }, + "Variability" : { + "comment" : "Coefficient of variation metric title" + }, "Version" : { "comment" : "Label for the app version row in the Support section" }, @@ -40874,10 +40990,10 @@ }, "Very High" : { - + "comment" : "Time-in-range band label (>250 mg/dL)" }, "Very Low" : { - + "comment" : "Time-in-range band label (<54 mg/dL)" }, "Viewing entry %lld of %lld" : { "localizations" : { diff --git a/Loop/Managers/Live Activity/ChartAxisGenerator.swift b/Loop/Managers/Live Activity/ChartAxisGenerator.swift index 536d10daa7..be4b621dc3 100644 --- a/Loop/Managers/Live Activity/ChartAxisGenerator.swift +++ b/Loop/Managers/Live Activity/ChartAxisGenerator.swift @@ -9,7 +9,6 @@ import Foundation import HealthKit import LoopAlgorithm -import SwiftCharts import UIKit struct ChartAxisGenerator { @@ -19,7 +18,6 @@ struct ChartAxisGenerator { private static let minSegmentCount: Double = 2 private static let addPaddingSegmentIfEdge = false - private static let axisLabelSettings = ChartLabelSettings(font: .systemFont(ofSize: 14), fontColor: UIColor.secondaryLabel) // This logic is copied/ported from generateYAxisValuesUsingLinearSegmentStep static func getYAxis(points: [Double], isMmol: Bool) -> [Double] { @@ -101,7 +99,7 @@ struct ChartAxisGenerator { { scalar = 0 } - return ChartAxisValueDouble(scalar, labelSettings: axisLabelSettings).scalar + return scalar } } @@ -119,7 +117,10 @@ struct ChartAxisGenerator { } } +infix operator >=~ : ComparisonPrecedence + fileprivate extension Double { + // `=~` is declared in Common/Extensions/Double.swift static func >=~ (a: Double, b: Double) -> Bool { return a =~ b || a > b } diff --git a/Loop/Managers/LoopAppManager.swift b/Loop/Managers/LoopAppManager.swift index 829f9f22f4..58d1938e46 100644 --- a/Loop/Managers/LoopAppManager.swift +++ b/Loop/Managers/LoopAppManager.swift @@ -161,6 +161,8 @@ class LoopAppManager: NSObject { var isLaunchComplete: Bool { state == .launchComplete } + var isInInitialState: Bool { state == .initialize } + private func resumeLaunch() async { if state == .checkProtectedDataAvailable { checkProtectedDataAvailable() diff --git a/Loop/Managers/StatusChartsManager.swift b/Loop/Managers/StatusChartsManager.swift index b72a4fd031..0666136655 100644 --- a/Loop/Managers/StatusChartsManager.swift +++ b/Loop/Managers/StatusChartsManager.swift @@ -9,8 +9,8 @@ import Foundation import LoopKit import LoopUI import LoopKitUI -import SwiftCharts import LoopAlgorithm +import UIKit class StatusChartsManager: ChartsManager { @@ -68,7 +68,7 @@ extension StatusChartsManager { invalidateChart(atIndex: ChartIndex.glucose.rawValue) } - func glucoseChart(withFrame frame: CGRect) -> Chart? { + func glucoseChart(withFrame frame: CGRect) -> UIView? { return chart(atIndex: ChartIndex.glucose.rawValue, frame: frame) } @@ -109,7 +109,7 @@ extension StatusChartsManager { invalidateChart(atIndex: ChartIndex.iob.rawValue) } - func iobChart(withFrame frame: CGRect, highlightLabelOffsetY: CGFloat) -> Chart? { + func iobChart(withFrame frame: CGRect, highlightLabelOffsetY: CGFloat) -> UIView? { return chart(atIndex: ChartIndex.iob.rawValue, frame: frame, highlightLabelOffsetY: highlightLabelOffsetY) } } @@ -121,7 +121,7 @@ extension StatusChartsManager { invalidateChart(atIndex: ChartIndex.dose.rawValue) } - func doseChart(withFrame frame: CGRect) -> Chart? { + func doseChart(withFrame frame: CGRect) -> UIView? { return chart(atIndex: ChartIndex.dose.rawValue, frame: frame) } } @@ -133,7 +133,7 @@ extension StatusChartsManager { invalidateChart(atIndex: ChartIndex.cob.rawValue) } - func cobChart(withFrame frame: CGRect) -> Chart? { + func cobChart(withFrame frame: CGRect) -> UIView? { return chart(atIndex: ChartIndex.cob.rawValue, frame: frame) } } diff --git a/Loop/SceneDelegate.swift b/Loop/SceneDelegate.swift new file mode 100644 index 0000000000..31b9e154d1 --- /dev/null +++ b/Loop/SceneDelegate.swift @@ -0,0 +1,88 @@ +// +// SceneDelegate.swift +// Loop +// +// Copyright © 2026 LoopKit Authors. All rights reserved. +// + +import UIKit +import LoopKit + +final class SceneDelegate: UIResponder, UIWindowSceneDelegate, WindowProvider { + + var window: UIWindow? + + private let log = DiagnosticLog(category: "SceneDelegate") + + private var loopAppManager: LoopAppManager? { + (UIApplication.shared.delegate as? AppDelegate)?.loopAppManager + } + + // MARK: - UIWindowSceneDelegate - Connection + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + log.default(#function) + + + guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { + return + } + let loopAppManager = appDelegate.loopAppManager + + guard loopAppManager.isInInitialState else { + return + } + + loopAppManager.initialize(windowProvider: self, launchOptions: appDelegate.launchOptions) + loopAppManager.launch() + + if let url = connectionOptions.urlContexts.first?.url { + _ = loopAppManager.handle(url) + } + for userActivity in connectionOptions.userActivities { + _ = loopAppManager.userActivity(userActivity, restorationHandler: { _ in }) + } + } + + // MARK: - UIWindowSceneDelegate - Life Cycle + + func sceneDidBecomeActive(_ scene: UIScene) { + log.default(#function) + + loopAppManager?.didBecomeActive() + } + + func sceneWillResignActive(_ scene: UIScene) { + log.default(#function) + } + + func sceneWillEnterForeground(_ scene: UIScene) { + log.default(#function) + + guard let loopAppManager, loopAppManager.isLaunchComplete else { + return + } + loopAppManager.askUserToConfirmLoopReset() + } + + func sceneDidEnterBackground(_ scene: UIScene) { + log.default(#function) + } + + // MARK: - UIWindowSceneDelegate - Deeplinking + + func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + guard let url = URLContexts.first?.url else { + return + } + _ = loopAppManager?.handle(url) + } + + // MARK: - UIWindowSceneDelegate - Continuity + + func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + log.default(#function) + + _ = loopAppManager?.userActivity(userActivity, restorationHandler: { _ in }) + } +} diff --git a/Loop/View Controllers/CarbAbsorptionViewController.swift b/Loop/View Controllers/CarbAbsorptionViewController.swift index cd4f44e2b0..3bc9c49415 100644 --- a/Loop/View Controllers/CarbAbsorptionViewController.swift +++ b/Loop/View Controllers/CarbAbsorptionViewController.swift @@ -275,7 +275,7 @@ final class CarbAbsorptionViewController: LoopChartsTableViewController, Identif switch ChartRow(rawValue: indexPath.row)! { case .carbEffect: cell.setChartGenerator(generator: { [weak self] (frame) in - return self?.charts.chart(atIndex: 0, frame: frame)?.view + return self?.charts.chart(atIndex: 0, frame: frame) }) } diff --git a/Loop/View Controllers/PredictionTableViewController.swift b/Loop/View Controllers/PredictionTableViewController.swift index df7f672d07..d6b06bec3f 100644 --- a/Loop/View Controllers/PredictionTableViewController.swift +++ b/Loop/View Controllers/PredictionTableViewController.swift @@ -138,9 +138,9 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable } if let lastPoint = self.glucoseChart.alternatePredictedGlucosePoints?.last?.y { - let valueAttributedString = NSMutableAttributedString(string: String(describing: lastPoint.copy), attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.glucoseTint]) + let valueAttributedString = NSMutableAttributedString(string: lastPoint.valueLabel ?? lastPoint.label, attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.glucoseTint]) let spacer = NSAttributedString(string: "\u{00a0}") - let unitAttributedString = NSAttributedString(string: String(describing: lastPoint).replacingOccurrences(of: String(describing: lastPoint.copy), with: "").trimmingCharacters(in: .whitespacesAndNewlines), attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.glucoseTint]) + let unitAttributedString = NSAttributedString(string: lastPoint.unitLabel ?? "", attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.glucoseTint]) valueAttributedString.append(spacer) valueAttributedString.append(unitAttributedString) @@ -222,7 +222,7 @@ class PredictionTableViewController: LoopChartsTableViewController, Identifiable let cell = tableView.dequeueReusableCell(withIdentifier: ChartTableViewCell.className, for: indexPath) as! ChartTableViewCell cell.contentView.layoutMargins.left = tableView.separatorInset.left cell.setChartGenerator(generator: { [weak self] (frame) in - return self?.charts.chart(atIndex: 0, frame: frame)?.view + return self?.charts.chart(atIndex: 0, frame: frame) }) self.tableView(tableView, updateTitleFor: cell, at: indexPath) diff --git a/Loop/View Controllers/StatusTableViewController.swift b/Loop/View Controllers/StatusTableViewController.swift index db0511d6b2..d8ed865e4a 100644 --- a/Loop/View Controllers/StatusTableViewController.swift +++ b/Loop/View Controllers/StatusTableViewController.swift @@ -14,7 +14,6 @@ import LoopKit import LoopKitUI import LoopTestingKit import LoopUI -import SwiftCharts import os.log import Combine import WidgetKit @@ -227,7 +226,7 @@ final class StatusTableViewController: LoopChartsTableViewController { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(true, animated: animated) - navigationController?.setToolbarHidden(false, animated: animated) + navigationController?.setToolbarHidden(true, animated: animated) alertPermissionsChecker.checkNow() @@ -541,9 +540,9 @@ final class StatusTableViewController: LoopChartsTableViewController { if !FeatureFlags.predictedGlucoseChartClampEnabled, let lastPoint = self.statusCharts.glucose.predictedGlucosePoints.last?.y { - let valueAttributedString = NSMutableAttributedString(string: String(describing: lastPoint.copy), attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.glucoseTint]) + let valueAttributedString = NSMutableAttributedString(string: lastPoint.valueLabel ?? lastPoint.label, attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.glucoseTint]) let spacer = NSAttributedString(string: "\u{00a0}") - let unitAttributedString = NSAttributedString(string: String(describing: lastPoint).replacingOccurrences(of: String(describing: lastPoint.copy), with: "").trimmingCharacters(in: .whitespacesAndNewlines), attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.glucoseTint]) + let unitAttributedString = NSAttributedString(string: lastPoint.unitLabel ?? "", attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.glucoseTint]) valueAttributedString.append(spacer) valueAttributedString.append(unitAttributedString) @@ -596,9 +595,10 @@ final class StatusTableViewController: LoopChartsTableViewController { charts.setCOBValues(cobValues) } if let index = charts.cob.cobPoints.closestIndex(priorTo: Date()) { - let valueAttributedString = NSMutableAttributedString(string: String(describing: charts.cob.cobPoints[index].y.copy), attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.carbTint]) + let cobValue = charts.cob.cobPoints[index].y + let valueAttributedString = NSMutableAttributedString(string: cobValue.valueLabel ?? cobValue.label, attributes: [.font: UIFont.systemFont(ofSize: 22, weight: .semibold), .foregroundColor: ChartColorPalette.primary.carbTint]) let spacer = NSAttributedString(string: "\u{00a0}") - let unitAttributedString = NSAttributedString(string: String(describing: charts.cob.cobPoints[index].y).replacingOccurrences(of: String(describing: charts.cob.cobPoints[index].y.copy), with: "").trimmingCharacters(in: .whitespacesAndNewlines), attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.carbTint]) + let unitAttributedString = NSAttributedString(string: cobValue.unitLabel ?? "", attributes: [.font: UIFont.systemFont(ofSize: 15, weight: .regular), .foregroundColor: ChartColorPalette.primary.carbTint]) valueAttributedString.append(spacer) valueAttributedString.append(unitAttributedString) @@ -643,7 +643,8 @@ final class StatusTableViewController: LoopChartsTableViewController { let statusRowMode = self.determineStatusRowMode() updateBannerAndHUDandStatusRows(statusRowMode: statusRowMode, newSize: currentContext.newSize, animated: animated) - + tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: UIDevice.current.orientation.isLandscape ? 0 : 52, right: 0) + redrawCharts() reloading = false @@ -1008,25 +1009,25 @@ final class StatusTableViewController: LoopChartsTableViewController { switch ChartRow(rawValue: indexPath.row)! { case .glucose: cell.setChartGenerator(generator: { [weak self] (frame) in - return self?.statusCharts.glucoseChart(withFrame: frame)?.view + return self?.statusCharts.glucoseChart(withFrame: frame) }) cell.setTitleLabelText(label: NSLocalizedString("Glucose", comment: "The title of the glucose and prediction graph")) cell.setTitleTextColor(color: ChartColorPalette.primary.glucoseTint) cell.doesNavigate = settingsManager.dosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled case .iob: cell.setSupplementalChartGenerator(generator: { [weak self] (frame) in - return self?.statusCharts.doseChart(withFrame: frame)?.view + return self?.statusCharts.doseChart(withFrame: frame) }) cell.setChartGenerator(generator: { [weak self] (frame) in - return self?.statusCharts.iobChart(withFrame: frame, highlightLabelOffsetY: cell.supplementalChartContentView?.bounds.height ?? 0)?.view + return self?.statusCharts.iobChart(withFrame: frame, highlightLabelOffsetY: cell.supplementalChartContentView?.bounds.height ?? 0) }) cell.setTitleLabelText(label: NSLocalizedString("Active Insulin", comment: "The title of the Insulin On-Board graph")) cell.setTitleTextColor(color: ChartColorPalette.primary.insulinTint) cell.setFooterView(content: iobFooterViewContent) case .cob: cell.setChartGenerator(generator: { [weak self] (frame) in - return self?.statusCharts.cobChart(withFrame: frame)?.view + return self?.statusCharts.cobChart(withFrame: frame) }) cell.setTitleLabelText(label: NSLocalizedString("Active Carbohydrates", comment: "The title of the Carbs On-Board graph")) cell.setTitleTextColor(color: ChartColorPalette.primary.carbTint) @@ -1208,7 +1209,7 @@ final class StatusTableViewController: LoopChartsTableViewController { // Compute the height of the HUD, defaulting to 70 let hudHeight = ceil(hudView?.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height ?? 74) var availableSize = max(tableView.bounds.width, tableView.bounds.height) - availableSize -= (tableView.safeAreaInsets.top + tableView.safeAreaInsets.bottom + hudHeight) + availableSize -= (tableView.safeAreaInsets.top + tableView.safeAreaInsets.bottom + tableView.contentInset.bottom + hudHeight) switch ChartRow(rawValue: indexPath.row)! { case .glucose: @@ -1785,7 +1786,6 @@ final class StatusTableViewController: LoopChartsTableViewController { let alert = UIAlertController(availablePumpManagers: availablePumpManagers) { [weak self] (identifier) in self?.addPumpManager(withIdentifier: identifier) } - alert.addCancelAction { _ in } present(alert, animated: true, completion: nil) } } @@ -1802,7 +1802,6 @@ final class StatusTableViewController: LoopChartsTableViewController { let alert = UIAlertController(availableCGMManagers: availableCGMManagers) { [weak self] identifier in self?.addCGMManager(withIdentifier: identifier) } - alert.addCancelAction { _ in } present(alert, animated: true, completion: nil) } } diff --git a/Loop/View Models/BolusEntryViewModel.swift b/Loop/View Models/BolusEntryViewModel.swift index 1ec763d9e4..2dea723af9 100644 --- a/Loop/View Models/BolusEntryViewModel.swift +++ b/Loop/View Models/BolusEntryViewModel.swift @@ -15,7 +15,6 @@ import LoopKit import LoopKitUI import LoopUI import SwiftUI -import SwiftCharts import LoopAlgorithm @MainActor diff --git a/Loop/Views/Charts/LoopChartView.swift b/Loop/Views/Charts/LoopChartView.swift index be6965c9b5..dd875477aa 100644 --- a/Loop/Views/Charts/LoopChartView.swift +++ b/Loop/Views/Charts/LoopChartView.swift @@ -22,7 +22,7 @@ struct LoopChartView: UIViewRepresentable { let view = ChartContainerView() view.chartGenerator = { [chartManager] frame in - chartManager.chart(atIndex: chartIndex, frame: frame)?.view + chartManager.chart(atIndex: chartIndex, frame: frame) } let gestureRecognizer = UILongPressGestureRecognizer() diff --git a/Loop/Views/SettingsView.swift b/Loop/Views/SettingsView.swift index 14efe111bd..d81ccdbba5 100644 --- a/Loop/Views/SettingsView.swift +++ b/Loop/Views/SettingsView.swift @@ -118,24 +118,14 @@ struct SettingsView: View { .insetGroupedListStyle() .navigationBarTitle(Text(NSLocalizedString("Settings", comment: "Settings screen title"))) .navigationBarItems(trailing: dismissButton) - .actionSheet(item: $actionSheet) { actionSheet in - switch actionSheet { - case .cgmPicker: - return ActionSheet( - title: Text("Add CGM", comment: "The title of the CGM chooser in settings"), - buttons: cgmChoices - ) - case .pumpPicker: - return ActionSheet( - title: Text("Add Pump", comment: "The title of the pump chooser in settings"), - buttons: pumpChoices - ) - case .servicePicker: - return ActionSheet( - title: Text("Add Service", comment: "The title of the add service action sheet in settings"), - buttons: serviceChoices - ) - } + .alert(NSLocalizedString("Add CGM", comment: "The title of the CGM chooser in settings"), isPresented: pickerBinding(.cgmPicker)) { + cgmChoices + } + .alert(NSLocalizedString("Add Pump", comment: "The title of the pump chooser in settings"), isPresented: pickerBinding(.pumpPicker)) { + pumpChoices + } + .alert(NSLocalizedString("Add Service", comment: "The title of the add service action sheet in settings"), isPresented: pickerBinding(.servicePicker)) { + serviceChoices } .alert(item: $alert) { alert in switch alert { @@ -480,14 +470,25 @@ extension SettingsView { } } - private var pumpChoices: [ActionSheet.Button] { - var result = viewModel.pumpManagerSettingsViewModel.availableDevices.map { availableDevice in - ActionSheet.Button.default(Text(availableDevice.localizedTitle)) { + private func pickerBinding(_ destination: Destination.ActionSheet) -> Binding { + Binding( + get: { actionSheet == destination }, + set: { isPresented in + if !isPresented, actionSheet == destination { + actionSheet = nil + } + } + ) + } + + @ViewBuilder + private var pumpChoices: some View { + ForEach(viewModel.pumpManagerSettingsViewModel.availableDevices, id: \.identifier) { availableDevice in + Button(availableDevice.localizedTitle) { self.viewModel.pumpManagerSettingsViewModel.didTapAdd(availableDevice) } } - result.append(.cancel()) - return result + Button(NSLocalizedString("Cancel", comment: "The title of the cancel action in an action sheet"), role: .cancel) {} } @ViewBuilder @@ -517,16 +518,14 @@ extension SettingsView { } } - private var cgmChoices: [ActionSheet.Button] { - var result = viewModel.cgmManagerSettingsViewModel.availableDevices - .sorted(by: {$0.localizedTitle < $1.localizedTitle}) - .map { availableDevice in - ActionSheet.Button.default(Text(availableDevice.localizedTitle)) { - self.viewModel.cgmManagerSettingsViewModel.didTapAdd(availableDevice) + @ViewBuilder + private var cgmChoices: some View { + ForEach(viewModel.cgmManagerSettingsViewModel.availableDevices.sorted(by: {$0.localizedTitle < $1.localizedTitle}), id: \.identifier) { availableDevice in + Button(availableDevice.localizedTitle) { + self.viewModel.cgmManagerSettingsViewModel.didTapAdd(availableDevice) } } - result.append(.cancel()) - return result + Button(NSLocalizedString("Cancel", comment: "The title of the cancel action in an action sheet"), role: .cancel) {} } private var servicesSection: some View { @@ -548,14 +547,14 @@ extension SettingsView { } } - private var serviceChoices: [ActionSheet.Button] { - var result = viewModel.servicesViewModel.inactiveServices().map { availableService in - ActionSheet.Button.default(Text(availableService.localizedTitle)) { + @ViewBuilder + private var serviceChoices: some View { + ForEach(viewModel.servicesViewModel.inactiveServices(), id: \.identifier) { availableService in + Button(availableService.localizedTitle) { self.viewModel.servicesViewModel.didTapAddService(availableService) } } - result.append(.cancel()) - return result + Button(NSLocalizedString("Cancel", comment: "The title of the cancel action in an action sheet"), role: .cancel) {} } private var deleteDataSection: some View { diff --git a/Loop/Views/StatusTableView.swift b/Loop/Views/StatusTableView.swift index 56c1425907..e7adcdbd46 100644 --- a/Loop/Views/StatusTableView.swift +++ b/Loop/Views/StatusTableView.swift @@ -132,136 +132,185 @@ struct StatusTableView: View { } var body: some View { - wrappedView - .ignoresSafeArea(edges: .bottom) - .onChange(of: viewModel.temporaryPresetsManager.activeOverride) { _, _ in - Task { - await viewController.reloadData(animated: true) + ActionTabView { + wrappedView + .ignoresSafeArea(edges: .bottom) + .onChange(of: viewModel.temporaryPresetsManager.activeOverride) { _, _ in + Task { + await viewController.reloadData(animated: true) + } + } + .sheet(item: $viewModel.pendingPreset) { preset in + // This is the active preset; edit disabled + PresetDetentView(preset: preset, roundBasalRate: viewModel.loopDataManager.deliveryDelegate?.roundBasalRate, didTapEdit: { }) + .accessibilityIdentifier("bar_Presets") } + } tabs: { + ActionTab( + title: "Add Carbs", + icon: "carbs", + tintColor: .carbTintColor + ) { + viewController.userTappedAddCarbs() } - .sheet(item: $viewModel.pendingPreset) { preset in - // This is the active preset; edit disabled - PresetDetentView(preset: preset, roundBasalRate: viewModel.loopDataManager.deliveryDelegate?.roundBasalRate, didTapEdit: { }) - .accessibilityIdentifier("bar_Presets") + + ActionTab( + title: "Bolus", + icon: "bolus", + tintColor: .insulinTintColor + ) { + viewController.presentBolusScreen() } - .toolbar { - if !isLandscape { - if #available(iOS 26, *) { - ToolbarItemGroup(placement: .bottomBar) { - carbTab - Spacer() - bolusTab - Spacer() - presetsTab - Spacer() - settingsTab - } - } else { - ToolbarItem(placement: .bottomBar) { - HStack { - carbTab - bolusTab - presetsTab - settingsTab - } - } - } - } + + ActionTab( + title: "Presets", + icon: viewModel.temporaryPresetsManager.activeOverride != nil + ? "presets-selected" + : "presets", + tintColor: .presets + ) { + viewController.presentPresets() + } + + ActionTab( + title: "Settings", + icon: "settings", + tintColor: .secondaryLabel + ) { + viewController.presentSettings() } - .toolbar(isLandscape ? .hidden : .visible, for: .bottomBar) - .toolbarBackground(.visible, for: .bottomBar) + } } - - var carbTab: some View { - Button { - viewController.userTappedAddCarbs() - } label: { - VStack(spacing: 0) { - Image("carbs") - .renderingMode(.template) - .resizable() - .scaledToFit() - .frame(height: 32) - .frame(maxWidth: .infinity) - .foregroundStyle(Color.carbs) +} - Text("Add Carbs") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize() - } +struct ActionTab: Identifiable { + let id = UUID() + let title: String + let icon: String + let tintColor: UIColor + let action: () -> Void +} + +struct ActionTabBar: UIViewRepresentable { + + let items: [ActionTab] + + func makeUIView(context: Context) -> UITabBar { + let bar = UITabBar() + bar.delegate = context.coordinator + let appearance = UITabBarAppearance() + appearance.configureWithOpaqueBackground() + bar.standardAppearance = appearance + bar.scrollEdgeAppearance = appearance + bar.tintColor = .label + return bar + } + + func updateUIView(_ uiView: UITabBar, context: Context) { + context.coordinator.tabs = items + uiView.items = items.enumerated().map { idx, item in + UITabBarItem( + title: item.title, + image: UIImage(named: item.icon)?.scaledToFit(height: 28).withTintColor(item.tintColor, renderingMode: .alwaysOriginal), + tag: idx + ) } - .buttonStyle(.plain) - .accessibilityIdentifier("statusTableViewControllerCarbsButton") } - - var bolusTab: some View { - Button { - viewController.presentBolusScreen() - } label: { - VStack(spacing: 0) { - Image("bolus") - .renderingMode(.template) - .resizable() - .scaledToFit() - .frame(height: 32) - .frame(maxWidth: .infinity) - .foregroundStyle(Color.insulin) - - Text("Bolus") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize() + + func makeCoordinator() -> Coordinator { Coordinator() } + + final class Coordinator: NSObject, UITabBarDelegate { + var tabs: [ActionTab] = [] + + func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { + guard tabs.indices.contains(item.tag) else { return } + tabs[item.tag].action() + DispatchQueue.main.async { + tabBar.selectedItem = nil } } - .buttonStyle(.plain) - .accessibilityIdentifier("statusTableViewControllerBolusButton") } +} + +private extension UIImage { + /// Tab icons come from assets of varying raw sizes; normalize them so every + /// tab renders at the same height. + func scaledToFit(height: CGFloat) -> UIImage { + guard size.height > 0, size.height != height else { return self } + let scale = height / size.height + let newSize = CGSize(width: size.width * scale, height: height) + let renderer = UIGraphicsImageRenderer(size: newSize) + return renderer.image { _ in + draw(in: CGRect(origin: .zero, size: newSize)) + } + } +} + +@resultBuilder +enum ActionTabBuilder { + static func buildBlock(_ components: ActionTab...) -> [ActionTab] { components } + static func buildOptional(_ component: [ActionTab]?) -> [ActionTab] { component ?? [] } + static func buildEither(first component: [ActionTab]) -> [ActionTab] { component } + static func buildEither(second component: [ActionTab]) -> [ActionTab] { component } + static func buildArray(_ components: [[ActionTab]]) -> [ActionTab] { components.flatMap { $0 } } +} + +struct LegacyTabBarBackground: ViewModifier { - var presetsTab: some View { - Button { - viewController.presentPresets() - } label: { - VStack(spacing: 0) { - Image(viewModel.temporaryPresetsManager.activeOverride != nil ? "presets-selected" : "presets") - .renderingMode(.template) - .resizable() - .scaledToFit() - .frame(height: 32) - .frame(maxWidth: .infinity) - .foregroundStyle(Color.presets) - .animation(.default, value: viewModel.temporaryPresetsManager.activeOverride) - - Text("Presets") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize() - } + private let isCompatibilityModeActive = Bundle.main.object(forInfoDictionaryKey: "UIDesignRequiresCompatibility") as? Bool ?? false + + func body(content: Content) -> some View { + if #available(iOS 26.0, *), !isCompatibilityModeActive { + content + .frame(height: 0) + } else { + content + .frame(height: 49) + .background( + Color(UIColor.systemBackground) + .ignoresSafeArea(edges: .bottom) + ) } - .buttonStyle(.plain) - .accessibilityIdentifier("statusTableViewPresetsButton") } +} + +struct ActionTabView: View { - var settingsTab: some View { - Button { - viewController.presentSettings() - } label: { - VStack(spacing: 0) { - Image("settings") - .renderingMode(.template) - .resizable() - .scaledToFit() - .frame(height: 32) - .frame(maxWidth: .infinity) - .foregroundStyle(Color.secondary) - - Text("Settings") - .font(.footnote) - .foregroundStyle(.secondary) - .fixedSize() + @State private var orientation: UIDeviceOrientation + + private let allowedOrientations: [UIDeviceOrientation] + private let content: Content + private let tabs: [ActionTab] + + init( + allowedOrientations: [UIDeviceOrientation] = [.portrait], + @ViewBuilder content: @escaping () -> Content, + @ActionTabBuilder tabs: @escaping () -> [ActionTab], + ) { + self.content = content() + self.tabs = tabs() + + self.allowedOrientations = allowedOrientations + self.orientation = UIDevice.current.orientation + } + + var body: some View { + content + .safeAreaInset(edge: .bottom, spacing: 0) { + if orientation == .unknown || allowedOrientations.contains(orientation) { + ActionTabBar(items: tabs) + .modifier(LegacyTabBarBackground()) + } } - } - .buttonStyle(.plain) - .accessibilityIdentifier("statusTableViewControllerSettingsButton") + .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in + orientation = UIDevice.current.orientation + } + } + + private static func currentOrientation() -> UIInterfaceOrientation { + UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .first? + .interfaceOrientation ?? .portrait } } diff --git a/LoopUI/Models/ChartLineModel.swift b/LoopUI/Models/ChartLineModel.swift deleted file mode 100644 index 346de2b871..0000000000 --- a/LoopUI/Models/ChartLineModel.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// ChartLineModel.swift -// Loop -// -// Copyright © 2017 LoopKit Authors. All rights reserved. -// - -import SwiftCharts - - -extension ChartLineModel { - /// Creates a model configured with the dashed prediction line style - /// - /// - Parameters: - /// - points: The points to construct the line - /// - color: The line color - /// - width: The line width - /// - Returns: A new line model - static func predictionLine(points: [T], color: UIColor, width: CGFloat) -> ChartLineModel { - // TODO: Bug in ChartPointsLineLayer requires a non-zero animation to draw the dash pattern - return self.init(chartPoints: points, lineColor: color, lineWidth: width, animDuration: 0.0001, animDelay: 0, dashPattern: [6, 5]) - } -}