From fcca3becdea6940b0ef2e816a2e51ff26eed4f1c Mon Sep 17 00:00:00 2001 From: Paul Plant Date: Fri, 22 Sep 2023 20:31:34 +0200 Subject: [PATCH 1/9] update project to work with new iOS17 EKEventStore requirements --- xdrip.xcodeproj/project.pbxproj | 2 +- .../en.lproj/SettingsViews.strings | 3 +- .../es.lproj/SettingsViews.strings | 3 +- .../nl.lproj/SettingsViews.strings | 3 +- xdrip/Supporting Files/Info.plist | 4 +- xdrip/Texts/TextsSettingsView.swift | 6 ++- ...tingsViewAppleWatchSettingsViewModel.swift | 51 +++++++++++++++---- 7 files changed, 55 insertions(+), 17 deletions(-) diff --git a/xdrip.xcodeproj/project.pbxproj b/xdrip.xcodeproj/project.pbxproj index f892943b7..160b87653 100644 --- a/xdrip.xcodeproj/project.pbxproj +++ b/xdrip.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ diff --git a/xdrip/Storyboards/en.lproj/SettingsViews.strings b/xdrip/Storyboards/en.lproj/SettingsViews.strings index 28c2d0d9e..07581d411 100644 --- a/xdrip/Storyboards/en.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/en.lproj/SettingsViews.strings @@ -99,7 +99,8 @@ "settingsviews_displayTrendInCalendarEvent" = "Display Trend?"; "displayUnitInCalendarEvent" = "Display Unit?"; "displayDeltaInCalendarEvent" = "Display Delta?"; -"infoCalendarAccessDeniedByUser" = "You previously denied access to your Calendar.\n\nTo enable it go to your device settings, privacy, calendars and enable it."; +"infoCalendarAccessDeniedByUser" = "You previously denied access to your calendars.\n\nGo to iPhone Settings > %@ > Calendars and enable full access."; +"infoCalendarAccessWriteOnly" = "You cannot use Calendar Events until you update the calendar access permission from 'Add Events Only' to 'Full Access'.\n\nGo to iPhone Settings > %@ > Calendars and select 'Full Access'."; "infoCalendarAccessRestricted" = "You cannot give authorization to %@ to access your calendar. This is possibly due to active restrictions such as parental controls being in place."; "settingsviews_CalenderIntervalTitle" = "Event Interval"; "settingsviews_CalenderIntervalMessage" = "Minimum interval between two calender events (mins)"; diff --git a/xdrip/Storyboards/es.lproj/SettingsViews.strings b/xdrip/Storyboards/es.lproj/SettingsViews.strings index a48bddb90..416f7c6e5 100644 --- a/xdrip/Storyboards/es.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/es.lproj/SettingsViews.strings @@ -87,7 +87,8 @@ "settingsviews_displayTrendInCalendarEvent" = "Mostrar Tendencia?"; "displayUnitInCalendarEvent" = "Mostrar Unidad?"; "displayDeltaInCalendarEvent" = "Mostrar Delta?"; -"infoCalendarAccessDeniedByUser" = "Has denegado previamente permiso para acceder al calendario.\n\nPara habilitarlo de nuevo, ir a Configuración en tu iPhone, Privacidad, Calendarios y habilitarlo."; +"infoCalendarAccessDeniedByUser" = "Has denegado previamente permiso para acceder al calendario.\n\nIr a Configuración iPhone > %@ > Calendarios y habilitarlo."; +"infoCalendarAccessWriteOnly" = "No puedes usar Eventos de Calendario hasta que actualices los permisos de 'Sólo agregar eventos' a 'Acceso completo'.\n\nIr a Configuración iPhone > %@ > Calendarios y seleccionar 'Acceso completo'."; "infoCalendarAccessRestricted" = "No se puede autorizar a que %@ tenga acceso a tu calendario. Podría ser debido a que restricciones tipo Controles Parentales o similares lo están impidiendo."; "sectionTitleTrace" = "Rastrear/Issue Reporting"; "sendTraceFile" = "Enviar Archivo de Rastreo"; diff --git a/xdrip/Storyboards/nl.lproj/SettingsViews.strings b/xdrip/Storyboards/nl.lproj/SettingsViews.strings index ed9e1f2a1..ce8f07bd9 100644 --- a/xdrip/Storyboards/nl.lproj/SettingsViews.strings +++ b/xdrip/Storyboards/nl.lproj/SettingsViews.strings @@ -83,7 +83,8 @@ "settingsviews_displayTrendInCalendarEvent" = "Toon Trend?"; "displayUnitInCalendarEvent" = "Toon Eenheid?"; "displayDeltaInCalendarEvent" = "Toon Delta?"; -"infoCalendarAccessDeniedByUser" = "In het verleden heb je toegang geweigerd tot je Agenda.\n\nOm toestemming te geven, ga naar iPhone Instellingen, Privacy, Agenda's en schakel in."; +"infoCalendarAccessDeniedByUser" = "In het verleden heb je toegang geweigerd tot je Agenda.\n\nGa naar iPhone-instellingen > %@ > Agenda's en kies 'Volledige toegang'."; +"infoCalendarAccessWriteOnly" = "Je kunt Agenda Activiteiten niet gebruiken totdat je de Agenda-toegang hebt gewijzigd van 'Voeg alleen activiteiten toe' naar 'Volledige toegang'.\n\nGa naar iPhone-instellingen > %@ > Agenda's en kies 'Volledige toegang'."; "infoCalendarAccessRestricted" = "Geen toegang voor %@ tot je agenda. Dit komt waarschijnlijk door actieve beperkingen zoals Ouderlijk Toezicht."; "sectionTitleTrace" = "Probleemrapportage"; "sendTraceFile" = "Verstuur Probleemrapportage"; diff --git a/xdrip/Supporting Files/Info.plist b/xdrip/Supporting Files/Info.plist index f7f5d223b..0366f0eb0 100644 --- a/xdrip/Supporting Files/Info.plist +++ b/xdrip/Supporting Files/Info.plist @@ -43,8 +43,10 @@ Connect to CGM Transmitter and M5Stack NSBluetoothPeripheralUsageDescription Connect to CGM Transmitter and M5Stack + NSCalendarsFullAccessUsageDescription + To create events with BG reading values, so that they can be viewed on Apple Watch and CarPlay NSCalendarsUsageDescription - To create events with reading values as title, so that it can be viewed on Apple Watch + To create events with BG reading values, so that they can be viewed on Apple Watch and CarPlay NSHealthShareUsageDescription Store bloodglucose readings NSHealthUpdateUsageDescription diff --git a/xdrip/Texts/TextsSettingsView.swift b/xdrip/Texts/TextsSettingsView.swift index c42641145..936700a52 100644 --- a/xdrip/Texts/TextsSettingsView.swift +++ b/xdrip/Texts/TextsSettingsView.swift @@ -465,7 +465,11 @@ class Texts_SettingsView { }() static let infoCalendarAccessDeniedByUser: String = { - return NSLocalizedString("infoCalendarAccessDeniedByUser", tableName: filename, bundle: Bundle.main, value: "You previously denied access to your Calendar.\n\nTo enable it go to your device settings, privacy, calendars and enable it", comment: "If user has earlier denied access to calendar, and then tries to activate creation of events in calendar, this message will be shown") + return String(format: NSLocalizedString("infoCalendarAccessDeniedByUser", tableName: filename, bundle: Bundle.main, value: "You previously denied access to your calendars.\n\nGo to iPhone Settings > %@ > Calendars and enable full access.", comment: "If user has earlier denied access to calendar, and then tries to activate creation of events in calendar, this message will be shown"), ConstantsHomeView.applicationName) + }() + + static let infoCalendarAccessWriteOnly: String = { + return String(format: NSLocalizedString("infoCalendarAccessWriteOnly", tableName: filename, bundle: Bundle.main, value: "You cannot use Calendar Events until you update the calendar access permission from 'Add Events Only' to 'Full Access'.\n\nGo to iPhone Settings > %@ > Calendars and select 'Full Access'.", comment: "The user needs to update their calendar permissions"), ConstantsHomeView.applicationName) }() static let infoCalendarAccessRestricted: String = { diff --git a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewAppleWatchSettingsViewModel.swift b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewAppleWatchSettingsViewModel.swift index 841ca11e1..d93f4f3b9 100644 --- a/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewAppleWatchSettingsViewModel.swift +++ b/xdrip/View Controllers/SettingsNavigationController/SettingsViewController/SettingsViewModels/SettingsViewAppleWatchSettingsViewModel.swift @@ -101,7 +101,11 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { // by clicking row, show what it means to be restricted, according to Apple doc return UITableViewCell.AccessoryType.disclosureIndicator - case .authorized: + case .writeOnly: + // by clicking row, show that the permission is restricted to Add Events Only instead of Full Access + return UITableViewCell.AccessoryType.disclosureIndicator + + case .authorized, .fullAccess: return UITableViewCell.AccessoryType.none @unknown default: @@ -162,11 +166,14 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { } // check authorization status - switch EKEventStore.authorizationStatus(for:.event) { + switch EKEventStore.authorizationStatus(for: .event) { case .notDetermined: - self.eventStore.requestAccess(to: .event, completion: - {(granted: Bool, error: Error?) -> Void in + if #available(iOS 17.0, *) { + // if iOS17 then run the new access request method + // https://developer.apple.com/documentation/eventkit/accessing_calendar_using_eventkit_and_eventkitui#4250785 + self.eventStore.requestFullAccessToEvents(completion: + {(granted: Bool, error: Error?) -> Void in if !granted { trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access not granted", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.createCalendarEvent = false @@ -174,13 +181,31 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access granted", log: self.log, category: ConstantsLog.categoryRootView, type: .info) UserDefaults.standard.createCalendarEvent = true } - }) + }) + } else { + // Fallback on earlier versions as .requestAccess() was deprecated in iOS17 and doesn't work anymore + self.eventStore.requestAccess(to: .event, completion: + {(granted: Bool, error: Error?) -> Void in + if !granted { + trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access not granted", log: self.log, category: ConstantsLog.categoryRootView, type: .error) + UserDefaults.standard.createCalendarEvent = false + } else { + trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access granted", log: self.log, category: ConstantsLog.categoryRootView, type: .info) + UserDefaults.standard.createCalendarEvent = true + } + }) + } case .restricted: // authorize not possible, according to apple doc "possibly due to active restrictions such as parental controls being in place", no need to change value of UserDefaults.standard.createCalendarEvent // we will probably never come here because if it's restricted, the uiview is not shown trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access restricted, according to apple doc 'possibly due to active restrictions such as parental controls being in place'", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.createCalendarEvent = false + + case .writeOnly: + // Full Access permission has not been granted to the app so we won't be able to delete old BG events, no need to change value of UserDefaults.standard.createCalendarEvent + trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access is 'Write Only', the user must update this to 'Full Access'", log: self.log, category: ConstantsLog.categoryRootView, type: .error) + UserDefaults.standard.createCalendarEvent = false case .denied: // access denied by user, need to change value of UserDefaults.standard.createCalendarEvent @@ -188,8 +213,8 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access denied by user", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.createCalendarEvent = false - case .authorized: - // authorize successful, no need to change value of UserDefaults.standard.createCalendarEvent + case .authorized, .fullAccess: + // authorize successful (or fullAccess is granted), no need to change value of UserDefaults.standard.createCalendarEvent trace("in SettingsViewAppleWatchSettingsViewModel, EKEventStore access authorized", log: self.log, category: ConstantsLog.categoryRootView, type: .error) UserDefaults.standard.createCalendarEvent = true @@ -260,16 +285,20 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { case .denied: // by clicking row, show info how to authorized - return SettingsSelectedRowAction.showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.infoCalendarAccessDeniedByUser + " " + ConstantsHomeView.applicationName) + return SettingsSelectedRowAction.showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.infoCalendarAccessDeniedByUser) - case .notDetermined, .authorized: - // if notDetermined or authorized, the uiview is shown, and app should only react on clicking the uiview, not the row + case .notDetermined, .authorized, .fullAccess: + // if notDetermined, fullAccess or authorized, the uiview is shown, and app should only react on clicking the uiview, not the row break case .restricted: // by clicking row, show what it means to be restricted, according to Apple doc return SettingsSelectedRowAction.showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.infoCalendarAccessRestricted) + case .writeOnly: + // by clicking row, show how to update the permissions + return SettingsSelectedRowAction.showInfoText(title: Texts_Common.warning, message: Texts_SettingsView.infoCalendarAccessWriteOnly) + @unknown default: trace("in SettingsViewAppleWatchSettingsViewModel, unknown case returned when authorizing EKEventStore ", log: self.log, category: ConstantsLog.categoryRootView, type: .error) @@ -302,7 +331,7 @@ class SettingsViewAppleWatchSettingsViewModel: SettingsViewModelProtocol { } - return SettingsSelectedRowAction.selectFromList(title: Texts_SettingsView.labelTransmitterId, data: data, selectedRow: selectedRow, actionTitle: nil, cancelTitle: nil, actionHandler: {(index:Int) in + return SettingsSelectedRowAction.selectFromList(title: Texts_SettingsView.calenderId, data: data, selectedRow: selectedRow, actionTitle: nil, cancelTitle: nil, actionHandler: {(index:Int) in if index != selectedRow { UserDefaults.standard.calenderId = data[index] } From 66f8fb373c3362fba4255a3f4f488e004d2b3d4e Mon Sep 17 00:00:00 2001 From: Paul Plant Date: Fri, 22 Sep 2023 20:57:20 +0200 Subject: [PATCH 2/9] update Spanish translations for Dexcom transmitter settings --- .../es.lproj/BluetoothPeripheralView.strings | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings b/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings index 65ddd116a..c7da911e4 100644 --- a/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings +++ b/xdrip/Storyboards/es.lproj/BluetoothPeripheralView.strings @@ -30,16 +30,6 @@ "confirmDisconnectTitle" = "Confirmar Desconexión"; "confirmDisconnectMessage" = "Haz click en 'Desconectar' para confirmar que deseas desconectar el transmisor."; "warmingUpUntil" = "Calentando hasta"; - -///////////////////////////////////////////////////////////////////////////////////////////// -///// Translation needed - remove this header after translation ///// -///////////////////////////////////////////////////////////////////////////////////////////// - -/// Dexcom bluetooth screen. Is another app used in parallel or not -"useOtherDexcomApp" = "Read from Dexcom app"; - -/// cell text, sensor start time -"sensorStartDate" = "Sensor Started"; - -/// cell text, transmitter start time -"transmittterStartDate" = "Transmitter Started"; +"useOtherDexcomApp" = "Usar a la vez la app de Dexcom"; +"sensorStartDate" = "Sensor iniciado"; +"transmittterStartDate" = "Transmisor iniciado"; From 644c5a685a310c67aab89a1b1bec32242cf6c68e Mon Sep 17 00:00:00 2001 From: Paul Plant Date: Sat, 23 Sep 2023 10:53:17 +0200 Subject: [PATCH 3/9] fix compiler errors in IB autolayout --- xdrip/Storyboards/Base.lproj/Main.storyboard | 42 ++++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/xdrip/Storyboards/Base.lproj/Main.storyboard b/xdrip/Storyboards/Base.lproj/Main.storyboard index 04db3152a..054c8806f 100644 --- a/xdrip/Storyboards/Base.lproj/Main.storyboard +++ b/xdrip/Storyboards/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -174,7 +174,7 @@ -