Skip to content
24 changes: 14 additions & 10 deletions LoopFollow.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@
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 */; };
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 */; };
ACE7F6DE0D065BEB52CDC0DB /* FutureCarbsAlarmEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7D2A4EFD18B7B7748B6669E /* FutureCarbsAlarmEditor.swift */; };
C3B9188E2FC3CDC700B65FE5 /* DashboardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B9188D2FC3CDC000B65FE5 /* DashboardViewModel.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 */; };
Expand Down Expand Up @@ -251,7 +255,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 */; };
DDDF6F492D479AF000884336 /* NoRemoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDDF6F482D479AEF00884336 /* NoRemoteView.swift */; };
Expand Down Expand Up @@ -292,7 +295,6 @@
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 */; };
Expand Down Expand Up @@ -425,7 +427,6 @@
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 */; };
Expand Down Expand Up @@ -518,9 +519,13 @@
65A100022F5AA00000AA1002 /* UnitsConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnitsConfigurationView.swift; sourceTree = "<group>"; };
65E153C22E4BB69100693A4F /* URLTokenValidationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLTokenValidationView.swift; sourceTree = "<group>"; };
65E8A2852E44B0300065037B /* VolumeButtonHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeButtonHandler.swift; sourceTree = "<group>"; };
A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = "<group>"; };
A1A1A10002000000A0CFEED2 /* LogRedactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRedactor.swift; sourceTree = "<group>"; };
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 = "<group>"; };
B7D2A4EFD18B7B7748B6669E /* FutureCarbsAlarmEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FutureCarbsAlarmEditor.swift; sourceTree = "<group>"; };
BDFBE69CEF18416D84959974 /* Telemetry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = "<group>"; };
C3B9188D2FC3CDC000B65FE5 /* DashboardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardViewModel.swift; sourceTree = "<group>"; };
DD0247582DB2E89600FCADF6 /* AlarmCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCondition.swift; sourceTree = "<group>"; };
DD02475B2DB2E8FB00FCADF6 /* BuildExpireCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildExpireCondition.swift; sourceTree = "<group>"; };
DD026E582EA2C8A200A39CB5 /* InsulinPrecisionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InsulinPrecisionManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -709,7 +714,6 @@
DDD10F0A2C54192A00D76A8E /* TemporaryTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemporaryTarget.swift; sourceTree = "<group>"; };
DDDB86F02DF7223C00AADDAC /* DeleteAlarmSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteAlarmSection.swift; sourceTree = "<group>"; };
DDDC01DC2E244B3100D9975C /* JWTManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWTManager.swift; sourceTree = "<group>"; };
A1A1A10002000000A0CFEED2 /* LogRedactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRedactor.swift; sourceTree = "<group>"; };
DDDC31CB2E13A7DF009EA0F3 /* AddAlarmSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAlarmSheet.swift; sourceTree = "<group>"; };
DDDC31CD2E13A811009EA0F3 /* AlarmTile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmTile.swift; sourceTree = "<group>"; };
DDDF6F482D479AEF00884336 /* NoRemoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoRemoteView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -878,15 +882,13 @@
FCA2DDE52501095000254A8C /* Timers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timers.swift; sourceTree = "<group>"; };
FCC0FAC124922A22003E610E /* DictionaryKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryKeyPath.swift; sourceTree = "<group>"; };
FCC688592489554800A0279D /* BackgroundTaskAudio.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundTaskAudio.swift; sourceTree = "<group>"; };
A1A1A10001000000A0CFEED2 /* APNsCredentialValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APNsCredentialValidator.swift; sourceTree = "<group>"; };
FCC6885B2489559400A0279D /* blank.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = blank.wav; sourceTree = "<group>"; };
FCC6885D24896A6C00A0279D /* silence.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = silence.mp3; sourceTree = "<group>"; };
FCC6886624898F8000A0279D /* UserDefaultsValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsValue.swift; sourceTree = "<group>"; };
FCC6886824898FB100A0279D /* UserDefaultsValueGroups.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsValueGroups.swift; sourceTree = "<group>"; };
FCC6886A24898FD800A0279D /* ObservationToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservationToken.swift; sourceTree = "<group>"; };
FCC6886C2489909D00A0279D /* AnyConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyConvertible.swift; sourceTree = "<group>"; };
FCC6886E2489A53800A0279D /* AppConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppConstants.swift; sourceTree = "<group>"; };
BDFBE69CEF18416D84959974 /* Telemetry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Telemetry.swift; sourceTree = "<group>"; };
FCC688702489A57C00A0279D /* Loop Follow.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Loop Follow.entitlements"; sourceTree = "<group>"; };
FCD2A27C24C9D044009F7B7B /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = "<group>"; };
FCE537BB249A4D7D00F80BF8 /* carbBolusArrays.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = carbBolusArrays.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1455,6 +1457,7 @@
FC16A9782499657E003D6245 /* Controllers */ = {
isa = PBXGroup;
children = (
C3B9188D2FC3CDC000B65FE5 /* DashboardViewModel.swift */,
DD7E19802ACDA0EA00DBD158 /* Nightscout */,
FC7CE589248ABEA3001F83B8 /* AlarmSound.swift */,
FC16A97924996673003D6245 /* NightScout.swift */,
Expand Down Expand Up @@ -2130,6 +2133,7 @@
DD4878202C7DAF890048F05C /* PushMessage.swift in Sources */,
DD0247712DB4337700FCADF6 /* BuildExpireCondition.swift in Sources */,
DDF6999B2C5AA32E0058A8D9 /* TempTargetPreset.swift in Sources */,
C3B9188E2FC3CDC700B65FE5 /* DashboardViewModel.swift in Sources */,
DD7F4C0F2DD51EC200D449E9 /* TempTargetStartCondition.swift in Sources */,
DDBD19962DFB44B0005C2D69 /* Alarm+byPriorityThenSpec.swift in Sources */,
656F8C102E49F36F0008DC1D /* QRCodeDisplayView.swift in Sources */,
Expand Down Expand Up @@ -2449,7 +2453,7 @@
CODE_SIGN_ENTITLEMENTS = LoopFollowLAExtensionExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)";
DEVELOPMENT_TEAM = N8YMZJKBLQ;
ENABLE_APP_SANDBOX = NO;
ENABLE_HARDENED_RUNTIME = NO;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -2501,7 +2505,7 @@
CODE_SIGN_ENTITLEMENTS = LoopFollowLAExtensionExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)";
DEVELOPMENT_TEAM = N8YMZJKBLQ;
ENABLE_APP_SANDBOX = NO;
ENABLE_HARDENED_RUNTIME = NO;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
Expand Down Expand Up @@ -2735,7 +2739,7 @@
CODE_SIGN_ENTITLEMENTS = "LoopFollow/Loop Follow.entitlements";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)";
DEVELOPMENT_TEAM = N8YMZJKBLQ;
INFOPLIST_FILE = LoopFollow/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -2760,7 +2764,7 @@
CODE_SIGN_ENTITLEMENTS = "LoopFollow/Loop Follow.entitlements";
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "$(LF_DEVELOPMENT_TEAM)";
DEVELOPMENT_TEAM = N8YMZJKBLQ;
INFOPLIST_FILE = LoopFollow/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 16.6;
LD_RUNPATH_SEARCH_PATHS = (
Expand Down
82 changes: 41 additions & 41 deletions LoopFollow/BackgroundRefresh/BackgroundRefreshSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import SwiftUI

struct BackgroundRefreshSettingsView: View {
@ObservedObject var viewModel: BackgroundRefreshSettingsViewModel
@State private var forceRefresh = false
@State private var timer: Timer?
Comment thread
greyghost99 marked this conversation as resolved.

@ObservedObject var bleManager = BLEManager.shared

Expand All @@ -20,12 +18,6 @@ struct BackgroundRefreshSettingsView: View {
availableDevicesSection
}
}
.onAppear {
startTimer()
}
.onDisappear {
stopTimer()
}
Comment thread
greyghost99 marked this conversation as resolved.
}
.preferredColorScheme(Storage.shared.appearanceMode.value.colorScheme)
.navigationBarTitle("Background Refresh Settings", displayMode: .inline)
Expand Down Expand Up @@ -85,7 +77,7 @@ struct BackgroundRefreshSettingsView: View {
Text(storedDevice.name ?? "Unknown Device")
.font(.headline)

deviceConnectionStatus(for: storedDevice)
ConnectionStatusView(device: storedDevice)
Comment thread
greyghost99 marked this conversation as resolved.

if storedDevice.rssi != 0 {
Text("RSSI: \(storedDevice.rssi) dBm")
Expand All @@ -112,7 +104,6 @@ struct BackgroundRefreshSettingsView: View {
}
.padding(.vertical, 8)
}
.id(forceRefresh)
Comment thread
greyghost99 marked this conversation as resolved.
}
}

Expand Down Expand Up @@ -143,47 +134,56 @@ struct BackgroundRefreshSettingsView: View {
.font(.subheadline)
.foregroundColor(.secondary)
}
}

private func deviceConnectionStatus(for device: BLEDevice) -> some View {
let expectedConnectionTime: TimeInterval = bleManager.expectedHeartbeatInterval() ?? 300
let now = Date()
let timeSinceLastConnection = device.isConnected ? 0 : now.timeIntervalSince(device.lastConnected ?? now)

if device.isConnected {
return Text("Connected")
.foregroundColor(.green)
} else if let lastConnected = device.lastConnected {
let timeRatio = timeSinceLastConnection / expectedConnectionTime
let timeString = formattedTimeString(from: timeSinceLastConnection)
/// Isolated view that handles the "seconds ticking" for connection status
private struct ConnectionStatusView: View {
let device: BLEDevice
@State private var now = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

if timeRatio < 1.0 {
return Text("Disconnected for \(timeString)")
var body: some View {
Group {
if device.isConnected {
Text("Connected")
.foregroundColor(.green)
} else if timeRatio <= 1.15 {
return Text("Disconnected for \(timeString)")
.foregroundColor(.orange)
} else if timeRatio <= 3.0 {
return Text("Disconnected for \(timeString)")
.foregroundColor(.red)
} else if let lastConnected = device.lastConnected {
statusText(lastConnected: lastConnected)
} else {
let date = dateTimeUtils.formattedDate(from: lastConnected)
return Text("Last connection: \(date)")
.foregroundColor(.red)
Text("Reconnecting...")
.foregroundColor(.orange)
}
} else {
return Text("Reconnecting...")
.foregroundColor(.orange)
}
.onReceive(timer) { input in
now = input
}
}

private func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.forceRefresh.toggle()
private func statusText(lastConnected: Date) -> Text {
let timeSinceLastConnection = now.timeIntervalSince(lastConnected)
let expectedConnectionTime: TimeInterval = BLEManager.shared.expectedHeartbeatInterval() ?? 300
let timeRatio = timeSinceLastConnection / expectedConnectionTime
let timeString = formattedTimeString(from: timeSinceLastConnection)

if timeRatio < 1.0 {
return Text("Disconnected for \(timeString)").foregroundColor(.green)
} else if timeRatio <= 1.15 {
return Text("Disconnected for \(timeString)").foregroundColor(.orange)
} else if timeRatio <= 3.0 {
return Text("Disconnected for \(timeString)").foregroundColor(.red)
} else {
let date = dateTimeUtils.formattedDate(from: lastConnected)
return Text("Last connection: \(date)").foregroundColor(.red)
}
}

private func stopTimer() {
timer?.invalidate()
timer = nil
private func formattedTimeString(from seconds: TimeInterval) -> String {
if seconds < 60 {
return "\(Int(seconds)) seconds"
} else {
let minutes = Int(seconds / 60)
let remainingSeconds = Int(seconds.truncatingRemainder(dividingBy: 60))
return "\(minutes):\(String(format: "%02d", remainingSeconds)) minutes"
}
Comment thread
greyghost99 marked this conversation as resolved.
}
}
Loading