diff --git a/LoopFollow.xcodeproj/project.pbxproj b/LoopFollow.xcodeproj/project.pbxproj index b162633e0..5a3f1c79c 100644 --- a/LoopFollow.xcodeproj/project.pbxproj +++ b/LoopFollow.xcodeproj/project.pbxproj @@ -7,10 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - B500000000000000000000A2 /* RemoteBolusHistoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */; }; - B500000000000000000000A4 /* QuickPickBolusesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000A3 /* QuickPickBolusesManager.swift */; }; - B500000000000000000000B2 /* RemoteMealHistoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */; }; - B500000000000000000000B4 /* QuickPickMealsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000B3 /* QuickPickMealsManager.swift */; }; + 18BA6357F867577712A116EB /* DBSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B81E18A2489A364AFC0A9E4 /* DBSize.swift */; }; 2D8068C66833EEAED7B4BEB8 /* FutureCarbsCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EBAB9EECE7095238A558060 /* FutureCarbsCondition.swift */; }; 374A77992F5BD8B200E96858 /* APNSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A77982F5BD8AB00E96858 /* APNSClient.swift */; }; 374A77A52F5BE17000E96858 /* AppGroupID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374A779F2F5BE17000E96858 /* AppGroupID.swift */; }; @@ -69,7 +66,23 @@ 65E153C32E4BB69100693A4F /* URLTokenValidationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E153C22E4BB69100693A4F /* URLTokenValidationView.swift */; }; 65E8A2862E44B0300065037B /* VolumeButtonHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65E8A2852E44B0300065037B /* VolumeButtonHandler.swift */; }; 66E3D12E66AA4534A144A54B /* BackgroundRefreshManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CA8BE0B3D247408FE088B4 /* BackgroundRefreshManager.swift */; }; + 9727B75402723679BD39CDE5 /* DBSizeTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBE9ECA96BEA20DBD21B570D /* DBSizeTask.swift */; }; + 9C7FB98C98BE4FF98F4815EE /* Telemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFBE69CEF18416D84959974 /* Telemetry.swift */; }; + A1A1A10001000000A0CFEED1 /* APNsCredentialValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */; }; + A1A1A10002000000A0CFEED1 /* LogRedactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10002000000A0CFEED2 /* LogRedactor.swift */; }; + A1B2C3D4E5F6A7B8C9D0E1F3 /* StatsDisplayModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6A7B8C9D0E1F2 /* StatsDisplayModel.swift */; }; + A1B2C3D4E5F6A7B8C9D0E1F5 /* StatsDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6A7B8C9D0E1F4 /* StatsDisplayView.swift */; }; + AA1B2C3D4E5F6A7B8C9D0E2F /* LoopFollowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1B2C3D4E5F6A7B8C9D0E1F /* LoopFollowApp.swift */; }; + AB1CD0012C7B30D40048F05C /* RemoteDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1CD0022C7B30D40048F05C /* RemoteDiagnostics.swift */; }; ACE7F6DE0D065BEB52CDC0DB /* FutureCarbsAlarmEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7D2A4EFD18B7B7748B6669E /* FutureCarbsAlarmEditor.swift */; }; + B500000000000000000000A2 /* RemoteBolusHistoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */; }; + B500000000000000000000A4 /* QuickPickBolusesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000A3 /* QuickPickBolusesManager.swift */; }; + B500000000000000000000B2 /* RemoteMealHistoryEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */; }; + B500000000000000000000B4 /* QuickPickMealsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000B3 /* QuickPickMealsManager.swift */; }; + B500000000000000000000C2 /* QuickPickSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000C1 /* QuickPickSectionHeader.swift */; }; + BB2C3D4E5F6A7B8C9D0E2F2A /* MainTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C3D4E5F6A7B8C9D0E1F2A /* MainTabView.swift */; }; + CC3D4E5F6A7B8C9D0E2F2A3B /* MoreMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3D4E5F6A7B8C9D0E1F2A3B /* MoreMenuView.swift */; }; + D53B243FBA69EC2A82755CDF /* DBSizeAlarmEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21EBF6ACF259782445DA1A7E /* DBSizeAlarmEditor.swift */; }; DD0247592DB2E89600FCADF6 /* AlarmCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0247582DB2E89600FCADF6 /* AlarmCondition.swift */; }; DD0247712DB4337700FCADF6 /* BuildExpireCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD02475B2DB2E8FB00FCADF6 /* BuildExpireCondition.swift */; }; DD026E592EA2C8A200A39CB5 /* InsulinPrecisionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD026E582EA2C8A200A39CB5 /* InsulinPrecisionManager.swift */; }; @@ -93,9 +106,6 @@ DD0C0C682C48529400DBADDF /* Metric.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C672C48529400DBADDF /* Metric.swift */; }; DD0C0C6B2C48562000DBADDF /* InsulinMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C6A2C48562000DBADDF /* InsulinMetric.swift */; }; DD0C0C6D2C48606200DBADDF /* CarbMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD0C0C6C2C48606200DBADDF /* CarbMetric.swift */; }; - DD4E5F6A7B8C9D0E2F2A3B4C /* RemoteContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4E5F6A7B8C9D0E1F2A3B4C /* RemoteContentView.swift */; }; - AA1B2C3D4E5F6A7B8C9D0E2F /* LoopFollowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1B2C3D4E5F6A7B8C9D0E1F /* LoopFollowApp.swift */; }; - BB2C3D4E5F6A7B8C9D0E2F2A /* MainTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB2C3D4E5F6A7B8C9D0E1F2A /* MainTabView.swift */; }; DD12D4872E1705E6004E0112 /* AlarmsContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD12D4862E1705E6004E0112 /* AlarmsContainerView.swift */; }; DD13BC752C3FD6210062313B /* InfoType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD13BC742C3FD6200062313B /* InfoType.swift */; }; DD13BC772C3FD64E0062313B /* InfoData.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD13BC762C3FD64E0062313B /* InfoData.swift */; }; @@ -104,13 +114,7 @@ DD16AF0D2C98485400FB655A /* SecureStorageValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD16AF0C2C98485400FB655A /* SecureStorageValue.swift */; }; DD16AF0F2C99592F00FB655A /* HKQuantityInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD16AF0E2C99592F00FB655A /* HKQuantityInputView.swift */; }; DD16AF112C997B4600FB655A /* LoadingButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD16AF102C997B4600FB655A /* LoadingButtonView.swift */; }; - B500000000000000000000C2 /* QuickPickSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B500000000000000000000C1 /* QuickPickSectionHeader.swift */; }; DD1D52B92E1EB5DC00432050 /* TabPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1D52B82E1EB5DC00432050 /* TabPosition.swift */; }; - CC3D4E5F6A7B8C9D0E2F2A3B /* MoreMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC3D4E5F6A7B8C9D0E1F2A3B /* MoreMenuView.swift */; }; - DD7A3B5D2F1E8D9A00B4C6E1 /* BGDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B5C2F1E8D9A00B4C6E1 /* BGDisplayView.swift */; }; - DD7A3B5F2F1E8DA000B4C6E1 /* LineChartWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B5E2F1E8DA000B4C6E1 /* LineChartWrapper.swift */; }; - DD7A3B612F1E8DA600B4C6E1 /* MainHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B602F1E8DA600B4C6E1 /* MainHomeView.swift */; }; - EE5F6A7B8C9D0E2F2A3B4C5D /* NightscoutContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE5F6A7B8C9D0E1F2A3B4C5D /* NightscoutContentView.swift */; }; DD1D52C02E4C100000000001 /* AppearanceMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1D52BF2E4C100000000001 /* AppearanceMode.swift */; }; DD1D52C22E4C100000000002 /* PredictionDisplayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD1D52C12E4C100000000002 /* PredictionDisplayType.swift */; }; DD2C2E4F2D3B8AF1006413A5 /* NightscoutSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2C2E4E2D3B8AEC006413A5 /* NightscoutSettingsView.swift */; }; @@ -120,7 +124,6 @@ DD4878052C7B2C970048F05C /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878042C7B2C970048F05C /* Storage.swift */; }; DD4878082C7B30BF0048F05C /* RemoteSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878072C7B30BF0048F05C /* RemoteSettingsView.swift */; }; DD48780A2C7B30D40048F05C /* RemoteSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878092C7B30D40048F05C /* RemoteSettingsViewModel.swift */; }; - AB1CD0012C7B30D40048F05C /* RemoteDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB1CD0022C7B30D40048F05C /* RemoteDiagnostics.swift */; }; DD48780E2C7B74A40048F05C /* TrioRemoteControlViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD48780D2C7B74A40048F05C /* TrioRemoteControlViewModel.swift */; }; DD4878102C7B74BF0048F05C /* TrioRemoteControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD48780F2C7B74BF0048F05C /* TrioRemoteControlView.swift */; }; DD4878132C7B750D0048F05C /* TempTargetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4878122C7B750D0048F05C /* TempTargetView.swift */; }; @@ -146,6 +149,10 @@ DD4AFB612DB68BBC00BB593F /* AlarmListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AFB602DB68BBC00BB593F /* AlarmListView.swift */; }; DD4AFB672DB68C5500BB593F /* UUID+Identifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AFB662DB68C5500BB593F /* UUID+Identifiable.swift */; }; DD4AFB6B2DB6BF2A00BB593F /* Binding+Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AFB6A2DB6BF2A00BB593F /* Binding+Optional.swift */; }; + DD4E5F6A7B8C9D0E2F2A3B4C /* RemoteContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4E5F6A7B8C9D0E1F2A3B4C /* RemoteContentView.swift */; }; + DD50C10A2F60A00000000001 /* SocketIO in Frameworks */ = {isa = PBXBuildFile; productRef = DD50C10A2F60A00000000003 /* SocketIO */; }; + DD50C10A2F60B00000000002 /* NightscoutSocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD50C10A2F60B00000000001 /* NightscoutSocketManager.swift */; }; + DD50C10A2F60B00000000004 /* NightscoutSocketDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD50C10A2F60B00000000003 /* NightscoutSocketDataHandler.swift */; }; DD50C7552D0862770057AE6F /* ContactImageUpdater.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD50C7542D0862770057AE6F /* ContactImageUpdater.swift */; }; DD5334212C60EBEE00062F9D /* InsulinCartridgeChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5334202C60EBEE00062F9D /* InsulinCartridgeChange.swift */; }; DD5334232C60ED3600062F9D /* IAge.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5334222C60ED3600062F9D /* IAge.swift */; }; @@ -161,6 +168,9 @@ DD608A0A2C23593900F91132 /* SMB.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A092C23593900F91132 /* SMB.swift */; }; DD608A0C2C27415C00F91132 /* BackgroundAlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */; }; DD6A935E2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */; }; + DD7A3B5D2F1E8D9A00B4C6E1 /* BGDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B5C2F1E8D9A00B4C6E1 /* BGDisplayView.swift */; }; + DD7A3B5F2F1E8DA000B4C6E1 /* LineChartWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B5E2F1E8DA000B4C6E1 /* LineChartWrapper.swift */; }; + DD7A3B612F1E8DA600B4C6E1 /* MainHomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7A3B602F1E8DA600B4C6E1 /* MainHomeView.swift */; }; DD7B0D442D730A3B0063DCB6 /* CycleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7B0D432D730A320063DCB6 /* CycleHelper.swift */; }; DD7E19842ACDA50C00DBD158 /* Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19832ACDA50C00DBD158 /* Overrides.swift */; }; DD7E19862ACDA59700DBD158 /* BGCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19852ACDA59700DBD158 /* BGCheck.swift */; }; @@ -259,7 +269,6 @@ DDD10F0B2C54192A00D76A8E /* TemporaryTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD10F0A2C54192A00D76A8E /* TemporaryTarget.swift */; }; DDDB86F12DF7223C00AADDAC /* DeleteAlarmSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDB86F02DF7223C00AADDAC /* DeleteAlarmSection.swift */; }; DDDC01DD2E244B3100D9975C /* JWTManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC01DC2E244B3100D9975C /* JWTManager.swift */; }; - A1A1A10002000000A0CFEED1 /* LogRedactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10002000000A0CFEED2 /* LogRedactor.swift */; }; DDDC31CC2E13A7DF009EA0F3 /* AddAlarmSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */; }; DDDC31CE2E13A811009EA0F3 /* AlarmTile.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */; }; DDE69ED22C7256260013EAEC /* RemoteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDE69ED12C7256260013EAEC /* RemoteType.swift */; }; @@ -288,6 +297,8 @@ DDFF3D852D14279B00BF9D9E /* BackgroundRefreshSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF3D842D14279B00BF9D9E /* BackgroundRefreshSettingsView.swift */; }; DDFF3D872D14280500BF9D9E /* BackgroundRefreshSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF3D862D14280500BF9D9E /* BackgroundRefreshSettingsViewModel.swift */; }; DDFF3D892D1429AB00BF9D9E /* BackgroundRefreshType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFF3D882D1429AB00BF9D9E /* BackgroundRefreshType.swift */; }; + E2BE9B6A33AE4F0FD750767E /* DBSizeCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D0728C33E857F13E8D9C2AD /* DBSizeCondition.swift */; }; + EE5F6A7B8C9D0E2F2A3B4C5D /* NightscoutContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE5F6A7B8C9D0E1F2A3B4C5D /* NightscoutContentView.swift */; }; F19449721F3B792730A0F4FD /* PendingFutureCarb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9BEC26E4E48EF9B811A372 /* PendingFutureCarb.swift */; }; FC16A97A24996673003D6245 /* NightScout.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A97924996673003D6245 /* NightScout.swift */; }; FC16A97B249966A3003D6245 /* AlarmSound.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7CE589248ABEA3001F83B8 /* AlarmSound.swift */; }; @@ -296,12 +307,9 @@ FC16A98124996C07003D6245 /* DateTime.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC16A98024996C07003D6245 /* DateTime.swift */; }; FC1BDD2B24A22650001B652C /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BDD2A24A22650001B652C /* Stats.swift */; }; FC1BDD2D24A23204001B652C /* MainViewController+updateStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BDD2C24A23204001B652C /* MainViewController+updateStats.swift */; }; - A1B2C3D4E5F6A7B8C9D0E1F3 /* StatsDisplayModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6A7B8C9D0E1F2 /* StatsDisplayModel.swift */; }; - A1B2C3D4E5F6A7B8C9D0E1F5 /* StatsDisplayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6A7B8C9D0E1F4 /* StatsDisplayView.swift */; }; FC1BDD3224A2585C001B652C /* DataStructs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BDD2E24A232A3001B652C /* DataStructs.swift */; }; FC3AE7B5249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */; }; FC3CAB022493B6220068A152 /* BackgroundTaskAudio.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC688592489554800A0279D /* BackgroundTaskAudio.swift */; }; - A1A1A10001000000A0CFEED1 /* APNsCredentialValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */; }; FC5A5C3D2497B229009C550E /* Config.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = FC5A5C3C2497B229009C550E /* Config.xcconfig */; }; FC7CE518248ABE37001F83B8 /* Siri_Alert_Calibration_Needed.caf in Resources */ = {isa = PBXBuildFile; fileRef = FC7CE4A9248ABE2B001F83B8 /* Siri_Alert_Calibration_Needed.caf */; }; FC7CE519248ABE37001F83B8 /* Rise_And_Shine.caf in Resources */ = {isa = PBXBuildFile; fileRef = FC7CE4AA248ABE2B001F83B8 /* Rise_And_Shine.caf */; }; @@ -432,15 +440,11 @@ FCC6886B24898FD800A0279D /* ObservationToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886A24898FD800A0279D /* ObservationToken.swift */; }; FCC6886D2489909D00A0279D /* AnyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886C2489909D00A0279D /* AnyConvertible.swift */; }; FCC6886F2489A53800A0279D /* AppConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCC6886E2489A53800A0279D /* AppConstants.swift */; }; - 9C7FB98C98BE4FF98F4815EE /* Telemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFBE69CEF18416D84959974 /* Telemetry.swift */; }; FCD2A27D24C9D044009F7B7B /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD2A27C24C9D044009F7B7B /* Globals.swift */; }; FCE537BC249A4D7D00F80BF8 /* carbBolusArrays.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCE537BB249A4D7D00F80BF8 /* carbBolusArrays.swift */; }; FCEF87AC24A141A700AE6FA0 /* Localizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEF87AA24A1417900AE6FA0 /* Localizer.swift */; }; FCFEEC9E2486E68E00402A7F /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCFEEC9D2486E68E00402A7F /* WebKit.framework */; }; FCFEECA02488157B00402A7F /* Chart.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCFEEC9F2488157B00402A7F /* Chart.swift */; }; - DD50C10A2F60A00000000001 /* SocketIO in Frameworks */ = {isa = PBXBuildFile; productRef = DD50C10A2F60A00000000003 /* SocketIO */; }; - DD50C10A2F60B00000000002 /* NightscoutSocketManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD50C10A2F60B00000000001 /* NightscoutSocketManager.swift */; }; - DD50C10A2F60B00000000004 /* NightscoutSocketDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD50C10A2F60B00000000003 /* NightscoutSocketDataHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -475,11 +479,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteBolusHistoryEntry.swift; sourceTree = ""; }; - B500000000000000000000A3 /* QuickPickBolusesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickBolusesManager.swift; sourceTree = ""; }; - B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteMealHistoryEntry.swift; sourceTree = ""; }; - B500000000000000000000B3 /* QuickPickMealsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickMealsManager.swift; sourceTree = ""; }; 059B0FA59AABFE72FE13DDDA /* Pods-LoopFollow.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoopFollow.release.xcconfig"; path = "Target Support Files/Pods-LoopFollow/Pods-LoopFollow.release.xcconfig"; sourceTree = ""; }; + 21EBF6ACF259782445DA1A7E /* DBSizeAlarmEditor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DBSizeAlarmEditor.swift; sourceTree = ""; }; 2B9BEC26E4E48EF9B811A372 /* PendingFutureCarb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingFutureCarb.swift; sourceTree = ""; }; 2EBAB9EECE7095238A558060 /* FutureCarbsCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FutureCarbsCondition.swift; sourceTree = ""; }; 374A77982F5BD8AB00E96858 /* APNSClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSClient.swift; sourceTree = ""; }; @@ -500,6 +501,7 @@ 37A4BDDC2F5B6B4A00EEB289 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = /System/Library/Frameworks/SwiftUI.framework; sourceTree = ""; }; 37E4DD0C2F7E0967000511C8 /* LALivenessStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LALivenessStore.swift; sourceTree = ""; }; 37E4DD0F2F7E0985000511C8 /* LALivenessMarker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LALivenessMarker.swift; sourceTree = ""; }; + 5D0728C33E857F13E8D9C2AD /* DBSizeCondition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DBSizeCondition.swift; sourceTree = ""; }; 654132E62E19EA7E00BDBE08 /* SimpleQRCodeScannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleQRCodeScannerView.swift; sourceTree = ""; }; 654132E92E19F24800BDBE08 /* TOTPGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TOTPGenerator.swift; sourceTree = ""; }; 654134172E1DC09700BDBE08 /* OverridePresetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverridePresetsView.swift; sourceTree = ""; }; @@ -532,9 +534,24 @@ 65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsConfigurationView.swift; sourceTree = ""; }; 65E153C22E4BB69100693A4F /* URLTokenValidationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLTokenValidationView.swift; sourceTree = ""; }; 65E8A2852E44B0300065037B /* VolumeButtonHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeButtonHandler.swift; sourceTree = ""; }; + 8B81E18A2489A364AFC0A9E4 /* DBSize.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DBSize.swift; sourceTree = ""; }; + A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = ""; }; + A1A1A10002000000A0CFEED2 /* LogRedactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRedactor.swift; sourceTree = ""; }; + A1B2C3D4E5F6A7B8C9D0E1F2 /* StatsDisplayModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsDisplayModel.swift; sourceTree = ""; }; + A1B2C3D4E5F6A7B8C9D0E1F4 /* StatsDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsDisplayView.swift; sourceTree = ""; }; A7D55B42A22051DAD69E89D0 /* Pods_LoopFollow.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LoopFollow.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A8CA8BE0B3D247408FE088B4 /* BackgroundRefreshManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundRefreshManager.swift; sourceTree = ""; }; + AA1B2C3D4E5F6A7B8C9D0E1F /* LoopFollowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopFollowApp.swift; sourceTree = ""; }; + AB1CD0022C7B30D40048F05C /* RemoteDiagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteDiagnostics.swift; sourceTree = ""; }; + B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteBolusHistoryEntry.swift; sourceTree = ""; }; + B500000000000000000000A3 /* QuickPickBolusesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickBolusesManager.swift; sourceTree = ""; }; + B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteMealHistoryEntry.swift; sourceTree = ""; }; + B500000000000000000000B3 /* QuickPickMealsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickMealsManager.swift; sourceTree = ""; }; + B500000000000000000000C1 /* QuickPickSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickSectionHeader.swift; sourceTree = ""; }; B7D2A4EFD18B7B7748B6669E /* FutureCarbsAlarmEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FutureCarbsAlarmEditor.swift; sourceTree = ""; }; + BB2C3D4E5F6A7B8C9D0E1F2A /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = ""; }; + BDFBE69CEF18416D84959974 /* Telemetry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = ""; }; + CC3D4E5F6A7B8C9D0E1F2A3B /* MoreMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreMenuView.swift; sourceTree = ""; }; DD0247582DB2E89600FCADF6 /* AlarmCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCondition.swift; sourceTree = ""; }; DD02475B2DB2E8FB00FCADF6 /* BuildExpireCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildExpireCondition.swift; sourceTree = ""; }; DD026E582EA2C8A200A39CB5 /* InsulinPrecisionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinPrecisionManager.swift; sourceTree = ""; }; @@ -558,9 +575,6 @@ DD0C0C672C48529400DBADDF /* Metric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metric.swift; sourceTree = ""; }; DD0C0C6A2C48562000DBADDF /* InsulinMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinMetric.swift; sourceTree = ""; }; DD0C0C6C2C48606200DBADDF /* CarbMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbMetric.swift; sourceTree = ""; }; - DD4E5F6A7B8C9D0E1F2A3B4C /* RemoteContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteContentView.swift; sourceTree = ""; }; - AA1B2C3D4E5F6A7B8C9D0E1F /* LoopFollowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopFollowApp.swift; sourceTree = ""; }; - BB2C3D4E5F6A7B8C9D0E1F2A /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = ""; }; DD12D4862E1705E6004E0112 /* AlarmsContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmsContainerView.swift; sourceTree = ""; }; DD13BC742C3FD6200062313B /* InfoType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoType.swift; sourceTree = ""; }; DD13BC762C3FD64E0062313B /* InfoData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoData.swift; sourceTree = ""; }; @@ -569,13 +583,7 @@ DD16AF0C2C98485400FB655A /* SecureStorageValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStorageValue.swift; sourceTree = ""; }; DD16AF0E2C99592F00FB655A /* HKQuantityInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HKQuantityInputView.swift; sourceTree = ""; }; DD16AF102C997B4600FB655A /* LoadingButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingButtonView.swift; sourceTree = ""; }; - B500000000000000000000C1 /* QuickPickSectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPickSectionHeader.swift; sourceTree = ""; }; DD1D52B82E1EB5DC00432050 /* TabPosition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabPosition.swift; sourceTree = ""; }; - CC3D4E5F6A7B8C9D0E1F2A3B /* MoreMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreMenuView.swift; sourceTree = ""; }; - DD7A3B5C2F1E8D9A00B4C6E1 /* BGDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGDisplayView.swift; sourceTree = ""; }; - DD7A3B5E2F1E8DA000B4C6E1 /* LineChartWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChartWrapper.swift; sourceTree = ""; }; - DD7A3B602F1E8DA600B4C6E1 /* MainHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeView.swift; sourceTree = ""; }; - EE5F6A7B8C9D0E1F2A3B4C5D /* NightscoutContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutContentView.swift; sourceTree = ""; }; DD1D52BF2E4C100000000001 /* AppearanceMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceMode.swift; sourceTree = ""; }; DD1D52C12E4C100000000002 /* PredictionDisplayType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PredictionDisplayType.swift; sourceTree = ""; }; DD2C2E4E2D3B8AEC006413A5 /* NightscoutSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSettingsView.swift; sourceTree = ""; }; @@ -585,7 +593,6 @@ DD4878042C7B2C970048F05C /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; DD4878072C7B30BF0048F05C /* RemoteSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSettingsView.swift; sourceTree = ""; }; DD4878092C7B30D40048F05C /* RemoteSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSettingsViewModel.swift; sourceTree = ""; }; - AB1CD0022C7B30D40048F05C /* RemoteDiagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteDiagnostics.swift; sourceTree = ""; }; DD48780D2C7B74A40048F05C /* TrioRemoteControlViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioRemoteControlViewModel.swift; sourceTree = ""; }; DD48780F2C7B74BF0048F05C /* TrioRemoteControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrioRemoteControlView.swift; sourceTree = ""; }; DD4878122C7B750D0048F05C /* TempTargetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetView.swift; sourceTree = ""; }; @@ -604,8 +611,6 @@ DD493AE42ACF2383009A6922 /* Treatments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Treatments.swift; sourceTree = ""; }; DD493AE62ACF23CF009A6922 /* DeviceStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStatus.swift; sourceTree = ""; }; DD493AE82ACF2445009A6922 /* BGData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGData.swift; sourceTree = ""; }; - DD50C10A2F60B00000000001 /* NightscoutSocketManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSocketManager.swift; sourceTree = ""; }; - DD50C10A2F60B00000000003 /* NightscoutSocketDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSocketDataHandler.swift; sourceTree = ""; }; DD4A407D2E6AFEE6007B318B /* AuthService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthService.swift; sourceTree = ""; }; DD4AFB3A2DB55CB600BB593F /* TimeOfDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeOfDay.swift; sourceTree = ""; }; DD4AFB3C2DB55D2900BB593F /* AlarmConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmConfiguration.swift; sourceTree = ""; }; @@ -613,6 +618,9 @@ DD4AFB602DB68BBC00BB593F /* AlarmListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmListView.swift; sourceTree = ""; }; DD4AFB662DB68C5500BB593F /* UUID+Identifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UUID+Identifiable.swift"; sourceTree = ""; }; DD4AFB6A2DB6BF2A00BB593F /* Binding+Optional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+Optional.swift"; sourceTree = ""; }; + DD4E5F6A7B8C9D0E1F2A3B4C /* RemoteContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteContentView.swift; sourceTree = ""; }; + DD50C10A2F60B00000000001 /* NightscoutSocketManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSocketManager.swift; sourceTree = ""; }; + DD50C10A2F60B00000000003 /* NightscoutSocketDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutSocketDataHandler.swift; sourceTree = ""; }; DD50C7542D0862770057AE6F /* ContactImageUpdater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactImageUpdater.swift; sourceTree = ""; }; DD5334202C60EBEE00062F9D /* InsulinCartridgeChange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinCartridgeChange.swift; sourceTree = ""; }; DD5334222C60ED3600062F9D /* IAge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IAge.swift; sourceTree = ""; }; @@ -628,6 +636,9 @@ DD608A092C23593900F91132 /* SMB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMB.swift; sourceTree = ""; }; DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundAlertManager.swift; sourceTree = ""; }; DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStatusOpenAPS.swift; sourceTree = ""; }; + DD7A3B5C2F1E8D9A00B4C6E1 /* BGDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGDisplayView.swift; sourceTree = ""; }; + DD7A3B5E2F1E8DA000B4C6E1 /* LineChartWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineChartWrapper.swift; sourceTree = ""; }; + DD7A3B602F1E8DA600B4C6E1 /* MainHomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainHomeView.swift; sourceTree = ""; }; DD7B0D432D730A320063DCB6 /* CycleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CycleHelper.swift; sourceTree = ""; }; DD7E19832ACDA50C00DBD158 /* Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Overrides.swift; sourceTree = ""; }; DD7E19852ACDA59700DBD158 /* BGCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGCheck.swift; sourceTree = ""; }; @@ -728,7 +739,6 @@ DDD10F0A2C54192A00D76A8E /* TemporaryTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemporaryTarget.swift; sourceTree = ""; }; DDDB86F02DF7223C00AADDAC /* DeleteAlarmSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAlarmSection.swift; sourceTree = ""; }; DDDC01DC2E244B3100D9975C /* JWTManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTManager.swift; sourceTree = ""; }; - A1A1A10002000000A0CFEED2 /* LogRedactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRedactor.swift; sourceTree = ""; }; DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAlarmSheet.swift; sourceTree = ""; }; DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmTile.swift; sourceTree = ""; }; DDE69ED12C7256260013EAEC /* RemoteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteType.swift; sourceTree = ""; }; @@ -758,15 +768,15 @@ DDFF3D862D14280500BF9D9E /* BackgroundRefreshSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundRefreshSettingsViewModel.swift; sourceTree = ""; }; DDFF3D882D1429AB00BF9D9E /* BackgroundRefreshType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundRefreshType.swift; sourceTree = ""; }; E7C2676561D686C6459CAA2D /* APNSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNSettingsView.swift; sourceTree = ""; }; + EBE9ECA96BEA20DBD21B570D /* DBSizeTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DBSizeTask.swift; sourceTree = ""; }; ECA3EFB4037410B4973BB632 /* Pods-LoopFollow.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LoopFollow.debug.xcconfig"; path = "Target Support Files/Pods-LoopFollow/Pods-LoopFollow.debug.xcconfig"; sourceTree = ""; }; + EE5F6A7B8C9D0E1F2A3B4C5D /* NightscoutContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightscoutContentView.swift; sourceTree = ""; }; FC16A97924996673003D6245 /* NightScout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NightScout.swift; sourceTree = ""; }; FC16A97C24996747003D6245 /* SpeakBG.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeakBG.swift; sourceTree = ""; }; FC16A97E249969E2003D6245 /* Graphs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Graphs.swift; sourceTree = ""; }; FC16A98024996C07003D6245 /* DateTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTime.swift; sourceTree = ""; }; FC1BDD2A24A22650001B652C /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = ""; }; FC1BDD2C24A23204001B652C /* MainViewController+updateStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MainViewController+updateStats.swift"; sourceTree = ""; }; - A1B2C3D4E5F6A7B8C9D0E1F2 /* StatsDisplayModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsDisplayModel.swift; sourceTree = ""; }; - A1B2C3D4E5F6A7B8C9D0E1F4 /* StatsDisplayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsDisplayView.swift; sourceTree = ""; }; FC1BDD2E24A232A3001B652C /* DataStructs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStructs.swift; sourceTree = ""; }; FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LoopFollow.xcdatamodel; sourceTree = ""; }; FC5A5C3C2497B229009C550E /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = ""; }; @@ -896,7 +906,6 @@ FCA2DDE52501095000254A8C /* Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timers.swift; sourceTree = ""; }; FCC0FAC124922A22003E610E /* DictionaryKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryKeyPath.swift; sourceTree = ""; }; FCC688592489554800A0279D /* BackgroundTaskAudio.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundTaskAudio.swift; sourceTree = ""; }; - A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = ""; }; FCC6885B2489559400A0279D /* blank.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = blank.wav; sourceTree = ""; }; FCC6885D24896A6C00A0279D /* silence.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = silence.mp3; sourceTree = ""; }; FCC6886624898F8000A0279D /* UserDefaultsValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsValue.swift; sourceTree = ""; }; @@ -904,7 +913,6 @@ FCC6886A24898FD800A0279D /* ObservationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservationToken.swift; sourceTree = ""; }; FCC6886C2489909D00A0279D /* AnyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyConvertible.swift; sourceTree = ""; }; FCC6886E2489A53800A0279D /* AppConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = ""; }; - BDFBE69CEF18416D84959974 /* Telemetry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = ""; }; FCC688702489A57C00A0279D /* Loop Follow.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Loop Follow.entitlements"; sourceTree = ""; }; FCD2A27C24C9D044009F7B7B /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; FCE537BB249A4D7D00F80BF8 /* carbBolusArrays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = carbBolusArrays.swift; sourceTree = ""; }; @@ -915,10 +923,50 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - 37A4BDDE2F5B6B4A00EEB289 /* LoopFollowLAExtension */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = LoopFollowLAExtension; sourceTree = ""; }; - 65AC25F52ECFD5E800421360 /* Stats */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Stats; sourceTree = ""; }; - 65AC26702ED245DF00421360 /* Treatments */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Treatments; sourceTree = ""; }; - DDCC3AD72DDE1790006F1C10 /* Tests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Tests; sourceTree = ""; }; + 37A4BDDE2F5B6B4A00EEB289 /* LoopFollowLAExtension */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = LoopFollowLAExtension; + sourceTree = ""; + }; + 65AC25F52ECFD5E800421360 /* Stats */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = Stats; + sourceTree = ""; + }; + 65AC26702ED245DF00421360 /* Treatments */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = Treatments; + sourceTree = ""; + }; + DDCC3AD72DDE1790006F1C10 /* Tests */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = Tests; + sourceTree = ""; + }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1028,6 +1076,24 @@ path = Pods; sourceTree = ""; }; + B500000000000000000000A5 /* QuickPickBoluses */ = { + isa = PBXGroup; + children = ( + B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */, + B500000000000000000000A3 /* QuickPickBolusesManager.swift */, + ); + path = QuickPickBoluses; + sourceTree = ""; + }; + B500000000000000000000B5 /* QuickPickMeals */ = { + isa = PBXGroup; + children = ( + B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */, + B500000000000000000000B3 /* QuickPickMealsManager.swift */, + ); + path = QuickPickMeals; + sourceTree = ""; + }; DD02475A2DB2E8CE00FCADF6 /* AlarmCondition */ = { isa = PBXGroup; children = ( @@ -1055,6 +1121,7 @@ DD0247582DB2E89600FCADF6 /* AlarmCondition.swift */, DD0650EE2DCE96FF004D3B41 /* HighBGCondition.swift */, DD0650F02DCE9A9E004D3B41 /* MissedReadingCondition.swift */, + 5D0728C33E857F13E8D9C2AD /* DBSizeCondition.swift */, ); path = AlarmCondition; sourceTree = ""; @@ -1069,24 +1136,6 @@ path = Metric; sourceTree = ""; }; - B500000000000000000000B5 /* QuickPickMeals */ = { - isa = PBXGroup; - children = ( - B500000000000000000000B1 /* RemoteMealHistoryEntry.swift */, - B500000000000000000000B3 /* QuickPickMealsManager.swift */, - ); - path = QuickPickMeals; - sourceTree = ""; - }; - B500000000000000000000A5 /* QuickPickBoluses */ = { - isa = PBXGroup; - children = ( - B500000000000000000000A1 /* RemoteBolusHistoryEntry.swift */, - B500000000000000000000A3 /* QuickPickBolusesManager.swift */, - ); - path = QuickPickBoluses; - sourceTree = ""; - }; DD0C0C6E2C4AFFB800DBADDF /* Remote */ = { isa = PBXGroup; children = ( @@ -1211,6 +1260,7 @@ DD5334222C60ED3600062F9D /* IAge.swift */, DD50C10A2F60B00000000001 /* NightscoutSocketManager.swift */, DD50C10A2F60B00000000003 /* NightscoutSocketDataHandler.swift */, + 8B81E18A2489A364AFC0A9E4 /* DBSize.swift */, ); path = Nightscout; sourceTree = ""; @@ -1321,6 +1371,7 @@ DDC7E53E2DBD8A1600EB1127 /* LowBgAlarmEditor.swift */, DD0650F22DCE9B3D004D3B41 /* MissedReadingEditor.swift */, DD0650F82DCFE7BE004D3B41 /* FastDropAlarmEditor.swift */, + 21EBF6ACF259782445DA1A7E /* DBSizeAlarmEditor.swift */, ); path = Editors; sourceTree = ""; @@ -1399,6 +1450,7 @@ DD9ACA032D32821200415D8A /* DeviceStatusTask.swift */, DDEF503E2D32754A00999A5D /* ProfileTask.swift */, DDEF503B2D31BE2A00999A5D /* TaskScheduler.swift */, + EBE9ECA96BEA20DBD21B570D /* DBSizeTask.swift */, ); path = Task; sourceTree = ""; @@ -1785,8 +1837,6 @@ 37A4BDDE2F5B6B4A00EEB289 /* LoopFollowLAExtension */, ); name = LoopFollowLAExtensionExtension; - packageProductDependencies = ( - ); productName = LoopFollowLAExtensionExtension; productReference = 37A4BDD92F5B6B4A00EEB289 /* LoopFollowLAExtensionExtension.appex */; productType = "com.apple.product-type.app-extension"; @@ -1808,8 +1858,6 @@ DDCC3AD72DDE1790006F1C10 /* Tests */, ); name = Tests; - packageProductDependencies = ( - ); productName = Tests; productReference = DDCC3AD62DDE1790006F1C10 /* Tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -2443,6 +2491,10 @@ DDEF50422D479BAA00884336 /* LoopAPNSCarbsView.swift in Sources */, DDEF50432D479BBA00884336 /* LoopAPNSBolusView.swift in Sources */, DDEF50452D479BDA00884336 /* LoopAPNSRemoteView.swift in Sources */, + 18BA6357F867577712A116EB /* DBSize.swift in Sources */, + 9727B75402723679BD39CDE5 /* DBSizeTask.swift in Sources */, + E2BE9B6A33AE4F0FD750767E /* DBSizeCondition.swift in Sources */, + D53B243FBA69EC2A82755CDF /* DBSizeAlarmEditor.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2853,20 +2905,6 @@ }; /* End XCConfigurationList section */ -/* Begin XCVersionGroup section */ - FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */ = { - isa = XCVersionGroup; - children = ( - FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */, - ); - currentVersion = FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */; - name = LoopFollow.xcdatamodeld; - path = LoopFollow/LoopFollow.xcdatamodeld; - sourceTree = ""; - versionGroupType = wrapper.xcdatamodel; - }; -/* End XCVersionGroup section */ - /* Begin XCRemoteSwiftPackageReference section */ DD50C10A2F60A00000000002 /* XCRemoteSwiftPackageReference "socket.io-client-swift" */ = { isa = XCRemoteSwiftPackageReference; @@ -2885,6 +2923,20 @@ productName = SocketIO; }; /* End XCSwiftPackageProductDependency section */ + +/* Begin XCVersionGroup section */ + FC3AE7B3249E8E0E00AAE1E0 /* LoopFollow.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */, + ); + currentVersion = FC3AE7B4249E8E0E00AAE1E0 /* LoopFollow.xcdatamodel */; + name = LoopFollow.xcdatamodeld; + path = LoopFollow/LoopFollow.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = FC97880C2485969B00A7906C /* Project object */; } diff --git a/LoopFollow/Alarm/Alarm.swift b/LoopFollow/Alarm/Alarm.swift index 2de36fb0f..bfd98d995 100644 --- a/LoopFollow/Alarm/Alarm.swift +++ b/LoopFollow/Alarm/Alarm.swift @@ -364,6 +364,15 @@ struct Alarm: Identifiable, Codable, Equatable { snoozeDuration = 0 aboveBG = 180 belowBG = 70 + case .dbSize: + /// Nightscout's own dbsize plugin warns at 60% and calls 75% urgent + soundFile = .wrongAnswer + threshold = 75 + snoozeDuration = 1 + /// The database fills over weeks, so there is never a reason to wake someone for it + activeOption = .day + playSoundOption = .day + repeatSoundOption = .day } } } @@ -383,7 +392,7 @@ extension AlarmType { case .iob, .cob, .missedBolus, .futureCarbs, .recBolus: return .insulin case .battery, .batteryDrop, .pump, .pumpBattery, .pumpChange, - .sensorChange, .notLooping, .buildExpire: + .sensorChange, .notLooping, .buildExpire, .dbSize: return .device case .overrideStart, .overrideEnd, .tempTargetStart, .tempTargetEnd: return .other @@ -410,6 +419,7 @@ extension AlarmType { case .sensorChange: return "sensor.tag.radiowaves.forward" case .notLooping: return "circle.slash" case .buildExpire: return "calendar.badge.exclamationmark" + case .dbSize: return "externaldrive.badge.exclamationmark" case .overrideStart: return "play.circle" case .overrideEnd: return "stop.circle" case .tempTargetStart: return "flag" @@ -438,6 +448,7 @@ extension AlarmType { case .sensorChange: return "Sensor change due." case .notLooping: return "Loop hasn’t completed." case .buildExpire: return "Looping-app build expiring." + case .dbSize: return "Nightscout database filling up." case .overrideStart: return "Override just started." case .overrideEnd: return "Override ended." case .tempTargetStart: return "Temp target started." diff --git a/LoopFollow/Alarm/AlarmCondition/DBSizeCondition.swift b/LoopFollow/Alarm/AlarmCondition/DBSizeCondition.swift new file mode 100644 index 000000000..8ad00d9c3 --- /dev/null +++ b/LoopFollow/Alarm/AlarmCondition/DBSizeCondition.swift @@ -0,0 +1,18 @@ +// LoopFollow +// DBSizeCondition.swift + +import Foundation + +/// Fires when the Nightscout database has filled **≥ threshold percent** +/// of the size limit configured on the site (`DBSIZE_MAX`). +struct DBSizeCondition: AlarmCondition { + static let type: AlarmType = .dbSize + init() {} + + func evaluate(alarm: Alarm, data: AlarmData, now _: Date) -> Bool { + guard let limitPercentage = alarm.threshold, limitPercentage > 0 else { return false } + guard let usedPercentage = data.dbSizePercentage else { return false } + + return usedPercentage >= limitPercentage + } +} diff --git a/LoopFollow/Alarm/AlarmData.swift b/LoopFollow/Alarm/AlarmData.swift index b960a9223..96fda5cac 100644 --- a/LoopFollow/Alarm/AlarmData.swift +++ b/LoopFollow/Alarm/AlarmData.swift @@ -23,4 +23,5 @@ struct AlarmData: Codable { let latestPumpBattery: Double? let batteryHistory: [DataStructs.batteryStruct] let recentCarbs: [CarbSample] + let dbSizePercentage: Double? } diff --git a/LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift b/LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift index e8ff4aff5..14901c5a1 100644 --- a/LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift +++ b/LoopFollow/Alarm/AlarmEditing/AlarmEditor.swift @@ -83,6 +83,7 @@ struct AlarmEditor: View { case .batteryDrop: BatteryDropAlarmEditor(alarm: $alarm) case .missedBolus: MissedBolusAlarmEditor(alarm: $alarm) case .futureCarbs: FutureCarbsAlarmEditor(alarm: $alarm) + case .dbSize: DBSizeAlarmEditor(alarm: $alarm) } } } diff --git a/LoopFollow/Alarm/AlarmEditing/Editors/DBSizeAlarmEditor.swift b/LoopFollow/Alarm/AlarmEditing/Editors/DBSizeAlarmEditor.swift new file mode 100644 index 000000000..8852cf4c7 --- /dev/null +++ b/LoopFollow/Alarm/AlarmEditing/Editors/DBSizeAlarmEditor.swift @@ -0,0 +1,33 @@ +// LoopFollow +// DBSizeAlarmEditor.swift + +import SwiftUI + +struct DBSizeAlarmEditor: View { + @Binding var alarm: Alarm + + var body: some View { + Group { + InfoBanner( + text: "This warns you when the Nightscout database has filled the percentage you choose. Nightscout measures the used space against its own DBSIZE_MAX setting, which is 496 MiB unless the site owner changed it, so the percentage is only meaningful when that setting matches the real hosting limit.", + alarmType: alarm.type + ) + + AlarmGeneralSection(alarm: $alarm) + + AlarmStepperSection( + header: "Database Size", + footer: "This alerts you when the database reaches or exceeds this percentage of the limit configured on the Nightscout site.", + title: "At or Above", + range: 0 ... 100, + step: 5, + unitLabel: "%", + value: $alarm.threshold + ) + + AlarmActiveSection(alarm: $alarm) + AlarmAudioSection(alarm: $alarm) + AlarmSnoozeSection(alarm: $alarm) + } + } +} diff --git a/LoopFollow/Alarm/AlarmManager.swift b/LoopFollow/Alarm/AlarmManager.swift index 3f5aa84ec..30f14c9ba 100644 --- a/LoopFollow/Alarm/AlarmManager.swift +++ b/LoopFollow/Alarm/AlarmManager.swift @@ -34,6 +34,7 @@ class AlarmManager { BatteryCondition.self, BatteryDropCondition.self, FutureCarbsCondition.self, + DBSizeCondition.self, ] ) { var dict = [AlarmType: AlarmCondition]() diff --git a/LoopFollow/Alarm/AlarmType/AlarmType+Snooze.swift b/LoopFollow/Alarm/AlarmType/AlarmType+Snooze.swift index 134e1fb5b..6fa92d50e 100644 --- a/LoopFollow/Alarm/AlarmType/AlarmType+Snooze.swift +++ b/LoopFollow/Alarm/AlarmType/AlarmType+Snooze.swift @@ -7,7 +7,7 @@ extension AlarmType { /// What “unit” we use for snoozeDuration for this alarmType. var snoozeTimeUnit: TimeUnit { switch self { - case .buildExpire: + case .buildExpire, .dbSize: return .day case .low, .high, .fastDrop, .fastRise, .missedReading, .notLooping, .missedBolus, diff --git a/LoopFollow/Alarm/AlarmType/AlarmType+SortDirection.swift b/LoopFollow/Alarm/AlarmType/AlarmType+SortDirection.swift index a60c664ad..68ea50f71 100644 --- a/LoopFollow/Alarm/AlarmType/AlarmType+SortDirection.swift +++ b/LoopFollow/Alarm/AlarmType/AlarmType+SortDirection.swift @@ -37,7 +37,7 @@ extension AlarmType { return (direction: .descending, key: { $0.threshold }) - case .sensorChange: + case .sensorChange, .dbSize: return (direction: .ascending, key: { $0.threshold }) diff --git a/LoopFollow/Alarm/AlarmType/AlarmType+canAcknowledge.swift b/LoopFollow/Alarm/AlarmType/AlarmType+canAcknowledge.swift index 9f5f3b5d1..a2c9096db 100644 --- a/LoopFollow/Alarm/AlarmType/AlarmType+canAcknowledge.swift +++ b/LoopFollow/Alarm/AlarmType/AlarmType+canAcknowledge.swift @@ -12,7 +12,7 @@ extension AlarmType { return true // These are alarms without memory, if they only are acknowledged - they would alarm again immediately case - .batteryDrop, .missedReading, .notLooping, .battery, .pumpBattery, .buildExpire, .iob, .sensorChange, .pumpChange, .pump: + .batteryDrop, .missedReading, .notLooping, .battery, .pumpBattery, .buildExpire, .iob, .sensorChange, .pumpChange, .pump, .dbSize: return false } } diff --git a/LoopFollow/Alarm/AlarmType/AlarmType.swift b/LoopFollow/Alarm/AlarmType/AlarmType.swift index 11a51885e..45c2aa9af 100644 --- a/LoopFollow/Alarm/AlarmType/AlarmType.swift +++ b/LoopFollow/Alarm/AlarmType/AlarmType.swift @@ -29,6 +29,7 @@ enum AlarmType: String, CaseIterable, Codable { case tempTargetStart = "Temp Target Started" case tempTargetEnd = "Temp Target Ended" case buildExpire = "Looping app expiration" + case dbSize = "Nightscout Database Size" } extension AlarmType { diff --git a/LoopFollow/Controllers/Nightscout/DBSize.swift b/LoopFollow/Controllers/Nightscout/DBSize.swift new file mode 100644 index 000000000..056971a4d --- /dev/null +++ b/LoopFollow/Controllers/Nightscout/DBSize.swift @@ -0,0 +1,62 @@ +// LoopFollow +// DBSize.swift + +import Foundation + +/// Response shape of `/api/v2/properties/dbsize`. +/// +/// Nightscout's `dbsize` plugin reports the Mongo `dataSize + indexSize` sum +/// against `DBSIZE_MAX` (defaults to 496 MiB when the site admin has not set it). +/// The key is absent when the plugin has not produced a property yet. +struct DBSizeProperties: Codable { + let dbsize: DBSizeData? +} + +struct DBSizeData: Codable { + /// Used size, in MiB. + let totalDataSize: Double? + /// Used size as a percentage of `details.maxSize`, floored by the server. + let dataPercentage: Int? + let details: Details? + + struct Details: Codable { + /// The configured limit in MiB (`DBSIZE_MAX`). + let maxSize: Double? + let dataSize: Double? + } +} + +extension MainViewController { + // NS Database Size Web Call + func webLoadNSDBSize() { + NightscoutUtils.executeRequest(eventType: .dbSize, parameters: [:]) { (result: Result) in + switch result { + case let .success(properties): + self.updateDBSize(data: properties.dbsize) + case let .failure(error): + LogManager.shared.log(category: .nightscout, message: "webLoadNSDBSize, error: \(error.localizedDescription)") + } + } + } + + // NS Database Size Response Processor + func updateDBSize(data: DBSizeData?) { + // Nightscout still reports the property when `db.stats()` failed, but with a zero + // size. Its own pill hides on that, so treat it as "no reading" rather than 0%. + guard let data = data, let usedMiB = data.totalDataSize, usedMiB > 0 else { + infoManager.clearInfoData(type: .dbSize) + Observable.shared.dbSizePercentage.set(nil) + return + } + + Observable.shared.dbSizePercentage.set(data.dataPercentage.map(Double.init)) + + let used = Localizer.formatToLocalizedString(usedMiB, maxFractionDigits: 0, minFractionDigits: 0) + + if let percentage = data.dataPercentage { + infoManager.updateInfoData(type: .dbSize, value: "\(used) MiB (\(percentage)%)") + } else { + infoManager.updateInfoData(type: .dbSize, value: "\(used) MiB") + } + } +} diff --git a/LoopFollow/Helpers/NightscoutUtils.swift b/LoopFollow/Helpers/NightscoutUtils.swift index 88b1995b7..0ea3c136c 100644 --- a/LoopFollow/Helpers/NightscoutUtils.swift +++ b/LoopFollow/Helpers/NightscoutUtils.swift @@ -44,6 +44,7 @@ class NightscoutUtils { case iage = "Insulin Change" case temporaryOverride = "Temporary Override" case temporaryOverrideCancel = "Temporary Override Cancel" + case dbSize var endpoint: String { switch self { @@ -57,6 +58,8 @@ class NightscoutUtils { return "/api/v1/devicestatus.json" case .temporaryOverride, .temporaryOverrideCancel: return "/api/v2/notifications/loop" + case .dbSize: + return "/api/v2/properties/dbsize" } } } diff --git a/LoopFollow/InfoTable/InfoType.swift b/LoopFollow/InfoTable/InfoType.swift index 14d0eb335..fd9868120 100644 --- a/LoopFollow/InfoTable/InfoType.swift +++ b/LoopFollow/InfoTable/InfoType.swift @@ -4,7 +4,7 @@ import Foundation enum InfoType: Int, CaseIterable { - case iob, cob, basal, override, battery, pump, pumpBattery, sage, cage, recBolus, minMax, carbsToday, autosens, profile, target, isf, carbRatio, updated, tdd, iage + case iob, cob, basal, override, battery, pump, pumpBattery, sage, cage, recBolus, minMax, carbsToday, autosens, profile, target, isf, carbRatio, updated, tdd, iage, dbSize var name: String { switch self { @@ -28,6 +28,7 @@ enum InfoType: Int, CaseIterable { case .updated: return "Updated" case .tdd: return "TDD" case .iage: return "IAGE" + case .dbSize: return "DB Size" } } diff --git a/LoopFollow/Settings/ImportExport/AlarmSelectionView.swift b/LoopFollow/Settings/ImportExport/AlarmSelectionView.swift index 3574eb2b2..a758ae2ac 100644 --- a/LoopFollow/Settings/ImportExport/AlarmSelectionView.swift +++ b/LoopFollow/Settings/ImportExport/AlarmSelectionView.swift @@ -239,6 +239,8 @@ struct AlarmSelectionRow: View { return "Temp Target Ended" case .buildExpire: return "Looping app expiration" + case .dbSize: + return "Nightscout Database Size" } } } diff --git a/LoopFollow/Storage/Observable.swift b/LoopFollow/Storage/Observable.swift index 4128918db..7acd14652 100644 --- a/LoopFollow/Storage/Observable.swift +++ b/LoopFollow/Storage/Observable.swift @@ -42,6 +42,7 @@ class Observable { var deviceRecBolus = ObservableValue(default: nil) var deviceBatteryLevel = ObservableValue(default: nil) var pumpBatteryLevel = ObservableValue(default: nil) + var dbSizePercentage = ObservableValue(default: nil) var enactedOrSuggested = ObservableValue(default: nil) var lastSentTOTP = ObservableValue(default: nil) diff --git a/LoopFollow/Task/AlarmTask.swift b/LoopFollow/Task/AlarmTask.swift index 0102d66ed..4ee1eb047 100644 --- a/LoopFollow/Task/AlarmTask.swift +++ b/LoopFollow/Task/AlarmTask.swift @@ -52,7 +52,8 @@ extension MainViewController { latestBattery: latestBattery, latestPumpBattery: latestPumpBattery, batteryHistory: self.deviceBatteryData, - recentCarbs: recentCarbs + recentCarbs: recentCarbs, + dbSizePercentage: Observable.shared.dbSizePercentage.value ) let finalAlarmData: AlarmData diff --git a/LoopFollow/Task/DBSizeTask.swift b/LoopFollow/Task/DBSizeTask.swift new file mode 100644 index 000000000..0edf50a7e --- /dev/null +++ b/LoopFollow/Task/DBSizeTask.swift @@ -0,0 +1,30 @@ +// LoopFollow +// DBSizeTask.swift + +import Foundation + +extension MainViewController { + /// Nightscout recomputes the database size on every data load, but the value only moves + /// by a few MiB per day, so a slow poll is enough. + private static let dbSizeInterval: TimeInterval = 6 * 60 * 60 + + func scheduleDBSizeTask(initialDelay: TimeInterval = 5) { + let firstRun = Date().addingTimeInterval(initialDelay) + + TaskScheduler.shared.scheduleTask(id: .dbSize, nextRun: firstRun) { [weak self] in + guard let self = self else { return } + self.dbSizeTaskAction() + } + } + + func dbSizeTaskAction() { + guard IsNightscoutEnabled() else { + TaskScheduler.shared.rescheduleTask(id: .dbSize, to: Date().addingTimeInterval(60)) + return + } + + webLoadNSDBSize() + + TaskScheduler.shared.rescheduleTask(id: .dbSize, to: Date().addingTimeInterval(Self.dbSizeInterval)) + } +} diff --git a/LoopFollow/Task/Task.swift b/LoopFollow/Task/Task.swift index 41a7df57b..05098891a 100644 --- a/LoopFollow/Task/Task.swift +++ b/LoopFollow/Task/Task.swift @@ -12,5 +12,6 @@ extension MainViewController { scheduleMinAgoTask() scheduleCalendarTask() scheduleAlarmTask() + scheduleDBSizeTask() } } diff --git a/LoopFollow/Task/TaskScheduler.swift b/LoopFollow/Task/TaskScheduler.swift index 51588fb7a..3b2a382db 100644 --- a/LoopFollow/Task/TaskScheduler.swift +++ b/LoopFollow/Task/TaskScheduler.swift @@ -13,6 +13,7 @@ enum TaskID: CaseIterable { case calendarWrite case alarmCheck case telemetry + case dbSize } struct ScheduledTask {