diff --git a/Signal/Images.xcassets/introducing-pins-dark.imageset/Contents.json b/Signal/Images.xcassets/introducing-pins-dark.imageset/Contents.json deleted file mode 100644 index c616234122..0000000000 --- a/Signal/Images.xcassets/introducing-pins-dark.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "PIN_splash_dark.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "PIN_splash_dark@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "PIN_splash_dark@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark.png b/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark.png deleted file mode 100644 index 5531ba2a11..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark.png and /dev/null differ diff --git a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@2x.png b/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@2x.png deleted file mode 100644 index 459fd50cdc..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@2x.png and /dev/null differ diff --git a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@3x.png b/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@3x.png deleted file mode 100644 index 50635ec439..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-dark.imageset/PIN_splash_dark@3x.png and /dev/null differ diff --git a/Signal/Images.xcassets/introducing-pins-light.imageset/Contents.json b/Signal/Images.xcassets/introducing-pins-light.imageset/Contents.json deleted file mode 100644 index 22a61fad71..0000000000 --- a/Signal/Images.xcassets/introducing-pins-light.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "PIN_splash.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "PIN_splash@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "PIN_splash@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash.png b/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash.png deleted file mode 100644 index b6129dac1f..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash.png and /dev/null differ diff --git a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@2x.png b/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@2x.png deleted file mode 100644 index bbcfb14702..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@2x.png and /dev/null differ diff --git a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@3x.png b/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@3x.png deleted file mode 100644 index d7b859fdf0..0000000000 Binary files a/Signal/Images.xcassets/introducing-pins-light.imageset/PIN_splash@3x.png and /dev/null differ diff --git a/Signal/src/Experience Upgrades/ExperienceUpgradeManager.swift b/Signal/src/Experience Upgrades/ExperienceUpgradeManager.swift index d79ced3ca1..0faa379a8e 100644 --- a/Signal/src/Experience Upgrades/ExperienceUpgradeManager.swift +++ b/Signal/src/Experience Upgrades/ExperienceUpgradeManager.swift @@ -150,8 +150,6 @@ class ExperienceUpgradeManager: NSObject { private static func hasSplash(forExperienceUpgrade experienceUpgrade: ExperienceUpgrade) -> Bool { switch experienceUpgrade.id { - case .introducingPins: - return true default: return false } @@ -159,8 +157,6 @@ class ExperienceUpgradeManager: NSObject { fileprivate static func splash(forExperienceUpgrade experienceUpgrade: ExperienceUpgrade) -> SplashViewController? { switch experienceUpgrade.id { - case .introducingPins: - return IntroducingPinsSplash(experienceUpgrade: experienceUpgrade) default: return nil } diff --git a/Signal/src/Experience Upgrades/Upgrade Views/IntroducingPINs.swift b/Signal/src/Experience Upgrades/Upgrade Views/IntroducingPINs.swift index 6056c1e2fb..947c34aaec 100644 --- a/Signal/src/Experience Upgrades/Upgrade Views/IntroducingPINs.swift +++ b/Signal/src/Experience Upgrades/Upgrade Views/IntroducingPINs.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. // import Foundation @@ -53,192 +53,3 @@ class IntroducingPinsMegaphone: MegaphoneView { fatalError("init(coder:) has not been implemented") } } - -class IntroducingPinsSplash: SplashViewController { - override var isReadyToComplete: Bool { KeyBackupService.hasMasterKey } - - override var canDismissWithGesture: Bool { return false } - - // MARK: - View lifecycle - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(true, animated: false) - } - - override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - navigationController?.setNavigationBarHidden(false, animated: false) - } - - override func loadView() { - - self.view = UIView.container() - self.view.backgroundColor = Theme.backgroundColor - - let heroImageView = UIImageView() - heroImageView.setImage(imageName: Theme.isDarkThemeEnabled ? "introducing-pins-dark" : "introducing-pins-light") - if let heroImage = heroImageView.image { - heroImageView.autoPinToAspectRatio(with: heroImage.size) - } else { - owsFailDebug("Missing hero image.") - } - view.addSubview(heroImageView) - heroImageView.autoPinTopToSuperviewMargin(withInset: 10) - heroImageView.autoHCenterInSuperview() - heroImageView.setContentHuggingLow() - heroImageView.setCompressionResistanceLow() - - let title = NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_PINS_SETUP_TITLE", comment: "Header for PINs splash screen") - - let attributedBody = NSMutableAttributedString( - string: NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_PINS_SETUP_DESCRIPTION", - comment: "Body text for PINs splash screen"), - attributes: [ - .font: UIFont.ows_dynamicTypeBody, - .foregroundColor: Theme.primaryTextColor - ] - ) - attributedBody.append(" ") - attributedBody.append(CommonStrings.learnMore, - attributes: [ - .link: URL(string: "https://support.signal.org/hc/articles/360007059792")!, - .font: UIFont.ows_dynamicTypeBody - ] - ) - - let hMargin: CGFloat = ScaleFromIPhone5To7Plus(16, 24) - - // Title label - let titleLabel = UILabel() - titleLabel.text = title - titleLabel.textAlignment = .center - titleLabel.font = UIFont.ows_dynamicTypeTitle1.ows_semibold - titleLabel.textColor = Theme.primaryTextColor - titleLabel.minimumScaleFactor = 0.5 - titleLabel.adjustsFontSizeToFitWidth = true - view.addSubview(titleLabel) - titleLabel.autoPinWidthToSuperview(withMargin: hMargin) - // The title label actually overlaps the hero image because it has a long shadow - // and we want the text to partially sit on top of this. - titleLabel.autoPinEdge(.top, to: .bottom, of: heroImageView, withOffset: -10) - titleLabel.setContentHuggingVerticalHigh() - - // Body label - let bodyLabel = LinkingTextView() - bodyLabel.attributedText = attributedBody - bodyLabel.isUserInteractionEnabled = true - bodyLabel.textColor = Theme.primaryTextColor - bodyLabel.textAlignment = .center - view.addSubview(bodyLabel) - bodyLabel.autoPinWidthToSuperview(withMargin: hMargin) - bodyLabel.autoPinEdge(.top, to: .bottom, of: titleLabel, withOffset: 6) - bodyLabel.setContentHuggingVerticalHigh() - - // Primary button - let primaryButton = OWSFlatButton.button(title: primaryButtonTitle(), - font: UIFont.ows_dynamicTypeBody.ows_semibold, - titleColor: .white, - backgroundColor: .ows_accentBlue, - target: self, - selector: #selector(didTapPrimaryButton)) - primaryButton.autoSetHeightUsingFont() - view.addSubview(primaryButton) - - primaryButton.autoPinBottomToSuperviewMargin(withInset: ScaleFromIPhone5(10)) - primaryButton.autoPinWidthToSuperview(withMargin: hMargin) - primaryButton.autoPinEdge(.top, to: .bottom, of: bodyLabel, withOffset: 28) - primaryButton.setContentHuggingVerticalHigh() - - // More button - let moreButton = UIButton() - moreButton.setTemplateImageName("more-horiz-24", tintColor: Theme.primaryIconColor) - moreButton.addTarget(self, action: #selector(didTapMoreButton), for: .touchUpInside) - view.addSubview(moreButton) - - moreButton.autoSetDimensions(to: CGSize(square: 44)) - moreButton.autoPinEdge(toSuperviewSafeArea: .trailing, withInset: 8) - moreButton.autoPinEdge(toSuperviewSafeArea: .top, withInset: 8) - } - - @objc - func didTapPrimaryButton(_ sender: UIButton) { - let vc = PinSetupViewController.creating { [weak self] _, _ in - self?.dismiss(animated: true) - } - navigationController?.pushViewController(vc, animated: true) - } - - @objc - func didTapMoreButton(_ sender: UIButton) { - let actionSheet = ActionSheetController() - actionSheet.addAction(OWSActionSheets.cancelAction) - - let learnMoreAction = ActionSheetAction( - title: NSLocalizedString( - "UPGRADE_EXPERIENCE_INTRODUCING_PINS_LEARN_MORE", - comment: "Learn more action on the one time splash screen that appears after upgrading" - ) - ) { [weak self] _ in - guard let self = self else { return } - let vc = SFSafariViewController(url: URL(string: "https://support.signal.org/hc/articles/360007059792")!) - self.present(vc, animated: true, completion: nil) - } - actionSheet.addAction(learnMoreAction) - - let skipAction = ActionSheetAction( - title: NSLocalizedString( - "UPGRADE_EXPERIENCE_INTRODUCING_PINS_SKIP", - comment: "Skip action on the one time splash screen that appears after upgrading" - ) - ) { [weak self] _ in - guard let self = self else { return } - PinSetupViewController.disablePinWithConfirmation(fromViewController: self).done { [weak self] pinDisabled in - guard pinDisabled else { return } - self?.dismiss(animated: true) - }.catch { [weak self] _ in - guard let self = self else { return } - OWSActionSheets.showActionSheet( - title: NSLocalizedString("PIN_DISABLE_ERROR_TITLE", - comment: "Error title indicating that the attempt to disable a PIN failed."), - message: NSLocalizedString("PIN_DISABLE_ERROR_MESSAGE", - comment: "Error body indicating that the attempt to disable a PIN failed.") - ) { _ in - self.dismissWithoutCompleting(animated: true) - } - } - } - actionSheet.addAction(skipAction) - - presentActionSheet(actionSheet) - } - - func primaryButtonTitle() -> String { - return NSLocalizedString("UPGRADE_EXPERIENCE_INTRODUCING_PINS_CREATE_BUTTON", - comment: "Button to start a create pin flow from the one time splash screen that appears after upgrading") - } - - func secondaryButtonTitle() -> String { - return CommonStrings.learnMore - } - - var toastText: String { - return KeyBackupService.hasBackedUpMasterKey - ? NSLocalizedString("PINS_MEGAPHONE_TOAST", comment: "Toast indicating that a PIN has been created.") - : NSLocalizedString("PINS_MEGAPHONE_TOAST_DISABLED", comment: "Toast indicating that a PIN has been disabled.") - } - - override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { - guard let fromViewController = presentingViewController else { - return // owsFailDebug("Trying to dismiss while not presented.") - } - - let toastText = self.toastText - super.dismiss(animated: flag) { [weak self] in - if let self = self, !self.isDismissWithoutCompleting { - fromViewController.presentToast(text: toastText) - } - completion?() - } - } -} diff --git a/Signal/src/ViewControllers/AppSettings/Account/AccountSettingsViewController.swift b/Signal/src/ViewControllers/AppSettings/Account/AccountSettingsViewController.swift index f07e36e099..2674462729 100644 --- a/Signal/src/ViewControllers/AppSettings/Account/AccountSettingsViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/Account/AccountSettingsViewController.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. // import Foundation @@ -337,7 +337,7 @@ class AccountSettingsViewController: OWSTableViewController2 { private func showCreatePin(enableRegistrationLock: Bool = false) { let vc = PinSetupViewController( - mode: .creating, + mode: .recreating, enableRegistrationLock: enableRegistrationLock ) { [weak self] _, _ in guard let self = self else { return } diff --git a/Signal/src/ViewControllers/OWSPinSetupViewController.swift b/Signal/src/ViewControllers/OWSPinSetupViewController.swift index 106eb6917c..803f9e399b 100644 --- a/Signal/src/ViewControllers/OWSPinSetupViewController.swift +++ b/Signal/src/ViewControllers/OWSPinSetupViewController.swift @@ -1,9 +1,12 @@ // -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. // import UIKit import SafariServices +import SignalCoreKit +import SignalServiceKit +import SignalUI @objc(OWSPinSetupViewController) public class PinSetupViewController: OWSViewController { @@ -607,12 +610,55 @@ public class PinSetupViewController: OWSViewController { self.recommendationLabel.alpha = 0 } - OWS2FAManager.shared.requestEnable2FA(withPin: pin, mode: .V2).then { () -> Promise in + enum PinSetupError: Error { + case networkFailure + case enable2FA + case enableRegistrationLock + } + + firstly { () -> Promise in + OWS2FAManager.shared.requestEnable2FA(withPin: pin, mode: .V2) + }.recover { error in + // If we have a network failure before even requesting to enable 2FA, we + // can just ask the user to retry without altering any state. We can be + // confident nothing has changed on the server. + if case OWSHTTPError.networkFailure = error { + throw PinSetupError.networkFailure + } + + owsFailDebug("Failed to enable 2FA with error: \(error)") + + // The client may have fallen out of sync with the service. + // Try to get back to a known good state by disabling 2FA + // whenever enabling it fails. + OWS2FAManager.shared.disable2FA(success: nil, failure: nil) + + throw PinSetupError.enable2FA + }.then { () -> Promise in if self.enableRegistrationLock { return OWS2FAManager.shared.enableRegistrationLockV2() } else { return Promise.value(()) } + }.recover { error -> Promise in + if error is PinSetupError { throw error } + + owsFailDebug("Failed to enable registration lock with error: \(error)") + + // If the registration lock wasn't already enabled, we have to notify + // the user of the failure and not attempt to enable it later. Otherwise, + // they would be left thinking they have registration lock enabled when + // they do not for some window of time. + guard OWS2FAManager.shared.isRegistrationLockV2Enabled else { + throw PinSetupError.enableRegistrationLock + } + + // Otherwise, attempt to update our account attributes. This may also fail, + // but if it does it will flag our attributes as dirty so we upload them + // ASAP (when we have the ability to talk to the service) and get the user + // switched over to their new PIN for registration lock. + TSAccountManager.shared.updateAccountAttributes().cauterize() + return Promise.value(()) }.done { AssertIsOnMainThread() @@ -627,13 +673,6 @@ public class PinSetupViewController: OWSViewController { }.catch { error in AssertIsOnMainThread() - Logger.error("Failed to enable 2FA with error: \(error)") - - // The client may have fallen out of sync with the service. - // Try to get back to a known good state by disabling 2FA - // whenever enabling it fails. - OWS2FAManager.shared.disable2FA(success: nil, failure: nil) - progressView.stopAnimating(success: false) { self.nextButton.alpha = 1 self.pinTextField.alpha = 1 @@ -643,23 +682,70 @@ public class PinSetupViewController: OWSViewController { self.view.isUserInteractionEnabled = true progressView.removeFromSuperview() - // If this is the first time the user is trying to create a PIN, it's a blocking flow. - // If for some reason they hit an error, notify them that we'll try again later and - // dismiss the flow so they aren't stuck. - if case .creating = self.initialMode { + guard let error = error as? PinSetupError else { + return owsFailDebug("Unexpected error during PIN setup \(error)") + } + + // Show special reglock themed error message. + switch error { + case .enableRegistrationLock: OWSActionSheets.showActionSheet( - title: NSLocalizedString("PIN_CREATION_ERROR_TITLE", - comment: "Error title indicating that the attempt to create a PIN failed."), - message: NSLocalizedString("PIN_CREATION_ERROR_MESSAGE", - comment: "Error body indicating that the attempt to create a PIN failed.") + title: NSLocalizedString( + "PIN_CREATION_REGLOCK_ERROR_TITLE", + comment: "Error title indicating that the attempt to create a PIN succeeded but enabling reglock failed."), + message: NSLocalizedString( + "PIN_CREATION_REGLOCK_ERROR_MESSAGE", + comment: "Error body indicating that the attempt to create a PIN succeeded but enabling reglock failed.") ) { _ in self.completionHandler(self, error) } - } else { - OWSActionSheets.showErrorAlert( - message: NSLocalizedString("ENABLE_2FA_VIEW_COULD_NOT_ENABLE_2FA", - comment: "Error indicating that attempt to enable 'two-factor auth' failed.") + case .networkFailure: + OWSActionSheets.showActionSheet( + title: NSLocalizedString( + "PIN_CREATION_NO_NETWORK_ERROR_TITLE", + comment: "Error title indicating that the attempt to create a PIN failed due to network issues."), + message: NSLocalizedString( + "PIN_CREATION_NO_NETWORK_ERROR_MESSAGE", + comment: "Error body indicating that the attempt to create a PIN failed due to network issues.") ) + case .enable2FA: + switch self.initialMode { + case .creating: + OWSActionSheets.showActionSheet( + title: NSLocalizedString( + "PIN_CREATION_ERROR_TITLE", + comment: "Error title indicating that the attempt to create a PIN failed."), + message: NSLocalizedString( + "PIN_CREATION_ERROR_MESSAGE", + comment: "Error body indicating that the attempt to create a PIN failed.") + ) { _ in + self.completionHandler(self, error) + } + case .changing: + OWSActionSheets.showActionSheet( + title: NSLocalizedString( + "PIN_CHANGE_ERROR_TITLE", + comment: "Error title indicating that the attempt to change a PIN failed."), + message: NSLocalizedString( + "PIN_CHANGE_ERROR_MESSAGE", + comment: "Error body indicating that the attempt to change a PIN failed.") + ) { _ in + self.completionHandler(self, error) + } + case .recreating: + OWSActionSheets.showActionSheet( + title: NSLocalizedString( + "PIN_RECREATION_ERROR_TITLE", + comment: "Error title indicating that the attempt to recreate a PIN failed."), + message: NSLocalizedString( + "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") + } } } } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index b868e72324..e0ec43e5ad 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -340,15 +340,6 @@ /* action sheet button title to enable built in speaker during a call */ "AUDIO_ROUTE_BUILT_IN_SPEAKER" = "Speaker"; -/* Action text for avatar builder megaphone */ -"AVATAR_BUILDER_MEGAPHONE_ACTION" = "Add Photo"; - -/* Body for avatar builder megaphone */ -"AVATAR_BUILDER_MEGAPHONE_BODY" = "Choose a look and color or customize your initials."; - -/* Title for avatar builder megaphone */ -"AVATAR_BUILDER_MEGAPHONE_TITLE" = "Add a profile photo"; - /* Text prompting the user to choose a color when editing their avatar */ "AVATAR_EDIT_VIEW_CHOOSE_A_COLOR" = "Choose a Color"; @@ -745,15 +736,6 @@ /* Tooltip highlighting the auto chat color option. */ "CHAT_COLORS_AUTO_TOOLTIP" = "Auto matches the color to the wallpaper"; -/* Action text for char colors megaphone */ -"CHAT_COLORS_MEGAPHONE_ACTION" = "Appearance"; - -/* Body for chat colors megaphone */ -"CHAT_COLORS_MEGAPHONE_BODY" = "Now you can change the colors in your chats with gradients and more."; - -/* Title for chat colors megaphone */ -"CHAT_COLORS_MEGAPHONE_TITLE" = "Custom Chat Colors"; - /* Title for the color & wallpaper settings view. */ "COLOR_AND_WALLPAPER_SETTINGS_TITLE" = "Chat Color & Wallpaper"; @@ -1711,9 +1693,6 @@ /* Full width label displayed when attempting to compose message */ "EMPTY_CONTACTS_LABEL_LINE2" = "Why don't you invite someone?"; -/* Error indicating that attempt to enable 'two-factor auth' failed. */ -"ENABLE_2FA_VIEW_COULD_NOT_ENABLE_2FA" = "Could not enable Registration Lock."; - /* Call setup status label */ "END_CALL_RESPONDER_IS_BUSY" = "Busy"; @@ -2131,12 +2110,6 @@ /* Text describing the local user in the group call members sheet when connected from another device. */ "GROUP_CALL_YOU_ON_ANOTHER_DEVICE" = "You (on another device)"; -/* Body for group calls megaphone */ -"GROUP_CALLS_MEGAPHONE_BODY" = "Open a New Group to start a free encrypted group call"; - -/* Title for group calls megaphone */ -"GROUP_CALLS_MEGAPHONE_TITLE" = "Introducing Group Calls"; - /* Message indicating that group was created by the local user. */ "GROUP_CREATED_BY_LOCAL_USER" = "You created the group."; @@ -3169,15 +3142,6 @@ /* Alert Title */ "LINKING_DEVICE_FAILED_TITLE" = "Linking Device Failed"; -/* Body for link previews megaphone */ -"LINKPREVIEWS_MEGAPHONE_BODY" = "Link previews will now be generated for all sites."; - -/* Disable button for link previews megaphone */ -"LINKPREVIEWS_MEGAPHONE_BUTTON_DISABLE" = "Disable"; - -/* Title for link previews megaphone */ -"LINKPREVIEWS_MEGAPHONE_TITLE" = "Preview Any Link"; - /* Body for local network permission action sheet */ "LOCAL_NETWORK_PERMISSION_ACTION_SHEET_BODY" = "In order to transfer your Signal account, you need to enable local network access on both devices."; @@ -4315,6 +4279,12 @@ /* 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"; @@ -4357,6 +4327,12 @@ /* Label indicating that the attempted PIN does not match the first PIN */ "PIN_CREATION_MISMATCH_ERROR" = "PINs don’t 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"; + /* Label indicating the user must use at least 4 digits */ "PIN_CREATION_NUMERIC_HINT" = "PIN must be at least 4 digits"; @@ -4381,6 +4357,12 @@ /* Title of the 'pin disable' reglock action sheet. */ "PIN_CREATION_REGLOCK_CONFIRMATION_TITLE" = "Turn Off Registration Lock?"; +/* Error body indicating that the attempt to create a PIN succeeded but enabling reglock failed. */ +"PIN_CREATION_REGLOCK_ERROR_MESSAGE" = "PIN creation succeeded, but registration lock could not be enabled. Check your connection and try again."; + +/* Error title indicating that the attempt to create a PIN succeeded but enabling reglock failed. */ +"PIN_CREATION_REGLOCK_ERROR_TITLE" = "Enable Registration Lock Failed"; + /* Skip action on the pin creation view */ "PIN_CREATION_SKIP" = "Disable PIN"; @@ -4396,6 +4378,12 @@ /* Error title indicating that the attempt to disable a PIN failed. */ "PIN_DISABLE_ERROR_TITLE" = "PIN Disable Failed"; +/* 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" = "Couldn’t 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, we’ll ask you to enter it periodically. We’ll ask less over time."; @@ -4442,7 +4430,7 @@ "PINS_MEGAPHONE_ACTION" = "Create PIN"; /* Body for PIN megaphone when user doesn't have a PIN */ -"PINS_MEGAPHONE_BODY" = "PINs keep information that’s stored with Signal encrypted"; +"PINS_MEGAPHONE_BODY" = "Finish creating your Signal PIN."; /* Toast indication that the user will be reminded later to setup their PIN. Embeds {{time until mandatory}} */ "PINS_MEGAPHONE_SNOOZE_TOAST_FORMAT" = "We’ll remind you later. Creating a PIN will become mandatory in %ld days."; @@ -4453,9 +4441,6 @@ /* Toast indicating that a PIN has been created. */ "PINS_MEGAPHONE_TOAST" = "PIN created. You can change it in settings."; -/* Toast indicating that a PIN has been disabled. */ -"PINS_MEGAPHONE_TOAST_DISABLED" = "PIN Disabled."; - /* Accessibility label for button to start media playback */ "PLAY_BUTTON_ACCESSABILITY_LABEL" = "Play Media"; @@ -4807,27 +4792,6 @@ /* No comment provided by engineer. */ "REREGISTER_FOR_PUSH" = "Re-register Push Notifications"; -/* Body for research megaphone */ -"RESEARCH_MEGAPHONE_BODY" = "To make Signal the best messaging app on the planet, we’d love to hear your feedback."; - -/* Title for research megaphone */ -"RESEARCH_MEGAPHONE_TITLE" = "Tell Signal what you think"; - -/* Text for the research modal footer */ -"RESEARCH_MODAL_FOOTER" = "The survey is hosted by Surveygizmo at the secure domain surveys.signalusers.org"; - -/* Button text for declining the research modal */ -"RESEARCH_MODAL_NO_THANKS" = "No thanks"; - -/* Text explaining why the user should take the survey */ -"RESEARCH_MODAL_PLEA" = "We believe in privacy.\n\nSignal doesn’t track you or collect your data. To improve Signal for everyone, we rely on user feedback, and we’d love yours.\n\nWe’re running a survey to understand how you use Signal. Our survey doesn't collect any data that will identify you. If you’re interested in sharing additional feedback, you'll have the option to provide contact information.\n\nIf you have a few minutes and feedback to offer, we’d love to hear from you."; - -/* Button text for taking the research survey */ -"RESEARCH_MODAL_TAKE_SURVEY" = "Take the survey"; - -/* Title for the research megaphone modal */ -"RESEARCH_MODAL_TITLE" = "Signal Research"; - /* Configure reactions reset button text */ "RESET" = "Reset"; @@ -6049,18 +6013,6 @@ /* Title of alert indicating sharing suggestions failed to deactivate */ "SHARING_SUGGESTIONS_DISABLE_ERROR" = "Failed to disable sharing suggestions."; -/* Body for sharing suggestions megaphone */ -"SHARING_SUGGESTIONS_MEGAPHONE_BODY" = "Signal chats can now be displayed as suggestions when sharing from other apps."; - -/* Title for sharing suggestions megaphone */ -"SHARING_SUGGESTIONS_MEGAPHONE_TITLE" = "Sharing Made Easier"; - -/* Disable button for sharing suggestions megaphone */ -"SHARING_SUGGESTIOONS_MEGAPHONE_BUTTON_DISABLE" = "Disable"; - -/* Enable button for sharing suggestions megaphone */ -"SHARING_SUGGESTIOONS_MEGAPHONE_BUTTON_ENABLE" = "Enable"; - /* Action sheet item */ "SHOW_SAFETY_NUMBER_ACTION" = "Show Safety Number"; @@ -6097,21 +6049,6 @@ /* Title for the captcha view controller */ "SPAM_CAPTCHA_VIEW_CONTROLLER" = "Complete verification"; -/* Footer for 'groups v2 and mentions' splash screen */ -"SPLASH_MEGAPHONE_GROUPS_V2_MENTIONS_NAMES_SPLASH_FOOTER" = "Existing groups will automatically get these features in the coming weeks."; - -/* Instructions for 'groups v2 and mentions' splash screen */ -"SPLASH_MEGAPHONE_GROUPS_V2_MENTIONS_NAMES_SPLASH_INSTRUCTIONS" = "New Group"; - -/* Joiner symbol in the instructions for 'groups v2 and mentions' splash screen */ -"SPLASH_MEGAPHONE_GROUPS_V2_MENTIONS_NAMES_SPLASH_INSTRUCTIONS_JOINER" = "+"; - -/* Header for 'groups v2 and mentions' splash screen */ -"SPLASH_MEGAPHONE_GROUPS_V2_MENTIONS_NAMES_SPLASH_TITLE" = "New Groups are here!"; - -/* Body text for 'groups v2 and mentions' splash screen */ -"SPLASH_MEGAPHONE_GROUPS_V2_MENTIONS_SPLASH_BODY" = "New Group features include @mentions, admins, and more. Try it out by tapping:"; - /* Preview text shown in notifications and conversation list for sticker messages. */ "STICKER_MESSAGE_PREVIEW" = "Sticker Message"; @@ -6529,21 +6466,6 @@ /* Error indicating that a group could not be updated due to network connectivity problems. */ "UPDATE_GROUP_FAILED_DUE_TO_NETWORK" = "Group could not be updated. Check your internet connection and try again."; -/* Button to start a create pin flow from the one time splash screen that appears after upgrading */ -"UPGRADE_EXPERIENCE_INTRODUCING_PINS_CREATE_BUTTON" = "Create your PIN"; - -/* Learn more action on the one time splash screen that appears after upgrading */ -"UPGRADE_EXPERIENCE_INTRODUCING_PINS_LEARN_MORE" = "Learn More About PINs"; - -/* Body text for PINs splash screen */ -"UPGRADE_EXPERIENCE_INTRODUCING_PINS_SETUP_DESCRIPTION" = "PINs keep information stored with Signal encrypted so only you can access it. Your profile, settings, and contacts will restore when you reinstall. You won’t need your PIN to open the app."; - -/* Header for PINs splash screen */ -"UPGRADE_EXPERIENCE_INTRODUCING_PINS_SETUP_TITLE" = "Introducing PINs"; - -/* Skip action on the one time splash screen that appears after upgrading */ -"UPGRADE_EXPERIENCE_INTRODUCING_PINS_SKIP" = "Disable PIN"; - /* Message for the alert indicating that user should upgrade iOS. */ "UPGRADE_IOS_ALERT_MESSAGE" = "Signal will soon require iOS 11 or later. Please upgrade in Settings app >> General >> Software Update."; diff --git a/SignalServiceKit/src/Util/ExperienceUpgradeFinder.swift b/SignalServiceKit/src/Util/ExperienceUpgradeFinder.swift index 5b39650191..18830f283a 100644 --- a/SignalServiceKit/src/Util/ExperienceUpgradeFinder.swift +++ b/SignalServiceKit/src/Util/ExperienceUpgradeFinder.swift @@ -111,6 +111,8 @@ public enum ExperienceUpgradeId: String, CaseIterable, Dependencies { switch self { case .pinReminder: return false + case .introducingPins: + return false default: return true } @@ -122,6 +124,8 @@ public enum ExperienceUpgradeId: String, CaseIterable, Dependencies { switch self { case .pinReminder: return false + case .introducingPins: + return false case .notificationPermissionReminder: return false case .contactPermissionReminder: diff --git a/SignalServiceKit/src/Util/OWS2FAManager.m b/SignalServiceKit/src/Util/OWS2FAManager.m index c7d0c31683..dc77f6f768 100644 --- a/SignalServiceKit/src/Util/OWS2FAManager.m +++ b/SignalServiceKit/src/Util/OWS2FAManager.m @@ -1,5 +1,5 @@ // -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. // #import "OWS2FAManager.h" @@ -123,6 +123,7 @@ const NSUInteger kLegacyTruncated2FAv1PinLength = 16; - (void)markDisabledWithTransaction:(SDSAnyWriteTransaction *)transaction { [OWS2FAManager.keyValueStore removeValueForKey:kOWS2FAManager_PinCode transaction:transaction]; + [OWS2FAManager.keyValueStore removeValueForKey:OWS2FAManager.isRegistrationLockV2EnabledKey transaction:transaction]; [transaction addSyncCompletion:^{ [[NSNotificationCenter defaultCenter] postNotificationNameAsync:NSNotificationName_2FAStateDidChange diff --git a/SignalServiceKit/src/Util/OWS2FAManager.swift b/SignalServiceKit/src/Util/OWS2FAManager.swift index 9b194aac20..4e6c6d26cb 100644 --- a/SignalServiceKit/src/Util/OWS2FAManager.swift +++ b/SignalServiceKit/src/Util/OWS2FAManager.swift @@ -1,11 +1,12 @@ // -// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// Copyright (c) 2022 Open Whisper Systems. All rights reserved. // import Foundation extension OWS2FAManager { + @objc public static var isRegistrationLockV2EnabledKey = "isRegistrationLockV2Enabled" @objc