diff --git a/cfg/VERSION b/cfg/VERSION index 1404f2d17fd..d8c51037cc5 100644 --- a/cfg/VERSION +++ b/cfg/VERSION @@ -1 +1 @@ -1.0.7.0 +1.1.1.3 diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index ee748d3396b..8af5f369338 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -285,6 +285,7 @@ B1B5A76024924B3D0029D5D7 /* FMDB in Frameworks */ = {isa = PBXBuildFile; productRef = B1B5A75F24924B3D0029D5D7 /* FMDB */; }; B1B9CF1F246ED2E8008F04F5 /* Sap_FilebucketTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B9CF1E246ED2E8008F04F5 /* Sap_FilebucketTests.swift */; }; B1BD9E7E24898A2300BD3930 /* ExposureDetectionViewController+DynamicTableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 714CD8662472885900F56450 /* ExposureDetectionViewController+DynamicTableViewModel.swift */; }; + B1BFE27224BDE1D500C1181D /* HomeViewController+HowRiskDetectionWorks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1BFE27124BDE1D500C1181D /* HomeViewController+HowRiskDetectionWorks.swift */; }; B1C6ECFF247F089E0066138F /* RiskImageItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B5B415246DF13D00DC5D3E /* RiskImageItemView.swift */; }; B1C6ED00247F23730066138F /* NotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D420D324586DCA00AD70CA /* NotificationName.swift */; }; B1C7EE4424938E9E00F1F284 /* ExposureDetection_DidEndPrematurelyReason+ErrorHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1C7EE4324938E9E00F1F284 /* ExposureDetection_DidEndPrematurelyReason+ErrorHandling.swift */; }; @@ -686,6 +687,7 @@ B1A9E70D246D73180024CC12 /* ExposureDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExposureDetection.swift; sourceTree = ""; }; B1A9E710246D782F0024CC12 /* SAPDownloadedPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAPDownloadedPackage.swift; sourceTree = ""; }; B1B9CF1E246ED2E8008F04F5 /* Sap_FilebucketTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sap_FilebucketTests.swift; sourceTree = ""; }; + B1BFE27124BDE1D500C1181D /* HomeViewController+HowRiskDetectionWorks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeViewController+HowRiskDetectionWorks.swift"; sourceTree = ""; }; B1C7EE4324938E9E00F1F284 /* ExposureDetection_DidEndPrematurelyReason+ErrorHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ExposureDetection_DidEndPrematurelyReason+ErrorHandling.swift"; sourceTree = ""; }; B1C7EE4524938EB700F1F284 /* ExposureDetection_DidEndPrematurelyReason+ErrorHandlingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ExposureDetection_DidEndPrematurelyReason+ErrorHandlingTests.swift"; sourceTree = ""; }; B1C7EE472493D97000F1F284 /* RiskProvidingConfigurationManualTriggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiskProvidingConfigurationManualTriggerTests.swift; sourceTree = ""; }; @@ -749,6 +751,12 @@ EE70C23B245B09E900AC9B2F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; EE70C23C245B09E900AC9B2F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; EE92A33F245D96DA006B97B0 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; + EEDD6DF524A4885200BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = tr; path = tr.lproj/usage.html; sourceTree = ""; }; + EEDD6DF624A4885200BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = tr; path = "tr.lproj/privacy-policy.html"; sourceTree = ""; }; + EEDD6DF724A4885D00BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/LaunchScreen.strings; sourceTree = ""; }; + EEDD6DF824A4889D00BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = ""; }; + EEDD6DF924A488A500BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + EEDD6DFA24A488AD00BC30D0 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = tr; path = tr.lproj/Localizable.stringsdict; sourceTree = ""; }; EEF10679246EBF8B009DFB4E /* ResetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResetViewController.swift; sourceTree = ""; }; F22C6E242492082B00712A6B /* DynamicTableViewSpaceCellTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicTableViewSpaceCellTests.swift; sourceTree = ""; }; F247572A24838AC8003E1FC5 /* DynamicTableViewControllerRowsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicTableViewControllerRowsTests.swift; sourceTree = ""; }; @@ -1098,6 +1106,7 @@ 51CE1B2E245F5CFC002CF42A /* HomeViewController.swift */, 5111E7622460BB1500ED6498 /* HomeInteractor.swift */, 51CE1B5424604DD2002CF42A /* HomeLayout.swift */, + B1BFE27124BDE1D500C1181D /* HomeViewController+HowRiskDetectionWorks.swift */, ); path = Home; sourceTree = ""; @@ -2112,6 +2121,7 @@ en, Base, de, + tr, ); mainGroup = 85D759322457048F008175F0; packageReferences = ( @@ -2332,6 +2342,7 @@ B11E619C246EE4E9004A056A /* UIFont+DynamicType.swift in Sources */, 71330E4524810A0500EB10F6 /* DynamicTableViewHeader.swift in Sources */, 0DF6BBB5248C04CF007E8B0C /* app_config_attenuation_duration.pb.swift in Sources */, + B1BFE27224BDE1D500C1181D /* HomeViewController+HowRiskDetectionWorks.swift in Sources */, B1EAEC8B24711884003BE9A2 /* URLSession+Convenience.swift in Sources */, 7154EB4C247E862100A467FF /* ExposureDetectionLoadingCell.swift in Sources */, A17366552484978A006BE209 /* OnboardingInfoViewControllerUtils.swift in Sources */, @@ -2570,6 +2581,7 @@ children = ( 13156CFE248C19D000AFC472 /* de */, 13156D00248CDECC00AFC472 /* en */, + EEDD6DF524A4885200BC30D0 /* tr */, ); name = usage.html; sourceTree = ""; @@ -2579,6 +2591,7 @@ children = ( 71F5418B248BEDBE006DB793 /* de */, 717D21EA248C072300D9717E /* en */, + EEDD6DF624A4885200BC30D0 /* tr */, ); name = "privacy-policy.html"; sourceTree = ""; @@ -2587,6 +2600,7 @@ isa = PBXVariantGroup; children = ( 85D7594D24570491008175F0 /* Base */, + EEDD6DF724A4885D00BC30D0 /* tr */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -2596,6 +2610,7 @@ children = ( EE269509248FCB0300BAE234 /* de */, EE26950B248FCB1600BAE234 /* en */, + EEDD6DF824A4889D00BC30D0 /* tr */, ); name = InfoPlist.strings; sourceTree = ""; @@ -2605,6 +2620,7 @@ children = ( EE70C23B245B09E900AC9B2F /* de */, EE70C23C245B09E900AC9B2F /* en */, + EEDD6DF924A488A500BC30D0 /* tr */, ); name = Localizable.strings; sourceTree = ""; @@ -2614,6 +2630,7 @@ children = ( EE92A33F245D96DA006B97B0 /* de */, 514C0A09247AEEE200F235F6 /* en */, + EEDD6DFA24A488AD00BC30D0 /* tr */, ); name = Localizable.stringsdict; sourceTree = ""; @@ -2693,7 +2710,7 @@ CODE_SIGN_ENTITLEMENTS = "${PROJECT}/Resources/ENACommunity.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = $IPHONE_APP_DEV_TEAM; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -2709,7 +2726,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.7; + MARKETING_VERSION = 1.1.1; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", "-DSQLITE_TEMP_STORE=3", @@ -2852,7 +2869,7 @@ CODE_SIGN_ENTITLEMENTS = "${PROJECT}/Resources/ENA.entitlements"; CODE_SIGN_IDENTITY = $IPHONE_APP_CODE_SIGN_IDENTITY; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 523TP53AQF; GCC_PREPROCESSOR_DEFINITIONS = "SQLITE_HAS_CODEC=1"; INFOPLIST_FILE = ENA/Resources/Info_Testflight.plist; @@ -2863,7 +2880,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.7; + MARKETING_VERSION = 1.1.1; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", "-DSQLITE_TEMP_STORE=3", @@ -3005,7 +3022,7 @@ CODE_SIGN_ENTITLEMENTS = "${PROJECT}/Resources/ENACommunity.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = $IPHONE_APP_DEV_TEAM; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -3020,7 +3037,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.7; + MARKETING_VERSION = 1.1.1; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", "-DSQLITE_TEMP_STORE=3", @@ -3224,7 +3241,7 @@ CODE_SIGN_ENTITLEMENTS = "${PROJECT}/Resources/ENATest.entitlements"; CODE_SIGN_IDENTITY = $IPHONE_APP_CODE_SIGN_IDENTITY; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 523TP53AQF; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -3239,7 +3256,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.7; + MARKETING_VERSION = 1.1.1; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", "-DSQLITE_TEMP_STORE=3", @@ -3268,7 +3285,7 @@ CODE_SIGN_ENTITLEMENTS = "${PROJECT}/Resources/ENA.entitlements"; CODE_SIGN_IDENTITY = $IPHONE_APP_CODE_SIGN_IDENTITY; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 0; + CURRENT_PROJECT_VERSION = 3; GCC_PREPROCESSOR_DEFINITIONS = "SQLITE_HAS_CODEC=1"; INFOPLIST_FILE = ENA/Resources/Info.plist; IPHONE_APP_CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -3278,7 +3295,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.7; + MARKETING_VERSION = 1.1.1; OTHER_CFLAGS = ( "-DSQLITE_HAS_CODEC", "-DSQLITE_TEMP_STORE=3", diff --git a/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENA.xcscheme b/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENA.xcscheme index ccf124f5b93..e8c232749dc 100644 --- a/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENA.xcscheme +++ b/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENA.xcscheme @@ -41,6 +41,8 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" + language = "de" + region = "DE" codeCoverageEnabled = "YES" onlyGenerateCoverageForSpecifiedTargets = "YES"> @@ -69,7 +71,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "de" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENATests.xcscheme b/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENATests.xcscheme index 33505914237..33854d4738d 100644 --- a/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENATests.xcscheme +++ b/src/xcode/ENA/ENA.xcodeproj/xcshareddata/xcschemes/ENATests.xcscheme @@ -27,6 +27,8 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES" + language = "de" + region = "DE" codeCoverageEnabled = "YES" onlyGenerateCoverageForSpecifiedTargets = "YES"> @@ -55,6 +57,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "de" + region = "DE" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/src/xcode/ENA/ENA/Resources/Info_Debug.plist b/src/xcode/ENA/ENA/Resources/Info_Debug.plist index f7410908695..352fe8b8fa6 100644 --- a/src/xcode/ENA/ENA/Resources/Info_Debug.plist +++ b/src/xcode/ENA/ENA/Resources/Info_Debug.plist @@ -23,7 +23,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) + de.rki.coronawarnapp-dev CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings index b1f33fbf015..59b69377105 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings @@ -115,6 +115,27 @@ "ExposureDetection_Button_Refresh" = "Aktualisieren"; +/* Active Tracing Section */ +"ExposureDetection_ActiveTracingSection_Title" = "Ermittlungszeitraum"; +"ExposureDetection_ActiveTracingSection_Subtitle" = "Dieser Zeitraum wird berücksichtigt"; + +/* + There are two paragraphs in this section. The first one just contains text… +*/ +"ExposureDetection_ActiveTracingSection_Text_Paragraph0" = "Die Berechnung des Infektionsrisikos kann nur für die Zeiträume erfolgen, an denen die Risiko-Ermittlung aktiv war. Die Risiko-Ermittlung sollte daher dauerhaft aktiv sein."; + +/* + … the second paragraph contains two columns. On the left there is our active + tracing indicator. On the right column there is just text that explains what + the indicator shows. + + Parameters: + - first: total number of relevant days (usually 14). + - second: the actual number of days with active tracing. + */ + +"ExposureDetection_ActiveTracingSection_Text_Paragraph1" = "Für Ihre Risiko-Ermittlung wird nur der Zeitraum der letzten %1$u Tage betrachtet. In diesem Zeitraum war Ihre Risiko-Ermittlung für eine Gesamtdauer von %2$u Tagen aktiv. Ältere Tage werden automatisch gelöscht, da sie aus Sicht des Infektionsschutzes nicht mehr relevant sind."; + /* Exposure Detection Errors */ "ExposureDetectionError_Alert_Title" = "Fehler"; @@ -122,6 +143,21 @@ "ExposureDetectionError_Alert_Message" = "Während der Risiko-Ermittlung ist ein Fehler aufgetreten."; +/* + How Risk Detection Works Alert. + First introduced due to EXPOSUREAPP-1738. + The alert only displays a single OK-button. We re-use the localized string + `Alert_ActionOk` for that. +*/ + +"How_Risk_Detection_Works_Alert_Title" = "Information zur Funktionsweise der Risiko-Ermittlung"; + +"How_Risk_Detection_Works_Alert_Message" = "Die Berechnung des Infektionsrisikos kann nur für die Zeiträume erfolgen, an denen die Risiko-Ermittlung aktiv war. Die Risiko-Ermittlung sollte daher dauerhaft aktiv sein. +Für Ihre Risiko-Ermittlung wird nur der Zeitraum der letzten %1$u Tage betrachtet. +Ältere Tage werden automatisch gelöscht, da sie aus Sicht des Infektionsschutzes nicht mehr relevant sind. + +Weitere Informationen finden Sie in den FAQ."; + /* Settings */ "Settings_StatusActive" = "An"; @@ -628,7 +664,8 @@ /* Home Low card */ "Home_Risk_Low_Title" = "Niedriges Risiko"; -"Home_Risk_Low_SaveDays_Item_Title" = "%@ von %@ Tagen aktiv"; +"Home_Risk_Low_SaveDays_Item_Title" = "Risiko-Ermittlung war für %1$u der letzten %2$u Tage aktiv"; +"Home_Risk_Low_SaveDays_Item_Title__Permanently_Active" = "Risiko-Ermittlung dauerhaft aktiv"; "Home_Risk_Low_Button" = "Aktualisieren"; @@ -930,3 +967,11 @@ "ENATanInput_CharacterIndex" = "Zeichen %1$u von %2$u"; +/* + Active Tracing Interval Formatting: + The following two entries are used together. If tracing was not active (almost) 14 days + during the last 14 days then `Active_Tracing_Interval_Partially_Active` is used – otherwise + `Active_Tracing_Interval_Partially_Active` will be used. + */ +"Active_Tracing_Interval_Partially_Active" = "Risiko-Ermittlung war für %1$u der letzten %2$u Tage aktiv"; +"Active_Tracing_Interval_Permanently_Active" = "Risiko-Ermittlung dauerhaft aktiv"; diff --git a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.strings b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.strings index 59de6290b01..70c6cd7a8e8 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.strings @@ -115,6 +115,27 @@ "ExposureDetection_Button_Refresh" = "Update"; +/* Active Tracing Section */ +"ExposureDetection_ActiveTracingSection_Title" = "Period logged"; +"ExposureDetection_ActiveTracingSection_Subtitle" = "This period is included in the calculation"; + +/* + There are two paragraphs in this section. The first one just contains text… + */ +"ExposureDetection_ActiveTracingSection_Text_Paragraph0" = "Your risk of infection can be calculated only for periods during which exposure logging was active. The logging feature should therefore remain active permanently."; + +/* + … the second paragraph contains two columns. On the left there is our active + tracing indicator. On the right column there is just text that explains what + the indicator shows. + + Parameters: + - first: total number of relevant days (usually 14). + - second: the actual number of days with active tracing. + */ + +"ExposureDetection_ActiveTracingSection_Text_Paragraph1" = "Exposure logging covers the last %1$u days. During this time, the logging feature on your device was active for %2$u days. The app automatically deletes older logs, as these are no longer relevant for infection prevention."; + /* Exposure Detection Errors */ "ExposureDetectionError_Alert_Title" = "Error"; @@ -122,6 +143,22 @@ "ExposureDetectionError_Alert_Message" = "An error occurred during exposure logging."; + +/* + How Risk Detection Works Alert. + First introduced due to EXPOSUREAPP-1738. + The alert only displays a single OK-button. We re-use the localized string + `Alert_ActionOk` for that. + */ + +"How_Risk_Detection_Works_Alert_Title" = "Information about exposure logging functionality"; + +"How_Risk_Detection_Works_Alert_Message" = "Your risk of infection can be calculated only for periods during which exposure logging was active. The logging feature should therefore remain active permanently. +Exposure logging covers the last %1$u days. +The app automatically deletes older logs, as these are no longer relevant for infection prevention. + +For further information, please see our FAQ page."; + /* Settings */ "Settings_StatusActive" = "On"; @@ -627,7 +664,8 @@ /* Home Low card */ "Home_Risk_Low_Title" = "Low Risk"; -"Home_Risk_Low_SaveDays_Item_Title" = "%@ of %@ days saved"; +"Home_Risk_Low_SaveDays_Item_Title" = "Risk detection was active for %u of %u days"; +"Home_Risk_Low_SaveDays_Item_Title__Permanently_Active" = "Risk detection permanently active"; "Home_Risk_Low_Button" = "Update"; @@ -929,3 +967,11 @@ "ENATanInput_CharacterIndex" = "Character %1$u of %2$u"; +/* + Active Tracing Interval Formatting: + The following two entries are used together. If tracing was not active (almost) 14 days + during the last 14 days then `Active_Tracing_Interval_Partially_Active` is used – otherwise + `Active_Tracing_Interval_Partially_Active` will be used. + */ +"Active_Tracing_Interval_Partially_Active" = "Exposure logging was active for %1$u of the last %2$u days."; +"Active_Tracing_Interval_Permanently_Active" = "Exposure logging permanently active"; diff --git a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.strings b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.strings index f86df61b9a3..81679bb3e9b 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.strings @@ -97,6 +97,28 @@ "ExposureDetection_Button_Refresh" = "Güncelle"; +/* Active Tracing Section */ +"ExposureDetection_ActiveTracingSection_Title" = "Dönem günlüğe kaydedildi"; +"ExposureDetection_ActiveTracingSection_Subtitle" = "Bu dönem hesaplamaya dahil edildi"; + +/* + There are two paragraphs in this section. The first one just contains text… + */ +"ExposureDetection_ActiveTracingSection_Text_Paragraph0" = "Enfeksiyon riskiniz yalnızca maruz kalma günlüğünün etkin olduğu dönemler için hesaplanabilir. Bu nedenle günlüğe kaydetme özelliğinin sürekli etkin kalması gerekir."; + +/* + … the second paragraph contains two columns. On the left there is our active + tracing indicator. On the right column there is just text that explains what + the indicator shows. + + Parameters: + - first: total number of relevant days (usually 14). + - second: the actual number of days with active tracing. + */ + +"ExposureDetection_ActiveTracingSection_Text_Paragraph1" = "Maruz kalma günlüğü son %1$u günü kapsar. Bu süre boyunca cihazınızdaki günlüğe kaydetme özelliği %2$u gün etkindi. Uygulama, enfeksiyondan korunma için artık ilgili olmadığından daha eski kayıtları otomatik olarak siler."; + + /* Exposure Detection Errors */ "ExposureDetectionError_Alert_Title" = "Bir sorun oluştu."; @@ -104,6 +126,22 @@ "ExposureDetectionError_Alert_Message" = "Maruz kalma günlüğü sırasında bir hata oluştu."; +/* + How Risk Detection Works Alert. + First introduced due to EXPOSUREAPP-1738. + The alert only displays a single OK-button. We re-use the localized string + `Alert_ActionOk` for that. + */ + +"How_Risk_Detection_Works_Alert_Title" = "Maruz kalma işlevi hakkında bilgi"; + +"How_Risk_Detection_Works_Alert_Message" = "Enfeksiyon riskiniz yalnızca maruz kalma günlüğünün etkin olduğu dönemler için hesaplanabilir. Bu nedenle günlüğe kaydetme özelliğinin sürekli etkin kalması gerekir. +Maruz kalma günlüğü son %1$u günü kapsar. +Uygulama, enfeksiyondan korunma için artık ilgili olmadığından daha eski kayıtları otomatik olarak siler. + +Daha fazla bilgi için lütfen SSS sayfamıza bakın."; + + /* Settings */ "Settings_StatusActive" = "Açık"; @@ -902,3 +940,12 @@ "ENATanInput_CharacterIndex" = "%1$u/%2$u karakter"; + +/* + Active Tracing Interval Formatting: + The following two entries are used together. If tracing was not active (almost) 14 days + during the last 14 days then `Active_Tracing_Interval_Partially_Active` is used – otherwise + `Active_Tracing_Interval_Partially_Active` will be used. + */ +"Active_Tracing_Interval_Partially_Active" = "Maruz kalma günlüğü son %2$u günde %1$u gün etkindi."; +"Active_Tracing_Interval_Permanently_Active" = "Maruz kalma günlüğü sürekli etkin"; diff --git a/src/xcode/ENA/ENA/Resources/Storyboards/ExposureNotificationSetting.storyboard b/src/xcode/ENA/ENA/Resources/Storyboards/ExposureNotificationSetting.storyboard index c4b28004556..08cd337162e 100644 --- a/src/xcode/ENA/ENA/Resources/Storyboards/ExposureNotificationSetting.storyboard +++ b/src/xcode/ENA/ENA/Resources/Storyboards/ExposureNotificationSetting.storyboard @@ -253,73 +253,98 @@ - + - + - - + + - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + - + diff --git a/src/xcode/ENA/ENA/Source/Models/Home/HomeRiskCellConfigurator/HomeRiskCellConfigurators/HomeLowRiskCellConfigurator.swift b/src/xcode/ENA/ENA/Source/Models/Home/HomeRiskCellConfigurator/HomeRiskCellConfigurators/HomeLowRiskCellConfigurator.swift index 11cb8468258..e81c535a75f 100644 --- a/src/xcode/ENA/ENA/Source/Models/Home/HomeRiskCellConfigurator/HomeRiskCellConfigurators/HomeLowRiskCellConfigurator.swift +++ b/src/xcode/ENA/ENA/Source/Models/Home/HomeRiskCellConfigurator/HomeRiskCellConfigurators/HomeLowRiskCellConfigurator.swift @@ -19,26 +19,29 @@ import UIKit final class HomeLowRiskCellConfigurator: HomeRiskLevelCellConfigurator { private var numberRiskContacts: Int - private var numberDays: Int - private var totalDays: Int + private var numberDays: Int { + activeTracing.inDays + } + private var totalDays: Int { + activeTracing.maximumNumberOfDays + } private let detectionInterval: Int + private let activeTracing: ActiveTracing // MARK: Creating a Home Risk Cell Configurator init( numberRiskContacts: Int, - numberDays: Int, - totalDays: Int, lastUpdateDate: Date?, isButtonHidden: Bool, detectionMode: DetectionMode, manualExposureDetectionState: ManualExposureDetectionState?, - detectionInterval: Int + detectionInterval: Int, + activeTracing: ActiveTracing ) { self.numberRiskContacts = numberRiskContacts - self.numberDays = numberDays - self.totalDays = totalDays self.detectionInterval = detectionInterval + self.activeTracing = activeTracing super.init( isLoading: false, isButtonEnabled: manualExposureDetectionState == .possible, @@ -76,15 +79,10 @@ final class HomeLowRiskCellConfigurator: HomeRiskLevelCellConfigurator { separatorColor: separatorColor ) ) - let numberDaysString = String(numberDays) - let totalDaysString = String(totalDays) - let saveDays = String( - format: AppStrings.Home.riskCardLowSaveDaysItemTitle, numberDaysString, totalDaysString - ) - let progressImage: String = numberDays >= totalDays ? "Icons_TracingCircleFull - Dark" : "Icons_TracingCircle-Dark_Step \(numberDays)" + let progressImage: String = numberDays >= totalDays ? "Icons_TracingCircleFull - Dark" : "Icons_TracingCircle-Dark_Step \(activeTracing.inDays)" itemCellConfigurators.append( HomeRiskImageItemViewConfigurator( - title: saveDays, + title: activeTracing.localizedDuration, titleColor: titleColor, iconImageName: progressImage, iconTintColor: titleColor, diff --git a/src/xcode/ENA/ENA/Source/Scenes/ENSetting/ExposureNotificationSettingViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/ENSetting/ExposureNotificationSettingViewController.swift index 8650903ef34..ced9e618e44 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/ENSetting/ExposureNotificationSettingViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/ENSetting/ExposureNotificationSettingViewController.swift @@ -213,11 +213,21 @@ extension ExposureNotificationSettingViewController { let colorConfig: (UIColor, UIColor) = (self.enState == .enabled) ? (UIColor.enaColor(for: .tint), UIColor.enaColor(for: .hairline)) : (UIColor.enaColor(for: .textPrimary2), UIColor.enaColor(for: .hairline)) + let activeTracing = store.tracingStatusHistory.activeTracing() + let text = [ + activeTracing.exposureDetectionActiveTracingSectionTextParagraph0, + activeTracing.exposureDetectionActiveTracingSectionTextParagraph1] + .joined(separator: "\n\n") + + let numberOfDaysWithActiveTracing = activeTracing.inDays + let title = NSLocalizedString("ExposureDetection_ActiveTracingSection_Title", comment: "") + let subtitle = NSLocalizedString("ExposureDetection_ActiveTracingSection_Subtitle", comment: "") - let numberOfDaysWithActiveTracing = store.tracingStatusHistory.activeTracing().inDays tracingCell.configure( progress: CGFloat(numberOfDaysWithActiveTracing), - text: String(format: AppStrings.ExposureNotificationSetting.tracingHistoryDescription, numberOfDaysWithActiveTracing), + title: title, + subtitle: subtitle, + text: text, colorConfigurationTuple: colorConfig ) return tracingCell diff --git a/src/xcode/ENA/ENA/Source/Scenes/ExposureDetection/ExposureDetectionViewController+DynamicTableViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/ExposureDetection/ExposureDetectionViewController+DynamicTableViewModel.swift index f0913f5b3df..8596fa54750 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/ExposureDetection/ExposureDetectionViewController+DynamicTableViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/ExposureDetection/ExposureDetectionViewController+DynamicTableViewModel.swift @@ -127,11 +127,11 @@ private extension DynamicCell { } } - static func riskStored(text: String, imageName: String) -> DynamicCell { + static func riskStored(activeTracing: ActiveTracing, imageName: String) -> DynamicCell { .risk { viewController, cell, _ in let state = viewController.state var numberOfDaysStored = state.risk?.details.numberOfDaysWithActiveTracing ?? 0 - cell.textLabel?.text = String(format: text, numberOfDaysStored) + cell.textLabel?.text = activeTracing.localizedDuration if numberOfDaysStored < 0 { numberOfDaysStored = 0 } if numberOfDaysStored > 13 { cell.imageView?.image = UIImage(named: "Icons_TracingCircleFull - Dark") @@ -280,6 +280,38 @@ extension ExposureDetectionViewController { ) } + private func activeTracingSection(accessibilityIdentifier: String?) -> DynamicSection { + let p0 = NSLocalizedString( + "ExposureDetection_ActiveTracingSection_Text_Paragraph0", + comment: "" + ) + + let p1 = state.risk?.details.activeTracing.exposureDetectionActiveTracingSectionTextParagraph1 ?? "" + + let body = [p0, p1].joined(separator: "\n\n") + + return .section( + header: .backgroundSpace(height: 8), + footer: .backgroundSpace(height: 16), + cells: [ + .header( + title: NSLocalizedString( + "ExposureDetection_ActiveTracingSection_Title", + comment: "" + ), + subtitle: NSLocalizedString( + "ExposureDetection_ActiveTracingSection_Subtitle", + comment: "" + ) + ), + .body( + text: body, + accessibilityIdentifier: accessibilityIdentifier + ) + ] + ) + } + private func explanationSection(text: String, isActive: Bool, accessibilityIdentifier: String?) -> DynamicSection { .section( header: .backgroundSpace(height: 8), @@ -351,16 +383,19 @@ extension ExposureDetectionViewController { } private var lowRiskModel: DynamicTableViewModel { - DynamicTableViewModel([ + let activeTracing = state.risk?.details.activeTracing ?? .init(interval: 0) + + return DynamicTableViewModel([ riskDataSection( cells: [ .riskContacts(text: AppStrings.ExposureDetection.numberOfContacts, image: UIImage(named: "Icons_KeineRisikoBegegnung")), - .riskStored(text: AppStrings.ExposureDetection.numberOfDaysStored, imageName: "Icons_TracingCircle-Dark_Step %u"), + .riskStored(activeTracing: activeTracing, imageName: "Icons_TracingCircle-Dark_Step %u"), .riskRefreshed(text: AppStrings.ExposureDetection.refreshed, image: UIImage(named: "Icons_Aktualisiert")) ]), riskRefreshSection, riskLoadingSection, standardGuideSection, + activeTracingSection(accessibilityIdentifier: "hello"), explanationSection( text: AppStrings.ExposureDetection.explanationTextLow, isActive: true, @@ -370,11 +405,12 @@ extension ExposureDetectionViewController { } private var highRiskModel: DynamicTableViewModel { - DynamicTableViewModel([ + let activeTracing = state.risk?.details.activeTracing ?? .init(interval: 0) + return DynamicTableViewModel([ riskDataSection(cells: [ .riskContacts(text: AppStrings.ExposureDetection.numberOfContacts, image: UIImage(named: "Icons_RisikoBegegnung")), .riskLastExposure(text: AppStrings.ExposureDetection.lastExposure, image: UIImage(named: "Icons_Calendar")), - .riskStored(text: AppStrings.ExposureDetection.numberOfDaysStored, imageName: "Icons_TracingCircle-Dark_Step %u"), + .riskStored(activeTracing: activeTracing, imageName: "Icons_TracingCircle-Dark_Step %u"), .riskRefreshed(text: AppStrings.ExposureDetection.refreshed, image: UIImage(named: "Icons_Aktualisiert")) ]), riskRefreshSection, @@ -393,6 +429,9 @@ extension ExposureDetectionViewController { ]) ] ), + activeTracingSection( + accessibilityIdentifier: AccessibilityIdentifiers.ExposureDetection.activeTracingSectionText + ), explanationSection( text: AppStrings.ExposureDetection.explanationTextHigh, isActive: true, @@ -401,3 +440,14 @@ extension ExposureDetectionViewController { ]) } } + +extension ActiveTracing { + var exposureDetectionActiveTracingSectionTextParagraph1: String { + let format = NSLocalizedString("ExposureDetection_ActiveTracingSection_Text_Paragraph1", comment: "") + return String(format: format, maximumNumberOfDays, inDays) + } + + var exposureDetectionActiveTracingSectionTextParagraph0: String { + return NSLocalizedString("ExposureDetection_ActiveTracingSection_Text_Paragraph0", comment: "") + } +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/Home/HomeInteractor.swift b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeInteractor.swift index f74644f9bab..59eeb816a70 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Home/HomeInteractor.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeInteractor.swift @@ -216,15 +216,15 @@ extension HomeInteractor { inactiveConfigurator?.activeAction = inActiveCellActionHandler case .low: + let activeTracing = risk?.details.activeTracing ?? .init(interval: 0) riskLevelConfigurator = HomeLowRiskCellConfigurator( numberRiskContacts: state.numberRiskContacts, - numberDays: state.risk?.details.numberOfDaysWithActiveTracing ?? 0, - totalDays: 14, lastUpdateDate: dateLastExposureDetection, isButtonHidden: detectionIsAutomatic, detectionMode: detectionMode, manualExposureDetectionState: riskProvider.manualExposureDetectionState, - detectionInterval: detectionInterval + detectionInterval: detectionInterval, + activeTracing: activeTracing ) case .increased: riskLevelConfigurator = HomeHighRiskCellConfigurator( diff --git a/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController+HowRiskDetectionWorks.swift b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController+HowRiskDetectionWorks.swift new file mode 100644 index 00000000000..485affa4698 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController+HowRiskDetectionWorks.swift @@ -0,0 +1,50 @@ +// +// Corona-Warn-App +// +// SAP SE and all other contributors +// copyright owners license this file to you under the Apache +// License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +import UIKit + +extension UIAlertController { + class func localizedHowRiskDetectionWorksAlertController( + maximumNumberOfDays: Int + ) -> UIAlertController { + let title = NSLocalizedString("How_Risk_Detection_Works_Alert_Title", comment: "") + let message = String( + format: NSLocalizedString( + "How_Risk_Detection_Works_Alert_Message", + comment: "" + ), + maximumNumberOfDays + ) + + let alert = UIAlertController( + title: title, + message: message, + preferredStyle: .alert + ) + + alert.addAction( + UIAlertAction( + title: NSLocalizedString("Alert_ActionOk", comment: ""), + style: .default + ) + ) + + return alert + } +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController.swift index b3016f0986b..01072a88acc 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController.swift @@ -23,7 +23,7 @@ protocol HomeViewControllerDelegate: AnyObject { } // swiftlint:disable:next type_body_length -final class HomeViewController: UIViewController { +final class HomeViewController: UIViewController, RequiresAppDependencies { // MARK: Creating a Home View Controller init?( coder: NSCoder, @@ -99,6 +99,20 @@ final class HomeViewController: UIViewController { updateBackgroundColor() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + guard store.userNeedsToBeInformedAboutHowRiskDetectionWorks else { + return + } + // TODO: Check whether or not we have to display some kind of different alert (eg. the forced update alert). + let alert = UIAlertController.localizedHowRiskDetectionWorksAlertController( + maximumNumberOfDays: TracingStatusHistory.maxStoredDays + ) + present(alert, animated: true) { + self.store.userNeedsToBeInformedAboutHowRiskDetectionWorks = false + } + } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) updateBackgroundColor() @@ -223,7 +237,6 @@ final class HomeViewController: UIViewController { delegate: self ) } -// addToUpdatingSetIfNeeded(vc) exposureDetectionController = vc as? ExposureDetectionViewController present(vc, animated: true) } diff --git a/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift b/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift index b126e2f9727..eca9e91c1ea 100644 --- a/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift +++ b/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift @@ -47,4 +47,5 @@ final class MockTestStore: Store { var allowRiskChangesNotification: Bool = true var allowTestsStatusNotification: Bool = true var hourlyFetchingEnabled: Bool = true + var userNeedsToBeInformedAboutHowRiskDetectionWorks = false } diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift b/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift index 887ba4d9821..a2270f85ca5 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift @@ -143,6 +143,8 @@ enum AccessibilityIdentifiers { static let explanationTextUnknown = "AppStrings.ExposureDetection.explanationTextUnknown" static let explanationTextLow = "AppStrings.ExposureDetection.explanationTextLow" static let explanationTextHigh = "AppStrings.ExposureDetection.explanationTextHigh" + + static let activeTracingSectionText = "AppStrings.ExposureDetection.activeTracingSection" } enum ExposureSubmissionDispatch { diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift index 8907f96d6fb..91f5c9da7d2 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift @@ -430,6 +430,8 @@ enum AppStrings { static let riskCardLowTitle = NSLocalizedString("Home_Risk_Low_Title", comment: "") static let riskCardLowSaveDaysItemTitle = NSLocalizedString("Home_Risk_Low_SaveDays_Item_Title", comment: "") + static let riskCardLowSaveDaysItemTitle_PermanentlyActive = NSLocalizedString("Home_Risk_Low_SaveDays_Item_Title__Permanently_Active", comment: "") + static let riskCardLowButton = NSLocalizedString("Home_Risk_Low_Button", comment: "") // High Card diff --git a/src/xcode/ENA/ENA/Source/Views/ENSetting/TracingHistoryTableViewCell.swift b/src/xcode/ENA/ENA/Source/Views/ENSetting/TracingHistoryTableViewCell.swift index 9ba17176c39..451ba05794d 100644 --- a/src/xcode/ENA/ENA/Source/Views/ENSetting/TracingHistoryTableViewCell.swift +++ b/src/xcode/ENA/ENA/Source/Views/ENSetting/TracingHistoryTableViewCell.swift @@ -19,10 +19,20 @@ import Foundation import UIKit class TracingHistoryTableViewCell: UITableViewCell { - @IBOutlet var circleView: CircularProgressView! - @IBOutlet var historyLabel: UILabel! + @IBOutlet private var circleView: CircularProgressView! + @IBOutlet private var historyLabel: UILabel! + @IBOutlet private var titleLabel: UILabel! + @IBOutlet private var subtitleLabel: UILabel! - func configure(progress: CGFloat, text: String, colorConfigurationTuple: (UIColor, UIColor)) { + func configure( + progress: CGFloat, + title: String, + subtitle: String, + text: String, + colorConfigurationTuple: (UIColor, UIColor) + ) { + titleLabel?.text = title + subtitleLabel?.text = subtitle if circleView.progressBarColor != colorConfigurationTuple.0 { circleView.progressBarColor = colorConfigurationTuple.0 } diff --git a/src/xcode/ENA/ENA/Source/Workers/ActiveTracing.swift b/src/xcode/ENA/ENA/Source/Workers/ActiveTracing.swift index b7524ae1e97..b09ddc73266 100644 --- a/src/xcode/ENA/ENA/Source/Workers/ActiveTracing.swift +++ b/src/xcode/ENA/ENA/Source/Workers/ActiveTracing.swift @@ -18,6 +18,7 @@ // import Foundation +import UIKit private extension TimeInterval { static let SEC_PER_HOUR: TimeInterval = 3600.0 @@ -41,6 +42,27 @@ struct ActiveTracing { } var inDays: Int { - Int((interval / TimeInterval.SEC_PER_DAY).rounded(.toNearestOrAwayFromZero)) + min(Int((interval / TimeInterval.SEC_PER_DAY).rounded(.toNearestOrAwayFromZero)), maximumNumberOfDays) + } +} + +extension ActiveTracing { + // There is a special case for the localized text that should be displayed on the home screen + // when there is a low risk level. + var localizedDuration: String { + switch inDays { + case maximumNumberOfDays: + // We will return the following in case tracing has been active for 14+ days + // and the current risk level is `low`. + // Yields something like: "Risk detection was permanently active" + return NSLocalizedString("Active_Tracing_Interval_Permanently_Active", comment: "") + default: + // Yields something like: "Risk detection was active for 4 out of 14 days" + return String( + format: NSLocalizedString("Active_Tracing_Interval_Partially_Active", comment: ""), + inDays, + maximumNumberOfDays + ) + } } } diff --git a/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift b/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift index cb41d0c45ed..c4f71d9683a 100644 --- a/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift +++ b/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift @@ -22,12 +22,10 @@ import Foundation /// The `SecureStore` class implements the `Store` protocol that defines all required storage attributes. /// It uses an SQLite Database that still needs to be encrypted final class SecureStore: Store { - - private let directoryURL: URL private let kvStore: SQLiteKeyValueStore - init (at directoryURL: URL, key: String) { + init(at directoryURL: URL, key: String) { self.directoryURL = directoryURL self.kvStore = SQLiteKeyValueStore(with: directoryURL, key: key) } @@ -39,7 +37,6 @@ final class SecureStore: Store { func clearAll(key: String?) { kvStore.clearAll(key: key) } - var testResultReceivedTimeStamp: Int64? { get { kvStore["testResultReceivedTimeStamp"] as Int64? } @@ -182,6 +179,11 @@ final class SecureStore: Store { } set { kvStore["previousRiskLevel"] = newValue?.rawValue } } + + var userNeedsToBeInformedAboutHowRiskDetectionWorks: Bool { + get { kvStore["userNeedsToBeInformedAboutHowRiskDetectionWorks"] as Bool? ?? true } + set { kvStore["userNeedsToBeInformedAboutHowRiskDetectionWorks"] = newValue } + } } diff --git a/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift b/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift index 585e5b4d664..a6f07646004 100644 --- a/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift +++ b/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift @@ -87,5 +87,9 @@ protocol Store: AnyObject { var previousRiskLevel: EitherLowOrIncreasedRiskLevel? { get set } + // `true` if the user needs to be informed about how risk detection works. + // We only inform the user once. By default the value of this property is `true`. + var userNeedsToBeInformedAboutHowRiskDetectionWorks: Bool { get set } + func clearAll(key: String?) } diff --git a/src/xcode/ENA/ENA/Source/Workers/__tests__/ActiveTracingTests.swift b/src/xcode/ENA/ENA/Source/Workers/__tests__/ActiveTracingTests.swift index bfe0d7cfbc3..3e674a75f0b 100644 --- a/src/xcode/ENA/ENA/Source/Workers/__tests__/ActiveTracingTests.swift +++ b/src/xcode/ENA/ENA/Source/Workers/__tests__/ActiveTracingTests.swift @@ -21,7 +21,7 @@ import XCTest @testable import ENA final class ActiveTracingTests: XCTestCase { - func testOneHour() { + func testOneHour() { let activeTracing = _activeTracing(interval: 3600) XCTAssertEqual(activeTracing.interval, 3600, accuracy: .high) XCTAssertEqual(activeTracing.inDays, 0) @@ -78,6 +78,31 @@ final class ActiveTracingTests: XCTestCase { 11 ) } + + func testLocalizedLowRiskLevelHomeScreenText() { + XCTAssertEqual( + _activeTracing(interval: 0).localizedDuration, + "Risiko-Ermittlung war für 0 der letzten 14 Tage aktiv" + ) + + // 13 hours = 1 day + XCTAssertEqual( + _activeTracing(interval: 3_600 * 13).localizedDuration, + "Risiko-Ermittlung war für 1 der letzten 14 Tage aktiv" + ) + + // 14 days yields different text + XCTAssertEqual( + _activeTracing(interval: 3_600 * 24 * 14).localizedDuration, + "Risiko-Ermittlung dauerhaft aktiv" + ) + + // 14+ days yields different text + XCTAssertEqual( + _activeTracing(interval: 3_600 * 24 * 15).localizedDuration, + "Risiko-Ermittlung dauerhaft aktiv" + ) + } } private func _activeTracing(interval: TimeInterval) -> ActiveTracing {