Path: blob/main/Signal/src/ViewControllers/AppSettings/Payments/PaymentsRestoreWalletCompleteViewController.swift
1 views
//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
public import SignalServiceKit
public import SignalUI
public class PaymentsRestoreWalletCompleteViewController: OWSTableViewController2 {
private let passphrase: PaymentsPassphrase
private weak var restoreWalletDelegate: PaymentsRestoreWalletDelegate?
private let bottomStack = UIStackView()
override open var bottomFooter: UIView? {
get { bottomStack }
set {}
}
public init(
restoreWalletDelegate: PaymentsRestoreWalletDelegate,
passphrase: PaymentsPassphrase,
) {
self.passphrase = passphrase
self.restoreWalletDelegate = restoreWalletDelegate
super.init()
self.shouldAvoidKeyboard = true
}
override public func viewDidLoad() {
super.viewDidLoad()
title = OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_TITLE",
comment: "Title for the 'restore payments wallet' view of the app settings.",
)
buildBottomView()
updateTableContents()
}
override public func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateTableContents()
}
override public func themeDidChange() {
super.themeDidChange()
updateTableContents()
}
private func buildBottomView() {
let doneButton = OWSFlatButton.button(
title: CommonStrings.doneButton,
font: UIFont.dynamicTypeHeadline,
titleColor: .white,
backgroundColor: .ows_accentBlue,
target: self,
selector: #selector(didTapDoneButton),
)
doneButton.autoSetHeightUsingFont()
let editButton = OWSFlatButton.button(
title: CommonStrings.editButton,
font: .dynamicTypeBody,
titleColor: .ows_accentBlue,
backgroundColor: self.tableBackgroundColor,
target: self,
selector: #selector(didTapEditButton),
)
editButton.autoSetHeightUsingFont()
bottomStack.axis = .vertical
bottomStack.alignment = .fill
bottomStack.isLayoutMarginsRelativeArrangement = true
bottomStack.layoutMargins = .init(top: 8, left: 20, bottom: 8, right: 20)
bottomStack.addArrangedSubviews([
doneButton,
UIView.spacer(withHeight: 8),
editButton,
])
}
private func updateTableContents() {
AssertIsOnMainThread()
let contents = OWSTableContents()
let section = OWSTableSection()
section.customHeaderView = buildHeader()
section.shouldDisableCellSelection = true
let passphrase = self.passphrase
section.add(OWSTableItem(
customCellBlock: {
let cell = OWSTableItem.newCell()
let passphraseGrid = PaymentsViewUtils.buildPassphraseGrid(passphrase: passphrase)
cell.contentView.addSubview(passphraseGrid)
passphraseGrid.autoPinEdgesToSuperviewMargins()
return cell
},
actionBlock: nil,
))
contents.add(section)
self.contents = contents
}
private func buildHeader() -> UIView {
let titleLabel = UILabel()
titleLabel.text = OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_COMPLETE_TITLE",
comment: "Title for the 'review payments passphrase' step of the 'restore payments wallet' views.",
)
titleLabel.font = UIFont.dynamicTypeTitle2Clamped.semibold()
titleLabel.textColor = Theme.primaryTextColor
titleLabel.textAlignment = .center
let explanationLabel = UILabel()
explanationLabel.text = OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_COMPLETE_EXPLANATION",
comment: "Explanation of the 'review payments passphrase' step of the 'restore payments wallet' views.",
)
explanationLabel.font = .dynamicTypeSubheadlineClamped
explanationLabel.textColor = Theme.secondaryTextAndIconColor
explanationLabel.textAlignment = .center
explanationLabel.numberOfLines = 0
explanationLabel.lineBreakMode = .byWordWrapping
let topStack = UIStackView(arrangedSubviews: [
titleLabel,
UIView.spacer(withHeight: 10),
explanationLabel,
])
topStack.axis = .vertical
topStack.alignment = .center
topStack.isLayoutMarginsRelativeArrangement = true
topStack.layoutMargins = .init(top: 32, left: 20, bottom: 40, right: 20)
return topStack
}
private func showInvalidPassphraseAlert() {
let actionSheet = ActionSheetController(
title: OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_INVALID_PASSPHRASE_TITLE",
comment: "Title for the 'invalid payments wallet passphrase' error alert in the app payments settings.",
),
message: OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_INVALID_PASSPHRASE_MESSAGE",
comment: "Message for the 'invalid payments wallet passphrase' error alert in the app payments settings.",
),
)
actionSheet.addAction(ActionSheetAction(
title: CommonStrings.okayButton,
style: .default,
) { [weak self] _ in
self?.returnToFirstWordView(shouldClearInput: true)
})
presentActionSheet(actionSheet)
}
private func showRestoreFailureAlert() {
OWSActionSheets.showErrorAlert(message: OWSLocalizedString(
"SETTINGS_PAYMENTS_RESTORE_WALLET_FAILED",
comment: "Error indicating that 'restore payments wallet failed' in the app payments settings.",
))
}
// MARK: - Events
@objc
private func didTapDoneButton() {
guard SUIEnvironment.shared.paymentsRef.paymentsEntropy == nil else {
owsFailDebug("paymentsEntropy already set.")
dismiss(animated: true, completion: nil)
showRestoreFailureAlert()
return
}
guard let paymentsEntropy = SUIEnvironment.shared.paymentsSwiftRef.paymentsEntropy(forPassphrase: passphrase) else {
showInvalidPassphraseAlert()
return
}
let didSucceed = SSKEnvironment.shared.databaseStorageRef.write { transaction in
SSKEnvironment.shared.paymentsHelperRef.enablePayments(
withPaymentsEntropy: paymentsEntropy,
transaction: transaction,
)
}
guard didSucceed else {
owsFailDebug("Could not restore payments entropy.")
dismiss(animated: true, completion: nil)
showRestoreFailureAlert()
return
}
let restoreWalletDelegate = self.restoreWalletDelegate
dismiss(animated: true, completion: {
restoreWalletDelegate?.restoreWalletDidComplete()
})
}
@objc
private func didTapEditButton() {
returnToFirstWordView(shouldClearInput: false)
}
private func returnToFirstWordView(shouldClearInput: Bool) {
guard let navigationController else {
return
}
// We want to pop back to the _first_ of the "enter wallet passphrase" views.
for viewController in navigationController.viewControllers {
guard let viewController = viewController as? PaymentsRestoreWalletWordViewController else {
continue
}
if shouldClearInput {
viewController.clearInput()
}
navigationController.popToViewController(viewController, animated: true)
return
}
owsFailDebug("Could not return to start of passphrase.")
}
}