From 31da5f832b52e3ccea897316f8b6b349ae44f71e Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 15:33:31 +0100 Subject: [PATCH 01/39] removed dummy test viewcontroller from TabBar --- .../ENA/ENA/Source/RootCoordinator.swift | 29 +------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/RootCoordinator.swift b/src/xcode/ENA/ENA/Source/RootCoordinator.swift index eef346f1541..8e00fe165c7 100644 --- a/src/xcode/ENA/ENA/Source/RootCoordinator.swift +++ b/src/xcode/ENA/ENA/Source/RootCoordinator.swift @@ -76,38 +76,11 @@ class RootCoordinator: RequiresAppDependencies { let tabbarVC = UITabBarController() tabbarVC.tabBar.tintColor = .enaColor(for: .tint) tabbarVC.tabBar.barTintColor = .enaColor(for: .background) - #if DEBUG - let dummyDataDonationViewControllre = DataDonationViewController( - store: self.store, - presentSelectValueList: { [weak self] selectValueViewModel in - self?.presentSelectValueList(selectValueViewModel: selectValueViewModel) - }, - didTapLegal: {} - ) - dummyDataDonationViewControllre.tabBarItem = UITabBarItem(title: "Dummy", image: UIImage(named: "bolt"), selectedImage: UIImage(named: "bolt.fill")) - let navigationController = ENANavigationControllerWithFooter(rootViewController: dummyDataDonationViewControllre) - tabbarVC.setViewControllers([homeCoordinator.rootViewController, diaryCoordinator.viewController, navigationController], animated: false) - #else tabbarVC.setViewControllers([homeCoordinator.rootViewController, diaryCoordinator.viewController], animated: false) - #endif - viewController.embedViewController(childViewController: tabbarVC) - } - // MARK: - Datadonation Test Code - - private func presentSelectValueList(selectValueViewModel: SelectValueViewModel) { - let selectValueViewController = SelectValueTableViewController( - selectValueViewModel, - dissmiss: { [weak self] in - self?.viewController.dismiss(animated: true) - }) - let navigationController = UINavigationController(rootViewController: selectValueViewController) - viewController.present(navigationController, animated: true) + viewController.embedViewController(childViewController: tabbarVC) } - // MARK: - - - func showTestResultFromNotification(with result: TestResult) { homeCoordinator?.showTestResultFromNotification(with: result) } From cd12527bf8644d46516f4de29c707a0910308a63 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 16:29:15 +0100 Subject: [PATCH 02/39] added missing strings to settingsa --- .../Resources/Localization/de.lproj/Localizable.strings | 9 +++++++++ 1 file changed, 9 insertions(+) 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 96c7ebd181b..655d301e674 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings @@ -231,6 +231,7 @@ "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.\nFür Ihre Risiko-Ermittlung wird nur der Zeitraum der letzten %1$u Tage betrachtet.\nÄltere Tage werden automatisch gelöscht, da sie aus Sicht des Infektionsschutzes nicht mehr relevant sind.\n\nWeitere Informationen finden Sie in den FAQ."; /* Settings */ + "Settings_Notification_StatusActive" = "An"; "Settings_Notification_StatusInactive" = "Aus"; @@ -265,6 +266,14 @@ "Settings_NavTitle" = "Einstellungen"; +"Settings_DataDonation_Label" = "Datenspende"; + +"Settings_DataDonation_Description" = "Erlauben Sie die Übermittlung Ihres Nutzerverhaltens."; + +"Settings_DataDonation_StatusActive" = "An"; + +"Settings_DataDonation_StatusInactive" = "Aus"; + /* Noticiation Settings */ "NotificationSettings_On_Title" = "Möchten Sie Mitteilungen zu Ihrem COVID-19-Risikostatus aktivieren?"; From 124e5354f674b15225d4ed152f08b0949ebb3c0f Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 16:33:54 +0100 Subject: [PATCH 03/39] added another missing string for settings --- .../ENA/ENA/Resources/Localization/de.lproj/Localizable.strings | 2 ++ 1 file changed, 2 insertions(+) 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 655d301e674..86964a49a1a 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.strings @@ -1755,6 +1755,8 @@ sein."; "DataDonation_Description" = "Sie können uns helfen, die Corona-Warn-App zu verbessern. Teilen Sie Daten über Ihre App-Nutzung mit dem RKI. Sie helfen damit dem RKI bei der Bewertung der Wirksamkeit der App. Ihre Daten ermöglichen außerdem, die Funktionen und Nutzerfreundlichkeit der App zu verbessern."; +"DataDonation_SubHead_Settings" = "EINSTELLUNG"; + "DataDonation_SubHead_YourState" = "Ihr Bundesland (optional)"; "DataDonation_SubHead_AgeGroup" = "Ihre Altersgruppe (optional)"; From 8233a756ec86f9dbc0473fee4e532505019d8799 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 16:44:20 +0100 Subject: [PATCH 04/39] added new section to app settings --- .../Contents.json | 12 ++++++++++++ .../Icons_Settings_Datenspende.pdf | Bin 0 -> 3771 bytes .../Settings/SettingsViewController.swift | 9 ++++++++- .../Settings/Settings/SettingsViewModel.swift | 9 +++++++++ .../View Helpers/AccessibilityIdentifiers.swift | 1 + .../ENA/ENA/Source/View Helpers/AppStrings.swift | 7 +++++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Contents.json create mode 100644 src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Icons_Settings_Datenspende.pdf diff --git a/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Contents.json b/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Contents.json new file mode 100644 index 00000000000..60cac38a707 --- /dev/null +++ b/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Icons_Settings_Datenspende.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Icons_Settings_Datenspende.pdf b/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Icons_Settings_Datenspende.pdf new file mode 100644 index 0000000000000000000000000000000000000000..739b7afd29df776aa624d1a0882237d94ad96ed8 GIT binary patch literal 3771 zcmbtXO>g5i5WVYH@UlSm5Lx^ZB_If}aW+NT-ENws=wZ7DMV1p4w&co6vD;tYHxxzE zPIfO9U_*W+XWqOSlH)fwmsh7eHA%u*#`=f962{KX*y2OeJ&sRI0K8@A=gEE?nrfTy zROCjR0&tdcp)?ol6mOZxG-o{JN@jVEu`(}>Fl@z>r0G^}HQvZWLRKeNn$xfar3XL5 zkaP3J4=X<$(bE89dW+@t<#pGNY;iO6^<6Wvb=$3mX5T*#b;BN-$F@sAdDYgV`(?3u zTkR5BeD`fXHrwlN-6!Pc77M`r8#}pbAGZ~>dJBEn;?uBdhPHb=#_yhYyG^rgx{+nc z`8iuPYnc65?S8Gc4O_fBy*OP4@c!Gbfx8}gPVDIu@slfWohTT5n4&nc^38aFo2+yz;Yu3ZP$2}cKwe0&7Y&(k>peE zq|AMGkn*T_?w%h;ifus=N>U7(Ey0trvbXiM%or7%P2M#AzC(nhDG6_-SdJK^PxHdZe4|2ZEeu_nm3k# zttn%qEV;81UvWlRqYTgnpJ&t74zt}cP`ZipF|fF7{%Pyx_NNQByi1~A^*;Fn~z!8xn9iJ$lKWnXt;7^`#1r7GAqc}h&0amDkD;Uwcq>x|$S z)W&ekHK{0bSs0pENTrMfWR%K989{YYrdlfwYGK|c;Y3L&#Um7$C{&&oggGY%m}67Z zYB#e?iMTP$n)IN-S;`FyUc#HF6QCO5IpP7_0CWKc(92L_fprlfjtNava23 z7uqV}l|4Y`s1d&?O`&6TcnT!LH4t=!5;8TVE=sGJ%L1fOsgSx*Hir%crg=g4Nu+L! z1$8}YKqI39uqNGdgX<_$s${`SkqT}M3Lwz&5IB0~9)vv~q6dQ#!G)L1Q?d45=t%mC z6#AGPcW6|&G3eBlX{J?P#F9y9!-b6XsuP_`kri27q8orF&y2E8oU(bEDO8G0t8)=U zURMvo1}}vqSv{6xuLsG2xm<~}7FHV_w!U zQ(}iua;RMWRF$d>2bN~Ri%N4NC3XiON5?}bFVEbAu;)YcARwntaN!|O1@=4`>T)Vq zcVwSp4`+go)Gcx`gDTC8&Y`JD6>3Ew4gPHRSqu>T_>cn%;w3sujr$^64opeG>74dn zBFxi)%`j7@Xi-Y8SY#0uCyT7eNys@{9*YahgBwIRhvUHzw09CiPMjKBe4TX3Z~yO7 zytq#|4ru$l(xSXF7OuzpZL+{k@2}nab@G{={0Uoc*%x;IbMpQk^yv0K>htKzpZWlS z$-X_{X#Au8;9b}CBO0*7mgc5H^E$OEADdNMeXq*`bICRSGSI;+^CH(`?%~jSPfh!t zQU5acLQ8ZnXkPb>+LRf*si>i4=pZI6>Sin!+L>S46?Ka?h+FS!*+0|rxe2qKD}}HJ z659%YTSAMvtj227Kf1Mc)vH9l4(Rd`r%a|i(l^VsmYM-~5AmXhq0^ZjY6K?Ll_lEw1Bhp6a1J4v;qW_xxHzUN#S2?fnqX@js&>=hp9*@= z>q{izWZ!R_x9p@{p%O{I#ckgs4fZdm{e9Q|+mK?&!G5fU(P}7h4kT~hy#I9dAI!-@ A{r~^~ literal 0 HcmV?d00001 diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift index 04ea34aa81f..773a8895342 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift @@ -85,6 +85,8 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating return AppStrings.Settings.resetDescription case .backgroundAppRefresh: return AppStrings.Settings.backgroundAppRefreshDescription + case .datadonation: + return AppStrings.Settings.Datadonation.description } } @@ -96,7 +98,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating switch section { case .reset: footerView.textLabel?.textAlignment = .center - case .tracing, .notifications, .backgroundAppRefresh: + case .tracing, .notifications, .backgroundAppRefresh, .datadonation: footerView.textLabel?.textAlignment = .left } } @@ -113,6 +115,8 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating cell = configureMainCell(indexPath: indexPath, model: settingsViewModel.notifications) case .backgroundAppRefresh: cell = configureMainCell(indexPath: indexPath, model: settingsViewModel.backgroundAppRefresh) + case .datadonation: + cell = configureMainCell(indexPath: indexPath, model: settingsViewModel.datadonation) case .reset: guard let labelCell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.reset.rawValue, for: indexPath) as? SettingsLabelCell else { fatalError("No cell for reuse identifier.") @@ -140,6 +144,8 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating onNotificationsCellTap() case .reset: onResetCellTap() + case .datadonation: + Log.debug("NYD") case .backgroundAppRefresh: onBackgroundAppRefreshCellTap() } @@ -168,6 +174,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating case tracing case notifications case backgroundAppRefresh + case datadonation case reset } diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewModel.swift index 2d1e8ada3a0..1205f9290e2 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewModel.swift @@ -10,6 +10,7 @@ final class SettingsViewModel { var notifications: CellModel = .notifications var backgroundAppRefresh: CellModel = .backgroundAppRefresh var reset: String = AppStrings.Settings.resetLabel + var datadonation:CellModel = .dataDonation } extension SettingsViewModel { @@ -48,6 +49,14 @@ extension SettingsViewModel.CellModel { accessibilityIdentifier: AccessibilityIdentifiers.Settings.backgroundAppRefreshLabel ) + static let dataDonation = SettingsViewModel.CellModel( + icon: "Icons_Settings_Datenspende", + description: AppStrings.Settings.Datadonation.label, + stateActive: AppStrings.Settings.Datadonation.statusActive, + stateInactive: AppStrings.Settings.Datadonation.statusInactive, + accessibilityIdentifier: AccessibilityIdentifiers.Settings.dataDonation + ) + mutating func setState(state newState: Bool) { state = newState ? stateActive : stateInactive } diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift b/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift index abf3e4156d8..3839ea60778 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AccessibilityIdentifiers.swift @@ -104,6 +104,7 @@ enum AccessibilityIdentifiers { static let backgroundAppRefreshLabel = "AppStrings.Settings.backgroundAppRefreshLabel" static let resetLabel = "AppStrings.Settings.resetLabel" static let backgroundAppRefreshImageDescription = "AppStrings.Settings.backgroundAppRefreshImageDescription" + static let dataDonation = "AppStrings.Settings.Datadonation.description" } enum AppInformation { diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift index 907fb38002b..fe36c80271e 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift @@ -439,6 +439,13 @@ enum AppStrings { static let navigationBarTitle = NSLocalizedString("Settings_NavTitle", comment: "") + enum Datadonation { + static let label = NSLocalizedString("Settings_DataDonation_Label", comment: "") + static let description = NSLocalizedString("Settings_DataDonation_Description", comment: "") + static let statusActive = NSLocalizedString("Settings_DataDonation_StatusActive", comment: "") + static let statusInactive = NSLocalizedString("Settings_DataDonation_StatusInactive", comment: "") + } + } enum NotificationSettings { From 3f728f1da1b9821fa850022bd8be8bcba17aa43f Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 16:47:46 +0100 Subject: [PATCH 05/39] added show datadonation screen to settings --- .../Settings/SettingsViewController.swift | 7 +++-- .../Scenes/Settings/SettingsCoordinator.swift | 27 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift index 773a8895342..f41b564a5f9 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift @@ -17,7 +17,8 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating onTracingCellTap: @escaping () -> Void, onNotificationsCellTap: @escaping () -> Void, onBackgroundAppRefreshCellTap: @escaping () -> Void, - onResetCellTap: @escaping () -> Void + onResetCellTap: @escaping () -> Void, + onDataDonationCellTap: @escaping () -> Void ) { self.store = store self.enState = initialEnState @@ -27,6 +28,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating self.onNotificationsCellTap = onNotificationsCellTap self.onBackgroundAppRefreshCellTap = onBackgroundAppRefreshCellTap self.onResetCellTap = onResetCellTap + self.onDataDonationCellTap = onDataDonationCellTap super.init(style: .grouped) } @@ -145,7 +147,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating case .reset: onResetCellTap() case .datadonation: - Log.debug("NYD") + onDataDonationCellTap() case .backgroundAppRefresh: onBackgroundAppRefreshCellTap() } @@ -195,6 +197,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating private let onNotificationsCellTap: () -> Void private let onBackgroundAppRefreshCellTap: () -> Void private let onResetCellTap: () -> Void + private let onDataDonationCellTap: () -> Void @objc private func updateUI() { diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift index 864b6025ce0..99eeb5d3db7 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift @@ -67,7 +67,11 @@ class SettingsCoordinator: ENStateHandlerUpdating { }, onResetCellTap: { [weak self] in self?.showResetScreen() + }, + onDataDonationCellTap: { [weak self] in + self?.showDataDonationScreen() } + ) }() @@ -111,5 +115,26 @@ class SettingsCoordinator: ENStateHandlerUpdating { parentNavigationController?.pushViewController(viewController, animated: true) } - + + private func showDataDonationScreen() { + let dummyDataDonationViewControllre = DataDonationViewController( + store: self.store, + presentSelectValueList: { [weak self] selectValueViewModel in + self?.presentSelectValueList(selectValueViewModel: selectValueViewModel) + }, + didTapLegal: {} + ) + parentNavigationController?.pushViewController(dummyDataDonationViewControllre, animated: true) + } + + private func presentSelectValueList(selectValueViewModel: SelectValueViewModel) { + let selectValueViewController = SelectValueTableViewController( + selectValueViewModel, + dissmiss: { [weak self] in + self?.parentNavigationController?.dismiss(animated: true) + }) + let navigationController = UINavigationController(rootViewController: selectValueViewController) + parentNavigationController?.present(navigationController, animated: true) + } + } From d9e4f38483c76d0e09ac3f713a54e5f11394f2a2 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 16:59:48 +0100 Subject: [PATCH 06/39] added a protocol for settings to use a different dataDonationViewModel --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 16 +++--- .../DataDonationViewController.swift | 4 +- ...ift => DefaultDataDonationViewModel.swift} | 49 +++++++++++-------- ...> DefaultDataDonationViewModelTests.swift} | 12 ++--- 4 files changed, 45 insertions(+), 36 deletions(-) rename src/xcode/ENA/ENA/Source/Scenes/Datadonation/{DataDonationViewModel.swift => DefaultDataDonationViewModel.swift} (93%) rename src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/{DataDonationViewModelTests.swift => DefaultDataDonationViewModelTests.swift} (87%) diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index 3be27a56949..6175b0f2b18 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -609,7 +609,7 @@ B1FF6B6E2497D0B50041CF02 /* CWASQLite.h in Headers */ = {isa = PBXBuildFile; fileRef = B1FF6B6C2497D0B50041CF02 /* CWASQLite.h */; settings = {ATTRIBUTES = (Public, ); }; }; B1FF6B772497D2330041CF02 /* sqlite3.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DFCC2712484DC8400E2811D /* sqlite3.h */; settings = {ATTRIBUTES = (Public, ); }; }; BA0073BE25D18A5B0036DFDD /* DataDonationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA0073BD25D18A5B0036DFDD /* DataDonationViewController.swift */; }; - BA0073EA25D196900036DFDD /* DataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA0073E925D196900036DFDD /* DataDonationViewModel.swift */; }; + BA0073EA25D196900036DFDD /* DefaultDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */; }; BA00740025D1A1810036DFDD /* District.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA0073FF25D1A1810036DFDD /* District.swift */; }; BA056F1B259B89B50022B0A4 /* RiskLegendDotBodyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA056F19259B89B50022B0A4 /* RiskLegendDotBodyCell.swift */; }; BA07735C25C2FCB800EAF6B8 /* PPACService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA07735B25C2FCB800EAF6B8 /* PPACService.swift */; }; @@ -649,7 +649,7 @@ BA7D177925D547D4006B9EBF /* DataDonationModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D177825D547D4006B9EBF /* DataDonationModelTests.swift */; }; BA7D178125D549B3006B9EBF /* testData.json in Resources */ = {isa = PBXBuildFile; fileRef = BA7D178025D549AA006B9EBF /* testData.json */; }; BA7D178925D5590C006B9EBF /* testDataInvalid.json in Resources */ = {isa = PBXBuildFile; fileRef = BA7D178825D558FD006B9EBF /* testDataInvalid.json */; }; - BA7D178E25D55EB1006B9EBF /* DataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D178D25D55EB1006B9EBF /* DataDonationViewModelTests.swift */; }; + BA7D178E25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */; }; BA7EABAD25C973FE001AA5FE /* DMKeyValueCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */; }; BA811B4D25D422B600C9BC98 /* DataDonationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */; }; BA8824D725D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json in Resources */ = {isa = PBXBuildFile; fileRef = BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */; }; @@ -1421,7 +1421,7 @@ B1FF6B6C2497D0B50041CF02 /* CWASQLite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CWASQLite.h; sourceTree = ""; }; B1FF6B6D2497D0B50041CF02 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BA0073BD25D18A5B0036DFDD /* DataDonationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationViewController.swift; sourceTree = ""; }; - BA0073E925D196900036DFDD /* DataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationViewModel.swift; sourceTree = ""; }; + BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultDataDonationViewModel.swift; sourceTree = ""; }; BA0073FF25D1A1810036DFDD /* District.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = District.swift; sourceTree = ""; }; BA056F19259B89B50022B0A4 /* RiskLegendDotBodyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiskLegendDotBodyCell.swift; sourceTree = ""; }; BA07735B25C2FCB800EAF6B8 /* PPACService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACService.swift; sourceTree = ""; }; @@ -1462,7 +1462,7 @@ BA7D177825D547D4006B9EBF /* DataDonationModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationModelTests.swift; sourceTree = ""; }; BA7D178025D549AA006B9EBF /* testData.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = testData.json; sourceTree = ""; }; BA7D178825D558FD006B9EBF /* testDataInvalid.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = testDataInvalid.json; sourceTree = ""; }; - BA7D178D25D55EB1006B9EBF /* DataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationViewModelTests.swift; sourceTree = ""; }; + BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultDataDonationViewModelTests.swift; sourceTree = ""; }; BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueCellViewModel.swift; sourceTree = ""; }; BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationModel.swift; sourceTree = ""; }; BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "ppdd-ppa-administrative-unit-set-ua-approved.json"; sourceTree = ""; }; @@ -3811,7 +3811,7 @@ 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */, BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */, BA0073BD25D18A5B0036DFDD /* DataDonationViewController.swift */, - BA0073E925D196900036DFDD /* DataDonationViewModel.swift */, + BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, BA0073FF25D1A1810036DFDD /* District.swift */, ); path = Datadonation; @@ -3984,7 +3984,7 @@ BA7D178025D549AA006B9EBF /* testData.json */, BA7D178825D558FD006B9EBF /* testDataInvalid.json */, BA7D177825D547D4006B9EBF /* DataDonationModelTests.swift */, - BA7D178D25D55EB1006B9EBF /* DataDonationViewModelTests.swift */, + BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */, ); path = __tests__; sourceTree = ""; @@ -4752,7 +4752,7 @@ 51D420B724583B7200AD70CA /* NSObject+Identifier.swift in Sources */, BA69A7F825CD87C200023265 /* SelectValueCellViewModel.swift in Sources */, CDCE11D6247D644100F30825 /* NotificationSettingsViewModel.swift in Sources */, - BA0073EA25D196900036DFDD /* DataDonationViewModel.swift in Sources */, + BA0073EA25D196900036DFDD /* DefaultDataDonationViewModel.swift in Sources */, BA6C8AAE254D6476008344F5 /* ENARange.swift in Sources */, 50BD2E6424FE232E00932566 /* AppInformationImprintViewModel.swift in Sources */, 71330E4724810A0C00EB10F6 /* DynamicTableViewFooter.swift in Sources */, @@ -5162,7 +5162,7 @@ B15382E7248290BB0010F007 /* AppleFilesWriterTests.swift in Sources */, AB1FCBD42521FC47005930BA /* ServerEnvironmentTests.swift in Sources */, 0123D5992501385200A91838 /* ExposureSubmissionErrorTests.swift in Sources */, - BA7D178E25D55EB1006B9EBF /* DataDonationViewModelTests.swift in Sources */, + BA7D178E25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift in Sources */, 50C51CB625CDEA4300D4C33A /* HTTPClient+SubmitAnalyticsDataTests.swift in Sources */, 01A23685251A23740043D9F8 /* ExposureSubmissionQRInfoModelTests.swift in Sources */, 2FD881CC2490F65C00BEC8FC /* ExposureSubmissionHotlineViewControllerTest.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift index b83525365bd..8be6aceee1c 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift @@ -24,7 +24,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie jsonFileURL: url ) - self.viewModel = DataDonationViewModel( + self.viewModel = DefaultDataDonationViewModel( store: store, presentSelectValueList: presentSelectValueList, datadonationModel: datadonationModel @@ -93,7 +93,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie private let presentSelectValueList: (SelectValueViewModel) -> Void private let didTapLegal: () -> Void - private let viewModel: DataDonationViewModel + private let viewModel: DefaultDataDonationViewModel private var subscriptions: [AnyCancellable] = [] private func setupTableView() { diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift similarity index 93% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewModel.swift rename to src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift index cdf624a277c..9bc2c5e8db5 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift @@ -6,7 +6,18 @@ import Foundation import UIKit import OpenCombine -final class DataDonationViewModel { +protocol DataDonationViewModelProtocol { + + var reloadTableView: Bool { get } + var friendlyFederalStateName: String { get } + var friendlyRegionName: String { get } + var friendlyAgeName: String { get } + var dynamicTableViewModel: DynamicTableViewModel { get } + + func save(consentGiven: Bool) +} + +final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { // MARK: - Init @@ -20,17 +31,21 @@ final class DataDonationViewModel { self.dataDonationModel = datadonationModel } - // MARK: - Public + // MARK: - DataDonationViewModelProtocol - func save(consentGiven: Bool) { - dataDonationModel.isConsentGiven = consentGiven - Log.debug("DataDonation consent value set to '\(consentGiven)'") - dataDonationModel.save() + @OpenCombine.Published private (set) var reloadTableView: Bool + + var friendlyFederalStateName: String { + return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState } - // MARK: - Internal + var friendlyRegionName: String { + return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion + } - @OpenCombine.Published private (set) var reloadTableView: Bool + var friendlyAgeName: String { + return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup + } var dynamicTableViewModel: DynamicTableViewModel { /// create the top section with the illustration and title text @@ -124,6 +139,12 @@ final class DataDonationViewModel { return dynamicTableViewModel } + func save(consentGiven: Bool) { + dataDonationModel.isConsentGiven = consentGiven + Log.debug("DataDonation consent value set to '\(consentGiven)'") + dataDonationModel.save() + } + // MARK: - Private private let presentSelectValueList: (SelectValueViewModel) -> Void @@ -131,18 +152,6 @@ final class DataDonationViewModel { private var dataDonationModel: DataDonationModel private var subscriptions: [AnyCancellable] = [] - private var friendlyFederalStateName: String { - return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState - } - - private var friendlyRegionName: String { - return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion - } - - private var friendlyAgeName: String { - return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup - } - private func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DefaultDataDonationViewModelTests.swift similarity index 87% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DataDonationViewModelTests.swift rename to src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DefaultDataDonationViewModelTests.swift index 26c398e652b..97b72efbb2d 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DataDonationViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DefaultDataDonationViewModelTests.swift @@ -5,7 +5,7 @@ import XCTest @testable import ENA -class DataDonationViewModelTests: XCTestCase { +class DefaultDataDonationViewModelTests: XCTestCase { /// test if the view model will format texts correct func testGIVEN_ViewModelWithStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { @@ -17,7 +17,7 @@ class DataDonationViewModelTests: XCTestCase { let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - let viewModel = DataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN let friendlyFederalStateName = viewModel.friendlyFederalStateName @@ -38,7 +38,7 @@ class DataDonationViewModelTests: XCTestCase { let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - let viewModel = DataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN let friendlyFederalStateName = viewModel.friendlyFederalStateName @@ -63,7 +63,7 @@ class DataDonationViewModelTests: XCTestCase { model.federalStateName = "Hessen" model.age = AgeGroup.ageBelow29.text - let viewModel = DataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN viewModel.save(consentGiven: true) @@ -88,7 +88,7 @@ class DataDonationViewModelTests: XCTestCase { model.federalStateName = "Hessen" model.age = AgeGroup.ageBelow29.text - let viewModel = DataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN viewModel.save(consentGiven: true) @@ -113,7 +113,7 @@ class DataDonationViewModelTests: XCTestCase { model.federalStateName = "Hessen" model.age = AgeGroup.ageBelow29.text - let viewModel = DataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN viewModel.save(consentGiven: false) From 4616bdbac33fa43afb095c635411d972c0c37e77 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 17:30:15 +0100 Subject: [PATCH 07/39] added @published property to DataDonationViewModelProtocol --- .../DataDonationViewController.swift | 25 ++++--------------- .../DefaultDataDonationViewModel.swift | 8 +++++- .../DeltaOnboardingDataDonation.swift | 17 ++++++++++--- .../Scenes/Settings/SettingsCoordinator.swift | 16 ++++++++++-- 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift index 8be6aceee1c..899f517adda 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift @@ -9,27 +9,12 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Init init( - store: Store, - presentSelectValueList: @escaping (SelectValueViewModel) -> Void, + viewModel: DataDonationViewModelProtocol, didTapLegal: @escaping () -> Void ) { - self.presentSelectValueList = presentSelectValueList + self.viewModel = viewModel self.didTapLegal = didTapLegal - guard let url = Bundle.main.url(forResource: "ppdd-ppa-administrative-unit-set-ua-approved", withExtension: "json") else { - preconditionFailure("missing json file") - } - let datadonationModel = DataDonationModel( - store: store, - jsonFileURL: url - ) - - self.viewModel = DefaultDataDonationViewModel( - store: store, - presentSelectValueList: presentSelectValueList, - datadonationModel: datadonationModel - ) - super.init(nibName: nil, bundle: nil) } @@ -90,10 +75,10 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie var finished: (() -> Void)? // MARK: - Private - private let presentSelectValueList: (SelectValueViewModel) -> Void + private let didTapLegal: () -> Void - private let viewModel: DefaultDataDonationViewModel + private let viewModel: DataDonationViewModelProtocol private var subscriptions: [AnyCancellable] = [] private func setupTableView() { @@ -112,7 +97,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie dynamicTableViewModel = viewModel.dynamicTableViewModel - viewModel.$reloadTableView + viewModel.reloadTableViewPublisher .receive(on: DispatchQueue.OCombine(.main)) .sink { [weak self] _ in guard let self = self else { return } diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift index 9bc2c5e8db5..d43703a226b 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift @@ -8,7 +8,11 @@ import OpenCombine protocol DataDonationViewModelProtocol { + /// use these 3 to definde @published in a prorocol var reloadTableView: Bool { get } + var reloadTableViewPublished: OpenCombine.Published { get } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } + var friendlyFederalStateName: String { get } var friendlyRegionName: String { get } var friendlyAgeName: String { get } @@ -33,7 +37,9 @@ final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { // MARK: - DataDonationViewModelProtocol - @OpenCombine.Published private (set) var reloadTableView: Bool + @OpenCombine.Published var reloadTableView: Bool + var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } var friendlyFederalStateName: String { return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState diff --git a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift index 654f8fcf363..4dc6d5a75f2 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift @@ -14,10 +14,13 @@ class DeltaOnboardingDataDonation: DeltaOnboarding { } func makeViewController() -> DeltaOnboardingViewControllerProtocol { - + guard let url = Bundle.main.url(forResource: "ppdd-ppa-administrative-unit-set-ua-approved", withExtension: "json") else { + preconditionFailure("missing json file") + } + weak var navigationController: DeltaOnboardingNavigationController? - - let dataDonationViewController = DataDonationViewController( + + let viewModel = DefaultDataDonationViewModel( store: store, presentSelectValueList: { selectValueViewModel in let selectValueViewController = SelectValueTableViewController( @@ -28,6 +31,14 @@ class DeltaOnboardingDataDonation: DeltaOnboarding { let selectValueNavigationController = UINavigationController(rootViewController: selectValueViewController) navigationController?.present(selectValueNavigationController, animated: true) }, + datadonationModel: DataDonationModel( + store: store, + jsonFileURL: url + ) + ) + + let dataDonationViewController = DataDonationViewController( + viewModel: viewModel, didTapLegal: {} ) diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift index 99eeb5d3db7..db62e008f74 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift @@ -117,11 +117,23 @@ class SettingsCoordinator: ENStateHandlerUpdating { } private func showDataDonationScreen() { - let dummyDataDonationViewControllre = DataDonationViewController( - store: self.store, + guard let jsonFileURL = Bundle.main.url(forResource: "ppdd-ppa-administrative-unit-set-ua-approved", withExtension: "json") else { + preconditionFailure("missing json file") + } + + let viewModel = DefaultDataDonationViewModel( + store: store, presentSelectValueList: { [weak self] selectValueViewModel in self?.presentSelectValueList(selectValueViewModel: selectValueViewModel) }, + datadonationModel: DataDonationModel( + store: store, + jsonFileURL: jsonFileURL + ) + ) + + let dummyDataDonationViewControllre = DataDonationViewController( + viewModel: viewModel, didTapLegal: {} ) parentNavigationController?.pushViewController(dummyDataDonationViewControllre, animated: true) From 322ece6911b63fa0d36315af08796355dbab7be4 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 17:38:41 +0100 Subject: [PATCH 08/39] moved files to cleanup, updated settings Icon --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 52 ++++- .../Icons_Settings_Datenspende.pdf | Bin 3771 -> 4265 bytes .../DataDonationModel.swift | 0 .../DataDonationModel}/District.swift | 0 .../DataDonationViewController.swift | 0 .../DataDonationViewModelProtocol.swift | 21 ++ .../DefaultDataDonationViewModel.swift | 43 ---- ...ynamicCell+LegalExtendedDataDonation.swift | 33 +++ .../SettingsDataDonationViewModel.swift | 203 ++++++++++++++++++ .../__tests__/DataDonationModelTests.swift | 0 .../DefaultDataDonationViewModelTests.swift | 0 .../__tests__/testData.json | 0 .../__tests__/testDataInvalid.json | 0 .../DataDonationDetailsViewController.swift | 0 .../DataDonationDetailsViewModel.swift | 0 15 files changed, 301 insertions(+), 51 deletions(-) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation/DataDonationModel}/DataDonationModel.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation/DataDonationModel}/District.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation}/DataDonationViewController.swift (100%) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation/DataDonationViewModels}/DefaultDataDonationViewModel.swift (80%) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation}/__tests__/DataDonationModelTests.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation}/__tests__/DefaultDataDonationViewModelTests.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation}/__tests__/testData.json (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonation}/__tests__/testDataInvalid.json (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonationDetails}/DataDonationDetailsViewController.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/{Datadonation => DataDonationDetails}/DataDonationDetailsViewModel.swift (100%) diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index e8541fc500f..33823c6ffcc 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -654,6 +654,9 @@ BA7D178125D549B3006B9EBF /* testData.json in Resources */ = {isa = PBXBuildFile; fileRef = BA7D178025D549AA006B9EBF /* testData.json */; }; BA7D178925D5590C006B9EBF /* testDataInvalid.json in Resources */ = {isa = PBXBuildFile; fileRef = BA7D178825D558FD006B9EBF /* testDataInvalid.json */; }; BA7D178E25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */; }; + BA7D17B725D59373006B9EBF /* SettingsDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */; }; + BA7D17BF25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */; }; + BA7D17C725D593FF006B9EBF /* DataDonationViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */; }; BA7EABAD25C973FE001AA5FE /* DMKeyValueCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */; }; BA811B4D25D422B600C9BC98 /* DataDonationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */; }; BA8824D725D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json in Resources */ = {isa = PBXBuildFile; fileRef = BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */; }; @@ -1471,6 +1474,9 @@ BA7D178025D549AA006B9EBF /* testData.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = testData.json; sourceTree = ""; }; BA7D178825D558FD006B9EBF /* testDataInvalid.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = testDataInvalid.json; sourceTree = ""; }; BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultDataDonationViewModelTests.swift; sourceTree = ""; }; + BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDataDonationViewModel.swift; sourceTree = ""; }; + BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DynamicCell+LegalExtendedDataDonation.swift"; sourceTree = ""; }; + BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationViewModelProtocol.swift; sourceTree = ""; }; BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueCellViewModel.swift; sourceTree = ""; }; BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationModel.swift; sourceTree = ""; }; BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "ppdd-ppa-administrative-unit-set-ua-approved.json"; sourceTree = ""; }; @@ -2877,7 +2883,8 @@ 85D759712457059A008175F0 /* Scenes */ = { isa = PBXGroup; children = ( - BA0073BB25D189E50036DFDD /* Datadonation */, + BA7D17D025D5947B006B9EBF /* DataDonationDetails */, + BA0073BB25D189E50036DFDD /* DataDonation */, 71176E30248957B1004B0C9F /* App */, EE85998B2462EFD4002E7AE2 /* AppInformation */, 0190982A257E5A9D0065D050 /* ContactDiary */, @@ -3823,18 +3830,15 @@ path = CWASQLite; sourceTree = ""; }; - BA0073BB25D189E50036DFDD /* Datadonation */ = { + BA0073BB25D189E50036DFDD /* DataDonation */ = { isa = PBXGroup; children = ( BA7D177725D547BE006B9EBF /* __tests__ */, - 506A2F1F25D2A08900B7DDFB /* DataDonationDetailsViewController.swift */, - 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */, - BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */, + BA7D17CC25D59465006B9EBF /* DataDonationModel */, BA0073BD25D18A5B0036DFDD /* DataDonationViewController.swift */, - BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, - BA0073FF25D1A1810036DFDD /* District.swift */, + BA7D17CB25D59440006B9EBF /* DataDonationViewModels */, ); - path = Datadonation; + path = DataDonation; sourceTree = ""; }; BA07735A25C2FC5E00EAF6B8 /* PPAccessControl */ = { @@ -4009,6 +4013,35 @@ path = __tests__; sourceTree = ""; }; + BA7D17CB25D59440006B9EBF /* DataDonationViewModels */ = { + isa = PBXGroup; + children = ( + BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */, + BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */, + BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, + BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */, + ); + path = DataDonationViewModels; + sourceTree = ""; + }; + BA7D17CC25D59465006B9EBF /* DataDonationModel */ = { + isa = PBXGroup; + children = ( + BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */, + BA0073FF25D1A1810036DFDD /* District.swift */, + ); + path = DataDonationModel; + sourceTree = ""; + }; + BA7D17D025D5947B006B9EBF /* DataDonationDetails */ = { + isa = PBXGroup; + children = ( + 506A2F1F25D2A08900B7DDFB /* DataDonationDetailsViewController.swift */, + 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */, + ); + path = DataDonationDetails; + sourceTree = ""; + }; BA9BCF7525B09B3A00DD7974 /* __tests__ */ = { isa = PBXGroup; children = ( @@ -4716,6 +4749,7 @@ ABDA2792251CE308006BAE84 /* DMServerEnvironmentViewController.swift in Sources */, 85E33444247EB357006E74EC /* CircularProgressView.swift in Sources */, AB1886D1252DE51E00D39BBE /* Bundle+Identifier.swift in Sources */, + BA7D17B725D59373006B9EBF /* SettingsDataDonationViewModel.swift in Sources */, 71FD8862246EB27F00E804D0 /* ExposureDetectionViewController.swift in Sources */, 013C413D255463A400826C9F /* DMDebugRiskCalculationViewController.swift in Sources */, BAB6C7EF25C4626100E042FB /* TimestampedToken.swift in Sources */, @@ -4767,6 +4801,7 @@ AB1011592507C15000D392A2 /* TracingStatusHistory.swift in Sources */, 017AD16525A4559300FA2B3F /* UITableView+Dequeue.swift in Sources */, 71FE1C71247AA7B700851FEB /* DynamicTableViewHeaderImageView.swift in Sources */, + BA7D17BF25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift in Sources */, 01D69491250272CE00B45BEA /* DatePickerDayViewModel.swift in Sources */, B16457BB24DC3309002879EB /* DMLogsViewController.swift in Sources */, 01B7232F24FE4F080064C0EB /* OptionGroupViewModel.swift in Sources */, @@ -4854,6 +4889,7 @@ AB2F094A25D1687300C16309 /* SurveyURLProvider.swift in Sources */, 013DC102245DAC4E00EE58B0 /* Store.swift in Sources */, 5270E9B8256D20A900B08606 /* NSTextAttachment+ImageHeight.swift in Sources */, + BA7D17C725D593FF006B9EBF /* DataDonationViewModelProtocol.swift in Sources */, B1FE13EF24891D0C00D012E5 /* RiskProvidingConfiguration.swift in Sources */, 014086BD2589033A00E9E5B2 /* DiaryEditEntriesCellModel.swift in Sources */, B1F82DF224718C7300E2E56A /* DMBackendConfigurationViewController.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Icons_Settings_Datenspende.pdf b/src/xcode/ENA/ENA/Resources/Assets/Assets.xcassets/Common/Icons_Settings_Datenspende.imageset/Icons_Settings_Datenspende.pdf index 739b7afd29df776aa624d1a0882237d94ad96ed8..b5d0486ba7dbfd78547f8b520e8448aeac17d490 100644 GIT binary patch delta 614 zcmZvZu}cFn6vmOeDyGGuorO45w`=k)mrI~@t8Nw)9K|Du4%MYMxD~|BMabgl>Q?CJ zKj+JNNsi(pa4+A>`z7DIpX2Y7O)s4g>S8i~sV}bUs=lYwDeidlF%@MQFc)+-!$qj= zrHg%6e^}Ya{;B;;himghSXMBuCCBrMMMU*5LyHct2uB2pP?~bkxHApfZ&ll&vE*yNK delta 196 zcmZ3fxLbAuE6ZdP7XQgkY^q|qMtX*ZW@eU_3MP8SW@bi)h6>5KT$A~jr8m!Dd%`A! zDL=W7w}sijz+kc{Uzo6=xt_71sfn?Hf+0x1g_)_*<~qJ6Mn4ln1)v%O1BE;;Fl}IL kU}=snWN2i7E@WhBiY{bqZaCRbAc)h%*oaG2)z#k(06)SilK=n! diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationModel.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/District.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/District.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationViewController.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift new file mode 100644 index 00000000000..35756f78227 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift @@ -0,0 +1,21 @@ +//// +// 🦠 Corona-Warn-App +// + +import Foundation +import OpenCombine + +protocol DataDonationViewModelProtocol { + + /// use these 3 to definde @published in a prorocol + var reloadTableView: Bool { get } + var reloadTableViewPublished: OpenCombine.Published { get } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } + + var friendlyFederalStateName: String { get } + var friendlyRegionName: String { get } + var friendlyAgeName: String { get } + var dynamicTableViewModel: DynamicTableViewModel { get } + + func save(consentGiven: Bool) +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift similarity index 80% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index d43703a226b..c3df3a0e761 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -6,21 +6,6 @@ import Foundation import UIKit import OpenCombine -protocol DataDonationViewModelProtocol { - - /// use these 3 to definde @published in a prorocol - var reloadTableView: Bool { get } - var reloadTableViewPublished: OpenCombine.Published { get } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } - - var friendlyFederalStateName: String { get } - var friendlyRegionName: String { get } - var friendlyAgeName: String { get } - var dynamicTableViewModel: DynamicTableViewModel { get } - - func save(consentGiven: Bool) -} - final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { // MARK: - Init @@ -216,31 +201,3 @@ final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { } } - -extension DynamicCell { - - /// A `legalExtendedDataDonation` to display legal text for Data Donation screen - /// - Parameters: - /// - title: The title/header for the legal foo. - /// - description: Optional description text. - /// - bulletPoints: A list of strings to be prefixed with bullet points. - /// - accessibilityIdentifier: Optional, but highly recommended, accessibility identifier. - /// - configure: Optional custom cell configuration - /// - Returns: A `DynamicCell` to display legal texts - static func legalExtendedDataDonation( - title: NSAttributedString, - description: NSAttributedString?, - bulletPoints: [NSAttributedString]? = nil, - accessibilityIdentifier: String? = nil, - configure: CellConfigurator? = nil - ) -> Self { - .identifier(DataDonationViewController.CustomCellReuseIdentifiers.legalExtended) { viewController, cell, indexPath in - guard let cell = cell as? DynamicLegalExtendedCell else { - fatalError("could not initialize cell of type `DynamicLegalExtendedCell`") - } - cell.configure(title: title, description: description, bulletPoints: bulletPoints) - configure?(viewController, cell, indexPath) - } - } - -} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift new file mode 100644 index 00000000000..2f4d97847fd --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift @@ -0,0 +1,33 @@ +//// +// 🦠 Corona-Warn-App +// + +import Foundation + +extension DynamicCell { + + /// A `legalExtendedDataDonation` to display legal text for Data Donation screen + /// - Parameters: + /// - title: The title/header for the legal foo. + /// - description: Optional description text. + /// - bulletPoints: A list of strings to be prefixed with bullet points. + /// - accessibilityIdentifier: Optional, but highly recommended, accessibility identifier. + /// - configure: Optional custom cell configuration + /// - Returns: A `DynamicCell` to display legal texts + static func legalExtendedDataDonation( + title: NSAttributedString, + description: NSAttributedString?, + bulletPoints: [NSAttributedString]? = nil, + accessibilityIdentifier: String? = nil, + configure: CellConfigurator? = nil + ) -> Self { + .identifier(DataDonationViewController.CustomCellReuseIdentifiers.legalExtended) { viewController, cell, indexPath in + guard let cell = cell as? DynamicLegalExtendedCell else { + fatalError("could not initialize cell of type `DynamicLegalExtendedCell`") + } + cell.configure(title: title, description: description, bulletPoints: bulletPoints) + configure?(viewController, cell, indexPath) + } + } + +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift new file mode 100644 index 00000000000..d9922894dee --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -0,0 +1,203 @@ +//// +// 🦠 Corona-Warn-App +// + +import Foundation +import UIKit +import OpenCombine + +final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { + + // MARK: - Init + + init( + store: Store, + presentSelectValueList: @escaping (SelectValueViewModel) -> Void, + datadonationModel: DataDonationModel + ) { + self.presentSelectValueList = presentSelectValueList + self.reloadTableView = false + self.dataDonationModel = datadonationModel + } + + // MARK: - DataDonationViewModelProtocol + + @OpenCombine.Published var reloadTableView: Bool + var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } + + var friendlyFederalStateName: String { + return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState + } + + var friendlyRegionName: String { + return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion + } + + var friendlyAgeName: String { + return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup + } + + var dynamicTableViewModel: DynamicTableViewModel { + /// create the top section with the illustration and title text + var dynamicTableViewModel = DynamicTableViewModel.with { + $0.add( + .section( + header: .image( + UIImage(named: "Illu_DataDonation"), + accessibilityLabel: "AppStrings.DataDonation.Info.accImageDescription", + accessibilityIdentifier: "AccessibilityIdentifiers.DataDonation.accImageDescription", + height: 250 + ), + cells: [ + .title1(text: AppStrings.DataDonation.Info.title, accessibilityIdentifier: "AppStrings.DataDonation.Info.title"), + .headline(text: AppStrings.DataDonation.Info.description) + ] + ) + ) + } + + /// section to show input fields with already given data + /// this will change numer of cells by the already entered data + let sectionCells: [DynamicCell] = [ + .headline(text: AppStrings.DataDonation.Info.subHeadState), + + .body(text: friendlyFederalStateName, style: .label, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in + self?.didTapSelectStateButton() + }), configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }), + dataDonationModel.federalStateName != nil ? + .body(text: friendlyRegionName, style: .label, accessibilityIdentifier: nil, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in + self?.didTapSelectRegionButton() + }), configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }) : + nil, + .headline(text: AppStrings.DataDonation.Info.subHeadAgeGroup), + .body(text: friendlyAgeName, style: .label, color: nil, accessibilityIdentifier: nil, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in + self?.didTapAgeButton() + }), configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }) + ] + .compactMap { $0 } + + dynamicTableViewModel.add( + .section( + cells: sectionCells + ) + ) + + /// section for the legal text + dynamicTableViewModel.add( + .section( + cells: [ + .legalExtendedDataDonation( + title: NSAttributedString(string: AppStrings.DataDonation.Info.legalTitle), + description: NSAttributedString( + string: AppStrings.DataDonation.Info.legalAcknowledgementContent, + attributes: [.font: UIFont.preferredFont(forTextStyle: .body)]), + bulletPoints: [ + NSAttributedString(string: AppStrings.DataDonation.Info.legalAcknowledgementBulletPoint1), + NSAttributedString(string: AppStrings.DataDonation.Info.legalAcknowledgementBulletPoint2), + NSAttributedString(string: AppStrings.DataDonation.Info.legalAcknowledgementBulletPoint3)], + accessibilityIdentifier: AppStrings.DataDonation.Info.legalTitle + ) + ] + ) + ) + + dynamicTableViewModel.add( + .section(separators: .all, cells: [ + .body( + text: AppStrings.DataDonation.Info.dataProcessingDetails, + style: DynamicCell.TextCellStyle.label, + accessibilityIdentifier: AccessibilityIdentifiers.ExposureSubmissionQRInfo.dataProcessingDetailInfo, + accessibilityTraits: UIAccessibilityTraits.link, + action: .pushDataDonationDetails(model: DataDonationDetailsViewModel().dynamicTableViewModel, + withTitle: AppStrings.DataDonation.DetailedInfo.title, + completion: nil + ), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + cell.selectionStyle = .default + }), + .space(height: 12) + ]) + ) + + return dynamicTableViewModel + } + + func save(consentGiven: Bool) { + dataDonationModel.isConsentGiven = consentGiven + Log.debug("DataDonation consent value set to '\(consentGiven)'") + dataDonationModel.save() + } + + // MARK: - Private + + private let presentSelectValueList: (SelectValueViewModel) -> Void + + private var dataDonationModel: DataDonationModel + private var subscriptions: [AnyCancellable] = [] + + private func didTapSelectStateButton() { + let selectValueViewModel = SelectValueViewModel( + dataDonationModel.allFederalStateNames, + title: AppStrings.DataDonation.ValueSelection.Title.State, + preselected: dataDonationModel.federalStateName + ) + selectValueViewModel.$selectedValue.sink { [weak self] federalState in + guard self?.dataDonationModel.federalStateName != federalState else { + return + } + // if a new fedaral state got selected reset region as well + self?.dataDonationModel.federalStateName = federalState + self?.dataDonationModel.region = nil + self?.reloadTableView.toggle() + }.store(in: &subscriptions) + presentSelectValueList(selectValueViewModel) + } + + private func didTapSelectRegionButton() { + guard let federalStateName = dataDonationModel.federalStateName else { + Log.debug("Missing federal state to load regions", log: .ppac) + return + } + + let selectValueViewModel = SelectValueViewModel( + dataDonationModel.allRegions(by: federalStateName), + title: AppStrings.DataDonation.ValueSelection.Title.Region, + preselected: dataDonationModel.region + ) + selectValueViewModel.$selectedValue .sink { [weak self] region in + guard self?.dataDonationModel.region != region else { + return + } + self?.dataDonationModel.region = region + self?.reloadTableView.toggle() + }.store(in: &subscriptions) + + presentSelectValueList(selectValueViewModel) + } + + private func didTapAgeButton() { + let selectValueViewModel = SelectValueViewModel( + AgeGroup.allCases.map({ $0.text }), + title: AppStrings.DataDonation.ValueSelection.Title.Age, + preselected: dataDonationModel.age + ) + selectValueViewModel.$selectedValue .sink { [weak self] age in + guard self?.dataDonationModel.age != age else { + return + } + self?.dataDonationModel.age = age + self?.reloadTableView.toggle() + }.store(in: &subscriptions) + + presentSelectValueList(selectValueViewModel) + } + +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DataDonationModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DataDonationModelTests.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DataDonationModelTests.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DataDonationModelTests.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DefaultDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DefaultDataDonationViewModelTests.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/DefaultDataDonationViewModelTests.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DefaultDataDonationViewModelTests.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/testData.json b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testData.json similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/testData.json rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testData.json diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/testDataInvalid.json b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testDataInvalid.json similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/__tests__/testDataInvalid.json rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testDataInvalid.json diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationDetailsViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewController.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationDetailsViewController.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewController.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationDetailsViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/Datadonation/DataDonationDetailsViewModel.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift From c5f82b5541fb269c57ca54d9c20f43858b51fb39 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 17:46:56 +0100 Subject: [PATCH 09/39] use SettingsDataDonationViewModel --- .../DataDonationViewModels/DataDonationViewModelProtocol.swift | 2 ++ .../ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift index 35756f78227..c065e379864 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift @@ -5,6 +5,8 @@ import Foundation import OpenCombine +/*** this protocol gets used to provide different view model classes for the dataDonationViewController */ + protocol DataDonationViewModelProtocol { /// use these 3 to definde @published in a prorocol diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift index db62e008f74..685393eee37 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift @@ -121,7 +121,7 @@ class SettingsCoordinator: ENStateHandlerUpdating { preconditionFailure("missing json file") } - let viewModel = DefaultDataDonationViewModel( + let viewModel = SettingsDataDonationViewModel( store: store, presentSelectValueList: { [weak self] selectValueViewModel in self?.presentSelectValueList(selectValueViewModel: selectValueViewModel) From c51066ecf75719d019af9615782b75cea8dc53a5 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Thu, 11 Feb 2021 18:01:30 +0100 Subject: [PATCH 10/39] added correct state of datadonation to the settings --- .../Scenes/Settings/Settings/SettingsViewController.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift index f41b564a5f9..8937ca1814f 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/Settings/SettingsViewController.swift @@ -204,6 +204,7 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating checkTracingStatus() checkNotificationSettings() checkBackgroundAppRefresh() + checkDataDonationIsConsentGiven() } private func registerCells() { @@ -273,6 +274,10 @@ final class SettingsViewController: UITableViewController, ExposureStateUpdating ) } + private func checkDataDonationIsConsentGiven() { + settingsViewModel.datadonation.setState(state: store.isPrivacyPreservingAnalyticsConsentGiven) + } + private func configureMainCell(indexPath: IndexPath, model: SettingsViewModel.CellModel) -> MainSettingsCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: ReuseIdentifier.main.rawValue, for: indexPath) as? MainSettingsCell else { fatalError("No cell for reuse identifier.") From 88d2399bfb6d922b1b617814601b476cebb4d5d3 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 12:09:44 +0100 Subject: [PATCH 11/39] added a toggle cell --- .../DataDonationViewController.swift | 2 +- .../SettingsDataDonationViewModel.swift | 76 ++++++++++++++----- .../ENA/Source/View Helpers/AppStrings.swift | 1 + 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index 30bc6ac0c26..8d22f0d338b 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -65,7 +65,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Protocol DismissHandling func wasAttemptedToBeDismissed() { - + Log.debug("tried to dissmis") } // MARK: - Public diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index d9922894dee..0b6cc41c748 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -60,26 +60,61 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { /// section to show input fields with already given data /// this will change numer of cells by the already entered data let sectionCells: [DynamicCell] = [ - .headline(text: AppStrings.DataDonation.Info.subHeadState), + .footnote(text: AppStrings.DataDonation.Info.settingsSubHeadline, accessibilityIdentifier: nil), + .body( + text: AppStrings.Settings.Datadonation.label, + style: .label, + color: nil, + accessibilityIdentifier: nil, + accessibilityTraits: .staticText, + action: .none, + configure: { [weak self] _, cell, _ in + guard let self = self else { + return + } + let toggleSwitch = UISwitch() + cell.accessoryView = toggleSwitch + toggleSwitch.isOn = self.dataDonationModel.isConsentGiven + toggleSwitch.onTintColor = .enaColor(for: .tint) + toggleSwitch.addTarget(self, action: #selector(self.didToggleDatadonationSwitch), for: .valueChanged) + }), + + .body( + text: friendlyFederalStateName, + style: .label, + accessibilityTraits: .button, + action: .execute(block: { [weak self] _, _ in + self?.didTapSelectStateButton() + }), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }), - .body(text: friendlyFederalStateName, style: .label, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in - self?.didTapSelectStateButton() - }), configure: { _, cell, _ in - cell.accessoryType = .disclosureIndicator - }), dataDonationModel.federalStateName != nil ? - .body(text: friendlyRegionName, style: .label, accessibilityIdentifier: nil, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in - self?.didTapSelectRegionButton() - }), configure: { _, cell, _ in - cell.accessoryType = .disclosureIndicator - }) : + .body( + text: friendlyRegionName, + style: .label, accessibilityIdentifier: nil, + accessibilityTraits: .button, + action: .execute(block: { [weak self] _, _ in + self?.didTapSelectRegionButton() + }), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }) : nil, - .headline(text: AppStrings.DataDonation.Info.subHeadAgeGroup), - .body(text: friendlyAgeName, style: .label, color: nil, accessibilityIdentifier: nil, accessibilityTraits: .button, action: .execute(block: { [weak self] _, _ in - self?.didTapAgeButton() - }), configure: { _, cell, _ in - cell.accessoryType = .disclosureIndicator - }) + + .body( + text: friendlyAgeName, + style: .label, + color: nil, + accessibilityIdentifier: nil, + accessibilityTraits: .button, + action: .execute(block: { [weak self] _, _ in + self?.didTapAgeButton() + }), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }) ] .compactMap { $0 } @@ -143,6 +178,13 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { private var dataDonationModel: DataDonationModel private var subscriptions: [AnyCancellable] = [] + @objc + private func didToggleDatadonationSwitch(sender: UISwitch) { + Log.debug("datadonation toggle -> save change") + save(consentGiven: sender.isOn) + reloadTableView.toggle() + } + private func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift index fe36c80271e..a1d2164453f 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift @@ -1208,6 +1208,7 @@ enum AppStrings { } enum Info { + static let settingsSubHeadline = NSLocalizedString("DataDonation_SubHead_Settings", comment: "") static let accImageDescription = NSLocalizedString("DataDonation_AccImageDescription", comment: "") static let title = NSLocalizedString("DataDonation_Headline", comment: "") static let description = NSLocalizedString("DataDonation_Description", comment: "") From fb153eed22fc575b93e92b536ae328ab4c10ab1d Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 12:32:13 +0100 Subject: [PATCH 12/39] updated logic when save will happen on datadonation settings --- .../DataDonation/DataDonationViewController.swift | 10 +++++++++- .../DataDonationViewModelProtocol.swift | 1 + .../DefaultDataDonationViewModel.swift | 4 ++++ .../SettingsDataDonationViewModel.swift | 12 ++++++++---- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index 8d22f0d338b..b4e91b3fe64 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -30,6 +30,14 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie setupTableView() } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + if isMovingFromParent { + viewModel.autosave() + } + } + override var navigationItem: UINavigationItem { navigationFooterItem } @@ -65,7 +73,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Protocol DismissHandling func wasAttemptedToBeDismissed() { - Log.debug("tried to dissmis") + Log.debug("tried to dismiss") } // MARK: - Public diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift index c065e379864..2471250d786 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift @@ -19,5 +19,6 @@ protocol DataDonationViewModelProtocol { var friendlyAgeName: String { get } var dynamicTableViewModel: DynamicTableViewModel { get } + func autosave() func save(consentGiven: Bool) } diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index c3df3a0e761..6d675930543 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -130,6 +130,10 @@ final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { return dynamicTableViewModel } + func autosave() { + dataDonationModel.save() + } + func save(consentGiven: Bool) { dataDonationModel.isConsentGiven = consentGiven Log.debug("DataDonation consent value set to '\(consentGiven)'") diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 0b6cc41c748..f4bc8fb37c6 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -165,6 +165,12 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { return dynamicTableViewModel } + /// will save the model in it's current state + func autosave() { + dataDonationModel.save() + } + + // will set consent given and save the model afterwards func save(consentGiven: Bool) { dataDonationModel.isConsentGiven = consentGiven Log.debug("DataDonation consent value set to '\(consentGiven)'") @@ -178,11 +184,9 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { private var dataDonationModel: DataDonationModel private var subscriptions: [AnyCancellable] = [] - @objc + @objc /// called if the consent given switch changes private func didToggleDatadonationSwitch(sender: UISwitch) { - Log.debug("datadonation toggle -> save change") - save(consentGiven: sender.isOn) - reloadTableView.toggle() + dataDonationModel.isConsentGiven = sender.isOn } private func didTapSelectStateButton() { From 697b8c2cde11608e51f2a07d5b90d26fca6275b0 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 13:24:06 +0100 Subject: [PATCH 13/39] a bit of refactoring SettingsDataDonationViewModel --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 8 +- .../DataDonationViewController.swift | 7 -- .../BaseDataDonationViewModel.swift | 76 +++++++++++++++++++ .../DataDonationViewModelProtocol.swift | 24 ------ .../DefaultDataDonationViewModel.swift | 50 +----------- .../SettingsDataDonationViewModel.swift | 61 +++------------ 6 files changed, 92 insertions(+), 134 deletions(-) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift delete mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index 33823c6ffcc..5d996fa8d2d 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -656,7 +656,6 @@ BA7D178E25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */; }; BA7D17B725D59373006B9EBF /* SettingsDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */; }; BA7D17BF25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */; }; - BA7D17C725D593FF006B9EBF /* DataDonationViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */; }; BA7EABAD25C973FE001AA5FE /* DMKeyValueCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */; }; BA811B4D25D422B600C9BC98 /* DataDonationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */; }; BA8824D725D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json in Resources */ = {isa = PBXBuildFile; fileRef = BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */; }; @@ -685,6 +684,7 @@ BACD671725B7002F00BAF5D0 /* RiskCalculationResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BACD671625B7002F00BAF5D0 /* RiskCalculationResultTests.swift */; }; BAD962FB25668F4000FAB615 /* TestResultAvailableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD962FA25668F4000FAB615 /* TestResultAvailableViewController.swift */; }; BAD9630025668F8E00FAB615 /* TestResultAvailableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */; }; + BADBC81B25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */; }; BAE20FF325C8321300162966 /* DMKeyValueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */; }; BAE2101025C8460900162966 /* PPACDeviceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */; }; BAE2101B25C8463400162966 /* PPACDeviceCheckMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */; }; @@ -1476,7 +1476,6 @@ BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultDataDonationViewModelTests.swift; sourceTree = ""; }; BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDataDonationViewModel.swift; sourceTree = ""; }; BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DynamicCell+LegalExtendedDataDonation.swift"; sourceTree = ""; }; - BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationViewModelProtocol.swift; sourceTree = ""; }; BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueCellViewModel.swift; sourceTree = ""; }; BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationModel.swift; sourceTree = ""; }; BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "ppdd-ppa-administrative-unit-set-ua-approved.json"; sourceTree = ""; }; @@ -1504,6 +1503,7 @@ BACD671625B7002F00BAF5D0 /* RiskCalculationResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiskCalculationResultTests.swift; sourceTree = ""; }; BAD962FA25668F4000FAB615 /* TestResultAvailableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestResultAvailableViewController.swift; sourceTree = ""; }; BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestResultAvailableViewModel.swift; sourceTree = ""; }; + BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModel.swift; sourceTree = ""; }; BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueTableViewCell.swift; sourceTree = ""; }; BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheck.swift; sourceTree = ""; }; BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheckMock.swift; sourceTree = ""; }; @@ -4017,7 +4017,7 @@ isa = PBXGroup; children = ( BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */, - BA7D17C625D593FF006B9EBF /* DataDonationViewModelProtocol.swift */, + BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */, BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */, ); @@ -4889,7 +4889,6 @@ AB2F094A25D1687300C16309 /* SurveyURLProvider.swift in Sources */, 013DC102245DAC4E00EE58B0 /* Store.swift in Sources */, 5270E9B8256D20A900B08606 /* NSTextAttachment+ImageHeight.swift in Sources */, - BA7D17C725D593FF006B9EBF /* DataDonationViewModelProtocol.swift in Sources */, B1FE13EF24891D0C00D012E5 /* RiskProvidingConfiguration.swift in Sources */, 014086BD2589033A00E9E5B2 /* DiaryEditEntriesCellModel.swift in Sources */, B1F82DF224718C7300E2E56A /* DMBackendConfigurationViewController.swift in Sources */, @@ -5123,6 +5122,7 @@ BA69A7D825CD787D00023265 /* SelectValueTableViewController.swift in Sources */, EBA403D12589260D00D1F039 /* ColorCompatibility.swift in Sources */, B161782524804AC3006E435A /* DownloadedPackagesSQLLiteStoreV1.swift in Sources */, + BADBC81B25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift in Sources */, 01909888257E7B900065D050 /* ExposureSubmissionQRInfoViewController.swift in Sources */, 8F270194259B5BA700E48CFE /* ContactDiaryMigration1To2.swift in Sources */, BA112DF7255586E9007F5712 /* WifiOnlyHTTPClient.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index 603fca08fcc..fbe9761d220 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -31,13 +31,6 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie setupTableView() } - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - if isMovingFromParent { - viewModel.autosave() - } - } - override var navigationItem: UINavigationItem { navigationFooterItem } diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift new file mode 100644 index 00000000000..a3421ecdad1 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift @@ -0,0 +1,76 @@ +//// +// 🦠 Corona-Warn-App +// + +import Foundation +import UIKit +import OpenCombine + +/*** this protocol gets used to provide different view model classes for the dataDonationViewController */ + +protocol DataDonationViewModelProtocol { + + /// use these 3 to definde @published in a prorocol + var reloadTableView: Bool { get } + var reloadTableViewPublished: OpenCombine.Published { get } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } + + var friendlyFederalStateName: String { get } + var friendlyRegionName: String { get } + var friendlyAgeName: String { get } + var dynamicTableViewModel: DynamicTableViewModel { get } + + func save(consentGiven: Bool) +} + +class BaseDataDonationViewModel: DataDonationViewModelProtocol { + + // MARK: - Init + + init( + store: Store, + presentSelectValueList: @escaping (SelectValueViewModel) -> Void, + datadonationModel: DataDonationModel + ) { + self.presentSelectValueList = presentSelectValueList + self.reloadTableView = false + self.dataDonationModel = datadonationModel + } + + // MARK: - DataDonationViewModelProtocol + + let presentSelectValueList: (SelectValueViewModel) -> Void + + @OpenCombine.Published var reloadTableView: Bool + + var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } + var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } + var dataDonationModel: DataDonationModel + var subscriptions: [AnyCancellable] = [] + + var dynamicTableViewModel: DynamicTableViewModel { + fatalError("base implementation should never get called") + } + + /// formatted name output + var friendlyFederalStateName: String { + return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState + } + + /// formatted region output + var friendlyRegionName: String { + return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion + } + + /// formatted age output + var friendlyAgeName: String { + return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup + } + + /// will set consent given and save the model afterwards + func save(consentGiven: Bool) { + dataDonationModel.isConsentGiven = consentGiven + Log.debug("DataDonation consent value set to '\(consentGiven)'") + dataDonationModel.save() + } +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift deleted file mode 100644 index 2471250d786..00000000000 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DataDonationViewModelProtocol.swift +++ /dev/null @@ -1,24 +0,0 @@ -//// -// 🦠 Corona-Warn-App -// - -import Foundation -import OpenCombine - -/*** this protocol gets used to provide different view model classes for the dataDonationViewController */ - -protocol DataDonationViewModelProtocol { - - /// use these 3 to definde @published in a prorocol - var reloadTableView: Bool { get } - var reloadTableViewPublished: OpenCombine.Published { get } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } - - var friendlyFederalStateName: String { get } - var friendlyRegionName: String { get } - var friendlyAgeName: String { get } - var dynamicTableViewModel: DynamicTableViewModel { get } - - func autosave() - func save(consentGiven: Bool) -} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index 6d675930543..2e9d60f3098 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -6,39 +6,10 @@ import Foundation import UIKit import OpenCombine -final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { - - // MARK: - Init - - init( - store: Store, - presentSelectValueList: @escaping (SelectValueViewModel) -> Void, - datadonationModel: DataDonationModel - ) { - self.presentSelectValueList = presentSelectValueList - self.reloadTableView = false - self.dataDonationModel = datadonationModel - } - - // MARK: - DataDonationViewModelProtocol - - @OpenCombine.Published var reloadTableView: Bool - var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } - - var friendlyFederalStateName: String { - return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState - } - - var friendlyRegionName: String { - return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion - } +final class DefaultDataDonationViewModel: BaseDataDonationViewModel { - var friendlyAgeName: String { - return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup - } - - var dynamicTableViewModel: DynamicTableViewModel { + /// override layout of the dynamiv tableview model + override var dynamicTableViewModel: DynamicTableViewModel { /// create the top section with the illustration and title text var dynamicTableViewModel = DynamicTableViewModel.with { $0.add( @@ -130,23 +101,8 @@ final class DefaultDataDonationViewModel: DataDonationViewModelProtocol { return dynamicTableViewModel } - func autosave() { - dataDonationModel.save() - } - - func save(consentGiven: Bool) { - dataDonationModel.isConsentGiven = consentGiven - Log.debug("DataDonation consent value set to '\(consentGiven)'") - dataDonationModel.save() - } - // MARK: - Private - private let presentSelectValueList: (SelectValueViewModel) -> Void - - private var dataDonationModel: DataDonationModel - private var subscriptions: [AnyCancellable] = [] - private func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index f4bc8fb37c6..166ef924ee0 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -6,39 +6,9 @@ import Foundation import UIKit import OpenCombine -final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { - - // MARK: - Init - - init( - store: Store, - presentSelectValueList: @escaping (SelectValueViewModel) -> Void, - datadonationModel: DataDonationModel - ) { - self.presentSelectValueList = presentSelectValueList - self.reloadTableView = false - self.dataDonationModel = datadonationModel - } - - // MARK: - DataDonationViewModelProtocol - - @OpenCombine.Published var reloadTableView: Bool - var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } - - var friendlyFederalStateName: String { - return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.noSelectionState - } - - var friendlyRegionName: String { - return dataDonationModel.region ?? AppStrings.DataDonation.Info.noSelectionRegion - } - - var friendlyAgeName: String { - return dataDonationModel.age ?? AppStrings.DataDonation.Info.noSelectionAgeGroup - } +final class SettingsDataDonationViewModel: BaseDataDonationViewModel { - var dynamicTableViewModel: DynamicTableViewModel { + override var dynamicTableViewModel: DynamicTableViewModel { /// create the top section with the illustration and title text var dynamicTableViewModel = DynamicTableViewModel.with { $0.add( @@ -165,28 +135,12 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { return dynamicTableViewModel } - /// will save the model in it's current state - func autosave() { - dataDonationModel.save() - } - - // will set consent given and save the model afterwards - func save(consentGiven: Bool) { - dataDonationModel.isConsentGiven = consentGiven - Log.debug("DataDonation consent value set to '\(consentGiven)'") - dataDonationModel.save() - } - - // MARK: - Private - - private let presentSelectValueList: (SelectValueViewModel) -> Void - - private var dataDonationModel: DataDonationModel - private var subscriptions: [AnyCancellable] = [] - @objc /// called if the consent given switch changes private func didToggleDatadonationSwitch(sender: UISwitch) { - dataDonationModel.isConsentGiven = sender.isOn + save(consentGiven: sender.isOn) + DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35) { [weak self] in + self?.reloadTableView.toggle() + } } private func didTapSelectStateButton() { @@ -202,6 +156,7 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { // if a new fedaral state got selected reset region as well self?.dataDonationModel.federalStateName = federalState self?.dataDonationModel.region = nil + self?.dataDonationModel.save() self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) @@ -223,6 +178,7 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { return } self?.dataDonationModel.region = region + self?.dataDonationModel.save() self?.reloadTableView.toggle() }.store(in: &subscriptions) @@ -240,6 +196,7 @@ final class SettingsDataDonationViewModel: DataDonationViewModelProtocol { return } self?.dataDonationModel.age = age + self?.dataDonationModel.save() self?.reloadTableView.toggle() }.store(in: &subscriptions) From 6c27df049117e1dcac2891381b098e0347038ae1 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 13:28:49 +0100 Subject: [PATCH 14/39] added closeOnSelection option to automatically close viewController --- .../SelectValueTableViewController.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/SelectValueViewController/SelectValueTableViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/SelectValueViewController/SelectValueTableViewController.swift index 8628de80caa..ec2aec04a09 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/SelectValueViewController/SelectValueTableViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/SelectValueViewController/SelectValueTableViewController.swift @@ -11,10 +11,12 @@ final class SelectValueTableViewController: UITableViewController { init( _ viewModel: SelectValueViewModel, - dissmiss: @escaping () -> Void + dissmiss: @escaping () -> Void, + closeOnSelection: Bool = true ) { self.viewModel = viewModel self.dissmiss = dissmiss + self.closeOnSelection = closeOnSelection self.subscriptions = [] /// we use .grouped to make seperators end with the last value super.init(style: .grouped) @@ -50,12 +52,16 @@ final class SelectValueTableViewController: UITableViewController { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { viewModel.selectValue(at: indexPath) + if closeOnSelection { + DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.38, execute: dissmiss) + } } // MARK: - Private private let viewModel: SelectValueViewModel private let dissmiss: () -> Void + private let closeOnSelection: Bool private var subscriptions: [AnyCancellable] private func setupTableView() { From 8458b31a1b2993303f29b63d93464c156e351a04 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 13:37:37 +0100 Subject: [PATCH 15/39] updated logic on datadonation toggle --- .../SettingsDataDonationViewModel.swift | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 166ef924ee0..c12d855d96a 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -49,18 +49,20 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { toggleSwitch.addTarget(self, action: #selector(self.didToggleDatadonationSwitch), for: .valueChanged) }), - .body( - text: friendlyFederalStateName, - style: .label, - accessibilityTraits: .button, - action: .execute(block: { [weak self] _, _ in - self?.didTapSelectStateButton() - }), - configure: { _, cell, _ in - cell.accessoryType = .disclosureIndicator - }), + dataDonationModel.isConsentGiven == true ? + .body( + text: friendlyFederalStateName, + style: .label, + accessibilityTraits: .button, + action: .execute(block: { [weak self] _, _ in + self?.didTapSelectStateButton() + }), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }): + nil, - dataDonationModel.federalStateName != nil ? + dataDonationModel.isConsentGiven == true && dataDonationModel.federalStateName != nil ? .body( text: friendlyRegionName, style: .label, accessibilityIdentifier: nil, @@ -73,18 +75,20 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { }) : nil, - .body( - text: friendlyAgeName, - style: .label, - color: nil, - accessibilityIdentifier: nil, - accessibilityTraits: .button, - action: .execute(block: { [weak self] _, _ in - self?.didTapAgeButton() - }), - configure: { _, cell, _ in - cell.accessoryType = .disclosureIndicator - }) + dataDonationModel.isConsentGiven == true ? + .body( + text: friendlyAgeName, + style: .label, + color: nil, + accessibilityIdentifier: nil, + accessibilityTraits: .button, + action: .execute(block: { [weak self] _, _ in + self?.didTapAgeButton() + }), + configure: { _, cell, _ in + cell.accessoryType = .disclosureIndicator + }) : + nil ] .compactMap { $0 } From 85a69f9488e11c183eb35b6b63eaf89a276cb4ba Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 13:45:15 +0100 Subject: [PATCH 16/39] changed fallback string if no value was given --- .../SettingsDataDonationViewModel.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index c12d855d96a..050fab67165 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -8,6 +8,16 @@ import OpenCombine final class SettingsDataDonationViewModel: BaseDataDonationViewModel { + /// we use a slitly different string if no federal state was selected + override var friendlyFederalStateName: String { + return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.subHeadState + } + + /// we use a slitly different string if no age was given + override var friendlyAgeName: String { + return dataDonationModel.age ?? AppStrings.DataDonation.Info.subHeadAgeGroup + } + override var dynamicTableViewModel: DynamicTableViewModel { /// create the top section with the illustration and title text var dynamicTableViewModel = DynamicTableViewModel.with { @@ -62,7 +72,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { }): nil, - dataDonationModel.isConsentGiven == true && dataDonationModel.federalStateName != nil ? + dataDonationModel.isConsentGiven == true ? .body( text: friendlyRegionName, style: .label, accessibilityIdentifier: nil, From d426b41d4808ff53d9d8ac695826df8d72455e94 Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 13:47:03 +0100 Subject: [PATCH 17/39] AppSettings data donation legal texts --- .../Resources/Localization/de.lproj/Localizable.legal.strings | 4 ++++ .../Resources/Localization/en.lproj/Localizable.legal.strings | 4 ++++ .../Resources/Localization/tr.lproj/Localizable.legal.strings | 4 ++++ .../SettingsDataDonationViewModel.swift | 4 ++-- src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift | 4 ++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings index 3860a0ef0b1..6f06465ff0f 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings @@ -99,3 +99,7 @@ "SurveyConsent_Details_Legal_Body1" = "Um die Echtheit Ihrer App zu bestätigen, erzeugt Ihr Smartphone eine eindeutige Kennung, die Informationen über die Version Ihres Smartphones und der App enthält. Das ist erforderlich, um zu verhindern, dass Nutzer mehrfach der Befragung teilnehmen und so die Ergebnisse der Befragung verfälschen. Die Kennung wird hier einmalig an Apple übermittelt. Dabei kann es auch zu einer Datenübermittlung in die USA kommen. Dort besteht kein dem europäischen Recht angemessenes Datenschutzniveau und Ihre europäischen Datenschutzrechte können eventuell nicht durchgesetzt werden. Insbesondere besteht die Möglichkeit, dass US-Sicherheitsbehörden, auch ohne einen konkreten Verdacht, auf die übermittelten Daten bei Apple zugreifen und diese auswerten, beispielsweise indem sie Daten mit anderen Informationen verknüpfen. Dies betrifft nur die an Apple übermittelte Kennung. Die weiteren Angaben über Ihre Teilnahme an der Befragung erhält Apple nicht."; "SurveyConsent_Details_Legal_Body2" = "Wenn Sie mit der Drittlandsübermittlung nicht einverstanden sind, tippen Sie bitte nicht „Einverstanden“ an. Sie können die App weiterhin nutzen, eine Teilnahme an dieser Befragung ist dann jedoch nicht möglich."; + +/* Data Donation App Settings*/ + +"ppa_settings_privacy_information_body" = "Indem Sie oben „Datenspende“ aktivieren, willigen Sie ein:\n\nDie App übermittelt täglich von ihr erfasste Angaben an das RKI. Die Daten betreffen angezeigte Risiko-Begegnungen und Warnungen, durch Sie abgerufene Testergebnisse, ob Sie andere Nutzer gewarnt haben sowie Angaben über das Betriebssystem Ihres Smartphones. Wenn Sie oben weitere Angaben gemacht haben (Region, Altersgruppe), werden auch diese an das RKI übermittelt.\n\nDas RKI wird diese Daten zu Statistiken zusammenfassen und auswerten, um die Wirksamkeit und Funktionsweise der App zu bewerten und Rückschlüsse auf das Pandemiegeschehen zu ziehen. Die dabei gefundenen Erkenntnisse helfen bei der Verbesserung der Funktionen und Nutzerfreundlichkeit der App sowie bei der Steuerung anderer Maßnahmen der Pandemiebekämpfung.\n\nBevor Ihre Daten ausgewertet werden, muss sichergestellt sein, dass jede an der Datenspende teilnehmende App nur einmal gezählt wird und die Statistiken nicht verfälscht werden. Hierfür muss die Echtheit Ihrer App geprüft werden. Dazu wird durch Ihr Smartphone eine eindeutige Kennung erzeugt und an Apple in die USA übermittelt, damit Apple die Echtheit Ihrer App gegenüber dem RKI bestätigen kann. Die Kennung enthält Informationen über die Version Ihres Smartphones und der App. Weitere Angaben aus der App erhält Apple hierbei nicht.\n\nSie können Ihr Einverständnis jederzeit zurücknehmen, indem Sie oben „Datenspende“ deaktivieren.“"; diff --git a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings index 1817b75a74d..bdb11b37083 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings @@ -108,3 +108,7 @@ "SurveyConsent_Details_Legal_Body1" = "To confirm the authenticity of your app, your smartphone will generate a unique identifier that contains information about the version of your smartphone and the app. This is necessary to prevent users from participating in the survey more than once, as this could distort the results of the survey. Once generated, the identifier will be transmitted once to Apple. This may result in data being transferred to the U.S.. There, the level of data protection is not considered adequate under European law and it may not be possible to enforce your European data protection rights. In particular, there is a possibility that once the transmitted data reaches Apple, it may be accessed and analysed by U.S. security authorities, even if they have no specific grounds for suspicion, for example by linking the data with other information. This only concerns the identifier sent to Apple. Apple will not receive the other information about your participation in the survey."; "SurveyConsent_Details_Legal_Body2" = "If you do not consent to this transfer of your data to a third country, please do not tap on “Accept”. You will still be able to use the app, but not participate in this survey."; + +/* Data Donation App Settings*/ + +"ppa_settings_privacy_information_body" = "By enabling “Share Data” above, you consent to the following:\n\nThe app will transmit information it records to the RKI, on a daily basis. The data concerns possible exposures and warnings that have been displayed to you, test results you have retrieved, and whether you have warned other users, and information about your smartphone’s operating system. If you have provided further details above (region, age group), then the RKI will also receive this information.\n\nThe RKI will compile this data into statistics and analyze it to assess the effectiveness and functioning of the app, and draw conclusions regarding the pandemic. The resulting knowledge will help to improve the app’s features and make it more user-friendly, as well as to inform other pandemic response measures.\n\nBefore your data is analyzed, it is necessary to ensure that each app that shares data is only counted once, so as not to distort the statistics. This is why the authenticity of your app needs to be verified. For this purpose, a unique identifier is generated by your smartphone and transmitted to Apple in the U.S., so that Apple can confirm the authenticity of your app to the RKI. The identifier contains information about the version of your smartphone and the app. Apple does not receive any other information from the app during this process.\n\n You can withdraw your consent at any time by disabling “Share Data” above."; diff --git a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings index 49271a22388..4444d526fd0 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings @@ -109,3 +109,7 @@ "SurveyConsent_Details_Legal_Body1" = "Uygulamanızın orijinal olduğunu onaylamak adına akıllı telefonunuz, akıllı telefonunuzun sürümü ve Uygulamaya ilişkin veriler içeren benzersiz bir kimlik kodu oluşturur. Kullanıcıların ankete birden çok kez katılmasını ve böylece anket sonuçlarını tahrif etmesini önlemek için bu kodun oluşturulması gerekmektedir. Bu kimlik kodları, sadece bir kez Apple’a aktarılır. Bu süreçte verilerin ABD’ye aktarılması da söz konusu olabilir. Orada Avrupa hukukuna uygun kişisel verilerin koruma seviyesi bulunmamaktadır ve Avrupa’daki veri koruma haklarınız uygulanmayabilir. Bu bağlamda özellikle ABD güvenlik makamlarının, somut bir şüphe olmasa bile, Apple’a aktarılan bu verilere erişme ve örneğin verileri diğer bilgilerle ilişkilendirerek bunları değerlendirmeye alma olasılığı bulunmaktadır. Bu durum sadece Apple’a aktarılan kimlik kodları için söz konusudur. Apple ankete katılımız ile ilgili daha fazla bilgi almaz."; "SurveyConsent_Details_Legal_Body2" = "Üçüncü ülkelere aktarımı kabul etmiyorsanız, lütfen “Kabul ediyorum” seçeneğine tıklamayın. Buna rağmen Uygulamayı kullanmaya devam edebilirsiniz, ancak ankete katılamazsınız."; + +/* Data Donation App Settings*/ + +"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\Uygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\n Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 166ef924ee0..872a95465fe 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -99,9 +99,9 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { .section( cells: [ .legalExtendedDataDonation( - title: NSAttributedString(string: AppStrings.DataDonation.Info.legalTitle), + title: NSAttributedString(string: AppStrings.), description: NSAttributedString( - string: AppStrings.DataDonation.Info.legalAcknowledgementContent, + string: AppStrings.DataDonation.AppSettings.ppaSettingsPrivacyInformationBody, attributes: [.font: UIFont.preferredFont(forTextStyle: .body)]), bulletPoints: [ NSAttributedString(string: AppStrings.DataDonation.Info.legalAcknowledgementBulletPoint1), diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift index a1d2164453f..d3bfcfe260d 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift @@ -1293,6 +1293,10 @@ enum AppStrings { static let bullet22_text = NSLocalizedString("DetailedInfosDataDonation_Misc_SubHead_BulletPoint_Region", comment: "") static let bullet23_text = NSLocalizedString("DetailedInfosDataDonation_Misc_SubHead_BulletPoint_TechSpecs", comment: "") } + + enum AppSettings { + static let ppaSettingsPrivacyInformationBody = NSLocalizedString("ppa_settings_privacy_information_body", tableName: "Localizable.legal", comment: "") + } } // swiftlint:disable:next file_length From 40753eff0c2fd27083028f3975331f224ab5f249 Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 14:27:49 +0100 Subject: [PATCH 18/39] fixed syntax error. fixed text formatting --- .../DataDonationDetailsViewModelTests.swift | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift new file mode 100644 index 00000000000..63687237da4 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -0,0 +1,29 @@ +//// +// 🦠 Corona-Warn-App +// + +import XCTest + +class DataDonationDetailsViewModelTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} From d455bc9abd453bfe8946857f25c102b23dc4988a Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 13:54:11 +0100 Subject: [PATCH 19/39] removed obsolete lines --- .../ENA/Source/View Helpers/AppStrings.swift | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift index d3bfcfe260d..6a48fb6e107 100644 --- a/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift +++ b/src/xcode/ENA/ENA/Source/View Helpers/AppStrings.swift @@ -1247,26 +1247,6 @@ enum AppStrings { static let bullet02_title = NSLocalizedString("DetailedInfosDataDonation_BulletPoint_ImproveddUserNavigation_BulletTitle", comment: "") static let bullet03_title = NSLocalizedString("DetailedInfosDataDonation_BulletPoint_AppSupport_BulletTitle", comment: "") static let bullet04_title = NSLocalizedString("DetailedInfosDataDonation_BulletPoint_ImprovedStatistics_BulletTitle", comment: "") - -// static let bullet05_title = NSLocalizedString("DetailedInfosDataDonation_RKI_DataCollection_BulletPoint_Date_BulletTitle", comment: "") -// static let bullet06_title = NSLocalizedString("DetailedInfosDataDonation_RKI_DataCollection_BulletPoint_ChangeOfWarnHistory_BulletTitle", comment: "") -// static let bullet07_title = NSLocalizedString("DetailedInfosDataDonation_RKI_DataCollection_BulletPoint_InfoAboutRisk_BulletTitle", comment: "") -// static let bullet08_title = NSLocalizedString("DetailedInfosDataDonation_RKI_DataCollection_BulletPoint_RiskStatus_Base_BulletTitle", comment: "") -// static let bullet09_title = NSLocalizedString("DetailedInfosDataDonation_RetrievedTestResult_BulletPoint_KindOfTestResult_BulletTitle", comment: "") -// static let bullet10_title = NSLocalizedString("DetailedInfosDataDonation_RetrievedTestResult_BulletPoint_CalculatedRisk_BulletTitle", comment: "") -// static let bullet11_title = NSLocalizedString("DetailedInfosDataDonation_RetrievedTestResult_BulletPoint_PeriodHighRisk_BulletTitle", comment: "") -// static let bullet12_title = NSLocalizedString("DetailedInfosDataDonation_RetrievedTestResult_BulletPoint_PeriodLastInfoHighRisk_BulletTitle", comment: "") -// static let bullet13_title = NSLocalizedString("DetailedInfosDataDonation_RetrievedTestResult_BulletPoint_SharedTestResult_BulletTitle", comment: "") -// static let bullet14_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_Canceled_BulletTitle", comment: "") -// static let bullet15_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_SymptompsStart_BulletTitle", comment: "") -// static let bullet16_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_Consent_BulletTitle", comment: "") -// static let bullet17_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_HowFar_BulletTitle", comment: "") -// static let bullet18_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_HoursUntilReceived_BulletTitle", comment: "") -// static let bullet19_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_DaysElapsed_BulletTitle", comment: "") -// static let bullet20_title = NSLocalizedString("DetailedInfosDataDonation_WarnOthers_BulletPoint_HoursSinceRegistration_BulletTitle", comment: "") -// static let bullet21_title = NSLocalizedString("DetailedInfosDataDonation_Misc_SubHead_BulletPoint_AgeGroup_BulletTitle", comment: "") -// static let bullet22_title = NSLocalizedString("DetailedInfosDataDonation_Misc_SubHead_BulletPoint_Region_BulletTitle", comment: "") -// static let bullet23_title = NSLocalizedString("DetailedInfosDataDonation_Misc_SubHead_BulletPoint_TechSpecs_BulletTitle", comment: "") static let bullet01_text = NSLocalizedString("DetailedInfosDataDonation_BulletPoint_ImproveddRiskDetermination", comment: "") static let bullet02_text = NSLocalizedString("DetailedInfosDataDonation_BulletPoint_ImproveddUserNavigation", comment: "") From dbaa0529a778358d1ca8e33da78ef72201894a20 Mon Sep 17 00:00:00 2001 From: Pascal Brause Date: Fri, 12 Feb 2021 13:52:25 +0100 Subject: [PATCH 20/39] review changes --- .../Scenes/DataDonation/DataDonationViewController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index fbe9761d220..66acd0bb0e3 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -70,7 +70,8 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Public // MARK: - Internal - + + /// Is called when when the one of the ENANavigationControllerWithFooter buttons is tapped. var finished: (() -> Void)? // MARK: - Private From 14e87e5a5ca42a1758395cfe7cdf01515526b384 Mon Sep 17 00:00:00 2001 From: Pascal Brause <75615785+pascal-brause@users.noreply.github.com> Date: Fri, 12 Feb 2021 14:22:53 +0100 Subject: [PATCH 21/39] Update src/xcode/ENA/ENA/Source/Scenes/Datadonation/District.swift Co-authored-by: Marcus Scherer --- .../Source/Scenes/DataDonation/DataDonationModel/District.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift index 31112e06c60..995854c2a19 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // From d975309aee6a2f38c1470d90995e360b15765019 Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 14:32:41 +0100 Subject: [PATCH 22/39] fixed syntax error fixed text formatting --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 12 +++++++++++ .../en.lproj/Localizable.legal.strings | 4 ++-- .../tr.lproj/Localizable.legal.strings | 2 +- .../SettingsDataDonationViewModel.swift | 2 +- .../DataDonationDetailsViewModelTests.swift | 20 ++++--------------- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index 5d996fa8d2d..47942246860 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -322,6 +322,7 @@ 505F508325C897B3004920EB /* OTPError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505F508225C897B3004920EB /* OTPError.swift */; }; 506A2F1B25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */; }; 506A2F2025D2A08900B7DDFB /* DataDonationDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506A2F1F25D2A08900B7DDFB /* DataDonationDetailsViewController.swift */; }; + 508DB7D525D6B49E00F153D6 /* DataDonationDetailsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508DB7D425D6B49E00F153D6 /* DataDonationDetailsViewModelTests.swift */; }; 509C69FE25B5D920000F2A4C /* ENAUITests-Statistics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 509C69FD25B5D920000F2A4C /* ENAUITests-Statistics.swift */; }; 50B1D6E72551621C00684C3C /* DayKeyPackageDownloadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B1D6E62551621C00684C3C /* DayKeyPackageDownloadTests.swift */; }; 50B5057D25CAEF5C00EEA380 /* OTPToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B5057C25CAEF5C00EEA380 /* OTPToken.swift */; }; @@ -1126,6 +1127,7 @@ 505F508225C897B3004920EB /* OTPError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPError.swift; sourceTree = ""; }; 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationDetailsViewModel.swift; sourceTree = ""; }; 506A2F1F25D2A08900B7DDFB /* DataDonationDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationDetailsViewController.swift; sourceTree = ""; }; + 508DB7D425D6B49E00F153D6 /* DataDonationDetailsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationDetailsViewModelTests.swift; sourceTree = ""; }; 509C69FD25B5D920000F2A4C /* ENAUITests-Statistics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ENAUITests-Statistics.swift"; sourceTree = ""; }; 50B1D6E62551621C00684C3C /* DayKeyPackageDownloadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayKeyPackageDownloadTests.swift; sourceTree = ""; }; 50B5057C25CAEF5C00EEA380 /* OTPToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPToken.swift; sourceTree = ""; }; @@ -2457,6 +2459,14 @@ path = __tests__; sourceTree = ""; }; + 508DB7D925D6B4AE00F153D6 /* __tests__ */ = { + isa = PBXGroup; + children = ( + 508DB7D425D6B49E00F153D6 /* DataDonationDetailsViewModelTests.swift */, + ); + path = __tests__; + sourceTree = ""; + }; 50B5058725CAF3C500EEA380 /* DMOTPService */ = { isa = PBXGroup; children = ( @@ -4036,6 +4046,7 @@ BA7D17D025D5947B006B9EBF /* DataDonationDetails */ = { isa = PBXGroup; children = ( + 508DB7D925D6B4AE00F153D6 /* __tests__ */, 506A2F1F25D2A08900B7DDFB /* DataDonationDetailsViewController.swift */, 506A2F1A25D2A06D00B7DDFB /* DataDonationDetailsViewModel.swift */, ); @@ -5195,6 +5206,7 @@ BA9DD53F2567BDAC00C326FF /* TestResultAvailableViewModelTest.swift in Sources */, 01B605CE258A38330093DB8E /* DiaryEntryTest.swift in Sources */, 50352C8B25C94961007193D2 /* OTPServiceTests.swift in Sources */, + 508DB7D525D6B49E00F153D6 /* DataDonationDetailsViewModelTests.swift in Sources */, BAB6C81225C4652D00E042FB /* PPACTokenTests.swift in Sources */, F2DC808E248989CE00EDC40A /* DynamicTableViewControllerRegisterCellsTests.swift in Sources */, EE22DB91247FB479001B0A71 /* MockStateHandlerObserverDelegate.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings index bdb11b37083..ac2035fdf1d 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/en.lproj/Localizable.legal.strings @@ -75,7 +75,7 @@ "DataDonation_Acknowledgement_Title" = "Your Consent"; -"DataDonation_Acknowledgement_Content" = "By tapping on “Accept”, you consent to the following:\n\nThe app will transmit information it records to the RKI, on a daily basis. The data concerns possible exposures and warnings that have been displayed to you, test results you have retrieved, and whether you have warned other users, and information about your smartphone’s operating system. If you have provided further details above (region, age group), then the RKI will also receive this information.\n\nThe RKI will compile this data into statistics and analyze it to assess the effectiveness and functioning of the app, and draw conclusions regarding the pandemic. The resulting knowledge will help to improve the app’s features and make it more user-friendly, as well as to inform other pandemic response measures.\n\nBefore your data is analyzed, it is necessary to ensure that each app that shares data is only counted once, so as not to distort the statistics. This is why the authenticity of your app needs to be verified. For this purpose, a unique identifier is generated by your smartphone and transmitted to Apple in the U.S., so that Apple can confirm the authenticity of your app to the RKI. The identifier contains information about the version of your smartphone and the app. Apple does not receive any other information from the app during this process.\n\You can withdraw your consent at any time by disabling the data sharing feature in the app's settings."; +"DataDonation_Acknowledgement_Content" = "By tapping on “Accept”, you consent to the following:\n\nThe app will transmit information it records to the RKI, on a daily basis. The data concerns possible exposures and warnings that have been displayed to you, test results you have retrieved, and whether you have warned other users, and information about your smartphone’s operating system. If you have provided further details above (region, age group), then the RKI will also receive this information.\n\nThe RKI will compile this data into statistics and analyze it to assess the effectiveness and functioning of the app, and draw conclusions regarding the pandemic. The resulting knowledge will help to improve the app’s features and make it more user-friendly, as well as to inform other pandemic response measures.\n\nBefore your data is analyzed, it is necessary to ensure that each app that shares data is only counted once, so as not to distort the statistics. This is why the authenticity of your app needs to be verified. For this purpose, a unique identifier is generated by your smartphone and transmitted to Apple in the U.S., so that Apple can confirm the authenticity of your app to the RKI. The identifier contains information about the version of your smartphone and the app. Apple does not receive any other information from the app during this process.\n\nYou can withdraw your consent at any time by disabling the data sharing feature in the app's settings."; "DataDonation_Acknowledgement_BulletPoint_1" = "Your consent is voluntary. If you do not give your consent, you will still be able to use the app."; @@ -111,4 +111,4 @@ /* Data Donation App Settings*/ -"ppa_settings_privacy_information_body" = "By enabling “Share Data” above, you consent to the following:\n\nThe app will transmit information it records to the RKI, on a daily basis. The data concerns possible exposures and warnings that have been displayed to you, test results you have retrieved, and whether you have warned other users, and information about your smartphone’s operating system. If you have provided further details above (region, age group), then the RKI will also receive this information.\n\nThe RKI will compile this data into statistics and analyze it to assess the effectiveness and functioning of the app, and draw conclusions regarding the pandemic. The resulting knowledge will help to improve the app’s features and make it more user-friendly, as well as to inform other pandemic response measures.\n\nBefore your data is analyzed, it is necessary to ensure that each app that shares data is only counted once, so as not to distort the statistics. This is why the authenticity of your app needs to be verified. For this purpose, a unique identifier is generated by your smartphone and transmitted to Apple in the U.S., so that Apple can confirm the authenticity of your app to the RKI. The identifier contains information about the version of your smartphone and the app. Apple does not receive any other information from the app during this process.\n\n You can withdraw your consent at any time by disabling “Share Data” above."; +"ppa_settings_privacy_information_body" = "By enabling “Share Data” above, you consent to the following:\n\nThe app will transmit information it records to the RKI, on a daily basis. The data concerns possible exposures and warnings that have been displayed to you, test results you have retrieved, and whether you have warned other users, and information about your smartphone’s operating system. If you have provided further details above (region, age group), then the RKI will also receive this information.\n\nThe RKI will compile this data into statistics and analyze it to assess the effectiveness and functioning of the app, and draw conclusions regarding the pandemic. The resulting knowledge will help to improve the app’s features and make it more user-friendly, as well as to inform other pandemic response measures.\n\nBefore your data is analyzed, it is necessary to ensure that each app that shares data is only counted once, so as not to distort the statistics. This is why the authenticity of your app needs to be verified. For this purpose, a unique identifier is generated by your smartphone and transmitted to Apple in the U.S., so that Apple can confirm the authenticity of your app to the RKI. The identifier contains information about the version of your smartphone and the app. Apple does not receive any other information from the app during this process.\n\nYou can withdraw your consent at any time by disabling “Share Data” above."; diff --git a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings index 4444d526fd0..a564cf49abc 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings @@ -112,4 +112,4 @@ /* Data Donation App Settings*/ -"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\Uygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\n Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; +"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\nUygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\nYukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 6c6005af221..104a2bd623b 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -113,7 +113,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { .section( cells: [ .legalExtendedDataDonation( - title: NSAttributedString(string: AppStrings.), + title: NSAttributedString(string: AppStrings.DataDonation.Info.legalTitle), description: NSAttributedString( string: AppStrings.DataDonation.AppSettings.ppaSettingsPrivacyInformationBody, attributes: [.font: UIFont.preferredFont(forTextStyle: .body)]), diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index 63687237da4..882851acdaa 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -3,27 +3,15 @@ // import XCTest +@testable import ENA class DataDonationDetailsViewModelTests: XCTestCase { - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } + let model = DataDonationDetailsViewModel() + let tableViewModel = model.dynamicTableViewModel - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } + } } From 306df9af30da02050b6a0317a153adea190ca232 Mon Sep 17 00:00:00 2001 From: Pascal Brause Date: Fri, 12 Feb 2021 14:40:19 +0100 Subject: [PATCH 23/39] Make sure every analytics data is removed when the user revokes his consent. Also, when he gives it, plain data are given. --- .../DataDonationModel/DataDonationModel.swift | 1 - .../ENA/ENA/Source/Workers/Store/SecureStore.swift | 10 +++++++++- src/xcode/ENA/ENA/Source/Workers/Store/Store.swift | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift index b86a15e13f3..c1728602c2d 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift @@ -57,7 +57,6 @@ struct DataDonationModel { mutating func save() { store.isPrivacyPreservingAnalyticsConsentGiven = isConsentGiven guard isConsentGiven else { - store.userMetadata = UserMetadata(federalState: nil, administrativeUnit: nil, ageGroup: nil) region = nil federalStateName = nil age = nil diff --git a/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift b/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift index 0fea20c4fb0..e646863e7c3 100644 --- a/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift +++ b/src/xcode/ENA/ENA/Source/Workers/Store/SecureStore.swift @@ -357,7 +357,15 @@ extension SecureStore: PrivacyPreservingProviding { var isPrivacyPreservingAnalyticsConsentGiven: Bool { get { kvStore["isPrivacyPreservingAnalyticsConsentGiven"] as Bool? ?? false } - set { kvStore["isPrivacyPreservingAnalyticsConsentGiven"] = newValue } + set { + kvStore["isPrivacyPreservingAnalyticsConsentGiven"] = newValue + currentRiskExposureMetadata = nil + previousRiskExposureMetadata = nil + userMetadata = nil + lastSubmittedPPAData = nil + lastAppReset = nil + lastSubmissionAnalytics = nil + } } var otpToken: OTPToken? { diff --git a/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift b/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift index 20f5883a29b..b82039568ec 100644 --- a/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift +++ b/src/xcode/ENA/ENA/Source/Workers/Store/Store.swift @@ -137,7 +137,7 @@ protocol StatisticsCaching: AnyObject { } protocol PrivacyPreservingProviding: AnyObject { - /// A boolean storing if the user has already confirmed to collect and submit the data for PPA + /// A boolean storing if the user has already confirmed to collect and submit the data for PPA. By setting it, the existing anlytics data will be reset. var isPrivacyPreservingAnalyticsConsentGiven: Bool { get set } /// OTP for user survey link generation var otpToken: OTPToken? { get set } From 8f67276768e508ad184e3d31e72a501f10a2a07c Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 14:43:05 +0100 Subject: [PATCH 24/39] addedd simpl unittest for model --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 22 +++++++--- .../DefaultDataDonationViewModelTests.swift | 0 .../__tests__/testData.json | 0 .../__tests__/testDataInvalid.json | 0 .../DataDonationModel.swift | 0 .../District.swift | 2 +- .../__tests__/DataDonationModelTests.swift | 0 .../Model/__tests__/DistrictTests.swift | 40 +++++++++++++++++++ 8 files changed, 58 insertions(+), 6 deletions(-) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{ => DataDonationViewModels}/__tests__/DefaultDataDonationViewModelTests.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{ => DataDonationViewModels}/__tests__/testData.json (100%) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{ => DataDonationViewModels}/__tests__/testDataInvalid.json (100%) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{DataDonationModel => Model}/DataDonationModel.swift (100%) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{DataDonationModel => Model}/District.swift (97%) rename src/xcode/ENA/ENA/Source/Scenes/DataDonation/{ => Model}/__tests__/DataDonationModelTests.swift (100%) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index 47942246860..ddebf3cea8b 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -686,6 +686,7 @@ BAD962FB25668F4000FAB615 /* TestResultAvailableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD962FA25668F4000FAB615 /* TestResultAvailableViewController.swift */; }; BAD9630025668F8E00FAB615 /* TestResultAvailableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */; }; BADBC81B25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */; }; + BADBC82925D6BB6400488DB7 /* DistrictTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC82825D6BB6400488DB7 /* DistrictTests.swift */; }; BAE20FF325C8321300162966 /* DMKeyValueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */; }; BAE2101025C8460900162966 /* PPACDeviceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */; }; BAE2101B25C8463400162966 /* PPACDeviceCheckMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */; }; @@ -1506,6 +1507,7 @@ BAD962FA25668F4000FAB615 /* TestResultAvailableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestResultAvailableViewController.swift; sourceTree = ""; }; BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestResultAvailableViewModel.swift; sourceTree = ""; }; BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModel.swift; sourceTree = ""; }; + BADBC82825D6BB6400488DB7 /* DistrictTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistrictTests.swift; sourceTree = ""; }; BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueTableViewCell.swift; sourceTree = ""; }; BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheck.swift; sourceTree = ""; }; BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheckMock.swift; sourceTree = ""; }; @@ -3843,8 +3845,7 @@ BA0073BB25D189E50036DFDD /* DataDonation */ = { isa = PBXGroup; children = ( - BA7D177725D547BE006B9EBF /* __tests__ */, - BA7D17CC25D59465006B9EBF /* DataDonationModel */, + BA7D17CC25D59465006B9EBF /* Model */, BA0073BD25D18A5B0036DFDD /* DataDonationViewController.swift */, BA7D17CB25D59440006B9EBF /* DataDonationViewModels */, ); @@ -4017,7 +4018,6 @@ children = ( BA7D178025D549AA006B9EBF /* testData.json */, BA7D178825D558FD006B9EBF /* testDataInvalid.json */, - BA7D177825D547D4006B9EBF /* DataDonationModelTests.swift */, BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */, ); path = __tests__; @@ -4026,6 +4026,7 @@ BA7D17CB25D59440006B9EBF /* DataDonationViewModels */ = { isa = PBXGroup; children = ( + BA7D177725D547BE006B9EBF /* __tests__ */, BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */, BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */, BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, @@ -4034,13 +4035,14 @@ path = DataDonationViewModels; sourceTree = ""; }; - BA7D17CC25D59465006B9EBF /* DataDonationModel */ = { + BA7D17CC25D59465006B9EBF /* Model */ = { isa = PBXGroup; children = ( + BADBC82D25D6BD2800488DB7 /* __tests__ */, BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */, BA0073FF25D1A1810036DFDD /* District.swift */, ); - path = DataDonationModel; + path = Model; sourceTree = ""; }; BA7D17D025D5947B006B9EBF /* DataDonationDetails */ = { @@ -4142,6 +4144,15 @@ path = TestResultAvailable; sourceTree = ""; }; + BADBC82D25D6BD2800488DB7 /* __tests__ */ = { + isa = PBXGroup; + children = ( + BA7D177825D547D4006B9EBF /* DataDonationModelTests.swift */, + BADBC82825D6BB6400488DB7 /* DistrictTests.swift */, + ); + path = __tests__; + sourceTree = ""; + }; BAEC99BE258B6FFA00B98ECA /* __tests__ */ = { isa = PBXGroup; children = ( @@ -5175,6 +5186,7 @@ 01A1B467252E19D000841B63 /* ExposureSubmissionCoordinatorModelTests.swift in Sources */, B1EAEC8F247118D1003BE9A2 /* URLSession+ConvenienceTests.swift in Sources */, A32C046524D96348005BEA61 /* HTTPClient+PlausibeDeniabilityTests.swift in Sources */, + BADBC82925D6BB6400488DB7 /* DistrictTests.swift in Sources */, 0156F05C25D2DA2300543640 /* DeadmanNotificationManagerTests.swift in Sources */, A372DA4224BF3E29003248BB /* MockExposureSubmissionCoordinator.swift in Sources */, BA9BCF7725B09B5500DD7974 /* DiaryOverviewDayCellModelTests.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DefaultDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DefaultDataDonationViewModelTests.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testData.json b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/testData.json similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testData.json rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/testData.json diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testDataInvalid.json b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/testDataInvalid.json similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/testDataInvalid.json rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/testDataInvalid.json diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/DataDonationModel.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/District.swift similarity index 97% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/District.swift index 995854c2a19..e95aaee84c3 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationModel/District.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/District.swift @@ -78,7 +78,7 @@ enum FederalStateName: String, CaseIterable, Codable { } } -enum FederalStateShortName: String, Codable { +enum FederalStateShortName: String, CaseIterable, Codable { case bb = "BB" case be = "BE" case bw = "BW" diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DataDonationModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift similarity index 100% rename from src/xcode/ENA/ENA/Source/Scenes/DataDonation/__tests__/DataDonationModelTests.swift rename to src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift new file mode 100644 index 00000000000..f7ef6256702 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift @@ -0,0 +1,40 @@ +//// +// 🦠 Corona-Warn-App +// + +import XCTest +@testable import ENA + +class DistrictTests: XCTestCase { + + func testGIVEN_FederalStateName_THEN_MatchesLastKnownValues() { + // GIVEN + let countStates = FederalStateName.allCases.count + let countShortname = FederalStateShortName.allCases.count + + // THEN + XCTAssertEqual(countStates, 16) + XCTAssertEqual(countShortname, 16) + } + + func testGIVEN_givenDistrictElement_THEN_ValuesAreSet() { + // GIVEN + let districtElement = DistrictElement( + districtName: "Göppingen", + districtShortName: "BW", + districtID: 1, + federalStateName: .badenWürttemberg, + federalStateShortName: .bw, + federalStateID: 1 + ) + + // THEN + XCTAssertEqual(districtElement.districtName, "Göppingen") + XCTAssertEqual(districtElement.districtShortName, "BW") + XCTAssertEqual(districtElement.districtID, 1) + XCTAssertEqual(districtElement.federalStateName, .badenWürttemberg) + XCTAssertEqual(districtElement.federalStateShortName, .bw) + XCTAssertEqual(districtElement.federalStateID, 1) + } + +} From 1c0ab51a35c52923fc230d30d3c35367675d5faf Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 14:49:18 +0100 Subject: [PATCH 25/39] unit test for DataDonationDetailsViewModel --- .../DataDonationDetailsViewModelTests.swift | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index 882851acdaa..1ae2266487e 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -7,11 +7,24 @@ import XCTest class DataDonationDetailsViewModelTests: XCTestCase { - func testExample() throws { - let model = DataDonationDetailsViewModel() + let model = DataDonationDetailsViewModel() + + func testForOneSection() throws { + // GIVEN let tableViewModel = model.dynamicTableViewModel + // WHEN + let numberOfSections = tableViewModel.content.count + // THEN + XCTAssertEqual(numberOfSections, 1) + } - - } + func testForNumberOfCells() throws { + // GIVEN + let tableViewModel = model.dynamicTableViewModel + // WHEN + let numberOfCells = tableViewModel.section(0).cells.count + // THEN + XCTAssertEqual(numberOfCells, 36) + } } From 2d0638bf1b073ac27df98f9685feb2c59d0d0f8d Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 15:08:04 +0100 Subject: [PATCH 26/39] unit test --- .../DataDonationDetailsViewModelTests.swift | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index 1ae2266487e..62c93834ffb 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -25,6 +25,30 @@ class DataDonationDetailsViewModelTests: XCTestCase { let numberOfCells = tableViewModel.section(0).cells.count // THEN XCTAssertEqual(numberOfCells, 36) + + let cell2 = tableViewModel.section(0).cells[2] + XCTAssertEqual(cell2.cellReuseIdentifier.rawValue, "roundedCell") + + } + + func testReuseIdentifierCell34() throws { + // GIVEN + let tableViewModel = model.dynamicTableViewModel + // WHEN + let cell34 = tableViewModel.section(0).cells[34] + // THEN + XCTAssertEqual(cell34.cellReuseIdentifier.rawValue, "bulletPointCell") + + } + + func testReuseIdentifierCell35() throws { + // GIVEN + let tableViewModel = model.dynamicTableViewModel + // WHEN + let cell35 = tableViewModel.section(0).cells[35] + // THEN + XCTAssertEqual(cell35.cellReuseIdentifier.rawValue, "labelCell") + } } From bf54ce737267fff5977144b98eebd2e0247625ac Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 15:10:21 +0100 Subject: [PATCH 27/39] refactoring unit test --- .../__tests__/DataDonationDetailsViewModelTests.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index 62c93834ffb..35867bc722e 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -25,10 +25,15 @@ class DataDonationDetailsViewModelTests: XCTestCase { let numberOfCells = tableViewModel.section(0).cells.count // THEN XCTAssertEqual(numberOfCells, 36) - + } + + func testReuseIdentifierCell2() throws { + // GIVEN + let tableViewModel = model.dynamicTableViewModel + // WHEN let cell2 = tableViewModel.section(0).cells[2] + // THEN XCTAssertEqual(cell2.cellReuseIdentifier.rawValue, "roundedCell") - } func testReuseIdentifierCell34() throws { @@ -38,7 +43,6 @@ class DataDonationDetailsViewModelTests: XCTestCase { let cell34 = tableViewModel.section(0).cells[34] // THEN XCTAssertEqual(cell34.cellReuseIdentifier.rawValue, "bulletPointCell") - } func testReuseIdentifierCell35() throws { @@ -48,7 +52,6 @@ class DataDonationDetailsViewModelTests: XCTestCase { let cell35 = tableViewModel.section(0).cells[35] // THEN XCTAssertEqual(cell35.cellReuseIdentifier.rawValue, "labelCell") - } } From f6ea7677a4b9737c3771928290b545898af1439c Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 15:29:01 +0100 Subject: [PATCH 28/39] refactoring and enhancing unit tests --- .../DataDonationDetailsViewModelTests.swift | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index 35867bc722e..ff1b8bf0d3c 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -27,7 +27,7 @@ class DataDonationDetailsViewModelTests: XCTestCase { XCTAssertEqual(numberOfCells, 36) } - func testReuseIdentifierCell2() throws { + func testReuseIdentifierRoundedCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel // WHEN @@ -36,22 +36,42 @@ class DataDonationDetailsViewModelTests: XCTestCase { XCTAssertEqual(cell2.cellReuseIdentifier.rawValue, "roundedCell") } - func testReuseIdentifierCell34() throws { + // cells 8-11, 13-16, 18-22, 24-30, 32-34 + func testReuseIdentifierBulletPointCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel + let indexSet = [8, 9, 10, 11, 13, 14, 15, 16, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34] // WHEN - let cell34 = tableViewModel.section(0).cells[34] - // THEN - XCTAssertEqual(cell34.cellReuseIdentifier.rawValue, "bulletPointCell") + for i in indexSet { + let cell = tableViewModel.section(0).cells[i] + // THEN + XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "bulletPointCell") + } } - func testReuseIdentifierCell35() throws { + // cells 0, 4, 6, 12, 17, 23, 31, 35 + func testReuseIdentifierLabelCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel + let indexSet = [0, 4, 6, 12, 17, 23, 31, 35] // WHEN - let cell35 = tableViewModel.section(0).cells[35] - // THEN - XCTAssertEqual(cell35.cellReuseIdentifier.rawValue, "labelCell") + for i in indexSet { + let cell = tableViewModel.section(0).cells[i] + // THEN + XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "labelCell") + } + } + + func testReuseIdentifierSpaceCell() throws { + // GIVEN + let tableViewModel = model.dynamicTableViewModel + let indexSet = [1, 3, 5, 7] + // WHEN + for i in indexSet { + let cell = tableViewModel.section(0).cells[i] + // THEN + XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "spaceCell") + } } } From 14dfde0fe71d9f1862c1170257b2e8bcf2816ab4 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 15:24:30 +0100 Subject: [PATCH 29/39] splitup tetst for BaseModel and DefaultModel --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 4 + .../DefaultDataDonationViewModel.swift | 10 +- .../BaseDataDonationViewModelTests.swift | 128 ++++++++++++++++++ .../DefaultDataDonationViewModelTests.swift | 104 +++++--------- .../Model/DataDonationModel.swift | 2 - 5 files changed, 172 insertions(+), 76 deletions(-) create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index ddebf3cea8b..f1744eea3fa 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -687,6 +687,7 @@ BAD9630025668F8E00FAB615 /* TestResultAvailableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */; }; BADBC81B25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */; }; BADBC82925D6BB6400488DB7 /* DistrictTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC82825D6BB6400488DB7 /* DistrictTests.swift */; }; + BADBC85625D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */; }; BAE20FF325C8321300162966 /* DMKeyValueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */; }; BAE2101025C8460900162966 /* PPACDeviceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */; }; BAE2101B25C8463400162966 /* PPACDeviceCheckMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */; }; @@ -1508,6 +1509,7 @@ BAD962FF25668F8E00FAB615 /* TestResultAvailableViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestResultAvailableViewModel.swift; sourceTree = ""; }; BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModel.swift; sourceTree = ""; }; BADBC82825D6BB6400488DB7 /* DistrictTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistrictTests.swift; sourceTree = ""; }; + BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModelTests.swift; sourceTree = ""; }; BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueTableViewCell.swift; sourceTree = ""; }; BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheck.swift; sourceTree = ""; }; BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheckMock.swift; sourceTree = ""; }; @@ -4018,6 +4020,7 @@ children = ( BA7D178025D549AA006B9EBF /* testData.json */, BA7D178825D558FD006B9EBF /* testDataInvalid.json */, + BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */, BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */, ); path = __tests__; @@ -5252,6 +5255,7 @@ 2FD881CC2490F65C00BEC8FC /* ExposureSubmissionHotlineViewControllerTest.swift in Sources */, 01A97DD12506768F00C07C37 /* DatePickerOptionViewModelTests.swift in Sources */, 0177F4B125503805009DD568 /* ScanInstanceTest.swift in Sources */, + BADBC85625D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift in Sources */, B120C7C924AFE7B800F68FF1 /* ActiveTracingTests.swift in Sources */, 35AA4AF4259B40FC00D32306 /* CryptoFallbackTests.swift in Sources */, 01B72BC02583875600A3E3BC /* DiaryDayViewModelTest.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index 2e9d60f3098..feb4b9ff5b7 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -8,6 +8,8 @@ import OpenCombine final class DefaultDataDonationViewModel: BaseDataDonationViewModel { + // MARK: - Overrides + /// override layout of the dynamiv tableview model override var dynamicTableViewModel: DynamicTableViewModel { /// create the top section with the illustration and title text @@ -101,9 +103,9 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { return dynamicTableViewModel } - // MARK: - Private + // MARK: - Internal - private func didTapSelectStateButton() { + func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, title: AppStrings.DataDonation.ValueSelection.Title.State, @@ -121,7 +123,7 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } - private func didTapSelectRegionButton() { + func didTapSelectRegionButton() { guard let federalStateName = dataDonationModel.federalStateName else { Log.debug("Missing federal state to load regions", log: .ppac) return @@ -143,7 +145,7 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } - private func didTapAgeButton() { + func didTapAgeButton() { let selectValueViewModel = SelectValueViewModel( AgeGroup.allCases.map({ $0.text }), title: AppStrings.DataDonation.ValueSelection.Title.Age, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift new file mode 100644 index 00000000000..21f82ac3bfe --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift @@ -0,0 +1,128 @@ +//// +// 🦠 Corona-Warn-App +// + +import XCTest +@testable import ENA + +class BaseDataDonationViewModelTests: XCTestCase { + + /// test if the view model will format texts correct + func testGIVEN_ViewModelWithStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + + let viewModel = BaseDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + let friendlyFederalStateName = viewModel.friendlyFederalStateName + let friendlyRegionName = viewModel.friendlyRegionName + let friendlyAgeName = viewModel.friendlyAgeName + + // THEN + XCTAssertEqual(friendlyFederalStateName, FederalStateName.schleswigHolstein.rawValue) + XCTAssertEqual(friendlyRegionName, "Herzogtum Lauenburg") + XCTAssertEqual(friendlyAgeName, AgeGroup.ageBelow29.text) + } + + /// test if the view model will format empty texts correct + func testGIVEN_ViewModelWithoutStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { + // GIVEN + let mockStore = MockTestStore() + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + + let viewModel = BaseDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + let friendlyFederalStateName = viewModel.friendlyFederalStateName + let friendlyRegionName = viewModel.friendlyRegionName + let friendlyAgeName = viewModel.friendlyAgeName + + // THEN + + XCTAssertEqual(friendlyFederalStateName, AppStrings.DataDonation.Info.noSelectionState) + XCTAssertEqual(friendlyRegionName, AppStrings.DataDonation.Info.noSelectionRegion) + XCTAssertEqual(friendlyAgeName, AppStrings.DataDonation.Info.noSelectionAgeGroup) + } + + // test if an empty store will update if the view model will save with consent given + func testGIVEN_ViewModelWithEmptyStore_WHEN_SaveWithConset_THEN_StoreIsUpdatedWithValues() throws { + // GIVEN + let mockStore = MockTestStore() + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + model.region = "Offenbach (Landkreis)" // ID = 11006438 + model.federalStateName = "Hessen" + model.age = AgeGroup.ageBelow29.text + + let viewModel = BaseDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + viewModel.save(consentGiven: true) + + // THEN + XCTAssertTrue(mockStore.isPrivacyPreservingAnalyticsConsentGiven) + XCTAssertEqual(mockStore.userMetadata?.ageGroup, .ageBelow29) + XCTAssertEqual(mockStore.userMetadata?.federalState, .hessen) + XCTAssertEqual(mockStore.userMetadata?.administrativeUnit, 11006438) + } + + // test if a non empty store will update if the view model will save with consent given + func testGIVEN_ViewModelWithStoredValues_WHEN_SaveWithConset_THEN_StoreIsUpdatedWithValues() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBetween30And59) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + model.region = "Offenbach (Landkreis)" // ID = 11006438 + model.federalStateName = "Hessen" + model.age = AgeGroup.ageBelow29.text + + let viewModel = BaseDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + viewModel.save(consentGiven: true) + + // THEN + XCTAssertTrue(mockStore.isPrivacyPreservingAnalyticsConsentGiven) + XCTAssertEqual(mockStore.userMetadata?.ageGroup, .ageBelow29) + XCTAssertEqual(mockStore.userMetadata?.federalState, .hessen) + XCTAssertEqual(mockStore.userMetadata?.administrativeUnit, 11006438) + } + + // test if a non empty store will cleared if the view model will save with consent not given + func testGIVEN_ViewModelWithStoredValues_WHEN_SaveWithoutConset_THEN_StoreIsUpdatedWithValues() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBetween30And59) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + model.region = "Offenbach (Landkreis)" // ID = 11006438 + model.federalStateName = "Hessen" + model.age = AgeGroup.ageBelow29.text + + let viewModel = BaseDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + viewModel.save(consentGiven: false) + + // THEN + XCTAssertFalse(mockStore.isPrivacyPreservingAnalyticsConsentGiven) +// XCTAssertNil(mockStore.userMetadata?.ageGroup) +// XCTAssertNil(mockStore.userMetadata?.federalState) +// XCTAssertNil(mockStore.userMetadata?.administrativeUnit) + } + +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift index 97b72efbb2d..f2b751afd0f 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/DefaultDataDonationViewModelTests.swift @@ -7,8 +7,7 @@ import XCTest class DefaultDataDonationViewModelTests: XCTestCase { - /// test if the view model will format texts correct - func testGIVEN_ViewModelWithStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { + func testGIVEN_DataDonationModel_WHEN_getDynamicTableViewModel_THEN_SectionsAndCellCountsMatch() throws { // GIVEN let mockStore = MockTestStore() mockStore.isPrivacyPreservingAnalyticsConsentGiven = true @@ -20,109 +19,74 @@ class DefaultDataDonationViewModelTests: XCTestCase { let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) // WHEN - let friendlyFederalStateName = viewModel.friendlyFederalStateName - let friendlyRegionName = viewModel.friendlyRegionName - let friendlyAgeName = viewModel.friendlyAgeName + let dynamicTableViewModel = viewModel.dynamicTableViewModel // THEN - XCTAssertEqual(friendlyFederalStateName, FederalStateName.schleswigHolstein.rawValue) - XCTAssertEqual(friendlyRegionName, "Herzogtum Lauenburg") - XCTAssertEqual(friendlyAgeName, AgeGroup.ageBelow29.text) + XCTAssertEqual(dynamicTableViewModel.numberOfSection, 4) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 0), 2) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 1), 5) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 2), 1) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 3), 2) } - /// test if the view model will format empty texts correct - func testGIVEN_ViewModelWithoutStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { + func testGIVEN_DataDonationModel_WHEN_TapSelectState_THEN_ClosureGetsCalled() throws { // GIVEN let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - - let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) // WHEN - let friendlyFederalStateName = viewModel.friendlyFederalStateName - let friendlyRegionName = viewModel.friendlyRegionName - let friendlyAgeName = viewModel.friendlyAgeName + viewModel.didTapSelectStateButton() // THEN - - XCTAssertEqual(friendlyFederalStateName, AppStrings.DataDonation.Info.noSelectionState) - XCTAssertEqual(friendlyRegionName, AppStrings.DataDonation.Info.noSelectionRegion) - XCTAssertEqual(friendlyAgeName, AppStrings.DataDonation.Info.noSelectionAgeGroup) + wait(for: [expectationPresentList], timeout: .medium) } - // test if an empty store will update if the view model will save with consent given - func testGIVEN_ViewModelWithEmptyStore_WHEN_SaveWithConset_THEN_StoreIsUpdatedWithValues() throws { - // GIVEN - let mockStore = MockTestStore() - - let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) - var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - model.region = "Offenbach (Landkreis)" // ID = 11006438 - model.federalStateName = "Hessen" - model.age = AgeGroup.ageBelow29.text - - let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) - - // WHEN - viewModel.save(consentGiven: true) - - // THEN - XCTAssertTrue(mockStore.isPrivacyPreservingAnalyticsConsentGiven) - XCTAssertEqual(mockStore.userMetadata?.ageGroup, .ageBelow29) - XCTAssertEqual(mockStore.userMetadata?.federalState, .hessen) - XCTAssertEqual(mockStore.userMetadata?.administrativeUnit, 11006438) - } - - // test if a non empty store will update if the view model will save with consent given - func testGIVEN_ViewModelWithStoredValues_WHEN_SaveWithConset_THEN_StoreIsUpdatedWithValues() throws { + func testGIVEN_DataDonationModel_WHEN_TapSelectRegion_THEN_ClosureGetsCalled() throws { // GIVEN let mockStore = MockTestStore() mockStore.isPrivacyPreservingAnalyticsConsentGiven = true - mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBetween30And59) + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) - var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - model.region = "Offenbach (Landkreis)" // ID = 11006438 - model.federalStateName = "Hessen" - model.age = AgeGroup.ageBelow29.text - - let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) // WHEN - viewModel.save(consentGiven: true) + viewModel.didTapSelectRegionButton() // THEN - XCTAssertTrue(mockStore.isPrivacyPreservingAnalyticsConsentGiven) - XCTAssertEqual(mockStore.userMetadata?.ageGroup, .ageBelow29) - XCTAssertEqual(mockStore.userMetadata?.federalState, .hessen) - XCTAssertEqual(mockStore.userMetadata?.administrativeUnit, 11006438) + wait(for: [expectationPresentList], timeout: .medium) } - // test if a non empty store will cleared if the view model will save with consent not given - func testGIVEN_ViewModelWithStoredValues_WHEN_SaveWithoutConset_THEN_StoreIsUpdatedWithValues() throws { + func testGIVEN_DataDonationModel_WHEN_TapSelectAge_THEN_ClosureGetsCalled() throws { // GIVEN let mockStore = MockTestStore() mockStore.isPrivacyPreservingAnalyticsConsentGiven = true - mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBetween30And59) + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) - var model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) - model.region = "Offenbach (Landkreis)" // ID = 11006438 - model.federalStateName = "Hessen" - model.age = AgeGroup.ageBelow29.text - - let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = DefaultDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) // WHEN - viewModel.save(consentGiven: false) + viewModel.didTapAgeButton() // THEN - XCTAssertFalse(mockStore.isPrivacyPreservingAnalyticsConsentGiven) - XCTAssertNil(mockStore.userMetadata?.ageGroup) - XCTAssertNil(mockStore.userMetadata?.federalState) - XCTAssertNil(mockStore.userMetadata?.administrativeUnit) + wait(for: [expectationPresentList], timeout: .medium) } } diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift index c1728602c2d..797c9af7b08 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift @@ -32,8 +32,6 @@ struct DataDonationModel { }?.districtName } - // MARK: - Public - // MARK: - Internal var isConsentGiven: Bool From 2bb754e03168f39e61e8426cc9dac6d342b8086e Mon Sep 17 00:00:00 2001 From: Pascal Brause Date: Fri, 12 Feb 2021 15:36:01 +0100 Subject: [PATCH 30/39] fix mock store --- .../Services/__tests__/Mocks/MockTestStore.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 a4fb2fe5a14..dbab82ea462 100644 --- a/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift +++ b/src/xcode/ENA/ENA/Source/Services/__tests__/Mocks/MockTestStore.swift @@ -78,7 +78,16 @@ final class MockTestStore: Store, AppConfigCaching, PrivacyPreservingProviding { // MARK: - PrivacyPreservingProviding - var isPrivacyPreservingAnalyticsConsentGiven: Bool = false + var isPrivacyPreservingAnalyticsConsentGiven: Bool = false { + didSet { + currentRiskExposureMetadata = nil + previousRiskExposureMetadata = nil + userMetadata = nil + lastSubmittedPPAData = nil + lastAppReset = nil + lastSubmissionAnalytics = nil + } + } var otpToken: OTPToken? var otpAuthorizationDate: Date? var ppacApiToken: TimestampedToken? From f41072a9a5ca5d74fe449e43164a4d1cb59474c8 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 15:40:43 +0100 Subject: [PATCH 31/39] added unittest for SettingsDataDonationViewModel --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 8 +- .../BaseDataDonationViewModel.swift | 28 +++++ ...ynamicCell+LegalExtendedDataDonation.swift | 33 ----- .../SettingsDataDonationViewModel.swift | 12 +- .../SettingsDataDonationViewModelTests.swift | 114 ++++++++++++++++++ 5 files changed, 154 insertions(+), 41 deletions(-) delete mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift create mode 100644 src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/SettingsDataDonationViewModelTests.swift diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index f1744eea3fa..14bc9a9488c 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -656,7 +656,6 @@ BA7D178925D5590C006B9EBF /* testDataInvalid.json in Resources */ = {isa = PBXBuildFile; fileRef = BA7D178825D558FD006B9EBF /* testDataInvalid.json */; }; BA7D178E25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */; }; BA7D17B725D59373006B9EBF /* SettingsDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */; }; - BA7D17BF25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */; }; BA7EABAD25C973FE001AA5FE /* DMKeyValueCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */; }; BA811B4D25D422B600C9BC98 /* DataDonationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */; }; BA8824D725D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json in Resources */ = {isa = PBXBuildFile; fileRef = BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */; }; @@ -688,6 +687,7 @@ BADBC81B25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */; }; BADBC82925D6BB6400488DB7 /* DistrictTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC82825D6BB6400488DB7 /* DistrictTests.swift */; }; BADBC85625D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */; }; + BADBC86725D6C7FD00488DB7 /* SettingsDataDonationViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADBC86625D6C7FD00488DB7 /* SettingsDataDonationViewModelTests.swift */; }; BAE20FF325C8321300162966 /* DMKeyValueTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */; }; BAE2101025C8460900162966 /* PPACDeviceCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */; }; BAE2101B25C8463400162966 /* PPACDeviceCheckMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */; }; @@ -1479,7 +1479,6 @@ BA7D178825D558FD006B9EBF /* testDataInvalid.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = testDataInvalid.json; sourceTree = ""; }; BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultDataDonationViewModelTests.swift; sourceTree = ""; }; BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDataDonationViewModel.swift; sourceTree = ""; }; - BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DynamicCell+LegalExtendedDataDonation.swift"; sourceTree = ""; }; BA7EABAC25C973FE001AA5FE /* DMKeyValueCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueCellViewModel.swift; sourceTree = ""; }; BA811B4C25D422B600C9BC98 /* DataDonationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataDonationModel.swift; sourceTree = ""; }; BA8824D625D2A88800AD9B11 /* ppdd-ppa-administrative-unit-set-ua-approved.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "ppdd-ppa-administrative-unit-set-ua-approved.json"; sourceTree = ""; }; @@ -1510,6 +1509,7 @@ BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModel.swift; sourceTree = ""; }; BADBC82825D6BB6400488DB7 /* DistrictTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistrictTests.swift; sourceTree = ""; }; BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDataDonationViewModelTests.swift; sourceTree = ""; }; + BADBC86625D6C7FD00488DB7 /* SettingsDataDonationViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDataDonationViewModelTests.swift; sourceTree = ""; }; BAE20FF125C8321300162966 /* DMKeyValueTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DMKeyValueTableViewCell.swift; sourceTree = ""; }; BAE2100125C83E4400162966 /* PPACDeviceCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheck.swift; sourceTree = ""; }; BAE2101A25C8463400162966 /* PPACDeviceCheckMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PPACDeviceCheckMock.swift; sourceTree = ""; }; @@ -4022,6 +4022,7 @@ BA7D178825D558FD006B9EBF /* testDataInvalid.json */, BADBC85525D6C1C500488DB7 /* BaseDataDonationViewModelTests.swift */, BA7D178D25D55EB1006B9EBF /* DefaultDataDonationViewModelTests.swift */, + BADBC86625D6C7FD00488DB7 /* SettingsDataDonationViewModelTests.swift */, ); path = __tests__; sourceTree = ""; @@ -4030,7 +4031,6 @@ isa = PBXGroup; children = ( BA7D177725D547BE006B9EBF /* __tests__ */, - BA7D17BE25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift */, BADBC81A25D6A7FF00488DB7 /* BaseDataDonationViewModel.swift */, BA0073E925D196900036DFDD /* DefaultDataDonationViewModel.swift */, BA7D17B625D59373006B9EBF /* SettingsDataDonationViewModel.swift */, @@ -4826,7 +4826,6 @@ AB1011592507C15000D392A2 /* TracingStatusHistory.swift in Sources */, 017AD16525A4559300FA2B3F /* UITableView+Dequeue.swift in Sources */, 71FE1C71247AA7B700851FEB /* DynamicTableViewHeaderImageView.swift in Sources */, - BA7D17BF25D593CB006B9EBF /* DynamicCell+LegalExtendedDataDonation.swift in Sources */, 01D69491250272CE00B45BEA /* DatePickerDayViewModel.swift in Sources */, B16457BB24DC3309002879EB /* DMLogsViewController.swift in Sources */, 01B7232F24FE4F080064C0EB /* OptionGroupViewModel.swift in Sources */, @@ -5241,6 +5240,7 @@ AB8BC34F2551BBE100F3B5A7 /* HourKeyPackagesDownloadTests.swift in Sources */, B1E23B8624FE4DD3006BCDA6 /* PublicKeyProviderTests.swift in Sources */, 01B605D9258A49E70093DB8E /* DiaryLocationTest.swift in Sources */, + BADBC86725D6C7FD00488DB7 /* SettingsDataDonationViewModelTests.swift in Sources */, F2DC809424898CE600EDC40A /* DynamicTableViewControllerFooterTests.swift in Sources */, 35358DD425A23169004FD0CB /* HTTPClientCertificatePinningTests.swift in Sources */, 01B72BA6258360FF00A3E3BC /* DiaryDayEmptyViewModelTest.swift in Sources */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift index a3421ecdad1..10d0ab77f78 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift @@ -74,3 +74,31 @@ class BaseDataDonationViewModel: DataDonationViewModelProtocol { dataDonationModel.save() } } + +internal extension DynamicCell { + + /// A `legalExtendedDataDonation` to display legal text for Data Donation screen + /// - Parameters: + /// - title: The title/header for the legal foo. + /// - description: Optional description text. + /// - bulletPoints: A list of strings to be prefixed with bullet points. + /// - accessibilityIdentifier: Optional, but highly recommended, accessibility identifier. + /// - configure: Optional custom cell configuration + /// - Returns: A `DynamicCell` to display legal texts + static func legalExtendedDataDonation( + title: NSAttributedString, + description: NSAttributedString?, + bulletPoints: [NSAttributedString]? = nil, + accessibilityIdentifier: String? = nil, + configure: CellConfigurator? = nil + ) -> Self { + .identifier(DataDonationViewController.CustomCellReuseIdentifiers.legalExtended) { viewController, cell, indexPath in + guard let cell = cell as? DynamicLegalExtendedCell else { + fatalError("could not initialize cell of type `DynamicLegalExtendedCell`") + } + cell.configure(title: title, description: description, bulletPoints: bulletPoints) + configure?(viewController, cell, indexPath) + } + } + +} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift deleted file mode 100644 index 2f4d97847fd..00000000000 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DynamicCell+LegalExtendedDataDonation.swift +++ /dev/null @@ -1,33 +0,0 @@ -//// -// 🦠 Corona-Warn-App -// - -import Foundation - -extension DynamicCell { - - /// A `legalExtendedDataDonation` to display legal text for Data Donation screen - /// - Parameters: - /// - title: The title/header for the legal foo. - /// - description: Optional description text. - /// - bulletPoints: A list of strings to be prefixed with bullet points. - /// - accessibilityIdentifier: Optional, but highly recommended, accessibility identifier. - /// - configure: Optional custom cell configuration - /// - Returns: A `DynamicCell` to display legal texts - static func legalExtendedDataDonation( - title: NSAttributedString, - description: NSAttributedString?, - bulletPoints: [NSAttributedString]? = nil, - accessibilityIdentifier: String? = nil, - configure: CellConfigurator? = nil - ) -> Self { - .identifier(DataDonationViewController.CustomCellReuseIdentifiers.legalExtended) { viewController, cell, indexPath in - guard let cell = cell as? DynamicLegalExtendedCell else { - fatalError("could not initialize cell of type `DynamicLegalExtendedCell`") - } - cell.configure(title: title, description: description, bulletPoints: bulletPoints) - configure?(viewController, cell, indexPath) - } - } - -} diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 104a2bd623b..a03366eb226 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -8,6 +8,8 @@ import OpenCombine final class SettingsDataDonationViewModel: BaseDataDonationViewModel { + // MARK: - Overrides + /// we use a slitly different string if no federal state was selected override var friendlyFederalStateName: String { return dataDonationModel.federalStateName ?? AppStrings.DataDonation.Info.subHeadState @@ -149,15 +151,17 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { return dynamicTableViewModel } + // MARK: - Internal + @objc /// called if the consent given switch changes - private func didToggleDatadonationSwitch(sender: UISwitch) { + func didToggleDatadonationSwitch(sender: UISwitch) { save(consentGiven: sender.isOn) DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35) { [weak self] in self?.reloadTableView.toggle() } } - private func didTapSelectStateButton() { + func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, title: AppStrings.DataDonation.ValueSelection.Title.State, @@ -176,7 +180,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } - private func didTapSelectRegionButton() { + func didTapSelectRegionButton() { guard let federalStateName = dataDonationModel.federalStateName else { Log.debug("Missing federal state to load regions", log: .ppac) return @@ -199,7 +203,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } - private func didTapAgeButton() { + func didTapAgeButton() { let selectValueViewModel = SelectValueViewModel( AgeGroup.allCases.map({ $0.text }), title: AppStrings.DataDonation.ValueSelection.Title.Age, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/SettingsDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/SettingsDataDonationViewModelTests.swift new file mode 100644 index 00000000000..e6df11b97b1 --- /dev/null +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/SettingsDataDonationViewModelTests.swift @@ -0,0 +1,114 @@ +//// +// 🦠 Corona-Warn-App +// + +import XCTest +@testable import ENA + +class SettingsDataDonationViewModelTests: XCTestCase { + + /// test if the view model will format empty texts correct + func testGIVEN_ViewModelWithoutStoredData_WHEN_getFriendlyTexts_THEN_ValuesAreEqualToStore() throws { + // GIVEN + let mockStore = MockTestStore() + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + + let viewModel = SettingsDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + let friendlyFederalStateName = viewModel.friendlyFederalStateName + let friendlyRegionName = viewModel.friendlyRegionName + let friendlyAgeName = viewModel.friendlyAgeName + + // THEN + + XCTAssertEqual(friendlyFederalStateName, AppStrings.DataDonation.Info.subHeadState ) + XCTAssertEqual(friendlyRegionName, AppStrings.DataDonation.Info.noSelectionRegion) + XCTAssertEqual(friendlyAgeName, AppStrings.DataDonation.Info.subHeadAgeGroup) + } + + func testGIVEN_DataDonationModel_WHEN_getDynamicTableViewModel_THEN_SectionsAndCellCountsMatch() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = false + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + + let viewModel = SettingsDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in }, datadonationModel: model) + + // WHEN + let dynamicTableViewModel = viewModel.dynamicTableViewModel + + // THEN + XCTAssertEqual(dynamicTableViewModel.numberOfSection, 4) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 0), 2) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 1), 2) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 2), 1) + XCTAssertEqual(dynamicTableViewModel.numberOfRows(section: 3), 2) + } + + func testGIVEN_DataDonationModel_WHEN_TapSelectState_THEN_ClosureGetsCalled() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = SettingsDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) + + // WHEN + viewModel.didTapSelectStateButton() + + // THEN + wait(for: [expectationPresentList], timeout: .medium) + } + + func testGIVEN_DataDonationModel_WHEN_TapSelectRegion_THEN_ClosureGetsCalled() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = SettingsDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) + + // WHEN + viewModel.didTapSelectRegionButton() + + // THEN + wait(for: [expectationPresentList], timeout: .medium) + } + + func testGIVEN_DataDonationModel_WHEN_TapSelectAge_THEN_ClosureGetsCalled() throws { + // GIVEN + let mockStore = MockTestStore() + mockStore.isPrivacyPreservingAnalyticsConsentGiven = true + mockStore.userMetadata = UserMetadata(federalState: FederalStateName.schleswigHolstein, administrativeUnit: 11001053, ageGroup: .ageBelow29) + + let fileURL = try XCTUnwrap(Bundle(for: type(of: self)).url(forResource: "testData", withExtension: "json")) + let model = DataDonationModel(store: mockStore, jsonFileURL: fileURL) + let expectationPresentList = expectation(description: "Present value list hit") + let viewModel = SettingsDataDonationViewModel(store: mockStore, presentSelectValueList: { _ in + expectationPresentList.fulfill() + }, datadonationModel: model) + + // WHEN + viewModel.didTapAgeButton() + + // THEN + wait(for: [expectationPresentList], timeout: .medium) + } + +} From c3799c63a83e746f64bbd6a66e83609aed93bef3 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 15:42:33 +0100 Subject: [PATCH 32/39] reenabled Unittest --- .../__tests__/BaseDataDonationViewModelTests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift index 21f82ac3bfe..304958fdc5b 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/__tests__/BaseDataDonationViewModelTests.swift @@ -120,9 +120,9 @@ class BaseDataDonationViewModelTests: XCTestCase { // THEN XCTAssertFalse(mockStore.isPrivacyPreservingAnalyticsConsentGiven) -// XCTAssertNil(mockStore.userMetadata?.ageGroup) -// XCTAssertNil(mockStore.userMetadata?.federalState) -// XCTAssertNil(mockStore.userMetadata?.administrativeUnit) + XCTAssertNil(mockStore.userMetadata?.ageGroup) + XCTAssertNil(mockStore.userMetadata?.federalState) + XCTAssertNil(mockStore.userMetadata?.administrativeUnit) } } From 6d6a820329cdb80e53848abcdcf5365696cbf641 Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 15:47:15 +0100 Subject: [PATCH 33/39] code cleanups --- src/xcode/ENA/ENA.xcodeproj/project.pbxproj | 6 ++-- .../DataDonationViewController.swift | 36 +++++++++---------- .../BaseDataDonationViewModel.swift | 4 +-- .../DefaultDataDonationViewModel.swift | 2 +- .../SettingsDataDonationViewModel.swift | 7 ++-- .../Model/DataDonationModel.swift | 2 +- .../__tests__/DataDonationModelTests.swift | 2 +- .../Model/__tests__/DistrictTests.swift | 2 +- 8 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj index 14bc9a9488c..2c6ca17157e 100644 --- a/src/xcode/ENA/ENA.xcodeproj/project.pbxproj +++ b/src/xcode/ENA/ENA.xcodeproj/project.pbxproj @@ -2897,11 +2897,11 @@ 85D759712457059A008175F0 /* Scenes */ = { isa = PBXGroup; children = ( - BA7D17D025D5947B006B9EBF /* DataDonationDetails */, - BA0073BB25D189E50036DFDD /* DataDonation */, 71176E30248957B1004B0C9F /* App */, EE85998B2462EFD4002E7AE2 /* AppInformation */, 0190982A257E5A9D0065D050 /* ContactDiary */, + BA0073BB25D189E50036DFDD /* DataDonation */, + BA7D17D025D5947B006B9EBF /* DataDonationDetails */, 71F76D0E24767AF100515A01 /* DynamicTableViewController */, 858F6F71245AEC05009FFD33 /* ENSetting */, 514E81312461946E00636861 /* ExposureDetection */, @@ -2911,9 +2911,9 @@ 7143D07424990A3100608DDE /* NavigationControllerWithFooter */, 51D420AF2458308400AD70CA /* Onboarding */, 01B7232524F8128B0064C0EB /* OptionGroup */, - BA69A7D625CD782900023265 /* SelectValueViewController */, 13091950247972CF0066E329 /* PrivacyProtectionViewController */, EE20EA0824699A3A00770683 /* RiskLegend */, + BA69A7D625CD782900023265 /* SelectValueViewController */, 51D420C224583D7B00AD70CA /* Settings */, 016E260C25AF43440077C64C /* StatisticsInfo */, EBB92C70259E10BD00013B41 /* UpdateOS */, diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index 66acd0bb0e3..a98f4573d12 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // @@ -34,21 +34,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie override var navigationItem: UINavigationItem { navigationFooterItem } - - private lazy var navigationFooterItem: ENANavigationFooterItem = { - let item = ENANavigationFooterItem() - item.primaryButtonTitle = AppStrings.DataDonation.Info.buttonOK - item.isPrimaryButtonEnabled = true - - item.secondaryButtonTitle = AppStrings.DataDonation.Info.buttonNOK - item.secondaryButtonHasBackground = true - item.isSecondaryButtonHidden = false - item.isSecondaryButtonEnabled = true - - return item - }() - // MARK: - Protocol ENANavigationControllerWithFooterChild func navigationController(_ navigationController: ENANavigationControllerWithFooter, didTapPrimaryButton button: UIButton) { @@ -64,11 +50,9 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Protocol DismissHandling func wasAttemptedToBeDismissed() { - Log.debug("tried to dismiss") + Log.debug("attemptedToBeDismissed") } - // MARK: - Public - // MARK: - Internal /// Is called when when the one of the ENANavigationControllerWithFooter buttons is tapped. @@ -81,6 +65,20 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie private let viewModel: DataDonationViewModelProtocol private var subscriptions: [AnyCancellable] = [] + private lazy var navigationFooterItem: ENANavigationFooterItem = { + let item = ENANavigationFooterItem() + + item.primaryButtonTitle = AppStrings.DataDonation.Info.buttonOK + item.isPrimaryButtonEnabled = true + + item.secondaryButtonTitle = AppStrings.DataDonation.Info.buttonNOK + item.secondaryButtonHasBackground = true + item.isSecondaryButtonHidden = false + item.isSecondaryButtonEnabled = true + + return item + }() + private func setupTableView() { view.backgroundColor = .enaColor(for: .background) tableView.separatorStyle = .none @@ -109,7 +107,7 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Cell reuse identifiers. -extension DataDonationViewController { +internal extension DataDonationViewController { enum CustomCellReuseIdentifiers: String, TableViewCellReuseIdentifiers { case roundedCell case legalExtended = "DynamicLegalExtendedCell" diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift index 10d0ab77f78..554876fa566 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // @@ -37,7 +37,7 @@ class BaseDataDonationViewModel: DataDonationViewModelProtocol { self.dataDonationModel = datadonationModel } - // MARK: - DataDonationViewModelProtocol + // MARK: - Protocol DataDonationViewModelProtocol let presentSelectValueList: (SelectValueViewModel) -> Void diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index feb4b9ff5b7..3585b051508 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index a03366eb226..4272c6b6768 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // @@ -153,7 +153,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { // MARK: - Internal - @objc /// called if the consent given switch changes + @objc /// consent given switch changes func didToggleDatadonationSwitch(sender: UISwitch) { save(consentGiven: sender.isOn) DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35) { [weak self] in @@ -161,6 +161,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { } } + /// user tapped select state func didTapSelectStateButton() { let selectValueViewModel = SelectValueViewModel( dataDonationModel.allFederalStateNames, @@ -180,6 +181,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } + /// user tapped select region func didTapSelectRegionButton() { guard let federalStateName = dataDonationModel.federalStateName else { Log.debug("Missing federal state to load regions", log: .ppac) @@ -203,6 +205,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { presentSelectValueList(selectValueViewModel) } + /// user tapped select age func didTapAgeButton() { let selectValueViewModel = SelectValueViewModel( AgeGroup.allCases.map({ $0.text }), diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift index 797c9af7b08..99eb0669689 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/DataDonationModel.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift index c489f6acaff..f4d0047124c 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DataDonationModelTests.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift index f7ef6256702..89566619b91 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/Model/__tests__/DistrictTests.swift @@ -1,4 +1,4 @@ -//// +// // 🦠 Corona-Warn-App // From ed173493e7d8fa19aaab76b0398229df8bf2bbdb Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 16:56:05 +0100 Subject: [PATCH 34/39] fixed legal text formatting --- .../Resources/Localization/de.lproj/Localizable.legal.strings | 2 +- .../Resources/Localization/tr.lproj/Localizable.legal.strings | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings index 6f06465ff0f..090120597b5 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/de.lproj/Localizable.legal.strings @@ -102,4 +102,4 @@ /* Data Donation App Settings*/ -"ppa_settings_privacy_information_body" = "Indem Sie oben „Datenspende“ aktivieren, willigen Sie ein:\n\nDie App übermittelt täglich von ihr erfasste Angaben an das RKI. Die Daten betreffen angezeigte Risiko-Begegnungen und Warnungen, durch Sie abgerufene Testergebnisse, ob Sie andere Nutzer gewarnt haben sowie Angaben über das Betriebssystem Ihres Smartphones. Wenn Sie oben weitere Angaben gemacht haben (Region, Altersgruppe), werden auch diese an das RKI übermittelt.\n\nDas RKI wird diese Daten zu Statistiken zusammenfassen und auswerten, um die Wirksamkeit und Funktionsweise der App zu bewerten und Rückschlüsse auf das Pandemiegeschehen zu ziehen. Die dabei gefundenen Erkenntnisse helfen bei der Verbesserung der Funktionen und Nutzerfreundlichkeit der App sowie bei der Steuerung anderer Maßnahmen der Pandemiebekämpfung.\n\nBevor Ihre Daten ausgewertet werden, muss sichergestellt sein, dass jede an der Datenspende teilnehmende App nur einmal gezählt wird und die Statistiken nicht verfälscht werden. Hierfür muss die Echtheit Ihrer App geprüft werden. Dazu wird durch Ihr Smartphone eine eindeutige Kennung erzeugt und an Apple in die USA übermittelt, damit Apple die Echtheit Ihrer App gegenüber dem RKI bestätigen kann. Die Kennung enthält Informationen über die Version Ihres Smartphones und der App. Weitere Angaben aus der App erhält Apple hierbei nicht.\n\nSie können Ihr Einverständnis jederzeit zurücknehmen, indem Sie oben „Datenspende“ deaktivieren.“"; +"ppa_settings_privacy_information_body" = "Indem Sie oben „Datenspende“ aktivieren, willigen Sie ein:\n\nDie App übermittelt täglich von ihr erfasste Angaben an das RKI. Die Daten betreffen angezeigte Risiko-Begegnungen und Warnungen, durch Sie abgerufene Testergebnisse, ob Sie andere Nutzer gewarnt haben sowie Angaben über das Betriebssystem Ihres Smartphones. Wenn Sie oben weitere Angaben gemacht haben (Region, Altersgruppe), werden auch diese an das RKI übermittelt.\n\nDas RKI wird diese Daten zu Statistiken zusammenfassen und auswerten, um die Wirksamkeit und Funktionsweise der App zu bewerten und Rückschlüsse auf das Pandemiegeschehen zu ziehen. Die dabei gefundenen Erkenntnisse helfen bei der Verbesserung der Funktionen und Nutzerfreundlichkeit der App sowie bei der Steuerung anderer Maßnahmen der Pandemiebekämpfung.\n\nBevor Ihre Daten ausgewertet werden, muss sichergestellt sein, dass jede an der Datenspende teilnehmende App nur einmal gezählt wird und die Statistiken nicht verfälscht werden. Hierfür muss die Echtheit Ihrer App geprüft werden. Dazu wird durch Ihr Smartphone eine eindeutige Kennung erzeugt und an Apple in die USA übermittelt, damit Apple die Echtheit Ihrer App gegenüber dem RKI bestätigen kann. Die Kennung enthält Informationen über die Version Ihres Smartphones und der App. Weitere Angaben aus der App erhält Apple hierbei nicht.\n\nSie können Ihr Einverständnis jederzeit zurücknehmen, indem Sie oben „Datenspende“ deaktivieren."; diff --git a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings index a564cf49abc..c45327288e0 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings @@ -112,4 +112,4 @@ /* Data Donation App Settings*/ -"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\nUygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\nYukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz Yukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; +"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\nUygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\nYukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; From 5a6b892345b1b4feb6e1f6ff80353f1ade799280 Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 17:02:48 +0100 Subject: [PATCH 35/39] typo fixed --- .../Resources/Localization/tr.lproj/Localizable.legal.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings index c45327288e0..71837bbe2b7 100644 --- a/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings +++ b/src/xcode/ENA/ENA/Resources/Localization/tr.lproj/Localizable.legal.strings @@ -112,4 +112,4 @@ /* Data Donation App Settings*/ -"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\nUygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple <, Uygulamadan daha fazla bilgi almaz.\n\nYukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; +"ppa_settings_privacy_information_body" = "Yukarıdaki “Veri bağışı” seçeneğini etkinleştirerek, şunlara onay vermiş olursunuz:\n\nUygulama, topladığı bilgileri her gün RKI’ye aktarır. Bunlar, görüntülenen riskli karşılaşmalar ve uyarılar, size gönderilen test sonuçları, diğer kullanıcıları uyarıp uyarmadığınız ve akıllı telefonunuzun işletim sistemine ilişkin verilerdir. Ayrıca başka bilgiler de verdiyseniz (bölge, yaş grubu gibi), bunlar da RKI’ye aktarılır.\n\nRKI, Uygulamanın etki gücünü ve işlevselliğini değerlendirmek ve pandemi hakkında yeni çıkarımlar elde etmek için, bu verileri birleştirecek ve istatistikler olarak değerlendirecektir. Bu süreçte edinilen bulgular, Uygulamanın işlevlerini ve kullanım kolaylığını iyileştirmenin yanı sıra pandemiye karşı mücadele için diğer önlemlerin yönlendirilmesine yardımcı olmaktadır.\n\nVerilerinizin değerlendirilmesinden önce, veri bağışına katılan her Uygulamanın yalnızca bir kez sayıma alındığı ve istatistiklerin tahrif edilmediği kontrol edilir. Bu bağlamda Uygulamanızın orijinal olduğunun incelenmesi gerekmektedir. Bunun için, akıllı telefonunuz tarafından benzersiz bir kimlik kodu oluşturulur ve Apple’ın Uygulamanızın orijinal ürün olduğunu RKI’ye doğrulaması için ABD’deki Apple’a aktarılır. Bu kimlik kodu, akıllı telefonunuzun sürümü ve Uygulama hakkında veriler içerir. Apple, Uygulamadan daha fazla bilgi almaz.\n\nYukarıdaki “Veri bağışı” seçeneğini devre dışı bırakarak, verdiğiniz rıza beyanını geri alabilirsiniz."; From 363dc0533f21f1c56c50dbceaf1ad583d7a3065c Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 17:09:53 +0100 Subject: [PATCH 36/39] fix build --- .../DataDonationViewController.swift | 6 +----- .../DeltaOnboardingDataDonation.swift | 6 +----- .../OnboardingInfoViewController.swift | 18 ++++++++++++++---- .../Scenes/Settings/SettingsCoordinator.swift | 7 ++----- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index a98f4573d12..20aad6a2fba 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -9,11 +9,9 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Init init( - viewModel: DataDonationViewModelProtocol, - didTapLegal: @escaping () -> Void + viewModel: DataDonationViewModelProtocol ) { self.viewModel = viewModel - self.didTapLegal = didTapLegal super.init(nibName: nil, bundle: nil) } @@ -60,8 +58,6 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie // MARK: - Private - private let didTapLegal: () -> Void - private let viewModel: DataDonationViewModelProtocol private var subscriptions: [AnyCancellable] = [] diff --git a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift index 4dc6d5a75f2..1499a855f5f 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/DeltaOnboarding/NewVersionFeatures/DeltaOnboardingDataDonation.swift @@ -37,11 +37,7 @@ class DeltaOnboardingDataDonation: DeltaOnboarding { ) ) - let dataDonationViewController = DataDonationViewController( - viewModel: viewModel, - didTapLegal: {} - ) - + let dataDonationViewController = DataDonationViewController(viewModel: viewModel) let deltaOnboardingNavigationController = DeltaOnboardingNavigationController(rootViewController: dataDonationViewController) deltaOnboardingNavigationController.navigationBar.prefersLargeTitles = true diff --git a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/OnboardingInfoViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/OnboardingInfoViewController.swift index 1f05e260703..3eaf81636f6 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Onboarding/OnboardingInfoViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Onboarding/OnboardingInfoViewController.swift @@ -147,9 +147,14 @@ final class OnboardingInfoViewController: UIViewController { } private func gotoDataDonationScreen() { - let dataDonationViewController = DataDonationViewController( + + guard let jsonFileURL = Bundle.main.url(forResource: "ppdd-ppa-administrative-unit-set-ua-approved", withExtension: "json") else { + preconditionFailure("missing json file") + } + + let viewModel = DefaultDataDonationViewModel( store: store, - presentSelectValueList: { [weak self] selectValueViewModel in + presentSelectValueList: { [weak self] selectValueViewModel in let selectValueViewController = SelectValueTableViewController( selectValueViewModel, dissmiss: { [weak self] in @@ -158,9 +163,14 @@ final class OnboardingInfoViewController: UIViewController { let selectValueNavigationController = UINavigationController(rootViewController: selectValueViewController) self?.navigationController?.present(selectValueNavigationController, animated: true) }, - didTapLegal: {} + datadonationModel: DataDonationModel( + store: store, + jsonFileURL: jsonFileURL + ) ) - + + let dataDonationViewController = DataDonationViewController(viewModel: viewModel) + dataDonationViewController.finished = { [weak self] in self?.finishOnBoarding() } diff --git a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift index 685393eee37..f032f63fa79 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/Settings/SettingsCoordinator.swift @@ -132,11 +132,8 @@ class SettingsCoordinator: ENStateHandlerUpdating { ) ) - let dummyDataDonationViewControllre = DataDonationViewController( - viewModel: viewModel, - didTapLegal: {} - ) - parentNavigationController?.pushViewController(dummyDataDonationViewControllre, animated: true) + let dataDonationViewController = DataDonationViewController(viewModel: viewModel) + parentNavigationController?.pushViewController(dataDonationViewController, animated: true) } private func presentSelectValueList(selectValueViewModel: SelectValueViewModel) { From 4dc258085e698757d6991463440e71f00d20e8db Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 17:37:45 +0100 Subject: [PATCH 37/39] Fixed broken layout constraints; adapted unit test accordingly --- .../DataDonationDetailsViewModel.swift | 5 ++--- .../DataDonationDetailsViewModelTests.swift | 15 ++++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift index 01a4c436cd5..9a5feff1100 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/DataDonationDetailsViewModel.swift @@ -39,11 +39,10 @@ final class DataDonationDetailsViewModel { ) } ), - .space(height: 8), + .space(height: 20), .headline(text: AppStrings.DataDonation.DetailedInfo.headline, accessibilityIdentifier: "AppStrings.DataDonation.DetailedInfo.headline"), - .space(height: 8), + .space(height: 20), .body(text: AppStrings.DataDonation.DetailedInfo.paragraph1, accessibilityIdentifier: "AppStrings.DataDonation.DetailedInfo.paragraph1"), - .space(height: 8), bulletPointCellWithBoldHeadline[0], bulletPointCellWithBoldHeadline[1], diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index ff1b8bf0d3c..d3156e8e1b9 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -7,6 +7,10 @@ import XCTest class DataDonationDetailsViewModelTests: XCTestCase { + let totalNumberOfCells = 35 + let indexOfBulletPointCell = [7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33] + let indexOfSpaceCell = [1, 3, 5] + let indexOfLabelCell = [0, 4, 6, 11, 16, 22, 30, 34] let model = DataDonationDetailsViewModel() func testForOneSection() throws { @@ -24,7 +28,7 @@ class DataDonationDetailsViewModelTests: XCTestCase { // WHEN let numberOfCells = tableViewModel.section(0).cells.count // THEN - XCTAssertEqual(numberOfCells, 36) + XCTAssertEqual(numberOfCells, totalNumberOfCells) } func testReuseIdentifierRoundedCell() throws { @@ -40,9 +44,8 @@ class DataDonationDetailsViewModelTests: XCTestCase { func testReuseIdentifierBulletPointCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel - let indexSet = [8, 9, 10, 11, 13, 14, 15, 16, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34] // WHEN - for i in indexSet { + for i in indexOfBulletPointCell { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "bulletPointCell") @@ -53,9 +56,8 @@ class DataDonationDetailsViewModelTests: XCTestCase { func testReuseIdentifierLabelCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel - let indexSet = [0, 4, 6, 12, 17, 23, 31, 35] // WHEN - for i in indexSet { + for i in indexOfLabelCell { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "labelCell") @@ -65,9 +67,8 @@ class DataDonationDetailsViewModelTests: XCTestCase { func testReuseIdentifierSpaceCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel - let indexSet = [1, 3, 5, 7] // WHEN - for i in indexSet { + for i in indexOfSpaceCell { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "spaceCell") From 912252f02551ca7cccaae05acd5c7aa826fd8adf Mon Sep 17 00:00:00 2001 From: Kai Teuber Date: Fri, 12 Feb 2021 18:24:35 +0100 Subject: [PATCH 38/39] refactoring to get rid of the usesless bool --- .../DataDonation/DataDonationViewController.swift | 6 ++++-- .../BaseDataDonationViewModel.swift | 14 +++++--------- .../DefaultDataDonationViewModel.swift | 3 --- .../SettingsDataDonationViewModel.swift | 7 +------ 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift index 20aad6a2fba..81eb4066945 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewController.swift @@ -91,12 +91,14 @@ class DataDonationViewController: DynamicTableViewController, DeltaOnboardingVie dynamicTableViewModel = viewModel.dynamicTableViewModel - viewModel.reloadTableViewPublisher + viewModel.dataDonationModelPublisher .receive(on: DispatchQueue.OCombine(.main)) .sink { [weak self] _ in guard let self = self else { return } self.dynamicTableViewModel = self.viewModel.dynamicTableViewModel - self.tableView.reloadData() + DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35) { + self.tableView.reloadData() + } }.store(in: &subscriptions) } } diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift index 554876fa566..59eea07cd25 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/BaseDataDonationViewModel.swift @@ -10,10 +10,9 @@ import OpenCombine protocol DataDonationViewModelProtocol { - /// use these 3 to definde @published in a prorocol - var reloadTableView: Bool { get } - var reloadTableViewPublished: OpenCombine.Published { get } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { get } + // dataDonationModel and it's Publisher to subscribe changes + var dataDonationModel: DataDonationModel { get } + var dataDonationModelPublisher: OpenCombine.Published.Publisher { get } var friendlyFederalStateName: String { get } var friendlyRegionName: String { get } @@ -33,7 +32,6 @@ class BaseDataDonationViewModel: DataDonationViewModelProtocol { datadonationModel: DataDonationModel ) { self.presentSelectValueList = presentSelectValueList - self.reloadTableView = false self.dataDonationModel = datadonationModel } @@ -41,11 +39,9 @@ class BaseDataDonationViewModel: DataDonationViewModelProtocol { let presentSelectValueList: (SelectValueViewModel) -> Void - @OpenCombine.Published var reloadTableView: Bool + @OpenCombine.Published var dataDonationModel: DataDonationModel + var dataDonationModelPublisher: OpenCombine.Published.Publisher { $dataDonationModel } - var reloadTableViewPublished: OpenCombine.Published { _reloadTableView } - var reloadTableViewPublisher: OpenCombine.Published.Publisher { $reloadTableView } - var dataDonationModel: DataDonationModel var subscriptions: [AnyCancellable] = [] var dynamicTableViewModel: DynamicTableViewModel { diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift index 3585b051508..4eb8da3d3dd 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/DefaultDataDonationViewModel.swift @@ -118,7 +118,6 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { // if a new fedaral state got selected reset region as well self?.dataDonationModel.federalStateName = federalState self?.dataDonationModel.region = nil - self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) } @@ -139,7 +138,6 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { return } self?.dataDonationModel.region = region - self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) @@ -156,7 +154,6 @@ final class DefaultDataDonationViewModel: BaseDataDonationViewModel { return } self?.dataDonationModel.age = age - self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift index 4272c6b6768..99591741c93 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonation/DataDonationViewModels/SettingsDataDonationViewModel.swift @@ -156,9 +156,6 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { @objc /// consent given switch changes func didToggleDatadonationSwitch(sender: UISwitch) { save(consentGiven: sender.isOn) - DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.35) { [weak self] in - self?.reloadTableView.toggle() - } } /// user tapped select state @@ -176,7 +173,6 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { self?.dataDonationModel.federalStateName = federalState self?.dataDonationModel.region = nil self?.dataDonationModel.save() - self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) } @@ -199,7 +195,6 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { } self?.dataDonationModel.region = region self?.dataDonationModel.save() - self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) @@ -218,7 +213,7 @@ final class SettingsDataDonationViewModel: BaseDataDonationViewModel { } self?.dataDonationModel.age = age self?.dataDonationModel.save() - self?.reloadTableView.toggle() +// self?.reloadTableView.toggle() }.store(in: &subscriptions) presentSelectValueList(selectValueViewModel) From 09ff0fc6f307c22e771faf69fa0f232993397751 Mon Sep 17 00:00:00 2001 From: Andreas Vogel Date: Fri, 12 Feb 2021 18:25:18 +0100 Subject: [PATCH 39/39] refactoring unit tests --- .../DataDonationDetailsViewModelTests.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift index d3156e8e1b9..9515f39ff1d 100644 --- a/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift +++ b/src/xcode/ENA/ENA/Source/Scenes/DataDonationDetails/__tests__/DataDonationDetailsViewModelTests.swift @@ -8,9 +8,9 @@ import XCTest class DataDonationDetailsViewModelTests: XCTestCase { let totalNumberOfCells = 35 - let indexOfBulletPointCell = [7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33] - let indexOfSpaceCell = [1, 3, 5] - let indexOfLabelCell = [0, 4, 6, 11, 16, 22, 30, 34] + let indexOfBulletPointCells = [7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33] + let indexOfSpaceCells = [1, 3, 5] + let indexOfLabelCells = [0, 4, 6, 11, 16, 22, 30, 34] let model = DataDonationDetailsViewModel() func testForOneSection() throws { @@ -40,24 +40,22 @@ class DataDonationDetailsViewModelTests: XCTestCase { XCTAssertEqual(cell2.cellReuseIdentifier.rawValue, "roundedCell") } - // cells 8-11, 13-16, 18-22, 24-30, 32-34 func testReuseIdentifierBulletPointCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel // WHEN - for i in indexOfBulletPointCell { + for i in indexOfBulletPointCells { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "bulletPointCell") } } - // cells 0, 4, 6, 12, 17, 23, 31, 35 func testReuseIdentifierLabelCell() throws { // GIVEN let tableViewModel = model.dynamicTableViewModel // WHEN - for i in indexOfLabelCell { + for i in indexOfLabelCells { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "labelCell") @@ -68,7 +66,7 @@ class DataDonationDetailsViewModelTests: XCTestCase { // GIVEN let tableViewModel = model.dynamicTableViewModel // WHEN - for i in indexOfSpaceCell { + for i in indexOfSpaceCells { let cell = tableViewModel.section(0).cells[i] // THEN XCTAssertEqual(cell.cellReuseIdentifier.rawValue, "spaceCell")