diff --git a/xdrip/BluetoothTransmitter/CGM/Dexcom/G5/CGMG5Transmitter.swift b/xdrip/BluetoothTransmitter/CGM/Dexcom/G5/CGMG5Transmitter.swift index 07e79619f..c19df2a90 100644 --- a/xdrip/BluetoothTransmitter/CGM/Dexcom/G5/CGMG5Transmitter.swift +++ b/xdrip/BluetoothTransmitter/CGM/Dexcom/G5/CGMG5Transmitter.swift @@ -1287,7 +1287,7 @@ class CGMG5Transmitter:BluetoothTransmitter, CGMTransmitter { var forceNewSensor = false - if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) { + if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) || activeSensorStartDate > sensorStartDate.addingTimeInterval(15.0) { forceNewSensor = true } @@ -1327,7 +1327,7 @@ class CGMG5Transmitter:BluetoothTransmitter, CGMTransmitter { var forceNewSensor = false - if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) { + if let sensorStartDate = self.sensorStartDate, let activeSensorStartDate = UserDefaults.standard.activeSensorStartDate, activeSensorStartDate < sensorStartDate.addingTimeInterval(-15.0) || activeSensorStartDate > sensorStartDate.addingTimeInterval(15.0) { forceNewSensor = true } diff --git a/xdrip/BluetoothTransmitter/CGM/Dexcom/G7/CGMG7Transmitter.swift b/xdrip/BluetoothTransmitter/CGM/Dexcom/G7/CGMG7Transmitter.swift index 3b94a1755..b682342ed 100644 --- a/xdrip/BluetoothTransmitter/CGM/Dexcom/G7/CGMG7Transmitter.swift +++ b/xdrip/BluetoothTransmitter/CGM/Dexcom/G7/CGMG7Transmitter.swift @@ -112,7 +112,7 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter { init(address:String?, name: String?, bluetoothTransmitterDelegate: BluetoothTransmitterDelegate, cGMG7TransmitterDelegate: CGMG7TransmitterDelegate, cGMTransmitterDelegate:CGMTransmitterDelegate) { // assign addressname and name or expected devicename - // For G7 we don't listen for a specific device name. Dexcom uses an advertising id, which already filters out all other devices (like tv's etc. We will verify in another way that we have the current active G7, and not an old one, which is still near + // For G7/ONE+ we don't listen for a specific device name. Dexcom uses an advertising id, which already filters out all other devices (like tv's etc. We will verify in another way that we have the current active G7/ONE+, and not an old one, which is still near var newAddressAndName: BluetoothTransmitter.DeviceAddressAndName = BluetoothTransmitter.DeviceAddressAndName.notYetConnected(expectedName: "DX") if let name = name { @@ -209,8 +209,20 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter { trace(" failed to create G7GlucoseMessage", log: log, category: ConstantsLog.categoryCGMG7, type: .error ) return } - - trace(" received g7GlucoseMessage mesage, calculatedValue = %{public}@, timeStamp = %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, g7GlucoseMessage.calculatedValue.description, g7GlucoseMessage.timeStamp.description(with: .current)) + + let maxSensorAgeInDays = ConstantsDexcomG7.maxSensorAgeInDays + let sensorAgeInDays = Double(round((g7GlucoseMessage.sensorAge / 3600 / 24) * 10) / 10) + + // G7/ONE+ has the peculiarity that it will keep sending/repeating the same BG value (without ever changing) via BLE even after the session officially ends. + // to avoid this, let's check if the sensor is still within maxSensorAge before we continue + guard sensorAgeInDays < maxSensorAgeInDays else { + trace(" G7 is expired so will not process reading. sensorAge: %{public}@ / maxSensorAgeInDays: %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .error, sensorAgeInDays.description, maxSensorAgeInDays.description) + return + } + + trace(" received g7GlucoseMessage mesage, calculatedValue = %{public}@, timeStamp = %{public}@, sensorAge = %{public}@ / %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, g7GlucoseMessage.calculatedValue.description, g7GlucoseMessage.timeStamp.description(with: .current)) + + trace(" received g7GlucoseMessage mesage, sensorAge = %{public}@ / %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, sensorAgeInDays.description, maxSensorAgeInDays.description) sensorAge = g7GlucoseMessage.sensorAge @@ -253,7 +265,7 @@ class CGMG7Transmitter: BluetoothTransmitter, CGMTransmitter { return } - if let sensorAge = sensorAge, let dexcomG7BackfillMessage = DexcomG7BackfillMessage(data: value, sensorAge: sensorAge) { + if let sensorAge = sensorAge, sensorAge < (ConstantsDexcomG7.maxSensorAgeInDays * 24 * 3600), let dexcomG7BackfillMessage = DexcomG7BackfillMessage(data: value, sensorAge: sensorAge) { trace(" received backfill mesage, calculatedValue = %{public}@, timeStamp = %{public}@", log: log, category: ConstantsLog.categoryCGMG7, type: .info, dexcomG7BackfillMessage.calculatedValue.description, dexcomG7BackfillMessage.timeStamp.description(with: .current)) backfill.append(GlucoseData(timeStamp: dexcomG7BackfillMessage.timeStamp, glucoseLevelRaw: dexcomG7BackfillMessage.calculatedValue)) diff --git a/xdrip/BluetoothTransmitter/CGM/Generic/CGMTransmitter.swift b/xdrip/BluetoothTransmitter/CGM/Generic/CGMTransmitter.swift index 30f94cb5d..81e63da29 100644 --- a/xdrip/BluetoothTransmitter/CGM/Generic/CGMTransmitter.swift +++ b/xdrip/BluetoothTransmitter/CGM/Generic/CGMTransmitter.swift @@ -82,10 +82,10 @@ enum CGMTransmitterType:String, CaseIterable { case dexcomG4 = "Dexcom G4" /// dexcom G5, G6 - case dexcom = "Dexcom" + case dexcom = "Dexcom G5/G6/ONE" /// dexcom G7 - case dexcomG7 = "Dexcom G7" + case dexcomG7 = "Dexcom G7/ONE+" /// miaomiao case miaomiao = "MiaoMiao" diff --git a/xdrip/Constants/ConstantsDexcomG7.swift b/xdrip/Constants/ConstantsDexcomG7.swift index 7d5ed1de1..e2e0f6566 100644 --- a/xdrip/Constants/ConstantsDexcomG7.swift +++ b/xdrip/Constants/ConstantsDexcomG7.swift @@ -11,7 +11,7 @@ enum ConstantsDexcomG7 { /// if there's a new connect within this period, but latest reading was less than this interval ago, then no need to request new reading static let minimumTimeBetweenTwoReadings = TimeInterval(minutes: 2.1) - /// how many days the sensor session lasts - static let maxSensorAgeInDays: Double = 10.0 + /// how many days the sensor session lasts. In the case of G7/ONE+ it is 10 days + a 12 hour grace period = 10.5 days + static let maxSensorAgeInDays: Double = 10.5 } diff --git a/xdrip/Constants/ConstantsHomeView.swift b/xdrip/Constants/ConstantsHomeView.swift index f8d77ce0c..f477b72b9 100644 --- a/xdrip/Constants/ConstantsHomeView.swift +++ b/xdrip/Constants/ConstantsHomeView.swift @@ -51,12 +51,12 @@ enum ConstantsHomeView { /// urgent time left / colour static let sensorProgressViewUrgentInMinutes: Double = 60 * 12.0 // 12 hours before the sensor reaches max age - static let sensorProgressViewProgressColorUrgent: UIColor = .red - static let sensorProgressViewProgressColorUrgentSwiftUI: Color = .red + static let sensorProgressViewProgressColorUrgent: UIColor = .orange + static let sensorProgressViewProgressColorUrgentSwiftUI: Color = .orange /// colour for an expired sensor - static let sensorProgressExpired: UIColor = .purple - static let sensorProgressExpiredSwiftUI: Color = .purple + static let sensorProgressExpired: UIColor = .red + static let sensorProgressExpiredSwiftUI: Color = .red /// colour for an normal text static let sensorProgressNormalTextColor: UIColor = .lightGray diff --git a/xdrip/Managers/Alerts/AlertManager.swift b/xdrip/Managers/Alerts/AlertManager.swift index a00717691..14dc984c1 100644 --- a/xdrip/Managers/Alerts/AlertManager.swift +++ b/xdrip/Managers/Alerts/AlertManager.swift @@ -822,8 +822,8 @@ public class AlertManager:NSObject { return true } else { - if !UserDefaults.standard.isMaster && !UserDefaults.standard.followerBackgroundKeepAliveType.shouldKeepAlive { - trace("in checkAlert, there's no need to raise alert %{public}@ because we're in follower mode and keep-alive is: %{public}@", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging(), UserDefaults.standard.followerBackgroundKeepAliveType.description) + if !UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled { + trace("in checkAlert, there's no need to raise alert '%{public}@' because we're in follower mode and keep-alive is disabled", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging()) } else { trace("in checkAlert, there's no need to raise alert %{public}@", log: self.log, category: ConstantsLog.categoryAlertManager, type: .info, alertKind.descriptionForLogging()) } diff --git a/xdrip/Managers/BluetoothPeripheral/AlgorithmType.swift b/xdrip/Managers/BluetoothPeripheral/AlgorithmType.swift index 07e7b7f7f..efdae54ce 100644 --- a/xdrip/Managers/BluetoothPeripheral/AlgorithmType.swift +++ b/xdrip/Managers/BluetoothPeripheral/AlgorithmType.swift @@ -8,19 +8,15 @@ import Foundation -/// types of live activity, namely when we should show the live activities +/// types of algorithms available to use public enum AlgorithmType: Int, CaseIterable { - - // when adding to LiveActivityType, add new cases at the end (ie 3, ...) - // if this is done in the middle then a database migration would be required, because the rawvalue is stored as Int16 in the coredata - - case transmitterAlgorithm = 0 + case nativeAlgorithm = 0 case xDripAlgorithm = 1 var description: String { switch self { - case .transmitterAlgorithm: - return Texts_BluetoothPeripheralView.transmitterAlgorithm + case .nativeAlgorithm: + return Texts_BluetoothPeripheralView.nativeAlgorithm case .xDripAlgorithm: return Texts_BluetoothPeripheralView.xDripAlgorithm } diff --git a/xdrip/Managers/ContactImage/ContactImageManager.swift b/xdrip/Managers/ContactImage/ContactImageManager.swift index 77c4af63a..0d32400c8 100644 --- a/xdrip/Managers/ContactImage/ContactImageManager.swift +++ b/xdrip/Managers/ContactImage/ContactImageManager.swift @@ -36,6 +36,8 @@ class ContactImageManager: NSObject { UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.displayTrendInContactImage.rawValue, options: .new, context: nil) UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.useHighContrastContactImage.rawValue, options: .new, context: nil) UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.bloodGlucoseUnitIsMgDl.rawValue, options: .new, context: nil) + UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.isMaster.rawValue, options: .new, context: nil) + UserDefaults.standard.addObserver(self, forKeyPath: UserDefaults.Key.followerBackgroundKeepAliveType.rawValue, options: .new, context: nil) } @@ -63,24 +65,7 @@ class ContactImageManager: NSObject { /// used by observevalue for UserDefaults.Key private func evaluateUserDefaultsChange(keyPathEnum: UserDefaults.Key) { - switch keyPathEnum { - - case UserDefaults.Key.enableContactImage: - // if the user has enabled the option, then update the existing contact or add a new one if it doesn't exist - // this isn't really the best way to do it as we should delete the contact if - // not required to "clean up", but too many users didn't re-select the new contact after - // re-enabling in the Watch complication and assumed that the app wasn't working - if UserDefaults.standard.enableContactImage { - updateContact() - } - - case UserDefaults.Key.displayTrendInContactImage, UserDefaults.Key.useHighContrastContactImage, UserDefaults.Key.bloodGlucoseUnitIsMgDl: - updateContact() - - default: - break - - } + updateContact() } /// this function will perform the following actions: @@ -94,8 +79,6 @@ class ContactImageManager: NSObject { self.workItem?.cancel() self.workItem = nil - guard UserDefaults.standard.enableContactImage else { return } - // check that access to contacts is authorized by the user guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else { trace("in updateContact, access to contacts is not authorized, setting enableContactImage to false", log: self.log, category: ConstantsLog.categoryContactImageManager, type: .info) @@ -109,10 +92,14 @@ class ContactImageManager: NSObject { let lastReading = self.bgReadingsAccessor.get2LatestBgReadings(minimumTimeIntervalInMinutes: 4.0) var contactImageView: ContactImageView + // disable the image (show "OFF") if the function is disabled or if the user is in follower mode with background keep-alive disabled + // as otherwise it would always be out of date + let disableContactImage: Bool = !UserDefaults.standard.enableContactImage || (!UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled) + if lastReading.count > 0 { let valueIsUpToDate = abs(lastReading[0].timeStamp.timeIntervalSinceNow) < 7 * 60 - contactImageView = ContactImageView(bgValue: lastReading[0].calculatedValue, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: UserDefaults.standard.displayTrendInContactImage ? lastReading[0].slopeArrow() : "", bgRangeDescription: lastReading[0].bgRangeDescription(), valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: UserDefaults.standard.useHighContrastContactImage) + contactImageView = ContactImageView(bgValue: lastReading[0].calculatedValue, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: UserDefaults.standard.displayTrendInContactImage ? lastReading[0].slopeArrow() : "", bgRangeDescription: lastReading[0].bgRangeDescription(), valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: UserDefaults.standard.useHighContrastContactImage, disableContactImage: disableContactImage) // schedule an update in 5 min 15 seconds - if no new data is received until then, the empty value will get rendered into the contact (this update will be canceled if new data is received) self.workItem = DispatchWorkItem(block: { @@ -123,7 +110,7 @@ class ContactImageManager: NSObject { DispatchQueue.main.asyncAfter(deadline: .now() + (5 * 60) + 15, execute: self.workItem!) } else { // create an 'empty' image view if there is no BG data to show - contactImageView = ContactImageView(bgValue: 0, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: "", bgRangeDescription: .inRange, valueIsUpToDate: false, useHighContrastContactImage: false) + contactImageView = ContactImageView(bgValue: 0, isMgDl: UserDefaults.standard.bloodGlucoseUnitIsMgDl, slopeArrow: "", bgRangeDescription: .inRange, valueIsUpToDate: false, useHighContrastContactImage: false, disableContactImage: disableContactImage) } // we're going to use the app name as the given name of the contact we want to use/create/update diff --git a/xdrip/Managers/LibreLinkUp/LibreLinkUpFollowManager.swift b/xdrip/Managers/LibreLinkUp/LibreLinkUpFollowManager.swift index 7f32c4e0d..4ea946c60 100644 --- a/xdrip/Managers/LibreLinkUp/LibreLinkUpFollowManager.swift +++ b/xdrip/Managers/LibreLinkUp/LibreLinkUpFollowManager.swift @@ -253,6 +253,7 @@ class LibreLinkUpFollowManager: NSObject { let graphResponse = try await requestGraph(patientId: patientId) // before processing the glucoseMeasurement values, let's set up the sensor info in coredata so that we can show it to the user in the settings screen + // starting with LLU 4.12.0 this data sometimes isn't sent for some users so we'll try and use it if available and if not, just continue as normal without throwing an error if let startDate = graphResponse.data?.activeSensors?.first?.sensor?.a, let serialNumber = graphResponse.data?.activeSensors?.first?.sensor?.sn { @@ -266,12 +267,12 @@ class LibreLinkUpFollowManager: NSObject { if serialNumber.range(of: #"^MH"#, options: .regularExpression) != nil { // MHxxxxxxxx - // must be a L2 sensor + // must be a L2 (or Libre 2 Plus) sensor activeSensorDescription = "Libre 2" } else if serialNumber.range(of: #"^0D"#, options: .regularExpression) != nil || serialNumber.range(of: #"^0E"#, options: .regularExpression) != nil || serialNumber.range(of: #"^0F"#, options: .regularExpression) != nil{ - // must be a Libre 3 sensor + // must be a Libre 3 (or Libre 3 Plus) sensor activeSensorDescription = "Libre 3" } @@ -281,9 +282,12 @@ class LibreLinkUpFollowManager: NSObject { } else { // this will only happen if the account doesn't have an active sensor connected + // reset the data just in case it was previously stored resetActiveSensorData() - throw LibreLinkUpFollowError.generalError + // for some reason no active sensor data was sent by the server. This seems to sometimes happen since LLU v4.12.0 for some users and for some (unknown) reason. + // instead of throwing an error, we'll just continue as normal and hide later (in the UI) the sensor information + trace(" in download, no active sensor data was returned by the server so just process the values if any", log: self.log, category: ConstantsLog.categoryLibreLinkUpFollowManager, type: .info) } @@ -305,9 +309,6 @@ class LibreLinkUpFollowManager: NSObject { followerDelegate.followerInfoReceived(followGlucoseDataArray: &followGlucoseDataArray) } - // schedule new download - //self.scheduleNewDownload() - } } diff --git a/xdrip/Managers/LiveActivity/LiveActivityManager.swift b/xdrip/Managers/LiveActivity/LiveActivityManager.swift index 5cb097e85..7869133fe 100644 --- a/xdrip/Managers/LiveActivity/LiveActivityManager.swift +++ b/xdrip/Managers/LiveActivity/LiveActivityManager.swift @@ -40,21 +40,18 @@ extension LiveActivityManager { /// - Parameter contentState: the contentState to show /// - Parameter forceRestart: will force the function to end and restart the live activity func runActivity(contentState: XDripWidgetAttributes.ContentState, forceRestart: Bool) { - - trace("in runActivity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) - // checking whether 'Live activities' is enabled for the app in settings if ActivityAuthorizationInfo().areActivitiesEnabled { // live activities are enabled. Now check if there is a currently // running activity (in which case update it) or if not, start a new one if eventActivity == nil { - trace(" starting new live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) + trace("in runActivity, starting new live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) startActivity(contentState: contentState) } else if forceRestart && eventStartDate < Date().addingTimeInterval(-ConstantsLiveActivity.allowLiveActivityRestartAfterMinutes) { // force an end/start cycle of the activity when the app comes to the foreground assuming at least 'x' hours have passed. This restarts the 8 hour limit. - trace(" restarting live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) + trace("in runActivity, restarting live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) Task { await endActivity() @@ -62,21 +59,21 @@ extension LiveActivityManager { } } else if eventStartDate < Date().addingTimeInterval(-ConstantsLiveActivity.endLiveActivityAfterMinutes) { // if the activity has been running for almost 8 hours, proactively end the activity before it goes stale - trace(" ending live activity on purpose to avoid staying on the screen when stale", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) + trace("in runActivity, ending live activity on purpose to avoid staying on the screen when stale", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) Task { await endActivity() } } else { // none of the above conditions are true so let's just update the activity - trace(" updating live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) + trace("in runActivity, updating live activity", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) Task { await updateActivity(to: contentState) } } } else { - trace(" live activities are disabled in the iPhone Settings or permission has not been given.", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) + trace("in runActivity, live activities are disabled in the iPhone Settings or permission has not been given.", log: self.log, category: ConstantsLog.categoryLiveActivityManager, type: .info) } } diff --git a/xdrip/Storyboards/ar.lproj/SettingsViews.strings b/xdrip/Storyboards/ar.lproj/SettingsViews.strings index 6aa1a2a42..da66744f1 100644 --- a/xdrip/Storyboards/ar.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/ar.lproj/SettingsViews.strings @@ -156,7 +156,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/da.lproj/SettingsViews.strings b/xdrip/Storyboards/da.lproj/SettingsViews.strings index 3522189e2..a56e062c8 100644 --- a/xdrip/Storyboards/da.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/da.lproj/SettingsViews.strings @@ -145,7 +145,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/de.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/de.lproj/BluetoothPeripheralView.strings index 2a2334f3e..1d837dae0 100644 --- a/xdrip/Storyboards/de.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/de.lproj/BluetoothPeripheralView.strings @@ -128,3 +128,10 @@ /// sensor warm-up text "warmingUpUntil" = "Warming up until"; + +"nativeAlgorithm" = "Nativer Algorithmus"; +"xDripAlgorithm" = "xDrip Algorithmus"; +"confirmAlgorithmChangeToTransmitterMessage" = "Bitte um Bestätigung, dass zum nativen/transmitter Algorithmus gewechselt werden soll"; +"confirmAlgorithmChangeToxDripMessage" = "itte um Bestätigung, dass zum xDrip Algorithmus gewechselt werden soll.\n\nDies stoppt für kurze Zeit die Datenübermittlung und Du wirst um einen initialen Kalibrierungswert (Blut) gebeten."; +"confirmCalibrationChangeToSinglePointMessage" = "Bitte um Bestätigung, dass zur Standard Kalibrierung gewechselt werden soll.\n\nDies stoppt für kurze Zeit die Datenübermittlung und Du wirst um einen initialen Kalibrierungswert (Blut) gebeten."; +"confirmCalibrationChangeToMultiPointMessage" = "Bitte um Bestätigung, dass zur Mehrpunkt Kalibrierung gewechselt werden soll.\n\n⚠️ Diese Methode ist nur für erfahrene Benutzer, es könnte ein falscher und damit gefährlicher Wert angezeigt werden, wenn die Kalibrierung nicht korrekt durchgeführt wurde.\n\nWenn Du unsicher bist, bitte drücke Abbruch/Cancel."; diff --git a/xdrip/Storyboards/de.lproj/CalibrationRequest.strings b/xdrip/Storyboards/de.lproj/CalibrationRequest.strings index 4945ea0b0..0c6780e27 100644 --- a/xdrip/Storyboards/de.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/de.lproj/CalibrationRequest.strings @@ -10,3 +10,6 @@ /// When calibration alert goess off, user clicks the notification, app opens, dialog pops up, this is the text in the dialog "enter_calibration_value" = "Eingabe Kalibrierungswert"; + +"singlePointCalibration" = "Standard"; +"multiPointCalibration" = "Multi-Punkt"; diff --git a/xdrip/Storyboards/de.lproj/SettingsViews.strings b/xdrip/Storyboards/de.lproj/SettingsViews.strings index ff64dd041..e96476799 100644 --- a/xdrip/Storyboards/de.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/de.lproj/SettingsViews.strings @@ -92,6 +92,10 @@ /// non fixed settings, title of the section "settingsviews_labelNonFixed" = "Mehrpunkt-Kalibrierung"; +"settingsviews_labelAlgorithmType" = "Algorithmus Typ"; +"settingsviews_labelCalibrationTitle" = "Sensor Kalibrierung"; +"settingsviews_labelCalibrationType" = "Kalibrierungs Typ"; + /// healthkit settings, literally 'healthkit' "settingsviews_healthkit" = "Apple Health nutzen"; @@ -370,7 +374,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/el.lproj/SettingsViews.strings b/xdrip/Storyboards/el.lproj/SettingsViews.strings index fcbce97bf..1f5b97af5 100644 --- a/xdrip/Storyboards/el.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/el.lproj/SettingsViews.strings @@ -135,7 +135,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/en.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/en.lproj/BluetoothPeripheralView.strings index 58912dad8..7f5e64037 100644 --- a/xdrip/Storyboards/en.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/en.lproj/BluetoothPeripheralView.strings @@ -42,3 +42,11 @@ "nfcErrorMessageScanFailed" = "Sensor scan has failed"; "nonFixedSlopeWarning" = "Multi-point calibration is an advanced feature.\n\nPlease do not use this feature until you have read the calibration section of the online help and understand how it works."; "warmingUpUntil" = "Warming up until"; + +"nativeAlgorithm" = "Native algorithm"; +"xDripAlgorithm" = "xDrip algorithm"; +"confirmAlgorithmChangeToTransmitterMessage" = "Please confirm that you want to change back to the native/transmitter algorithm"; +"confirmAlgorithmChangeToxDripMessage" = "Please confirm that you want to change the the xDrip algorithm.\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready."; +"confirmCalibrationChangeToSinglePointMessage" = "Please confirm that you want to change the calibration type to the standard calibration\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready."; +"confirmCalibrationChangeToMultiPointMessage" = "Please confirm that you want to change the calibration type to multi-point\n\n⚠️ Please note that this method is only for advanced users and could potentially give dangerous results if not correctly calibrated.\n\nIf you are unsure how to use this method, please press Cancel."; +"confirm" = "Confirm"; diff --git a/xdrip/Storyboards/en.lproj/CalibrationRequest.strings b/xdrip/Storyboards/en.lproj/CalibrationRequest.strings index 55fbd6673..4bab5e3e6 100644 --- a/xdrip/Storyboards/en.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/en.lproj/CalibrationRequest.strings @@ -2,3 +2,5 @@ "calibration_title" = "Calibration"; "calibration_notification_title" = "Calibration"; "calibration_notification_body" = "Click the Notification to Calibrate"; +"singlePointCalibration" = "Standard"; +"multiPointCalibration" = "Multi-point"; diff --git a/xdrip/Storyboards/en.lproj/Common.strings b/xdrip/Storyboards/en.lproj/Common.strings index ad71c209f..9705cc446 100644 --- a/xdrip/Storyboards/en.lproj/Common.strings +++ b/xdrip/Storyboards/en.lproj/Common.strings @@ -50,3 +50,4 @@ "common_dontshowagain" = "Don't Show Again"; "common_enabled" = "Enabled"; "common_disabled" = "Disabled"; +"common_notRequired" = "Not required"; diff --git a/xdrip/Storyboards/en.lproj/SettingsViews.strings b/xdrip/Storyboards/en.lproj/SettingsViews.strings index 97f18be4f..f73d523e5 100644 --- a/xdrip/Storyboards/en.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/en.lproj/SettingsViews.strings @@ -29,7 +29,7 @@ "settingsviews_enterUsername" = "Enter your username (e-mail)"; "settingsviews_enterPassword" = "Enter your password"; "settingsviews_libreLinkUpReAcceptNeeded" = "Need to accept terms"; -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; "settingsviews_showReadingInNotification" = "Show BG in Notifications"; "settingsviews_labelShowReadingInAppBadge" = "Show BG in the App Badge"; "settingsviews_multipleAppBadgeValueWith10" = "Multiply App Badge Reading by 10"; @@ -76,6 +76,9 @@ "settingsviews_webooptransmitter" = "Use Transmitter Algorithm"; "settingsviews_nonfixedtransmitter" = "Enable Multi-point Calibration"; "settingsviews_labelNonFixed" = "Multi-point Calibration"; +"settingsviews_labelAlgorithmType" = "Algorithm Type"; +"settingsviews_labelCalibrationTitle" = "Sensor Calibration"; +"settingsviews_labelCalibrationType" = "Calibration Type"; "settingsviews_labelWebOOP" = "xDrip or Transmitter Algorithm"; "settingsviews_sectiontitlealerting" = "Alarms"; "settingsviews_row_alert_types" = "Alarm Types"; @@ -134,7 +137,7 @@ "settingsviews_CalenderIntervalMessage" = "Minimum interval between two calender events (mins)"; "settingsviews_infoContactsAccessRestricted" = "You cannot give authorization to %@ to access your contacts. This is possibly due to active restrictions such as parental controls being in place."; "settingsviews_contactImageSectionTitle" = "Contact Image"; -"settingsviews_enableContactImage" = "Create Contact"; +"settingsviews_enableContactImage" = "Enable Contact Image"; "settingsviews_displayTrendInContactImage" = "Show Trend"; "settingsviews_contactImageCreatedByString" = "Contact automatically created by"; "sectionTitleTrace" = "Issue Reporting"; diff --git a/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings index 833ad088c..ce1d4dd3f 100644 --- a/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings @@ -64,3 +64,12 @@ /// Tell the user the scan was successful and to just wait now for connection "nfcScanSuccessfulMessage" = "\n✅ Scan successful ✅\n\nClick OK and just wait to allow the sensor to finish connecting via bluetooth.\n\nIn a short while the status should change to 'Connected'."; + + +"nativeAlgorithm" = "Algoritmo nativo"; +"xDripAlgorithm" = "Algoritmo xDrip"; +"confirmAlgorithmChangeToTransmitterMessage" = "Por favor, confirmar que deseas cambiar al algoritmo nativo"; +"confirmAlgorithmChangeToxDripMessage" = "Por favor, confirmar que deseas cambiar al algoritmo de xDrip.\n\nEsto hará que dejes de recibir lecturas durante un breve tiempo y la app te pedirá introducir una calibración inicial en cuanto sea necesario."; +"confirmCalibrationChangeToSinglePointMessage" = "Por favor, confirmar que deseas usar la calibración estándar.\n\nEsto hará que dejes de recibir lecturas durante un breve tiempo y la app te pedirá introducir una calibración inicial en cuanto sea necesario."; +"confirmCalibrationChangeToMultiPointMessage" = "Por favor, confirmar que deseas usar la calibración multi-puntos.\n\n⚠️ Ten en cuenta que este método de calibración es únicamente para usuarios avanzados y podría ser incluso peligroso si no se hace correctamente.\n\nSi tienes claro cómo funciona esta opción, por favor, apreta Cancelar"; +"confirm" = "Confirmar"; diff --git a/xdrip/Storyboards/es.lproj/CalibrationRequest.strings b/xdrip/Storyboards/es.lproj/CalibrationRequest.strings index c9bd89a72..e547c97d6 100644 --- a/xdrip/Storyboards/es.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/es.lproj/CalibrationRequest.strings @@ -2,3 +2,5 @@ "calibration_title" = "Calibración"; "calibration_notification_title" = "Calibración"; "calibration_notification_body" = "Haz click en la notificación para calibrar"; +"singlePointCalibration" = "Estándar"; +"multiPointCalibration" = "Multi-punto"; diff --git a/xdrip/Storyboards/es.lproj/Common.strings b/xdrip/Storyboards/es.lproj/Common.strings index fb2af5bff..07b2f1a95 100644 --- a/xdrip/Storyboards/es.lproj/Common.strings +++ b/xdrip/Storyboards/es.lproj/Common.strings @@ -50,3 +50,4 @@ "common_dontshowagain" = "No Volver a Mostrar"; "common_enabled" = "Habilitado"; "common_disabled" = "Deshabilitado"; +"common_notRequired" = "No requerido"; diff --git a/xdrip/Storyboards/es.lproj/SettingsViews.strings b/xdrip/Storyboards/es.lproj/SettingsViews.strings index 4160c4dd1..09a9ed6ca 100644 --- a/xdrip/Storyboards/es.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/es.lproj/SettingsViews.strings @@ -24,7 +24,7 @@ "settingsviews_enterUsername" = "Entrar tu usuario (e-mail)"; "settingsviews_enterPassword" = "Entrar tu contraseña"; "settingsviews_libreLinkUpReAcceptNeeded" = "Aceptar terminos"; -"settingsviews_libreLinkUpNoActiveSensor" = "Sin sensor activo"; +"settingsviews_libreLinkUpNoActiveSensor" = "Sin datos de sensor activo"; "settingsviews_translateOnlineHelp" = "Traducir Documentación"; "settingsviews_showHelpIcon" = "Mostrar icono"; "settingsviews_restartNeeded" = "(Pendiente reiniciar)"; @@ -69,6 +69,9 @@ "settingsviews_resetDexcomTransmitterMessage" = "\nEsta opción intentará resetear el transmisor durante la próxima conexión.\n\nEsto solo puede funcionar con transmisores G5 y transmisores G6 Anubis.\n\nNo funciona para transmisores normales tipo G6 y One."; "settingsviews_nonfixedtransmitter" = "Habilitar Calibración Multi-punto"; "settingsviews_labelNonFixed" = "Calibración Multi-punto"; +"settingsviews_labelAlgorithmType" = "Tipo de Algoritmo"; +"settingsviews_labelCalibrationTitle" = "Calibración de Sensor"; +"settingsviews_labelCalibrationType" = "Tipo de Calibración"; "settingsviews_sectiontitlealerting" = "Alarmas"; "settingsviews_row_alert_types" = "Tipos de Alarmas"; "settingsviews_row_alerts" = "Alarmas"; @@ -143,7 +146,7 @@ "settingsviews_sectiontitlehomescreen" = "Inicio"; "settingsviews_infoContactsAccessRestricted" = "No has podido dar permiso a %@ para accesar a tus contactos. Esto es probablemente debido a restriciones como el control parental o similar."; "settingsviews_contactImageSectionTitle" = "Imagen de Contacto"; -"settingsviews_enableContactImage" = "Crear Contacto"; +"settingsviews_enableContactImage" = "Habilitar Contacto"; "settingsviews_displayTrendInContactImage" = "Mostrar Tendencia"; "settingsviews_contactImageCreatedByString" = "Contacto creado automáticamente por"; diff --git a/xdrip/Storyboards/fi.lproj/SettingsViews.strings b/xdrip/Storyboards/fi.lproj/SettingsViews.strings index 5461653e3..c68da7b58 100644 --- a/xdrip/Storyboards/fi.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/fi.lproj/SettingsViews.strings @@ -186,7 +186,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/fr.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/fr.lproj/BluetoothPeripheralView.strings index 73d1f0fa1..04c8b79b5 100644 --- a/xdrip/Storyboards/fr.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/fr.lproj/BluetoothPeripheralView.strings @@ -70,3 +70,6 @@ /// sensor warm-up text "warmingUpUntil" = "Warming up until"; + +"nativeAlgorithm" = "Algorithme natif"; +"xDripAlgorithm" = "Algorithme xDrip"; diff --git a/xdrip/Storyboards/fr.lproj/CalibrationRequest.strings b/xdrip/Storyboards/fr.lproj/CalibrationRequest.strings index 1add3a00b..ec299cc0f 100644 --- a/xdrip/Storyboards/fr.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/fr.lproj/CalibrationRequest.strings @@ -2,3 +2,5 @@ "calibration_title" = "Calibration"; "calibration_notification_title" = "Calibration"; "calibration_notification_body" = "Cliquez la notification pour calibrer"; +"singlePointCalibration" = "Standard"; +"multiPointCalibration" = "Multi-points"; diff --git a/xdrip/Storyboards/fr.lproj/SettingsViews.strings b/xdrip/Storyboards/fr.lproj/SettingsViews.strings index e8b7a5c31..446e0d092 100644 --- a/xdrip/Storyboards/fr.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/fr.lproj/SettingsViews.strings @@ -113,6 +113,9 @@ /// non fixed settings, title of the section "settingsviews_labelNonFixed" = "Calibration Multi-point"; +"settingsviews_labelAlgorithmType" = "Type d'algorithme"; +"settingsviews_labelCalibrationType" = "Type de calibration"; + /// In Settings, Alerts section, there's an option to test the volume of the sound player, this is the title of the row "volumeTestSoundPlayer" = "Test Volume (Si Ignorer Mode silencieux)"; @@ -211,7 +214,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/it.lproj/SettingsViews.strings b/xdrip/Storyboards/it.lproj/SettingsViews.strings index fd5eca5c3..2ae7d44c2 100644 --- a/xdrip/Storyboards/it.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/it.lproj/SettingsViews.strings @@ -408,7 +408,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/nl.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/nl.lproj/BluetoothPeripheralView.strings index 463a2c4be..495e03c70 100644 --- a/xdrip/Storyboards/nl.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/nl.lproj/BluetoothPeripheralView.strings @@ -67,3 +67,10 @@ /// sensor warm-up text "warmingUpUntil" = "Warming up until"; + +"nativeAlgorithm" = "Native algoritme"; +"xDripAlgorithm" = "xDrip algoritme"; +"confirmAlgorithmChangeToTransmitterMessage" = "Je wil dus terug naar het native algoritme?"; +"confirmAlgorithmChangeToxDripMessage" = "Je wil dus naar het xDrip algoritme?\n\nJe zult na de aanpassing gedurende korte tijd geen metingen krijgen en er zal je gevraagd worden om te kalibreren."; +"confirmCalibrationChangeToSinglePointMessage" = "Je wil dus het kalibratie type veranderen naar standaard kalibratie?\n\nJe zult na de aanpassing gedurende korte tijd geen metingen krijgen en er zal je gevraagd worden om te kalibreren."; +"confirmCalibrationChangeToMultiPointMessage" = "Je wil dus het kalibratie type veranderen naar meerpunts kalibratie?\n\n⚠️ Dit kalibratietype is voor ervaren gebruikers en kan bij foute kalibratie gevaarlijke resultaten geven.\n\nAls je niet zeker bent dat je deze methode goed kunt gebruiken, kies dan Annuleer."; diff --git a/xdrip/Storyboards/nl.lproj/CalibrationRequest.strings b/xdrip/Storyboards/nl.lproj/CalibrationRequest.strings index 7062350ba..9c21c38ba 100644 --- a/xdrip/Storyboards/nl.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/nl.lproj/CalibrationRequest.strings @@ -2,3 +2,5 @@ "calibration_title" = "Kalibratie"; "calibration_notification_title" = "Kalibratie"; "calibration_notification_body" = "Klik op de Notificatie om te Kalibreren"; +"singlePointCalibration" = "Standaard"; +"multiPointCalibration" = "Meerpunts"; diff --git a/xdrip/Storyboards/nl.lproj/SettingsViews.strings b/xdrip/Storyboards/nl.lproj/SettingsViews.strings index 857f66af9..2897961f5 100644 --- a/xdrip/Storyboards/nl.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/nl.lproj/SettingsViews.strings @@ -30,6 +30,9 @@ "settingsviews_resettransmitter" = "Reset Transmitter (Anubis)"; "settingsviews_nonfixedtransmitter" = "Schakel Meerpuntskalibratie In"; "settingsviews_labelNonFixed" = "Meerpuntskalibratie"; +"settingsviews_labelAlgorithmType" = "Type algoritme"; +"settingsviews_labelCalibrationTitle" = "Sensor Kalibratie"; +"settingsviews_labelCalibrationType" = "Type kalibratie"; "settingsviews_sectiontitlealerting" = "Alarmen"; "settingsviews_row_alert_types" = "Alarm Types"; "settingsviews_row_alerts" = "Alarmen"; @@ -204,7 +207,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/pl-PL.lproj/SettingsViews.strings b/xdrip/Storyboards/pl-PL.lproj/SettingsViews.strings index fd5eca5c3..2ae7d44c2 100644 --- a/xdrip/Storyboards/pl-PL.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/pl-PL.lproj/SettingsViews.strings @@ -408,7 +408,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/pt.lproj/SettingsViews.strings b/xdrip/Storyboards/pt.lproj/SettingsViews.strings index f8725d93b..28c7fccf0 100644 --- a/xdrip/Storyboards/pt.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/pt.lproj/SettingsViews.strings @@ -158,7 +158,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/ru.lproj/SettingsViews.strings b/xdrip/Storyboards/ru.lproj/SettingsViews.strings index 971ca16ef..64a9bbe68 100644 --- a/xdrip/Storyboards/ru.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/ru.lproj/SettingsViews.strings @@ -135,7 +135,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/sl.lproj/SettingsViews.strings b/xdrip/Storyboards/sl.lproj/SettingsViews.strings index 0be28e44d..7f53bc2d2 100644 --- a/xdrip/Storyboards/sl.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/sl.lproj/SettingsViews.strings @@ -408,7 +408,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/sv.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/sv.lproj/BluetoothPeripheralView.strings index 13023ff86..c87d27173 100644 --- a/xdrip/Storyboards/sv.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/sv.lproj/BluetoothPeripheralView.strings @@ -69,3 +69,6 @@ /// sensor warm-up text "warmingUpUntil" = "Warming up until"; + +"nativeAlgorithm" = "Inbyggd Algoritm"; +"xDripAlgorithm" = "xDrip Algoritm"; diff --git a/xdrip/Storyboards/sv.lproj/CalibrationRequest.strings b/xdrip/Storyboards/sv.lproj/CalibrationRequest.strings index c8b2b1215..50a2299da 100644 --- a/xdrip/Storyboards/sv.lproj/CalibrationRequest.strings +++ b/xdrip/Storyboards/sv.lproj/CalibrationRequest.strings @@ -2,3 +2,5 @@ "calibration_title" = "Kalibrering"; "calibration_notification_title" = "Kalibrering"; "calibration_notification_body" = "Klicka på notis för att kalibrera"; +"singlePointCalibration" = "Standard"; +"multiPointCalibration" = "Flerpunkts"; diff --git a/xdrip/Storyboards/sv.lproj/SettingsViews.strings b/xdrip/Storyboards/sv.lproj/SettingsViews.strings index 8ef5552f4..5f6ac3a93 100644 --- a/xdrip/Storyboards/sv.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/sv.lproj/SettingsViews.strings @@ -32,6 +32,11 @@ "settingsviews_resettransmitter" = "Återställ sändare (Anubis)"; "settingsviews_nonfixedtransmitter" = "Använd flerpunktskalibrering"; "settingsviews_labelNonFixed" = "Flerpunktskalibrering"; + +"settingsviews_labelAlgorithmType" = "Algoritm typ"; +"settingsviews_labelCalibrationTitle" = "Sensor Kalibrering"; +"settingsviews_labelCalibrationType" = "Kalibreringstyp"; + "settingsviews_sectiontitlealerting" = "Larm"; "settingsviews_row_alert_types" = "Typ av larm"; "settingsviews_row_alerts" = "Larm"; @@ -167,7 +172,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/tr.lproj/SettingsViews.strings b/xdrip/Storyboards/tr.lproj/SettingsViews.strings index a09673eb2..50d954daf 100644 --- a/xdrip/Storyboards/tr.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/tr.lproj/SettingsViews.strings @@ -121,7 +121,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/uk.lproj/SettingsViews.strings b/xdrip/Storyboards/uk.lproj/SettingsViews.strings index f273fae33..57f1fe78f 100644 --- a/xdrip/Storyboards/uk.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/uk.lproj/SettingsViews.strings @@ -368,7 +368,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/Storyboards/zh.lproj/SettingsViews.strings b/xdrip/Storyboards/zh.lproj/SettingsViews.strings index 74aba4c2c..628f26360 100644 --- a/xdrip/Storyboards/zh.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/zh.lproj/SettingsViews.strings @@ -333,7 +333,7 @@ "settingsviews_followerKeepAliveTypeAggressiveMessage" = "Background keep-alive is set to aggressive.\n\nWhen the app is not on screen, we will aggressively attempt to keep it running for you in the background so that BG updates are received and alarms can be triggered.\n\nThis mode has a very noticeable impact on the battery of your device and should only be used if absolutely necessary."; /// libre link up follower settings, no active sensor -"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor"; +"settingsviews_libreLinkUpNoActiveSensor" = "No active sensor data"; /// data source settings, keep-alive mode is set to disabled "settingsviews_followerKeepAliveTypeDisabledMessage" = "Background keep-alive is disabled.\n\nWhen the app is not on screen, no alarms, app badges, notifications or BG updates will take place.\n\nThe app will remain sleeping until you open it again.\n\nThis mode has very little impact on the battery of your device."; diff --git a/xdrip/SwiftUIViews/BgReadingsDetailView.swift b/xdrip/SwiftUIViews/BgReadingsDetailView.swift index 8b18dd1e7..2a9c74fb3 100644 --- a/xdrip/SwiftUIViews/BgReadingsDetailView.swift +++ b/xdrip/SwiftUIViews/BgReadingsDetailView.swift @@ -30,8 +30,8 @@ struct BgReadingsDetailView: View { Section(header: Text(Texts_BgReadings.slopeSectionHeader)) { row(title: Texts_BgReadings.slopeArrow, data: bgReading.slopeArrow()) - row(title: Texts_BgReadings.slopePerMinute, data: (bgReading.calculatedValueSlope * 60000).formatted(.number.rounded(increment: isMgDl ? 0.01 : 0.001)) + " " + String(isMgDl ? Texts_Common.mgdl : Texts_Common.mmol)) - row(title: Texts_BgReadings.slopePer5Minutes, data: (bgReading.calculatedValueSlope * 60000 * 5).formatted(.number.rounded(increment: isMgDl ? 0.01 : 0.001)) + " " + String(isMgDl ? Texts_Common.mgdl : Texts_Common.mmol)) + row(title: Texts_BgReadings.slopePerMinute, data: (bgReading.calculatedValueSlope.mgDlToMmol(mgDl: isMgDl) * 60000).formatted(.number.rounded(increment: isMgDl ? 0.01 : 0.001)) + " " + String(isMgDl ? Texts_Common.mgdl : Texts_Common.mmol)) + row(title: Texts_BgReadings.slopePer5Minutes, data: (bgReading.calculatedValueSlope.mgDlToMmol(mgDl: isMgDl) * 60000 * 5).formatted(.number.rounded(increment: isMgDl ? 0.01 : 0.001)) + " " + String(isMgDl ? Texts_Common.mgdl : Texts_Common.mmol)) } if let calibration = bgReading.calibration { diff --git a/xdrip/SwiftUIViews/ContactImageView.swift b/xdrip/SwiftUIViews/ContactImageView.swift index 9885f33e5..39e687daa 100644 --- a/xdrip/SwiftUIViews/ContactImageView.swift +++ b/xdrip/SwiftUIViews/ContactImageView.swift @@ -10,6 +10,7 @@ struct ContactImageView: View { var bgRangeDescription: BgRangeDescription var valueIsUpToDate: Bool var useHighContrastContactImage: Bool + var disableContactImage: Bool var uiImage: UIImage { return getImage() @@ -21,6 +22,10 @@ struct ContactImageView: View { } var bgColor: UIColor { + if disableContactImage { + return useHighContrastContactImage ? .white : .systemCyan + } + guard bgValue > 0, valueIsUpToDate else { return ConstantsContactImage.unknownColor } // if the user isn't requesting a high contrast image, then return the correct bg color @@ -64,43 +69,28 @@ struct ContactImageView: View { } } + if disableContactImage { + fontSize = 100 + } + return UIFont.systemFont(ofSize: fontSize, weight: .bold) } -// var slopeArrowFont: UIFont { -// var fontSize: CGFloat = 100 -// -// if isMgDl { -// switch bgValue { -// case 1..<100: -// fontSize = 90 -// case 100..<200: -// fontSize = 90 -// default: -// fontSize = 100 -// } -// } else { -// switch bgValue.mgDlToMmol() { -// case 0.1..<10.0: -// fontSize = 100 -// case 10.0..<20.0: -// fontSize = 120 -// default: -// fontSize = 120 -// } -// } -// -// return UIFont.systemFont(ofSize: 80, weight: .bold) -// } - func getImage() -> UIImage { let width = 256.0 let height = 256.0 let rect = CGRect(x: 0, y: 0, width: width, height: height) // if there is no current value, 0 will be received so show this as a relevant "---" string - let bgValueString: String = bgValue > 0 ? bgValue.mgDlToMmolAndToString(mgDl: isMgDl) : isMgDl ? "---" : "-.-" - let showSlopeArrow: Bool = (valueIsUpToDate && slopeArrow != "") ? true : false + var bgValueString: String = bgValue > 0 ? bgValue.mgDlToMmolAndToString(mgDl: isMgDl) : isMgDl ? "---" : "-.-" + + var showSlopeArrow: Bool = (valueIsUpToDate && slopeArrow != "") ? true : false + + // override the value and slope if the user is in follower mode and has disabled the keep-alive (to prevent showing an almost always out of date value) + if disableContactImage { + bgValueString = "OFF" + showSlopeArrow = false + } UIGraphicsBeginImageContext(rect.size) @@ -157,10 +147,11 @@ struct ContactImageViewPreview: View { var bgRangeDescription: BgRangeDescription var valueIsUpToDate: Bool var useHighContrastContactImage: Bool + var disableContactImage: Bool var body: some View { ZStack { - ContactImageView(bgValue: bgValue, isMgDl: isMgDl, slopeArrow: slopeArrow, bgRangeDescription: bgRangeDescription, valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: useHighContrastContactImage) + ContactImageView(bgValue: bgValue, isMgDl: isMgDl, slopeArrow: slopeArrow, bgRangeDescription: bgRangeDescription, valueIsUpToDate: valueIsUpToDate, useHighContrastContactImage: useHighContrastContactImage, disableContactImage: disableContactImage) Circle() .stroke(lineWidth: 20) .foregroundColor(.white) @@ -174,22 +165,23 @@ struct ContactImageViewPreview: View { struct ContactImageView_Previews: PreviewProvider { struct Preview: View { var body: some View { + ContactImageViewPreview(bgValue: 88, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.notUrgent, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: true).previewDisplayName("OFF") - ContactImageViewPreview(bgValue: 88, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.notUrgent, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("88") - ContactImageViewPreview(bgValue: 88, isMgDl: true, slopeArrow: "\u{2192}" /* → */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: true).previewDisplayName("88 →") - ContactImageViewPreview(bgValue: 188, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("188") - ContactImageViewPreview(bgValue: 188, isMgDl: true, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("188 ↘") - ContactImageViewPreview(bgValue: 388, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("388") - ContactImageViewPreview(bgValue: 388, isMgDl: true, slopeArrow: "\u{2191}\u{2191}" /* ↑↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("388 ↑↑") + ContactImageViewPreview(bgValue: 88, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.notUrgent, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("88") + ContactImageViewPreview(bgValue: 88, isMgDl: true, slopeArrow: "\u{2192}" /* → */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: true, disableContactImage: false).previewDisplayName("88 →") + ContactImageViewPreview(bgValue: 188, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("188") + ContactImageViewPreview(bgValue: 188, isMgDl: true, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("188 ↘") + ContactImageViewPreview(bgValue: 388, isMgDl: true, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("388") + ContactImageViewPreview(bgValue: 388, isMgDl: true, slopeArrow: "\u{2191}\u{2191}" /* ↑↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("388 ↑↑") - ContactImageViewPreview(bgValue: 160, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("8.9") /* → */ - ContactImageViewPreview(bgValue: 160, isMgDl: false, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("8.9 ↘") /* → */ - ContactImageViewPreview(bgValue: 188, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("10.4") - ContactImageViewPreview(bgValue: 188, isMgDl: false, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("10.4 ↘") - ContactImageViewPreview(bgValue: 400, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("22.2") - ContactImageViewPreview(bgValue: 400, isMgDl: false, slopeArrow: "\u{2191}\u{2191}" /* ↑↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false).previewDisplayName("22.2 ↑↑") + ContactImageViewPreview(bgValue: 160, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("8.9") /* → */ + ContactImageViewPreview(bgValue: 160, isMgDl: false, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("8.9 ↘") /* → */ + ContactImageViewPreview(bgValue: 188, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("10.4") + ContactImageViewPreview(bgValue: 188, isMgDl: false, slopeArrow: "\u{2198}" /* ↘ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("10.4 ↘") + ContactImageViewPreview(bgValue: 400, isMgDl: false, slopeArrow: "", bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("22.2") + ContactImageViewPreview(bgValue: 400, isMgDl: false, slopeArrow: "\u{2191}\u{2191}" /* ↑↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: true, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("22.2 ↑↑") - ContactImageViewPreview(bgValue: 120, isMgDl: true, slopeArrow: "\u{2191}" /* ↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: false, useHighContrastContactImage: false).previewDisplayName("120, not current") + ContactImageViewPreview(bgValue: 120, isMgDl: true, slopeArrow: "\u{2191}" /* ↑ */, bgRangeDescription: BgRangeDescription.inRange, valueIsUpToDate: false, useHighContrastContactImage: false, disableContactImage: false).previewDisplayName("120, not current") } } static var previews: some View { diff --git a/xdrip/Texts/TextsBluetoothPeripheralView.swift b/xdrip/Texts/TextsBluetoothPeripheralView.swift index 2cec441c2..43aeadfd4 100644 --- a/xdrip/Texts/TextsBluetoothPeripheralView.swift +++ b/xdrip/Texts/TextsBluetoothPeripheralView.swift @@ -148,28 +148,28 @@ class Texts_BluetoothPeripheralView { return NSLocalizedString("warmingUpUntil", tableName: filename, bundle: Bundle.main, value: "Warming up until", comment: "sensor warm-up text") }() - static let transmitterAlgorithm: String = { - return NSLocalizedString("transmitterAlgorithm", tableName: filename, bundle: Bundle.main, value: "Transmitter", comment: "transmitter algorithm type text") + static let nativeAlgorithm: String = { + return NSLocalizedString("nativeAlgorithm", tableName: filename, bundle: Bundle.main, value: "Native Algorithm", comment: "native or transmitter algorithm type text") }() static let xDripAlgorithm: String = { - return NSLocalizedString("xDripAlgorithm", tableName: filename, bundle: Bundle.main, value: "xDrip", comment: "xDrip algorithm type text") + return NSLocalizedString("xDripAlgorithm", tableName: filename, bundle: Bundle.main, value: "xDrip Algorithm", comment: "xDrip algorithm type text") }() static let confirmAlgorithmChangeToTransmitterMessage: String = { - return NSLocalizedString("confirmAlgorithmChangeToTransmitterMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change back to the standard/transmitter algorithm.", comment: "Confirm that the user wants to really change the transmitter or native algorithm type, message") + return NSLocalizedString("confirmAlgorithmChangeToTransmitterMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change back to the native/transmitter algorithm.", comment: "Confirm that the user wants to really change the transmitter or native algorithm type, message") }() static let confirmAlgorithmChangeToxDripMessage: String = { - return NSLocalizedString("confirmAlgorithmChangeToxDripMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the the xDrip algorithm.\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready", comment: "Confirm that the user wants to really change the xDrip algorithm type, message") + return NSLocalizedString("confirmAlgorithmChangeToxDripMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the the xDrip algorithm.\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready.", comment: "Confirm that the user wants to really change the xDrip algorithm type, message") }() static let confirmCalibrationChangeToSinglePointMessage: String = { - return NSLocalizedString("confirmCalibrationChangeToSinglePointMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the calibration type to the standard calibration\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready", comment: "Confirm that the user wants to really change the calibration type to multi-point, message") + return NSLocalizedString("confirmCalibrationChangeToSinglePointMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the calibration type to the standard calibration\n\nThis will stop readings for a short time and ask you for a initial calibration value when ready.", comment: "Confirm that the user wants to really change the calibration type to multi-point, message") }() static let confirmCalibrationChangeToMultiPointMessage: String = { - return NSLocalizedString("confirmCalibrationChangeToMultiPointMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the calibration type to multi-point\n\n⚠️ Please note that this method is only for advanced users and could potentially give dangerous results if not correctly calibrated.\n\nIf you are unsure how to use this method, please press Cancel", comment: "Confirm that the user wants to really change the calibration type to multi-point, message") + return NSLocalizedString("confirmCalibrationChangeToMultiPointMessage", tableName: filename, bundle: Bundle.main, value: "Please confirm that you want to change the calibration type to multi-point\n\n⚠️ Please note that this method is only for advanced users and could potentially give dangerous results if not correctly calibrated.\n\nIf you are unsure how to use this method, please press Cancel.", comment: "Confirm that the user wants to really change the calibration type to multi-point, message") }() static let confirm: String = { diff --git a/xdrip/Texts/TextsCalibration.swift b/xdrip/Texts/TextsCalibration.swift index b9df6c587..e7e395688 100644 --- a/xdrip/Texts/TextsCalibration.swift +++ b/xdrip/Texts/TextsCalibration.swift @@ -17,11 +17,11 @@ enum Texts_Calibrations { }() static let singlePointCalibration:String = { - return NSLocalizedString("singlePointCalibration", tableName: filename, bundle: Bundle.main, value: "Standard Calibration", comment: "text for standard/single-point calibration") + return NSLocalizedString("singlePointCalibration", tableName: filename, bundle: Bundle.main, value: "Standard", comment: "text for standard/single-point calibration") }() static let multiPointCalibration:String = { - return NSLocalizedString("multiPointCalibration", tableName: filename, bundle: Bundle.main, value: "Multi-point Calibration", comment: "text for multi-point/non-fixed slope calibration") + return NSLocalizedString("multiPointCalibration", tableName: filename, bundle: Bundle.main, value: "Multi-point", comment: "text for multi-point/non-fixed slope calibration") }() } diff --git a/xdrip/Texts/TextsCommon.swift b/xdrip/Texts/TextsCommon.swift index 2473f626a..ad32f8568 100644 --- a/xdrip/Texts/TextsCommon.swift +++ b/xdrip/Texts/TextsCommon.swift @@ -227,6 +227,6 @@ class Texts_Common { }() static let notRequired = { - return NSLocalizedString("common_notRequired", tableName: filename, bundle: Bundle.main, value: "Not Required", comment: "not required") + return NSLocalizedString("common_notRequired", tableName: filename, bundle: Bundle.main, value: "Not required", comment: "not required") }() } diff --git a/xdrip/Texts/TextsSettingsView.swift b/xdrip/Texts/TextsSettingsView.swift index 7d473430f..bf4a361f6 100644 --- a/xdrip/Texts/TextsSettingsView.swift +++ b/xdrip/Texts/TextsSettingsView.swift @@ -157,7 +157,7 @@ class Texts_SettingsView { }() static let libreLinkUpNoActiveSensor = { - return NSLocalizedString("settingsviews_libreLinkUpNoActiveSensor", tableName: filename, bundle: Bundle.main, value: "No active sensor", comment: "libre link up follower settings, no active sensor") + return NSLocalizedString("settingsviews_libreLinkUpNoActiveSensor", tableName: filename, bundle: Bundle.main, value: "No active sensor data", comment: "libre link up follower settings, no active sensor") }() // MARK: - Section Notifications @@ -709,7 +709,7 @@ class Texts_SettingsView { }() static let enableContactImage: String = { - return NSLocalizedString("settingsviews_enableContactImage", tableName: filename, bundle: Bundle.main, value: "Create Contact", comment: "Contact Image Settings - text in row where contact image is enabled or disabled ") + return NSLocalizedString("settingsviews_enableContactImage", tableName: filename, bundle: Bundle.main, value: "Enable Contact Image", comment: "Contact Image Settings - text in row where contact image is enabled or disabled ") }() static let displayTrendInContactImage: String = { diff --git a/xdrip/View Controllers/BluetoothPeripheralsNavigationController/BluetoothPeripheralsViewController/BluetoothPeripheralViewController/BluetoothPeripheralViewController.swift b/xdrip/View Controllers/BluetoothPeripheralsNavigationController/BluetoothPeripheralsViewController/BluetoothPeripheralViewController/BluetoothPeripheralViewController.swift index 31571639b..87580ea3a 100644 --- a/xdrip/View Controllers/BluetoothPeripheralsNavigationController/BluetoothPeripheralsViewController/BluetoothPeripheralViewController/BluetoothPeripheralViewController.swift +++ b/xdrip/View Controllers/BluetoothPeripheralsNavigationController/BluetoothPeripheralsViewController/BluetoothPeripheralViewController/BluetoothPeripheralViewController.swift @@ -1343,7 +1343,7 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD } cell.textLabel?.text = Texts_SettingsView.labelAlgorithmType - cell.detailTextLabel?.text = currentWebOOPEnabledValue ? Texts_BluetoothPeripheralView.transmitterAlgorithm : Texts_BluetoothPeripheralView.xDripAlgorithm + cell.detailTextLabel?.text = currentWebOOPEnabledValue ? Texts_BluetoothPeripheralView.nativeAlgorithm : Texts_BluetoothPeripheralView.xDripAlgorithm cell.accessoryType = .disclosureIndicator cell.accessoryView = disclosureAccessoryView @@ -1479,13 +1479,13 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD // first off all check that BluetoothPeripheral already exists guard let bluetoothPeripheral = bluetoothPeripheral else {return} - // data to be displayed in list from which user needs to pick a live activity type + // data to be displayed in list from which user needs to pick an algorithm type var data = [String]() var selectedRow: Int? var index = 0 - let currentAlgorithmType = bluetoothPeripheral.blePeripheral.webOOPEnabled ? AlgorithmType.transmitterAlgorithm : AlgorithmType.xDripAlgorithm + let currentAlgorithmType = bluetoothPeripheral.blePeripheral.webOOPEnabled ? AlgorithmType.nativeAlgorithm : AlgorithmType.xDripAlgorithm - // get all data source types and add the description to data. Search for the type that matches the FollowerDataSourceType that is currently stored in userdefaults. + // get all data source types and add the description to data. Search for the type that matches the AlgorithmType that is currently stored in userdefaults. for algorithmType in AlgorithmType.allCases { data.append(algorithmType.description) @@ -1502,20 +1502,20 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD let oldAlgorithmType = currentAlgorithmType if index != selectedRow { - let newAlgorithmType = AlgorithmType(rawValue: index) ?? .transmitterAlgorithm + let newAlgorithmType = AlgorithmType(rawValue: index) ?? .nativeAlgorithm // create uialertcontroller to ask the user if they really want to change algorithm - let confirmAlgorithmChangeAlertController = UIAlertController(title: Texts_SettingsView.labelAlgorithmType , message: newAlgorithmType == .transmitterAlgorithm ? Texts_BluetoothPeripheralView.confirmAlgorithmChangeToTransmitterMessage : Texts_BluetoothPeripheralView.confirmAlgorithmChangeToxDripMessage, preferredStyle: .alert) + let confirmAlgorithmChangeAlertController = UIAlertController(title: Texts_SettingsView.labelAlgorithmType , message: newAlgorithmType == .nativeAlgorithm ? Texts_BluetoothPeripheralView.confirmAlgorithmChangeToTransmitterMessage : Texts_BluetoothPeripheralView.confirmAlgorithmChangeToxDripMessage, preferredStyle: .alert) // create buttons for UIAlertController let OKAction = UIAlertAction(title: Texts_BluetoothPeripheralView.confirm, style: .default) { (action:UIAlertAction!) in - bluetoothPeripheral.blePeripheral.webOOPEnabled = (newAlgorithmType == .transmitterAlgorithm) ? true : false + bluetoothPeripheral.blePeripheral.webOOPEnabled = (newAlgorithmType == .nativeAlgorithm) ? true : false - bluetoothPeripheralManager.receivedNewValue(webOOPEnabled: (newAlgorithmType == .transmitterAlgorithm) ? true : false, for: bluetoothPeripheral) + bluetoothPeripheralManager.receivedNewValue(webOOPEnabled: (newAlgorithmType == .nativeAlgorithm) ? true : false, for: bluetoothPeripheral) - if newAlgorithmType == .transmitterAlgorithm { + if newAlgorithmType == .nativeAlgorithm { bluetoothPeripheral.blePeripheral.nonFixedSlopeEnabled = false bluetoothPeripheralManager.receivedNewValue(nonFixedSlopeEnabled: false, for: bluetoothPeripheral) } @@ -1564,7 +1564,7 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD var index = 0 let currentCalibrationType = bluetoothPeripheral.blePeripheral.nonFixedSlopeEnabled ? CalibrationType.multiPoint : CalibrationType.singlePoint - // get all data source types and add the description to data. Search for the type that matches the FollowerDataSourceType that is currently stored in userdefaults. + // get all data source types and add the description to data. Search for the type that matches the CalibrationType that is currently stored in userdefaults. for calibrationType in CalibrationType.allCases { data.append(calibrationType.description) @@ -1583,7 +1583,7 @@ extension BluetoothPeripheralViewController: UITableViewDataSource, UITableViewD if index != selectedRow { let newCalibrationType = CalibrationType(rawValue: index) ?? .singlePoint - // create uialertcontroller to ask the user if they really want to change algorithm + // create uialertcontroller to ask the user if they really want to change calibration type let confirmCalibrationChangeAlertController = UIAlertController(title: Texts_SettingsView.labelCalibrationType , message: newCalibrationType == .singlePoint ? Texts_BluetoothPeripheralView.confirmCalibrationChangeToSinglePointMessage : Texts_BluetoothPeripheralView.confirmCalibrationChangeToMultiPointMessage, preferredStyle: .alert) // create buttons for UIAlertController diff --git a/xdrip/View Controllers/Root View Controller/RootViewController.swift b/xdrip/View Controllers/Root View Controller/RootViewController.swift index 0f72ca5b1..016da0869 100644 --- a/xdrip/View Controllers/Root View Controller/RootViewController.swift +++ b/xdrip/View Controllers/Root View Controller/RootViewController.swift @@ -3305,11 +3305,6 @@ final class RootViewController: UIViewController, ObservableObject { dataSourceSensorMaxAgeOutlet.textColor = .systemRed dataSourceSensorMaxAgeOutlet.text = Texts_HomeView.libreLinkUpAccountCredentialsMissing - } else if sensorStartDate == nil || sensorMaxAgeInMinutes == 0 { - - dataSourceSensorMaxAgeOutlet.textColor = .systemRed - dataSourceSensorMaxAgeOutlet.text = Texts_HomeView.noSensorData - } } @@ -3988,6 +3983,8 @@ extension RootViewController: FollowerDelegate { // ask calendarManager to process new reading, ignore last connection change timestamp because this is follower mode, there is no connection to a transmitter calendarManager?.processNewReading(lastConnectionStatusChangeTimeStamp: nil) + contactImageManager?.processNewReading() + loopManager?.share() watchManager?.updateWatchApp(forceComplicationUpdate: false) diff --git a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewContactImageSettingsViewModel.swift b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewContactImageSettingsViewModel.swift index d2dcc5dcf..5d899487e 100644 --- a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewContactImageSettingsViewModel.swift +++ b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewContactImageSettingsViewModel.swift @@ -29,7 +29,7 @@ class SettingsViewContactImageSettingsViewModel: SettingsViewModelProtocol { func storeMessageHandler(messageHandler: ((String, String) -> Void)) { // this ViewModel does need to send back messages to the viewcontroller asynchronously } - + func storeRowReloadClosure(rowReloadClosure: ((Int) -> Void)) {} func sectionTitle() -> String? { @@ -50,9 +50,9 @@ class SettingsViewContactImageSettingsViewModel: SettingsViewModelProtocol { case .useHighContrastContactImage: return Texts_SettingsView.useHighContrastContactImage - + } - + } func accessoryType(index: Int) -> UITableViewCell.AccessoryType { @@ -62,42 +62,50 @@ class SettingsViewContactImageSettingsViewModel: SettingsViewModelProtocol { switch setting { case .enableContactImage: + // check if in follower with keep-alive disabled. If so, disable this option + if !UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled { + return .detailButton + } + // if access to Contacts was previously denied by user, then show disclosure indicator, clicking the row will give info how user should authorize access // also if access is restricted switch CNContactStore.authorizationStatus(for: .contacts) { case .denied: // by clicking row, show info how to authorized - return UITableViewCell.AccessoryType.disclosureIndicator + return .disclosureIndicator case .notDetermined: - return UITableViewCell.AccessoryType.none + return .none case .restricted, .limited: // by clicking row, show what it means to be restricted, according to Apple doc - return UITableViewCell.AccessoryType.disclosureIndicator + return .disclosureIndicator case .authorized: - return UITableViewCell.AccessoryType.none + return .none @unknown default: trace("in SettingsViewContactImageSettingsViewModel, unknown case returned when authorizing EKEventStore ", log: self.log, category: ConstantsLog.categoryRootView, type: .error) - return UITableViewCell.AccessoryType.none + return .none } case .displayTrend, .useHighContrastContactImage: return UITableViewCell.AccessoryType.none - + } } - + func detailedText(index: Int) -> String? { guard let setting = Setting(rawValue: index) else { fatalError("Unexpected Section") } switch setting { - case .enableContactImage, .displayTrend, .useHighContrastContactImage: + case .enableContactImage: + // check if in follower with keep-alive disabled. If so, disable this option + return (UserDefaults.standard.enableContactImage && !UserDefaults.standard.isMaster && UserDefaults.standard.followerBackgroundKeepAliveType == .disabled) ? "⚠️ No keep-alive" : nil + case .displayTrend, .useHighContrastContactImage: return nil } } @@ -152,7 +160,7 @@ class SettingsViewContactImageSettingsViewModel: SettingsViewModelProtocol { case .denied: trace("in SettingsViewContactImageSettingsViewModel, CNContactStore access denied by user", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.enableContactImage = false - + case .authorized: trace("in SettingsViewContactImageSettingsViewModel, CNContactStore access authorized", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.enableContactImage = true @@ -169,7 +177,7 @@ class SettingsViewContactImageSettingsViewModel: SettingsViewModelProtocol { case .useHighContrastContactImage: return UISwitch(isOn: UserDefaults.standard.useHighContrastContactImage, action: {(isOn:Bool) in UserDefaults.standard.useHighContrastContactImage = isOn}) - + } } diff --git a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewDataSourceSettingsViewModel.swift b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewDataSourceSettingsViewModel.swift index 82de275ee..0af768d93 100644 --- a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewDataSourceSettingsViewModel.swift +++ b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewDataSourceSettingsViewModel.swift @@ -525,7 +525,7 @@ class SettingsViewDataSourceSettingsViewModel: NSObject, SettingsViewModelProtoc } else { - return "" + return "-" } default: return "" @@ -546,7 +546,7 @@ class SettingsViewDataSourceSettingsViewModel: NSObject, SettingsViewModelProtoc return returnString } else { - return "" + return "-" } default: