Skip to content

Tweaked the behaviour of the database migration errors #428

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
99 changes: 69 additions & 30 deletions Session/Meta/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
})

// Always offer the 'Clear Data' option
alert.addAction(UIAlertAction(title: "clearDevice".localized(), style: .destructive) { [weak self, dependencies] _ in
let alert: UIAlertController = UIAlertController(
title: "clearDevice".localized(),
message: "clearDeviceDescription".localized(),
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "clear".localized(), style: .destructive) { _ in
NukeDataModal.deleteAllLocalData(using: dependencies)
})

alert.addAction(UIAlertAction(title: "cancel".localized(), style: .default) { _ in
DispatchQueue.main.async {
self?.showFailedStartupAlert(
calledFrom: lifecycleMethod,
error: error
)
}
})
self?.window?.rootViewController?.present(alert, animated: animated, completion: nil)
})

switch error {
// Don't offer the 'Restore' option if it was a 'startupFailed' error as a restore is unlikely to
// resolve it (most likely the database is locked or the key was somehow lost - safer to get them
Expand All @@ -534,38 +556,55 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD

// Offer the 'Restore' option if it was a migration error
case .databaseError:
alert.addAction(UIAlertAction(title: "onboardingAccountExists".localized(), style: .destructive) { [dependencies] _ in
// Reset the current database for a clean migration
dependencies[singleton: .storage].resetForCleanMigration()

// Hide the top banner if there was one
TopBannerController.hide()
alert.addAction(UIAlertAction(title: "clearDeviceRestore".localized(), style: .destructive) { [weak self, dependencies] _ in
let alert: UIAlertController = UIAlertController(
title: "clearDeviceRestore".localized(),
message: "databaseErrorRestoreDataWarning".localized(),
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "clear".localized(), style: .destructive) { _ in
// Reset the current database for a clean migration
dependencies[singleton: .storage].resetForCleanMigration()

// Hide the top banner if there was one
TopBannerController.hide()

// The re-run the migration (should succeed since there is no data)
AppSetup.runPostSetupMigrations(
additionalMigrationTargets: [DeprecatedUIKitMigrationTarget.self],
migrationProgressChanged: { [weak self] progress, minEstimatedTotalTime in
self?.loadingViewController?.updateProgress(
progress: progress,
minEstimatedTotalTime: minEstimatedTotalTime
)
},
migrationsCompletion: { [weak self] result in
switch result {
case .failure:
DispatchQueue.main.async {
self?.showFailedStartupAlert(
calledFrom: lifecycleMethod,
error: .failedToRestore
)
}

case .success:
self?.completePostMigrationSetup(calledFrom: lifecycleMethod)
}
},
using: dependencies
)
})

// The re-run the migration (should succeed since there is no data)
AppSetup.runPostSetupMigrations(
additionalMigrationTargets: [DeprecatedUIKitMigrationTarget.self],
migrationProgressChanged: { [weak self] progress, minEstimatedTotalTime in
self?.loadingViewController?.updateProgress(
progress: progress,
minEstimatedTotalTime: minEstimatedTotalTime
alert.addAction(UIAlertAction(title: "cancel".localized(), style: .default) { _ in
DispatchQueue.main.async {
self?.showFailedStartupAlert(
calledFrom: lifecycleMethod,
error: error
)
},
migrationsCompletion: { [weak self] result in
switch result {
case .failure:
DispatchQueue.main.async {
self?.showFailedStartupAlert(
calledFrom: lifecycleMethod,
error: .failedToRestore
)
}

case .success:
self?.completePostMigrationSetup(calledFrom: lifecycleMethod)
}
},
using: dependencies
)
}
})
self?.window?.rootViewController?.present(alert, animated: animated, completion: nil)
})

default: break
Expand Down
2 changes: 1 addition & 1 deletion Session/Meta/Translations/InfoPlist.xcstrings

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Session/Settings/NukeDataModal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ final class NukeDataModal: Modal {
.receive(on: DispatchQueue.main)
.sinkUntilComplete(
receiveCompletion: { _ in
self?.deleteAllLocalData()
NukeDataModal.deleteAllLocalData(using: dependencies)
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
}
)
Expand Down Expand Up @@ -256,7 +256,7 @@ final class NukeDataModal: Modal {
// If all of the nodes successfully deleted the data then proceed
// to delete the local data
guard !potentiallyMaliciousSnodes.isEmpty else {
self?.deleteAllLocalData()
NukeDataModal.deleteAllLocalData(using: dependencies)
return
}

Expand All @@ -278,15 +278,15 @@ final class NukeDataModal: Modal {
}
}

private func deleteAllLocalData() {
public static func deleteAllLocalData(using dependencies: Dependencies) {
/// Unregister push notifications if needed
let isUsingFullAPNs: Bool = dependencies[defaults: .standard, key: .isUsingFullAPNs]
let maybeDeviceToken: String? = dependencies[defaults: .standard, key: .deviceToken]

if isUsingFullAPNs {
UIApplication.shared.unregisterForRemoteNotifications()

if let deviceToken: String = maybeDeviceToken {
if let deviceToken: String = maybeDeviceToken, dependencies[singleton: .storage].isValid {
PushNotificationAPI
.unsubscribeAll(token: Data(hex: deviceToken), using: dependencies)
.sinkUntilComplete()
Expand Down