// // Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import MultipeerConnectivity import SignalServiceKit import SignalUI class ProvisioningTransferProgressViewController: ProvisioningBaseViewController { let progressView: TransferProgressView init(provisioningController: ProvisioningController, progress: Progress) { self.progressView = TransferProgressView(progress: progress) super.init(provisioningController: provisioningController) navigationItem.hidesBackButton = true } override func viewDidLoad() { super.viewDidLoad() let titleLabel = UILabel.titleLabelForRegistration(text: OWSLocalizedString( "DEVICE_TRANSFER_RECEIVING_TITLE", comment: "The title on the view that shows receiving progress" )) titleLabel.accessibilityIdentifier = "onboarding.transferProgress.titleLabel" let explanationLabel = UILabel.titleLabelForRegistration(text: OWSLocalizedString( "DEVICE_TRANSFER_RECEIVING_EXPLANATION", comment: "The explanation on the view that shows receiving progress" )) explanationLabel.accessibilityIdentifier = "onboarding.transferProgress.bodyLabel" let cancelButton = UIButton( configuration: .mediumSecondary(title: CommonStrings.cancelButton), primaryAction: UIAction { [weak self] _ in self?.didTapCancel() } ) let topSpacer = UIView.vStretchingSpacer() let bottomSpacer = UIView.vStretchingSpacer() let stackView = addStaticContentStackView(arrangedSubviews: [ topSpacer, titleLabel, explanationLabel, progressView, bottomSpacer, cancelButton.enclosedInVerticalStackView(isFullWidthButton: false) ]) stackView.setCustomSpacing(24, after: explanationLabel) topSpacer.translatesAutoresizingMaskIntoConstraints = false bottomSpacer.translatesAutoresizingMaskIntoConstraints = false topSpacer.heightAnchor.constraint(equalTo: bottomSpacer.heightAnchor, multiplier: 0.5).isActive = true } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) progressView.startUpdatingProgress() AppEnvironment.shared.deviceTransferServiceRef.addObserver(self) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) progressView.stopUpdatingProgress() AppEnvironment.shared.deviceTransferServiceRef.removeObserver(self) AppEnvironment.shared.deviceTransferServiceRef.cancelTransferFromOldDevice() } // MARK: - Events private func didTapCancel() { Logger.info("") guard let navigationController = navigationController else { return owsFailDebug("unexpectedly missing nav controller") } 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 ) { _ in self.provisioningController.pushTransferChoiceView(onto: navigationController) } actionSheet.addAction(okAction) present(actionSheet, animated: true) } } extension ProvisioningTransferProgressViewController: 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() { owsFail("Relaunch not supported for provisioning; only on the receiving device during transfer") } }