Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display warning icon in Sync Settings cell when data syncing is disabled #2281

Merged
merged 3 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Core/UserDefaultsPropertyWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public struct UserDefaultsWrapper<T> {
case syncIsEligibleForFaviconsFetcherOnboarding = "com.duckduckgo.ios.sync-is-eligible-for-favicons-fetcher-onboarding"
case syncDidPresentFaviconsFetcherOnboarding = "com.duckduckgo.ios.sync-did-present-favicons-fetcher-onboarding"
case syncDidMigrateToImprovedListsHandling = "com.duckduckgo.ios.sync-did-migrate-to-improved-lists-handling"
case syncDidShowSyncPausedByFeatureFlagAlert = "com.duckduckgo.ios.sync-did-show-sync-paused-by-feature-flag-alert"

case networkProtectionDebugOptionAlwaysOnDisabled = "com.duckduckgo.network-protection.always-on.disabled"
case networkProtectionWaitlistTermsAndConditionsAccepted = "com.duckduckgo.ios.vpn.terms-and-conditions-accepted"
Expand Down
40 changes: 40 additions & 0 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,13 @@ class MainViewController: UIViewController {
private var favoritesViewModel: FavoritesListInteracting
let syncService: DDGSyncing
let syncDataProviders: SyncDataProviders

@UserDefaultsWrapper(key: .syncDidShowSyncPausedByFeatureFlagAlert, defaultValue: false)
private var syncDidShowSyncPausedByFeatureFlagAlert: Bool

private var localUpdatesCancellable: AnyCancellable?
private var syncUpdatesCancellable: AnyCancellable?
private var syncFeatureFlagsCancellable: AnyCancellable?
private var favoritesDisplayModeCancellable: AnyCancellable?
private var emailCancellables = Set<AnyCancellable>()

Expand Down Expand Up @@ -349,6 +354,21 @@ class MainViewController: UIViewController {
selector: #selector(showSyncPausedError),
name: SyncCredentialsAdapter.credentialsSyncLimitReached,
object: nil)
syncFeatureFlagsCancellable = syncService.featureFlagsPublisher
.dropFirst()
.map { $0.contains(.dataSyncing) }
.receive(on: DispatchQueue.main)
.sink { [weak self] isDataSyncingAvailable in
guard let self else {
return
}
if isDataSyncingAvailable {
self.syncDidShowSyncPausedByFeatureFlagAlert = false
} else if self.syncService.authState == .active, !self.syncDidShowSyncPausedByFeatureFlagAlert {
self.showSyncPausedByFeatureFlagAlert()
self.syncDidShowSyncPausedByFeatureFlagAlert = true
}
}
}

@objc private func showSyncPausedError(_ notification: Notification) {
Expand Down Expand Up @@ -378,6 +398,26 @@ class MainViewController: UIViewController {
}
}

private func showSyncPausedByFeatureFlagAlert(upgradeRequired: Bool = false) {
let title = UserText.syncPausedTitle
let description = upgradeRequired ? UserText.syncUnavailableMessageUpgradeRequired : UserText.syncUnavailableMessage
if self.presentedViewController is SyncSettingsViewController {
return
}
self.presentedViewController?.dismiss(animated: true)
let alert = UIAlertController(title: title,
message: description,
preferredStyle: .alert)
if syncService.featureFlags.contains(.userInterface) {
let learnMoreAction = UIAlertAction(title: UserText.syncPausedAlertLearnMoreButton, style: .default) { _ in
self.segueToSettingsSync()
}
alert.addAction(learnMoreAction)
}
alert.addAction(UIAlertAction(title: UserText.syncPausedAlertOkButton, style: .cancel))
self.present(alert, animated: true)
}

func registerForSettingsChangeNotifications() {
NotificationCenter.default.addObserver(self, selector:
#selector(onAddressBarPositionChanged),
Expand Down
5 changes: 3 additions & 2 deletions DuckDuckGo/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class SettingsViewController: UITableViewController {
}

private var shouldShowSyncCell: Bool {
return syncService.featureFlags.contains(.userInterface) || internalUserDecider.isInternalUser
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the || internalUserDecider.isInternalUser is a remainder from the original feature flags PR when we were supposed to show the UI to internal users anyway, even if Sync top-level feature flag is disabled. We've replaced that on Apple platforms by setting top-level flag to "internal", so this code shouldn't end up here.

return syncService.featureFlags.contains(.userInterface)
}

private var shouldShowTextSizeCell: Bool {
Expand Down Expand Up @@ -260,7 +260,8 @@ class SettingsViewController: UITableViewController {

private func configureSyncCell() {
syncCell.textLabel?.text = "Sync & Backup"
if SyncBookmarksAdapter.isSyncBookmarksPaused || SyncCredentialsAdapter.isSyncCredentialsPaused {
let isDataSyncingDisabled = !syncService.featureFlags.contains(.dataSyncing) && syncService.authState == .active
if SyncBookmarksAdapter.isSyncBookmarksPaused || SyncCredentialsAdapter.isSyncCredentialsPaused || isDataSyncingDisabled {
syncCell.textLabel?.text = "⚠️ " + "Sync & Backup"
}
syncCell.isHidden = !shouldShowSyncCell
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,9 @@ But if you *do* want a peek under the hood, you can find more information about
public static let unableToTurnSyncOffDescription = NSLocalizedString("alert.unable-to-turn-sync-off-description", value: "Unable to turn sync off.", comment: "Description for unable to turn sync off error")
public static let unableToDeleteDataDescription = NSLocalizedString("alert.unable-to-delete-data-description", value: "Unable to delete data on the server.", comment: "Description for unable to delete data error")
public static let unableToRemoveDeviceDescription = NSLocalizedString("alert.unable-to-remove-device-description", value: "Unable to remove the specified device from the synchronized devices.", comment: "Description for unable to remove device error")
static let syncPausedTitle = NSLocalizedString("sync.warning.sync.paused", value: "Sync & Backup is Paused", comment: "Title of the warning message")
static let syncUnavailableMessage = NSLocalizedString("sync.warning.data.syncing.disabled", value: "Sorry, but Sync & Backup is currently unavailable. Please try again later.", comment: "Data syncing unavailable warning message")
static let syncUnavailableMessageUpgradeRequired = NSLocalizedString("sync.warning.data.syncing.disabled.upgrade.required", value: "Sorry, but Sync & Backup is no longer available in this app version. Please update DuckDuckGo to the latest version to continue.", comment: "Data syncing unavailable warning message")

static let preemptiveCrashTitle = NSLocalizedString("error.preemptive-crash.title", value: "App issue detected", comment: "Alert title")
static let preemptiveCrashBody = NSLocalizedString("error.preemptive-crash.body", value: "Looks like there's an issue with the app and it needs to close. Please reopen to continue.", comment: "Alert message")
Expand Down
9 changes: 9 additions & 0 deletions DuckDuckGo/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,15 @@ But if you *do* want a peek under the hood, you can find more information about
/* No comment provided by engineer. */
"sync.remove-device.message" = "\"%@\" will no longer be able to access your synced data.";

/* Data syncing unavailable warning message */
"sync.warning.data.syncing.disabled" = "Sorry, but Sync & Backup is currently unavailable. Please try again later.";

/* Data syncing unavailable warning message */
"sync.warning.data.syncing.disabled.upgrade.required" = "Sorry, but Sync & Backup is no longer available in this app version. Please update DuckDuckGo to the latest version to continue.";

/* Title of the warning message */
"sync.warning.sync.paused" = "Sync & Backup is Paused";

/* Accessibility label on remove button */
"tab.close.home" = "Close home tab";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ struct UserText {
static let fetchFaviconsOnboardingButtonTitle = NSLocalizedString("fetch.favicons.onboarding.button.title", value: "Keep Bookmarks Icons Updated", comment: "Fetch Favicons Onboarding - Button Title")

// Sync Feature Flags
static let serviceUnavailable = NSLocalizedString("sync.warning.service.unavailable", value: "Service Unavailable", comment: "Title of the warning message")
static let warningSyncDisabled = NSLocalizedString("sync.warning.sync.disabled", value: "We apologize, but the service is currently unavailable. Please try again later.", comment: "Sync unavailable warning message")
static let warningAccountCreationDisabled = NSLocalizedString("sync.warning.account.creation.disabled", value: "We apologize, but new account creation is currently unavailable for this service. Please try again later.", comment: "Sync unavailable warning message")
static let syncUnavailableTitle = NSLocalizedString("sync.warning.sync.unavailable", value: "Sync & Backup is Unavailable", comment: "Title of the warning message")
static let syncPausedTitle = NSLocalizedString("sync.warning.sync.paused", value: "Sync & Backup is Paused", comment: "Title of the warning message")
static let syncUnavailableMessage = NSLocalizedString("sync.warning.data.syncing.disabled", value: "Sorry, but Sync & Backup is currently unavailable. Please try again later.", comment: "Data syncing unavailable warning message")
static let syncUnavailableMessageUpgradeRequired = NSLocalizedString("sync.warning.data.syncing.disabled.upgrade.required", value: "Sorry, but Sync & Backup is no longer available in this app version. Please update DuckDuckGo to the latest version to continue.", comment: "Data syncing unavailable warning message")

// swiftlint:enable line_length
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ extension SyncSettingsView {

@ViewBuilder
fileprivate func syncUnavailableViewWhileLoggedOut() -> some View {
if !model.isDataSyncingAvailable || !model.isConnectingDevicesAvailable {
SyncWarningMessageView(title: UserText.serviceUnavailable, message: UserText.warningSyncDisabled)
} else if !model.isAccountCreationAvailable {
SyncWarningMessageView(title: UserText.serviceUnavailable, message: UserText.warningAccountCreationDisabled)
if !model.isDataSyncingAvailable || !model.isConnectingDevicesAvailable || !model.isAccountCreationAvailable {
SyncWarningMessageView(title: UserText.syncUnavailableTitle, message: UserText.syncUnavailableMessage)
} else {
EmptyView()
}
Expand Down Expand Up @@ -182,7 +180,7 @@ extension SyncSettingsView {
if model.isDataSyncingAvailable {
EmptyView()
} else {
SyncWarningMessageView(title: UserText.serviceUnavailable, message: UserText.warningSyncDisabled)
SyncWarningMessageView(title: UserText.syncPausedTitle, message: UserText.syncUnavailableMessage)
}
}

Expand Down
Loading