Skip to content

Commit fcc45d7

Browse files
committed
Merge branch 'dev' into widgets
2 parents 03ec3d9 + f04d40f commit fcc45d7

22 files changed

+449
-1093
lines changed

.github/workflows/inactive_issues.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Close inactive issues
2+
on:
3+
schedule:
4+
- cron: "30 1 * * *"
5+
6+
jobs:
7+
close-issues:
8+
runs-on: ubuntu-latest
9+
permissions:
10+
issues: write
11+
pull-requests: write
12+
steps:
13+
- uses: actions/stale@v5
14+
with:
15+
operations-per-run: 100
16+
days-before-issue-stale: 30
17+
days-before-issue-close: 14
18+
stale-issue-label: "stale"
19+
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
20+
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
21+
days-before-pr-stale: -1
22+
days-before-pr-close: -1
23+
repo-token: ${{ secrets.GITHUB_TOKEN }}

Loop.xcodeproj/project.pbxproj

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,6 @@
365365
A98556852493F901000FD662 /* AlertStore+SimulatedCoreData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98556842493F901000FD662 /* AlertStore+SimulatedCoreData.swift */; };
366366
A987CD4924A58A0100439ADC /* ZipArchive.swift in Sources */ = {isa = PBXBuildFile; fileRef = A987CD4824A58A0100439ADC /* ZipArchive.swift */; };
367367
A999D40624663D18004C89D4 /* PumpManagerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A999D40524663D18004C89D4 /* PumpManagerError.swift */; };
368-
A99A114229A581F4007919CE /* BolusAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114129A581F4007919CE /* BolusAction.swift */; };
369-
A99A114429A5829A007919CE /* CarbAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114329A5829A007919CE /* CarbAction.swift */; };
370-
A99A114629A582A2007919CE /* OverrideAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114529A582A2007919CE /* OverrideAction.swift */; };
371-
A99A114E29A5879D007919CE /* BolusActionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114B29A5879C007919CE /* BolusActionTests.swift */; };
372-
A99A114F29A5879D007919CE /* CarbActionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114C29A5879C007919CE /* CarbActionTests.swift */; };
373-
A99A115029A5879D007919CE /* OverrideActionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A99A114D29A5879C007919CE /* OverrideActionTests.swift */; };
374368
A9A056B324B93C62007CF06D /* CriticalEventLogExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A056B224B93C62007CF06D /* CriticalEventLogExportView.swift */; };
375369
A9A056B524B94123007CF06D /* CriticalEventLogExportViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9A056B424B94123007CF06D /* CriticalEventLogExportViewModel.swift */; };
376370
A9A63F8E246B271600588D5B /* NSTimeInterval.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439897341CD2F7DE00223065 /* NSTimeInterval.swift */; };
@@ -1366,12 +1360,6 @@
13661360
A98556842493F901000FD662 /* AlertStore+SimulatedCoreData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlertStore+SimulatedCoreData.swift"; sourceTree = "<group>"; };
13671361
A987CD4824A58A0100439ADC /* ZipArchive.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipArchive.swift; sourceTree = "<group>"; };
13681362
A999D40524663D18004C89D4 /* PumpManagerError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PumpManagerError.swift; sourceTree = "<group>"; };
1369-
A99A114129A581F4007919CE /* BolusAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BolusAction.swift; sourceTree = "<group>"; };
1370-
A99A114329A5829A007919CE /* CarbAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarbAction.swift; sourceTree = "<group>"; };
1371-
A99A114529A582A2007919CE /* OverrideAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverrideAction.swift; sourceTree = "<group>"; };
1372-
A99A114B29A5879C007919CE /* BolusActionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BolusActionTests.swift; sourceTree = "<group>"; };
1373-
A99A114C29A5879C007919CE /* CarbActionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CarbActionTests.swift; sourceTree = "<group>"; };
1374-
A99A114D29A5879C007919CE /* OverrideActionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverrideActionTests.swift; sourceTree = "<group>"; };
13751363
A9A056B224B93C62007CF06D /* CriticalEventLogExportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalEventLogExportView.swift; sourceTree = "<group>"; };
13761364
A9A056B424B94123007CF06D /* CriticalEventLogExportViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalEventLogExportViewModel.swift; sourceTree = "<group>"; };
13771365
A9B607AF247F000F00792BE4 /* UserNotifications+Loop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserNotifications+Loop.swift"; sourceTree = "<group>"; };
@@ -2898,19 +2886,6 @@
28982886
A99A114029A581D6007919CE /* Remote */ = {
28992887
isa = PBXGroup;
29002888
children = (
2901-
A99A114129A581F4007919CE /* BolusAction.swift */,
2902-
A99A114329A5829A007919CE /* CarbAction.swift */,
2903-
A99A114529A582A2007919CE /* OverrideAction.swift */,
2904-
);
2905-
path = Remote;
2906-
sourceTree = "<group>";
2907-
};
2908-
A99A114A29A58789007919CE /* Remote */ = {
2909-
isa = PBXGroup;
2910-
children = (
2911-
A99A114B29A5879C007919CE /* BolusActionTests.swift */,
2912-
A99A114C29A5879C007919CE /* CarbActionTests.swift */,
2913-
A99A114D29A5879C007919CE /* OverrideActionTests.swift */,
29142889
);
29152890
path = Remote;
29162891
sourceTree = "<group>";
@@ -2926,7 +2901,6 @@
29262901
A9E6DFED246A0460005B1A1C /* Models */ = {
29272902
isa = PBXGroup;
29282903
children = (
2929-
A99A114A29A58789007919CE /* Remote */,
29302904
A9DFAFB224F0415E00950D1E /* CarbBackfillRequestUserInfoTests.swift */,
29312905
A963B279252CEBAE0062AA12 /* SetBolusUserInfoTests.swift */,
29322906
A9DFAFB424F048A000950D1E /* WatchHistoricalCarbsTests.swift */,
@@ -3965,7 +3939,6 @@
39653939
C17824A01E19CF9800D9D25C /* GlucoseThresholdTableViewController.swift in Sources */,
39663940
4372E487213C86240068E043 /* SampleValue.swift in Sources */,
39673941
437CEEE41CDE5C0A003C8C80 /* UIImage.swift in Sources */,
3968-
A99A114229A581F4007919CE /* BolusAction.swift in Sources */,
39693942
C1201E2C23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift in Sources */,
39703943
1D49795824E7289700948F05 /* ServicesViewModel.swift in Sources */,
39713944
1D4A3E2D2478628500FD601B /* StoredAlert+CoreDataClass.swift in Sources */,
@@ -4030,7 +4003,6 @@
40304003
1D6B1B6726866D89009AC446 /* AlertPermissionsChecker.swift in Sources */,
40314004
4F08DE8F1E7BB871006741EA /* CollectionType+Loop.swift in Sources */,
40324005
A9F703772489D8AA00C98AD8 /* PersistentDeviceLog+SimulatedCoreData.swift in Sources */,
4033-
A99A114629A582A2007919CE /* OverrideAction.swift in Sources */,
40344006
E9B080B1253BDA6300BAD8F8 /* UserDefaults+LoopIntents.swift in Sources */,
40354007
C1AF062329426300002C1B19 /* ManualGlucoseEntryRow.swift in Sources */,
40364008
C148CEE724FD91BD00711B3B /* DeliveryUncertaintyAlertManager.swift in Sources */,
@@ -4081,7 +4053,6 @@
40814053
A9C62D842331700E00535612 /* DiagnosticLog+Subsystem.swift in Sources */,
40824054
895FE0952201234000FCF18A /* OverrideSelectionViewController.swift in Sources */,
40834055
C1EF747228D6A44A00C8C083 /* CrashRecoveryManager.swift in Sources */,
4084-
A99A114429A5829A007919CE /* CarbAction.swift in Sources */,
40854056
A9F66FC3247F451500096EA7 /* UIDevice+Loop.swift in Sources */,
40864057
439706E622D2E84900C81566 /* PredictionSettingTableViewCell.swift in Sources */,
40874058
430D85891F44037000AF2D4F /* HUDViewTableViewCell.swift in Sources */,
@@ -4253,12 +4224,10 @@
42534224
buildActionMask = 2147483647;
42544225
files = (
42554226
A9DF02CB24F72B9E00B7C988 /* CriticalEventLogTests.swift in Sources */,
4256-
A99A114F29A5879D007919CE /* CarbActionTests.swift in Sources */,
42574227
B44251B3252350CE00605937 /* ChartAxisValuesStaticGeneratorTests.swift in Sources */,
42584228
1D80313D24746274002810DF /* AlertStoreTests.swift in Sources */,
42594229
C1777A6625A125F100595963 /* ManualEntryDoseViewModelTests.swift in Sources */,
42604230
C16B984026B4898800256B05 /* DoseEnactorTests.swift in Sources */,
4261-
A99A115029A5879D007919CE /* OverrideActionTests.swift in Sources */,
42624231
A9A63F8E246B271600588D5B /* NSTimeInterval.swift in Sources */,
42634232
A9DFAFB324F0415E00950D1E /* CarbBackfillRequestUserInfoTests.swift in Sources */,
42644233
A963B27A252CEBAE0062AA12 /* SetBolusUserInfoTests.swift in Sources */,
@@ -4278,7 +4247,6 @@
42784247
B4CAD8792549D2540057946B /* LoopCompletionFreshnessTests.swift in Sources */,
42794248
1D8D55BC252274650044DBB6 /* BolusEntryViewModelTests.swift in Sources */,
42804249
A91E4C2124F867A700BE9213 /* StoredAlertTests.swift in Sources */,
4281-
A99A114E29A5879D007919CE /* BolusActionTests.swift in Sources */,
42824250
1DA7A84224476EAD008257F0 /* AlertManagerTests.swift in Sources */,
42834251
A91E4C2324F86F1000BE9213 /* CriticalEventLogExportManagerTests.swift in Sources */,
42844252
E9C58A7324DB4A2700487A17 /* LoopDataManagerTests.swift in Sources */,

Loop/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5+
<key>NFCReaderUsageDescription</key>
6+
<string>The app uses NFC to pair with diabetes devices.</string>
57
<key>AppGroupIdentifier</key>
68
<string>$(APP_GROUP_IDENTIFIER)</string>
79
<key>AppStoreURL</key>

Loop/Loop.entitlements

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
<true/>
99
<key>com.apple.developer.healthkit.access</key>
1010
<array/>
11+
<key>com.apple.developer.nfc.readersession.formats</key>
12+
<array>
13+
<string>TAG</string>
14+
</array>
1115
<key>com.apple.developer.siri</key>
1216
<true/>
1317
<key>com.apple.developer.usernotifications.time-sensitive</key>

Loop/Managers/AnalyticsServicesManager.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,17 @@ final class AnalyticsServicesManager {
3636
analyticsServices.forEach { $0.recordAnalyticsEvent(name, withProperties: properties, outOfSession: outOfSession) }
3737
}
3838

39-
private func identify(_ property: String, value: String) {
39+
func identify(_ property: String, value: String) {
4040
log.debug("Identify %{public}@: %{public}@", property, value)
4141
analyticsServices.forEach { $0.recordIdentify(property, value: value) }
4242
}
4343

44+
func identify(_ property: String, array: [String]) {
45+
log.debug("Identify %{public}@: %{public}@", property, array)
46+
analyticsServices.forEach { $0.recordIdentify(property, array: array) }
47+
}
48+
49+
4450
// MARK: - UIApplicationDelegate
4551

4652
func application(didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any]?) {
@@ -253,3 +259,14 @@ extension AnalyticsServicesManager: PresetActivationObserver {
253259
}
254260
}
255261

262+
extension AutomaticDosingStrategy {
263+
var analyticsValue: String {
264+
switch self {
265+
case .automaticBolus:
266+
return "Automatic Bolus"
267+
case .tempBasalOnly:
268+
return "Temp Basal"
269+
}
270+
}
271+
}
272+

Loop/Managers/DeviceDataManager.swift

Lines changed: 11 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ final class DeviceDataManager {
407407
overrideHistory: overrideHistory,
408408
insulinDeliveryStore: doseStore.insulinDeliveryStore
409409
)
410-
411410

412411
settingsManager.remoteDataServicesManager = remoteDataServicesManager
413412

@@ -416,7 +415,10 @@ final class DeviceDataManager {
416415
alertManager: alertManager,
417416
analyticsServicesManager: analyticsServicesManager,
418417
loggingServicesManager: loggingServicesManager,
419-
remoteDataServicesManager: remoteDataServicesManager
418+
remoteDataServicesManager: remoteDataServicesManager,
419+
settingsManager: settingsManager,
420+
servicesManagerDelegate: loopManager,
421+
servicesManagerDosingDelegate: self
420422
)
421423

422424
let criticalEventLogs: [CriticalEventLog] = [settingsManager.settingsStore, glucoseStore, carbStore, dosingDecisionStore, doseStore, deviceLog, alertManager.alertStore]
@@ -1271,7 +1273,7 @@ extension DeviceDataManager {
12711273

12721274
func deleteTestingCGMData(completion: ((Error?) -> Void)? = nil) {
12731275
guard let testingCGMManager = cgmManager as? TestingCGMManager else {
1274-
assertionFailure("\(#function) should be invoked only when a testing CGM manager is in use")
1276+
completion?(nil)
12751277
return
12761278
}
12771279

@@ -1339,6 +1341,7 @@ extension DeviceDataManager: LoopDataManagerDelegate {
13391341
self.crashRecoveryManager.dosingFinished()
13401342
}
13411343
}
1344+
13421345
}
13431346

13441347
extension Notification.Name {
@@ -1347,152 +1350,14 @@ extension Notification.Name {
13471350
static let PumpEventsAdded = Notification.Name(rawValue: "com.loopKit.notification.PumpEventsAdded")
13481351
}
13491352

1350-
// MARK: - Remote Notification Handling
1351-
extension DeviceDataManager {
1352-
1353-
func handleRemoteNotification(_ notification: [String: AnyObject]) {
1354-
Task {
1355-
let backgroundTask = await beginBackgroundTask(name: "Remote Data Upload")
1356-
await handleRemoteNotification(notification)
1357-
await endBackgroundTask(backgroundTask)
1358-
}
1359-
}
1360-
1361-
func handleRemoteNotification(_ notification: [String: AnyObject]) async {
1362-
1363-
defer {
1364-
log.default("Remote Notification: Finished handling")
1365-
}
1366-
1367-
guard FeatureFlags.remoteCommandsEnabled else {
1368-
log.error("Remote Notification: Remote Commands not enabled.")
1369-
return
1370-
}
1371-
1372-
let command: RemoteCommand
1373-
do {
1374-
command = try await remoteDataServicesManager.commandFromPushNotification(notification)
1375-
} catch {
1376-
log.error("Remote Notification: Parse Error: %{public}@", String(describing: error))
1377-
return
1378-
}
1379-
1380-
await handleRemoteCommand(command)
1381-
}
1382-
1383-
func handleRemoteCommand(_ command: RemoteCommand) async {
1384-
1385-
log.default("Remote Notification: Handling command %{public}@", String(describing: command))
1386-
1387-
switch command.action {
1388-
case .temporaryScheduleOverride(let overrideAction):
1389-
do {
1390-
try command.validate()
1391-
try await handleOverrideAction(overrideAction)
1392-
} catch {
1393-
log.error("Remote Notification: Override Action Error: %{public}@", String(describing: error))
1394-
}
1395-
case .cancelTemporaryOverride(let overrideCancelAction):
1396-
do {
1397-
try command.validate()
1398-
try await handleOverrideCancelAction(overrideCancelAction)
1399-
} catch {
1400-
log.error("Remote Notification: Override Action Cancel Error: %{public}@", String(describing: error))
1401-
}
1402-
case .bolusEntry(let bolusAction):
1403-
do {
1404-
try command.validate()
1405-
try await handleBolusAction(bolusAction)
1406-
} catch {
1407-
await NotificationManager.sendRemoteBolusFailureNotification(for: error, amount: bolusAction.amountInUnits)
1408-
log.error("Remote Notification: Bolus Action Error: %{public}@", String(describing: error))
1409-
}
1410-
case .carbsEntry(let carbAction):
1411-
do {
1412-
try command.validate()
1413-
try await handleCarbAction(carbAction)
1414-
} catch {
1415-
await NotificationManager.sendRemoteCarbEntryFailureNotification(for: error, amountInGrams: carbAction.amountInGrams)
1416-
log.error("Remote Notification: Carb Action Error: %{public}@", String(describing: error))
1417-
}
1418-
}
1419-
}
1420-
1421-
//Remote Overrides
1422-
1423-
func handleOverrideAction(_ action: OverrideAction) async throws {
1424-
let remoteOverride = try action.toValidOverride(allowedPresets: loopManager.settings.overridePresets)
1425-
await activateRemoteOverride(remoteOverride)
1426-
}
1427-
1428-
func handleOverrideCancelAction(_ action: OverrideCancelAction) async throws {
1429-
await activateRemoteOverride(nil)
1430-
}
1431-
1432-
func activateRemoteOverride(_ remoteOverride: TemporaryScheduleOverride?) async {
1433-
loopManager.mutateSettings { settings in settings.scheduleOverride = remoteOverride }
1434-
await remoteDataServicesManager.triggerUpload(for: .overrides)
1435-
}
1436-
1437-
//Remote Bolus
1438-
1439-
func handleBolusAction(_ action: BolusAction) async throws {
1440-
let validBolusAmount = try action.toValidBolusAmount(maximumBolus: loopManager.settings.maximumBolus)
1441-
try await self.enactBolus(units: validBolusAmount, activationType: .manualNoRecommendation)
1442-
await remoteDataServicesManager.triggerUpload(for: .dose)
1443-
self.analyticsServicesManager.didBolus(source: "Remote", units: validBolusAmount)
1444-
}
1445-
1446-
//Remote Carb Entry
1447-
1448-
func handleCarbAction(_ action: CarbAction) async throws {
1449-
let candidateCarbEntry = try action.toValidCarbEntry(defaultAbsorptionTime: carbStore.defaultAbsorptionTimes.medium,
1450-
minAbsorptionTime: LoopConstants.minCarbAbsorptionTime,
1451-
maxAbsorptionTime: LoopConstants.maxCarbAbsorptionTime,
1452-
maxCarbEntryQuantity: LoopConstants.maxCarbEntryQuantity.doubleValue(for: .gram()),
1453-
maxCarbEntryPastTime: LoopConstants.maxCarbEntryPastTime,
1454-
maxCarbEntryFutureTime: LoopConstants.maxCarbEntryFutureTime
1455-
)
1456-
1457-
let _ = try await addRemoteCarbEntry(candidateCarbEntry)
1458-
await remoteDataServicesManager.triggerUpload(for: .carb)
1459-
}
1460-
1461-
//Can't add this concurrency wrapper method to LoopKit due to the minimum iOS version
1462-
func addRemoteCarbEntry(_ carbEntry: NewCarbEntry) async throws -> StoredCarbEntry {
1463-
return try await withCheckedThrowingContinuation { continuation in
1464-
carbStore.addCarbEntry(carbEntry) { result in
1465-
switch result {
1466-
case .success(let storedCarbEntry):
1467-
self.analyticsServicesManager.didAddCarbs(source: "Remote", amount: carbEntry.quantity.doubleValue(for: .gram()))
1468-
continuation.resume(returning: storedCarbEntry)
1469-
case .failure(let error):
1470-
continuation.resume(throwing: error)
1471-
}
1472-
}
1473-
}
1474-
}
1475-
1476-
//Background Uploads
1353+
// MARK: - ServicesManagerDosingDelegate
1354+
1355+
extension DeviceDataManager: ServicesManagerDosingDelegate {
14771356

1478-
func beginBackgroundTask(name: String) async -> UIBackgroundTaskIdentifier? {
1479-
var backgroundTask: UIBackgroundTaskIdentifier?
1480-
backgroundTask = await UIApplication.shared.beginBackgroundTask(withName: name) {
1481-
guard let backgroundTask = backgroundTask else {return}
1482-
Task {
1483-
await UIApplication.shared.endBackgroundTask(backgroundTask)
1484-
}
1485-
1486-
self.log.error("Background Task Expired: %{public}@", name)
1487-
}
1488-
1489-
return backgroundTask
1357+
func deliverBolus(amountInUnits: Double) async throws {
1358+
try await enactBolus(units: amountInUnits, activationType: .manualNoRecommendation)
14901359
}
14911360

1492-
func endBackgroundTask(_ backgroundTask: UIBackgroundTaskIdentifier?) async {
1493-
guard let backgroundTask else {return}
1494-
await UIApplication.shared.endBackgroundTask(backgroundTask)
1495-
}
14961361
}
14971362

14981363
// MARK: - Critical Event Log Export

0 commit comments

Comments
 (0)