Skip to content

Commit 1d4d76a

Browse files
authored
Merge pull request #9802 from woocommerce/issue/9616-settings-CTA
[Privacy Choices] Handle "Settings" CTA
2 parents 4b5a2a4 + 2cf6bd8 commit 1d4d76a

File tree

8 files changed

+74
-12
lines changed

8 files changed

+74
-12
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Privacy/PrivacyBannerPresenter.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,22 @@ final class PrivacyBannerPresenter {
4141
let privacyBanner = PrivacyBannerViewController(onCompletion: { [weak self] result in
4242
switch result {
4343
case .success(let destination):
44-
switch destination {
45-
case .dismiss:
46-
viewController.dismiss(animated: true)
47-
48-
case .settings:
49-
print("Dismiss and Go to settings")
44+
viewController.dismiss(animated: true)
45+
if destination == .settings {
46+
MainTabBarController.navigateToPrivacySettings()
5047
}
48+
5149
case .failure(let error):
5250
switch error {
53-
case .sync(let analyticsOptOut):
51+
case .sync(let analyticsOptOut, let intendedDestination):
5452
viewController.dismiss(animated: true)
5553
self?.showErrorNotice(optOut: analyticsOptOut)
54+
55+
/// Even if we fail, we should redirect the user to settings screen so they can further customize their privacy settings
56+
///
57+
if intendedDestination == .settings {
58+
MainTabBarController.navigateToPrivacySettings()
59+
}
5660
}
5761
}
5862
})

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Privacy/PrivacyBannerViewController.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ struct PrivacyBanner: View {
8686

8787
HStack {
8888
Button(Localization.goToSettings) {
89-
print("Tapped Settings")
89+
Task {
90+
await viewModel.submitChanges(destination: .settings)
91+
}
9092
}
9193
.buttonStyle(SecondaryButtonStyle())
9294

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Privacy/PrivacyBannerViewModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ final class PrivacyBannerViewModel: ObservableObject {
5151
try await useCase.update(optOut: !analyticsEnabled)
5252
onCompletion(.success(destination))
5353
} catch {
54-
onCompletion(.failure(.sync(analyticsOptOut: !analyticsEnabled)))
54+
onCompletion(.failure(.sync(analyticsOptOut: !analyticsEnabled, intendedDestination: destination)))
5555
}
5656

5757
// Revert Loading state
@@ -72,6 +72,6 @@ extension PrivacyBannerViewModel {
7272
/// Defined errors.
7373
///
7474
enum Error: Swift.Error {
75-
case sync(analyticsOptOut: Bool)
75+
case sync(analyticsOptOut: Bool, intendedDestination: Destination)
7676
}
7777
}

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Privacy/UpdateAnalyticsSettingsUseCase.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ final class UpdateAnalyticsSettingUseCase {
2727
/// For WPCOM stores: Updates remotely and locally. - The local update only happens after a successful remote update.
2828
/// For NON-WPCOM stores: Updates locally.
2929
///
30-
func update(optOut: Bool) async throws {
30+
@MainActor func update(optOut: Bool) async throws {
31+
// There is no need to perform any request if the user hasn't changed the current analytic setting.
32+
guard analytics.userHasOptedIn == optOut else {
33+
return updateLocally(optOut: optOut)
34+
}
35+
3136
// If we can't find an account(non-jp sites), lets commit the change immediately.
3237
guard let defaultAccount = stores.sessionManager.defaultAccount else {
3338
return updateLocally(optOut: optOut)
@@ -54,7 +59,7 @@ final class UpdateAnalyticsSettingUseCase {
5459

5560
/// Updates the local analytics setting
5661
///
57-
private func updateLocally(optOut: Bool) {
62+
@MainActor private func updateLocally(optOut: Bool) {
5863
analytics.setUserHasOptedOut(optOut)
5964
userDefaults[.hasSavedPrivacyBannerSettings] = true
6065
}

WooCommerce/Classes/ViewRelated/Hub Menu/HubMenuViewController.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ final class HubMenuViewController: UIHostingController<HubMenu> {
3535
return inPersonPaymentsMenuViewController
3636
}
3737

38+
/// Pushes the Settings & Privacy screen onto the navigation stack.
39+
///
40+
func showPrivacySettings() {
41+
guard let navigationController else {
42+
return DDLogError("⛔️ Could not find a navigation controller context.")
43+
}
44+
guard let privacy = UIStoryboard.dashboard.instantiateViewController(ofClass: PrivacySettingsViewController.self) else {
45+
return DDLogError("⛔️ Could not instantiate PrivacySettingsViewController")
46+
}
47+
48+
let settings = SettingsViewController()
49+
navigationController.setViewControllers(navigationController.viewControllers + [settings, privacy], animated: true)
50+
}
51+
3852
override func viewWillAppear(_ animated: Bool) {
3953
super.viewWillAppear(animated)
4054

WooCommerce/Classes/ViewRelated/MainTabBarController.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,17 @@ extension MainTabBarController {
448448
viewController?.openSimplePaymentsAmountFlow()
449449
}
450450
}
451+
452+
/// Switches to the hub Menu & Navigates to the Privacy Settings Screen.
453+
///
454+
static func navigateToPrivacySettings() {
455+
switchToHubMenuTab {
456+
guard let hubMenuViewController: HubMenuViewController = childViewController() else {
457+
return DDLogError("⛔️ Could not switch to the Hub Menu")
458+
}
459+
hubMenuViewController.showPrivacySettings()
460+
}
461+
}
451462
}
452463

453464
// MARK: - DeeplinkForwarder

WooCommerce/WooCommerceTests/ViewRelated/Settings/Privacy/PrivacyBannerViewModelTest.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import TestKit
4949
}
5050

5151
// When
52+
viewModel.analyticsEnabled = false
5253
Task {
5354
await viewModel.submitChanges(destination: .dismiss)
5455
}

WooCommerce/WooCommerceTests/ViewRelated/Settings/Privacy/UpdateAnalyticsSettingsUseCaseTests.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ final class UpdateAnalyticsSettingsUseCaseTests: XCTestCase {
8282
XCTAssertEqual(userDefaults[.hasSavedPrivacyBannerSettings], true)
8383
}
8484

85+
@MainActor func test_not_updating_analytic_setting_does_not_fire_a_request() async throws {
86+
// Given
87+
let stores = MockStoresManager(sessionManager: .makeForTesting(authenticated: true, isWPCom: true, displayName: "Test Account"))
88+
stores.whenReceivingAction(ofType: AccountAction.self) { action in
89+
switch action {
90+
case .updateAccountSettings(_, _, let onCompletion):
91+
onCompletion(.success(()))
92+
XCTFail("Test should not fire a network request")
93+
default:
94+
break
95+
}
96+
}
97+
let analytics = WaitingTimeTrackerTests.TestAnalytics()
98+
let userDefaults = try XCTUnwrap(UserDefaults(suiteName: "TestingSuite"))
99+
analytics.setUserHasOptedOut(true)
100+
101+
// When
102+
let useCase = UpdateAnalyticsSettingUseCase(stores: stores, analytics: analytics, userDefaults: userDefaults)
103+
try await useCase.update(optOut: true)
104+
105+
// Then
106+
XCTAssertFalse(analytics.userHasOptedIn)
107+
XCTAssertEqual(userDefaults[.hasSavedPrivacyBannerSettings], true)
108+
}
109+
85110
override class func tearDown() {
86111
super.tearDown()
87112
SessionManager.removeTestingDatabase()

0 commit comments

Comments
 (0)