Simplify PIN creation error handling

This commit is contained in:
Sasha Weiss 2026-06-01 11:04:13 -07:00 committed by GitHub
parent 44e6c6cb43
commit dcf02125a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 43 additions and 96 deletions

View File

@ -21,18 +21,17 @@ class IntroducingPinsMegaphone: MegaphoneView {
let viewController = PinSetupViewController(
mode: .creating,
showCancelButton: true,
completionHandler: { [weak self, weak fromViewController] _, error in
guard let self, let fromViewController else { return }
if let error {
Logger.error("failed to create pin: \(error)")
} else {
// success
self.markAsCompleteWithSneakyTransaction()
}
self.dismiss(animated: false)
fromViewController.dismiss(animated: true) {
self.presentToast(
text: OWSLocalizedString("PINS_MEGAPHONE_TOAST", comment: "Toast indicating that a PIN has been created."),
onSuccess: { pinSetupViewController in
pinSetupViewController.dismiss(animated: true) { [weak self, weak fromViewController] in
guard let self, let fromViewController else { return }
markAsCompleteWithSneakyTransaction()
presentToast(
text: OWSLocalizedString(
"PINS_MEGAPHONE_TOAST",
comment: "Toast indicating that a PIN has been created.",
),
fromViewController: fromViewController,
)
}

View File

@ -498,7 +498,7 @@ class AccountSettingsViewController: OWSTableViewController2 {
// MARK: -
private func showChangePin() {
let vc = PinSetupViewController(mode: .changing) { [weak self] _, _ in
let vc = PinSetupViewController(mode: .changing) { [weak self] _ in
guard let self else { return }
self.navigationController?.popToViewController(self, animated: true)
}
@ -508,7 +508,7 @@ class AccountSettingsViewController: OWSTableViewController2 {
private func showCreatePin() {
let vc = PinSetupViewController(
mode: .creating,
) { [weak self] _, _ in
) { [weak self] _ in
guard let self else { return }
self.navigationController?.popToViewController(self, animated: true)
}

View File

@ -113,7 +113,7 @@ class AdvancedPinSettingsTableViewController: OWSTableViewController2 {
private func showCreatePin() {
let viewController = PinSetupViewController(
mode: .creating,
completionHandler: { [weak self] _, _ in
onSuccess: { [weak self] _ in
guard let self else { return }
self.navigationController?.popToViewController(self, animated: true)
self.updateTableContents()

View File

@ -339,7 +339,10 @@ public class PinReminderViewController: OWSViewController {
let viewController = PinSetupViewController(
mode: .creating,
showCancelButton: true,
completionHandler: { [weak self] _, _ in self?.completionHandler?(.changedPin) },
onSuccess: { [weak self] _ in
guard let self else { return }
completionHandler?(.changedPin)
},
)
present(OWSNavigationController(rootViewController: viewController), animated: true)
}

View File

@ -180,22 +180,20 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
private let showCancelButton: Bool
// Called once pin setup has finished. Error will be nil upon success
private let completionHandler: (PinSetupViewController, Error?) -> Void
private let onSuccess: (PinSetupViewController) -> Void
private let context: ViewControllerContext
convenience init(
mode: Mode,
showCancelButton: Bool = false,
completionHandler: @escaping (PinSetupViewController, Error?) -> Void,
onSuccess: @escaping (PinSetupViewController) -> Void,
) {
self.init(
mode: mode,
initialMode: mode,
pinType: .numeric,
showCancelButton: showCancelButton,
completionHandler: completionHandler,
onSuccess: onSuccess,
)
}
@ -204,14 +202,14 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
initialMode: Mode,
pinType: OWS2FAManager.PinType,
showCancelButton: Bool,
completionHandler: @escaping (PinSetupViewController, Error?) -> Void,
onSuccess: @escaping (PinSetupViewController) -> Void,
) {
assert(DependenciesBridge.shared.tsAccountManager.registrationStateWithMaybeSneakyTransaction.isRegisteredPrimaryDevice)
self.mode = mode
self.initialMode = initialMode
self.pinType = pinType
self.showCancelButton = showCancelButton
self.completionHandler = completionHandler
self.onSuccess = onSuccess
// TODO[ViewContextPiping]
self.context = ViewControllerContext.shared
super.init()
@ -339,7 +337,7 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
initialMode: initialMode,
pinType: pinType,
showCancelButton: false, // we're pushing, so we never need a cancel button
completionHandler: completionHandler,
onSuccess: onSuccess,
)
navigationController?.pushViewController(confirmingVC, animated: true)
case .confirming:
@ -436,11 +434,6 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
}
}
private enum PinSetupError: Error {
case networkFailure
case enable2FA
}
private func enable2FAAndContinue(withPin pin: String) {
Logger.debug("")
@ -474,7 +467,7 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
DispatchQueue.main.async {
// The completion handler always dismisses this view, so we don't want to animate anything.
progressView.stopAnimatingImmediately()
self.completionHandler(self, nil)
self.onSuccess(self)
}
} catch {
DispatchQueue.main.async {
@ -487,53 +480,22 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
self.view.isUserInteractionEnabled = true
progressView.removeFromSuperview()
guard let error = error as? PinSetupError else {
return owsFailDebug("Unexpected error during PIN setup \(error)")
}
switch error {
case .networkFailure:
if error.isNetworkFailureOrTimeout {
OWSActionSheets.showActionSheet(
title: OWSLocalizedString(
"PIN_CREATION_NO_NETWORK_ERROR_TITLE",
comment: "Error title indicating that the attempt to create a PIN failed due to network issues.",
),
message: OWSLocalizedString(
"PIN_CREATION_NO_NETWORK_ERROR_MESSAGE",
comment: "Error body indicating that the attempt to create a PIN failed due to network issues.",
"PIN_CREATION_NETWORK_ERROR_MESSAGE",
comment: "Message when a network error occurs while creating a PIN.",
),
)
case .enable2FA:
switch self.initialMode {
case .changing:
OWSActionSheets.showActionSheet(
title: OWSLocalizedString(
"PIN_CHANGE_ERROR_TITLE",
comment: "Error title indicating that the attempt to change a PIN failed.",
),
message: OWSLocalizedString(
"PIN_CHANGE_ERROR_MESSAGE",
comment: "Error body indicating that the attempt to change a PIN failed.",
),
) { _ in
self.completionHandler(self, error)
}
case .creating:
OWSActionSheets.showActionSheet(
title: OWSLocalizedString(
"PIN_RECREATION_ERROR_TITLE",
comment: "Error title indicating that the attempt to recreate a PIN failed.",
),
message: OWSLocalizedString(
"PIN_RECRETION_ERROR_MESSAGE",
comment: "Error body indicating that the attempt to recreate a PIN failed.",
),
) { _ in
self.completionHandler(self, error)
}
case .confirming:
owsFailDebug("Unexpected initial mode")
}
} else {
OWSActionSheets.showContactSupportActionSheet(
message: OWSLocalizedString(
"PIN_CREATION_GENERIC_ERROR_MESSAGE",
comment: "Message when a generic error occurs while creating a PIN.",
),
emailFilter: .custom("PinCreateFailure"),
fromViewController: self,
)
}
}
}
@ -551,12 +513,7 @@ public class PinSetupViewController: OWSViewController, OWSNavigationChildContro
try await ows2FAManager.enablePin(pin)
} catch {
owsFailDebug("Failed to set PIN! \(error)")
if error.isNetworkFailureOrTimeout {
throw PinSetupError.networkFailure
}
throw PinSetupError.enable2FA
throw error
}
await DependenciesBridge.shared.db.awaitableWrite { tx in

View File

@ -6808,12 +6808,6 @@
/* Pressing this button pins a thread */
"PIN_ACTION" = "Pin";
/* Error body indicating that the attempt to change a PIN failed. */
"PIN_CHANGE_ERROR_MESSAGE" = "Couldn't create your new PIN. Your existing PIN has been disabled. Check your connection and try again.";
/* Error title indicating that the attempt to change a PIN failed. */
"PIN_CHANGE_ERROR_TITLE" = "PIN Change Failed";
/* Label indicating the user must use at least 4 characters */
"PIN_CREATION_ALPHANUMERIC_HINT" = "PIN must be at least 4 characters";
@ -6844,6 +6838,9 @@
/* The explanation in the 'pin creation' view. */
"PIN_CREATION_EXPLANATION" = "PINs keep information stored with Signal encrypted so only you can access it. Your profile, settings, and contacts will restore when you reinstall. You wont need your PIN to open the app.";
/* Message when a generic error occurs while creating a PIN. */
"PIN_CREATION_GENERIC_ERROR_MESSAGE" = "Something went wrong creating your PIN. Please contact support.";
/* Learn more action on the pin creation view */
"PIN_CREATION_LEARN_MORE" = "More About PINs";
@ -6856,11 +6853,8 @@
/* Label indicating that the attempted PIN does not match the first PIN */
"PIN_CREATION_MISMATCH_ERROR" = "PINs dont match. Try again.";
/* Error body indicating that the attempt to create a PIN failed due to network issues. */
"PIN_CREATION_NO_NETWORK_ERROR_MESSAGE" = "Check your connection and try again.";
/* Error title indicating that the attempt to create a PIN failed due to network issues. */
"PIN_CREATION_NO_NETWORK_ERROR_TITLE" = "No Network Connection";
/* Message when a network error occurs while creating a PIN. */
"PIN_CREATION_NETWORK_ERROR_MESSAGE" = "Something went wrong creating your PIN. Check your connection and try again.";
/* Label indicating the user must use at least 4 digits */
"PIN_CREATION_NUMERIC_HINT" = "PIN must be at least 4 digits";
@ -6892,12 +6886,6 @@
/* If the user is re-registering, they need to enter their PIN to restore all their data. If they don't remember their PIN, they may remember their Recovery Key which can be used instead of a PIN. */
"PIN_ENTER_EXISTING_USE_RECOVERY_KEY" = "Use Recovery Key";
/* Error title indicating that the attempt to recreate a PIN failed. */
"PIN_RECREATION_ERROR_TITLE" = "PIN Creation Failed";
/* Error body indicating that the attempt to recreate a PIN failed. */
"PIN_RECRETION_ERROR_MESSAGE" = "Couldnt create your PIN. Check your connection and try again.";
/* The explanation for the 'pin reminder' dialog. */
"PIN_REMINDER_EXPLANATION" = "To help you memorize your PIN, well ask you to enter it periodically. Well ask less over time.";