Skip to content

Commit 196298a

Browse files
committed
transfer v2.2.11 updates from LF to LF_3
1 parent 62bed2b commit 196298a

27 files changed

Lines changed: 690 additions & 211 deletions

Config.xcconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
unique_id = ${DEVELOPMENT_TEAM}
77

88
//Version (DEFAULT)
9-
LOOP_FOLLOW_MARKETING_VERSION = 2.2.10
9+
LOOP_FOLLOW_MARKETING_VERSION = 2.2.11

LoopFollow.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
DD608A0A2C23593900F91132 /* SMB.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A092C23593900F91132 /* SMB.swift */; };
7171
DD608A0C2C27415C00F91132 /* BackgroundAlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */; };
7272
DD6A935E2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */; };
73+
DD7B0D442D730A3B0063DCB6 /* CycleHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7B0D432D730A320063DCB6 /* CycleHelper.swift */; };
7374
DD7E19842ACDA50C00DBD158 /* Overrides.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19832ACDA50C00DBD158 /* Overrides.swift */; };
7475
DD7E19862ACDA59700DBD158 /* BGCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19852ACDA59700DBD158 /* BGCheck.swift */; };
7576
DD7E19882ACDA5DA00DBD158 /* Notes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD7E19872ACDA5DA00DBD158 /* Notes.swift */; };
@@ -88,6 +89,9 @@
8889
DD9ED0CA2D355257000D2A63 /* LogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ED0C92D355256000D2A63 /* LogView.swift */; };
8990
DD9ED0CC2D35526E000D2A63 /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ED0CB2D35526E000D2A63 /* SearchBar.swift */; };
9091
DD9ED0CE2D35587A000D2A63 /* LogEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9ED0CD2D355879000D2A63 /* LogEntry.swift */; };
92+
DDA9ACA82D6A66E200E6F1A9 /* ContactColorOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9ACA72D6A66DD00E6F1A9 /* ContactColorOption.swift */; };
93+
DDA9ACAA2D6A6B8300E6F1A9 /* ContactIncludeOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9ACA92D6A6B8200E6F1A9 /* ContactIncludeOption.swift */; };
94+
DDA9ACAC2D6B317100E6F1A9 /* ContactType.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDA9ACAB2D6B316F00E6F1A9 /* ContactType.swift */; };
9195
DDAD162F2D2EF9830084BE10 /* RileyLinkHeartbeatBluetoothDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAD162E2D2EF97C0084BE10 /* RileyLinkHeartbeatBluetoothDevice.swift */; };
9296
DDB0AF522BB1A8BE00AFA48B /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB0AF512BB1A8BE00AFA48B /* BuildDetails.swift */; };
9397
DDB0AF552BB1B24A00AFA48B /* BuildDetails.plist in Resources */ = {isa = PBXBuildFile; fileRef = DDB0AF542BB1B24A00AFA48B /* BuildDetails.plist */; };
@@ -344,6 +348,7 @@
344348
DD608A092C23593900F91132 /* SMB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMB.swift; sourceTree = "<group>"; };
345349
DD608A0B2C27415C00F91132 /* BackgroundAlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundAlertManager.swift; sourceTree = "<group>"; };
346350
DD6A935D2BFA6FA2003FFB8E /* DeviceStatusOpenAPS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceStatusOpenAPS.swift; sourceTree = "<group>"; };
351+
DD7B0D432D730A320063DCB6 /* CycleHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CycleHelper.swift; sourceTree = "<group>"; };
347352
DD7E19832ACDA50C00DBD158 /* Overrides.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Overrides.swift; sourceTree = "<group>"; };
348353
DD7E19852ACDA59700DBD158 /* BGCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGCheck.swift; sourceTree = "<group>"; };
349354
DD7E19872ACDA5DA00DBD158 /* Notes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notes.swift; sourceTree = "<group>"; };
@@ -362,6 +367,9 @@
362367
DD9ED0C92D355256000D2A63 /* LogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogView.swift; sourceTree = "<group>"; };
363368
DD9ED0CB2D35526E000D2A63 /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
364369
DD9ED0CD2D355879000D2A63 /* LogEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogEntry.swift; sourceTree = "<group>"; };
370+
DDA9ACA72D6A66DD00E6F1A9 /* ContactColorOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactColorOption.swift; sourceTree = "<group>"; };
371+
DDA9ACA92D6A6B8200E6F1A9 /* ContactIncludeOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactIncludeOption.swift; sourceTree = "<group>"; };
372+
DDA9ACAB2D6B316F00E6F1A9 /* ContactType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactType.swift; sourceTree = "<group>"; };
365373
DDAD162E2D2EF97C0084BE10 /* RileyLinkHeartbeatBluetoothDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RileyLinkHeartbeatBluetoothDevice.swift; sourceTree = "<group>"; };
366374
DDB0AF502BB1A84500AFA48B /* capture-build-details.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "capture-build-details.sh"; sourceTree = "<group>"; };
367375
DDB0AF512BB1A8BE00AFA48B /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = "<group>"; };
@@ -706,6 +714,9 @@
706714
DD50C74D2D0828250057AE6F /* Contact */ = {
707715
isa = PBXGroup;
708716
children = (
717+
DDA9ACAB2D6B316F00E6F1A9 /* ContactType.swift */,
718+
DDA9ACA92D6A6B8200E6F1A9 /* ContactIncludeOption.swift */,
719+
DDA9ACA72D6A66DD00E6F1A9 /* ContactColorOption.swift */,
709720
DD50C7512D0828B40057AE6F /* Settings */,
710721
DD50C7542D0862770057AE6F /* ContactImageUpdater.swift */,
711722
);
@@ -1098,6 +1109,7 @@
10981109
FCC688542489367300A0279D /* Helpers */ = {
10991110
isa = PBXGroup;
11001111
children = (
1112+
DD7B0D432D730A320063DCB6 /* CycleHelper.swift */,
11011113
DDF6999C2C5AAA4C0058A8D9 /* Views */,
11021114
FCC6886E2489A53800A0279D /* AppConstants.swift */,
11031115
FCC6886A24898FD800A0279D /* ObservationToken.swift */,
@@ -1437,6 +1449,7 @@
14371449
FC16A97B249966A3003D6245 /* AlarmSound.swift in Sources */,
14381450
DDBE3ABD2CB5A961006B37DC /* OverrideView.swift in Sources */,
14391451
DDB0AF522BB1A8BE00AFA48B /* BuildDetails.swift in Sources */,
1452+
DDA9ACAA2D6A6B8300E6F1A9 /* ContactIncludeOption.swift in Sources */,
14401453
DD0C0C622C4175FD00DBADDF /* NSProfile.swift in Sources */,
14411454
DD58171E2D299FCA0041FB98 /* BluetoothDeviceDelegate.swift in Sources */,
14421455
DDE69ED22C7256260013EAEC /* RemoteType.swift in Sources */,
@@ -1449,13 +1462,15 @@
14491462
DD4878172C7B75350048F05C /* BolusView.swift in Sources */,
14501463
DD493AE72ACF23CF009A6922 /* DeviceStatus.swift in Sources */,
14511464
FCFEECA2248857A600402A7F /* SettingsViewController.swift in Sources */,
1465+
DD7B0D442D730A3B0063DCB6 /* CycleHelper.swift in Sources */,
14521466
DD9ACA0C2D33BB8600415D8A /* CalendarTask.swift in Sources */,
14531467
DD13BC792C3FE63A0062313B /* InfoManager.swift in Sources */,
14541468
DD0C0C702C4AFFE800DBADDF /* RemoteViewController.swift in Sources */,
14551469
DD48780A2C7B30D40048F05C /* RemoteSettingsViewModel.swift in Sources */,
14561470
FCFEECA02488157B00402A7F /* Chart.swift in Sources */,
14571471
DDCF979424C0D380002C9752 /* UIViewExtension.swift in Sources */,
14581472
DD0C0C6D2C48606200DBADDF /* CarbMetric.swift in Sources */,
1473+
DDA9ACA82D6A66E200E6F1A9 /* ContactColorOption.swift in Sources */,
14591474
DD7E19882ACDA5DA00DBD158 /* Notes.swift in Sources */,
14601475
FCEF87AC24A141A700AE6FA0 /* Localizer.swift in Sources */,
14611476
FC1BDD3224A2585C001B652C /* DataStructs.swift in Sources */,
@@ -1518,6 +1533,7 @@
15181533
DD4878032C7B297E0048F05C /* StorageValue.swift in Sources */,
15191534
DD4878192C7C56D60048F05C /* TrioNightscoutRemoteController.swift in Sources */,
15201535
FC1BDD2B24A22650001B652C /* Stats.swift in Sources */,
1536+
DDA9ACAC2D6B317100E6F1A9 /* ContactType.swift in Sources */,
15211537
DDDF6F432D479A9900884336 /* LoopNightscoutRemoteView.swift in Sources */,
15221538
DDD10F052C529DA200D76A8E /* ObservableValue.swift in Sources */,
15231539
FC1BDD2D24A23204001B652C /* StatsView.swift in Sources */,

LoopFollow/BackgroundRefresh/BT/BLEDeviceSelectionView.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,27 @@ struct BLEDeviceSelectionView: View {
1313
var body: some View {
1414
VStack {
1515
List {
16-
if bleManager.devices.filter({ selectedFilter.matches($0) && !isSelected($0) }).isEmpty {
16+
let filteredDevices = bleManager.devices.filter { selectedFilter.matches($0) && !isSelected($0) }
17+
if filteredDevices.isEmpty {
1718
Text("No devices found yet. They'll appear here when discovered.")
1819
.foregroundColor(.secondary)
1920
.multilineTextAlignment(.center)
2021
.padding()
2122
} else {
22-
ForEach(bleManager.devices.filter { selectedFilter.matches($0) && !isSelected($0) }, id: \.id) { device in
23+
ForEach(filteredDevices, id: \.id) { device in
2324
HStack {
2425
VStack(alignment: .leading) {
2526
Text(device.name ?? "Unknown")
2627

2728
Text("RSSI: \(device.rssi) dBm")
2829
.foregroundColor(.secondary)
2930
.font(.footnote)
31+
32+
if let offset = BLEManager.shared.expectedSensorFetchOffsetString(for: device) {
33+
Text("Expected bg delay: \(offset)")
34+
.foregroundColor(.secondary)
35+
.font(.footnote)
36+
}
3037
}
3138
Spacer()
3239
}

LoopFollow/BackgroundRefresh/BT/BLEManager.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,42 @@ extension BLEManager: BluetoothDeviceDelegate {
213213
TaskScheduler.shared.checkTasksNow()
214214
}
215215
}
216+
217+
extension BLEManager {
218+
/// Returns the expected sensor fetch offset as a formatted string ("mm:ss (fetch delay: XX sec)")
219+
/// for Dexcom and RileyLink devices. The expected offset is computed as the sensor's schedule offset plus the polling delay.
220+
/// The device’s lastSeen time is used (mod cycleDuration) to calculate the effective delay between when the sensor value
221+
/// becomes available and when the fetch is actually triggered.
222+
func expectedSensorFetchOffsetString(for device: BLEDevice) -> String? {
223+
guard
224+
let matchedType = BackgroundRefreshType.allCases.first(where: { $0.matches(device) }),
225+
let heartBeatInterval = matchedType.heartBeatInterval,
226+
let sensorOffset = Storage.shared.sensorScheduleOffset.value
227+
else {
228+
return nil
229+
}
230+
231+
let heartbeatLast: Date? = {
232+
if matchedType.estimatedDelayBasedOnHeartbeat {
233+
guard device.isConnected, let lastHeartbeat = activeDevice?.lastHeartbeatTime else {
234+
return nil
235+
}
236+
return lastHeartbeat
237+
} else {
238+
return device.lastSeen
239+
}
240+
}()
241+
242+
guard let heartbeatLast = heartbeatLast else {
243+
return nil
244+
}
245+
246+
let pollingDelay: TimeInterval = Double(UserDefaultsRepository.bgUpdateDelay.value)
247+
248+
let expectedOffset = sensorOffset + pollingDelay
249+
250+
let effectiveDelay = CycleHelper.computeDelay(sensorOffset: expectedOffset, heartbeatLast: heartbeatLast, heartbeatInterval: heartBeatInterval)
251+
252+
return "\(Int(effectiveDelay)) sec"
253+
}
254+
}

LoopFollow/BackgroundRefresh/BT/Devices/RileyLinkHeartbeatBluetoothDevice.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class RileyLinkHeartbeatBluetoothDevice: BluetoothDevice {
2727

2828
override func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
2929
super.centralManager(central, didConnect: peripheral)
30-
31-
self.bluetoothDeviceDelegate?.heartBeat()
3230
}
3331

3432
override func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

LoopFollow/BackgroundRefresh/BackgroundRefreshSettingsView.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ struct BackgroundRefreshSettingsView: View {
7373
.foregroundColor(.secondary)
7474

7575
case .dexcom:
76-
Text("Requires a Dexcom G6/ONE/G7/ONE+ transmitter within Bluetooth range. Provides updates every 5 minutes and uses less battery than the silent tune method.")
76+
Text("Requires a Dexcom G6/ONE/G7/ONE+ transmitter within Bluetooth range. Provides updates every 5 minutes and uses less battery than the silent tune method. If you have more than one device to choose from, select the one with the smallest expected bg delay.")
7777
.font(.footnote)
7878
.foregroundColor(.secondary)
7979
}
@@ -97,6 +97,11 @@ struct BackgroundRefreshSettingsView: View {
9797
.foregroundColor(.secondary)
9898
.font(.footnote)
9999
}
100+
if let offset = BLEManager.shared.expectedSensorFetchOffsetString(for: storedDevice) {
101+
Text("Expected bg delay: \(offset)")
102+
.foregroundColor(.secondary)
103+
.font(.footnote)
104+
}
100105

101106
HStack {
102107
Spacer()

LoopFollow/BackgroundRefresh/BackgroundRefreshType.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,26 @@ enum BackgroundRefreshType: String, Codable, CaseIterable {
2323
}
2424
}
2525

26+
var heartBeatInterval: TimeInterval? {
27+
switch self {
28+
case .rileyLink:
29+
return 60
30+
case .dexcom:
31+
return 5 * 60
32+
case .silentTune, .none:
33+
return nil
34+
}
35+
}
36+
37+
var estimatedDelayBasedOnHeartbeat: Bool {
38+
switch self {
39+
case .rileyLink:
40+
return true
41+
case .dexcom, .silentTune, .none:
42+
return false
43+
}
44+
}
45+
2646
/// Determines if a BLEDevice matches the specific device type
2747
func matches(_ device: BLEDevice) -> Bool {
2848
switch self {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// ContactColorOption.swift
3+
// LoopFollow
4+
//
5+
// Created by Jonas Björkert on 2025-02-22.
6+
// Copyright © 2025 Jon Fawcett. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
enum ContactColorOption: String, CaseIterable {
12+
case red, blue, cyan, green, yellow, orange, purple, white, black
13+
14+
var uiColor: UIColor {
15+
switch self {
16+
case .red: return .red
17+
case .blue: return .blue
18+
case .cyan: return .cyan
19+
case .green: return .green
20+
case .yellow: return .yellow
21+
case .orange: return .orange
22+
case .purple: return .purple
23+
case .white: return .white
24+
case .black: return .black
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)