The old UIButton API is still functional as long as we don't use UIButton.Configuration, so we can safely ignore these warnings until we're ready to adopt the configuration API across the codebase.
258 lines
9.6 KiB
Swift
258 lines
9.6 KiB
Swift
//
|
|
// Copyright 2023 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import MultipeerConnectivity
|
|
import SignalServiceKit
|
|
import SignalUI
|
|
import UIKit
|
|
|
|
public class RegistrationTransferProgressViewController: OWSViewController {
|
|
|
|
let progressView: TransferProgressView
|
|
|
|
public init(progress: Progress) {
|
|
self.progressView = TransferProgressView(progress: progress)
|
|
super.init()
|
|
}
|
|
|
|
override public func loadView() {
|
|
view = UIView()
|
|
|
|
view.backgroundColor = Theme.backgroundColor
|
|
|
|
let titleLabel = UILabel.titleLabelForRegistration(
|
|
text: OWSLocalizedString(
|
|
"DEVICE_TRANSFER_RECEIVING_TITLE",
|
|
comment: "The title on the view that shows receiving progress"
|
|
)
|
|
)
|
|
view.addSubview(titleLabel)
|
|
titleLabel.accessibilityIdentifier = "onboarding.transferProgress.titleLabel"
|
|
titleLabel.setContentHuggingHigh()
|
|
|
|
let explanationLabel = UILabel.explanationLabelForRegistration(
|
|
text: OWSLocalizedString(
|
|
"DEVICE_TRANSFER_RECEIVING_EXPLANATION",
|
|
comment: "The explanation on the view that shows receiving progress"
|
|
)
|
|
)
|
|
explanationLabel.accessibilityIdentifier = "onboarding.transferProgress.bodyLabel"
|
|
explanationLabel.setContentHuggingHigh()
|
|
|
|
let cancelButton = OWSFlatButton.linkButtonForRegistration(
|
|
title: CommonStrings.cancelButton,
|
|
target: self,
|
|
selector: #selector(didTapCancel)
|
|
)
|
|
|
|
let topSpacer = UIView.vStretchingSpacer()
|
|
let bottomSpacer = UIView.vStretchingSpacer()
|
|
|
|
let stackView = UIStackView(arrangedSubviews: [
|
|
titleLabel,
|
|
explanationLabel,
|
|
topSpacer,
|
|
progressView,
|
|
bottomSpacer,
|
|
cancelButton
|
|
])
|
|
stackView.axis = .vertical
|
|
stackView.alignment = .fill
|
|
stackView.spacing = 12
|
|
view.addSubview(stackView)
|
|
stackView.autoPinEdgesToSuperviewMargins()
|
|
|
|
topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)
|
|
}
|
|
|
|
override public func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
navigationItem.setHidesBackButton(true, animated: false)
|
|
}
|
|
|
|
override public func viewWillAppear(_ animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
|
|
progressView.startUpdatingProgress()
|
|
|
|
deviceTransferService.addObserver(self)
|
|
}
|
|
|
|
public override func viewWillDisappear(_ animated: Bool) {
|
|
super.viewWillDisappear(animated)
|
|
|
|
progressView.stopUpdatingProgress()
|
|
|
|
deviceTransferService.removeObserver(self)
|
|
deviceTransferService.cancelTransferFromOldDevice()
|
|
}
|
|
|
|
// MARK: - Events
|
|
|
|
@objc
|
|
func didTapCancel() {
|
|
Logger.info("")
|
|
|
|
let actionSheet = ActionSheetController(
|
|
title: OWSLocalizedString("DEVICE_TRANSFER_CANCEL_CONFIRMATION_TITLE",
|
|
comment: "The title of the dialog asking the user if they want to cancel a device transfer"),
|
|
message: OWSLocalizedString("DEVICE_TRANSFER_CANCEL_CONFIRMATION_MESSAGE",
|
|
comment: "The message of the dialog asking the user if they want to cancel a device transfer")
|
|
)
|
|
actionSheet.addAction(OWSActionSheets.cancelAction)
|
|
|
|
let okAction = ActionSheetAction(
|
|
title: OWSLocalizedString("DEVICE_TRANSFER_CANCEL_CONFIRMATION_ACTION",
|
|
comment: "The stop action of the dialog asking the user if they want to cancel a device transfer"),
|
|
style: .destructive
|
|
) { [weak self] _ in
|
|
// viewWillDissapear will cancel the transfer
|
|
self?.navigationController?.popViewController(animated: true)
|
|
}
|
|
actionSheet.addAction(okAction)
|
|
|
|
present(actionSheet, animated: true)
|
|
}
|
|
}
|
|
|
|
extension RegistrationTransferProgressViewController: DeviceTransferServiceObserver {
|
|
func deviceTransferServiceDiscoveredNewDevice(peerId: MCPeerID, discoveryInfo: [String: String]?) {}
|
|
|
|
func deviceTransferServiceDidStartTransfer(progress: Progress) {}
|
|
|
|
func deviceTransferServiceDidEndTransfer(error: DeviceTransferService.Error?) {
|
|
guard let error = error else { return }
|
|
|
|
switch error {
|
|
case .assertion:
|
|
progressView.renderError(
|
|
text: OWSLocalizedString("DEVICE_TRANSFER_ERROR_GENERIC",
|
|
comment: "An error indicating that something went wrong with the transfer and it could not complete")
|
|
)
|
|
case .backgroundedDevice:
|
|
progressView.renderError(
|
|
text: OWSLocalizedString(
|
|
"DEVICE_TRANSFER_ERROR_BACKGROUNDED",
|
|
comment: "An error indicating that the other device closed signal mid-transfer and it could not complete"
|
|
)
|
|
)
|
|
case .cancel:
|
|
// User initiated, nothing to do
|
|
break
|
|
case .certificateMismatch:
|
|
owsFailDebug("This should never happen on the new device")
|
|
case .notEnoughSpace:
|
|
progressView.renderError(
|
|
text: OWSLocalizedString("DEVICE_TRANSFER_ERROR_NOT_ENOUGH_SPACE",
|
|
comment: "An error indicating that the user does not have enough free space on their device to complete the transfer")
|
|
)
|
|
case .unsupportedVersion:
|
|
progressView.renderError(
|
|
text: OWSLocalizedString("DEVICE_TRANSFER_ERROR_UNSUPPORTED_VERSION",
|
|
comment: "An error indicating the user must update their device before trying to transfer.")
|
|
)
|
|
case .modeMismatch:
|
|
owsFailDebug("This should never happen on the new device")
|
|
}
|
|
}
|
|
|
|
func deviceTransferServiceDidRequestAppRelaunch() {
|
|
self.present(TransferRelaunchSheet(), animated: true)
|
|
}
|
|
}
|
|
|
|
private class TransferRelaunchSheet: InteractiveSheetViewController {
|
|
let stackView = UIStackView()
|
|
|
|
public override var canBeDismissed: Bool { false }
|
|
|
|
public override var sheetBackgroundColor: UIColor { Theme.tableView2PresentedBackgroundColor }
|
|
|
|
override public func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
minimizedHeight = 460
|
|
super.allowsExpansion = false
|
|
|
|
stackView.axis = .vertical
|
|
stackView.layoutMargins = UIEdgeInsets(hMargin: 24, vMargin: 24)
|
|
stackView.spacing = 22
|
|
stackView.isLayoutMarginsRelativeArrangement = true
|
|
contentView.addSubview(stackView)
|
|
|
|
let image = UIImage(named: "transfer_complete")
|
|
let imageView = UIImageView(image: image)
|
|
imageView.contentMode = .scaleAspectFit
|
|
stackView.addArrangedSubview(imageView)
|
|
imageView.autoSetDimensions(to: CGSize(width: 128, height: 64))
|
|
|
|
let titleLabel = UILabel()
|
|
titleLabel.textAlignment = .center
|
|
titleLabel.font = UIFont.dynamicTypeTitle2.semibold()
|
|
titleLabel.text = OWSLocalizedString(
|
|
"TRANSFER_COMPLETE_SHEET_TITLE",
|
|
comment: "Title for bottom sheet shown when device transfer completes on the receiving device."
|
|
)
|
|
stackView.addArrangedSubview(titleLabel)
|
|
|
|
let subtitleLabel = UILabel()
|
|
subtitleLabel.text = OWSLocalizedString(
|
|
"TRANSFER_COMPLETE_SHEET_SUBTITLE",
|
|
comment: "Subtitle for bottom sheet shown when device transfer completes on the receiving device."
|
|
)
|
|
subtitleLabel.textAlignment = .center
|
|
subtitleLabel.font = .dynamicTypeBody
|
|
subtitleLabel.numberOfLines = 0
|
|
subtitleLabel.lineBreakMode = .byWordWrapping
|
|
stackView.addArrangedSubview(subtitleLabel)
|
|
|
|
let exitButton = UIButton()
|
|
exitButton.backgroundColor = .ows_accentBlue
|
|
exitButton.layer.cornerRadius = 8
|
|
exitButton.ows_titleEdgeInsets = UIEdgeInsets(hMargin: 0, vMargin: 18)
|
|
exitButton.setTitleColor(.ows_white, for: .normal)
|
|
exitButton.setTitle(
|
|
OWSLocalizedString(
|
|
"TRANSFER_COMPLETE_SHEET_BUTTON",
|
|
comment: "Button for bottom sheet shown when device transfer completes on the receiving device. Tapping will terminate the Signal app and trigger a notification to relaunch."
|
|
),
|
|
for: .normal
|
|
)
|
|
exitButton.addTarget(self, action: #selector(didTapExitButton), for: .touchUpInside)
|
|
contentView.addSubview(exitButton)
|
|
exitButton.autoPinEdge(
|
|
.leading,
|
|
to: .leading,
|
|
of: contentView,
|
|
withOffset: 32,
|
|
relation: .greaterThanOrEqual
|
|
).priority = .required
|
|
exitButton.autoPinEdge(
|
|
.trailing,
|
|
to: .trailing,
|
|
of: contentView,
|
|
withOffset: -32,
|
|
relation: .greaterThanOrEqual
|
|
).priority = .required
|
|
exitButton.autoSetDimension(.width, toSize: 325, relation: .greaterThanOrEqual)
|
|
exitButton.autoSetDimension(.height, toSize: 48, relation: .greaterThanOrEqual)
|
|
exitButton.autoPinEdge(.bottom, to: .bottom, of: contentView, withOffset: -50)
|
|
exitButton.autoHCenterInSuperview()
|
|
|
|
stackView.autoPinEdge(.top, to: .top, of: contentView)
|
|
stackView.autoPinWidth(toWidthOf: contentView)
|
|
stackView.autoHCenterInSuperview()
|
|
}
|
|
|
|
@objc
|
|
private func didTapExitButton() {
|
|
Logger.info("")
|
|
notificationPresenter.notifyUserToRelaunchAfterTransfer {
|
|
Logger.info("Deliberately terminating app post-transfer.")
|
|
exit(0)
|
|
}
|
|
}
|
|
}
|