123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- //
- // AccountSetupController.swift
- // deltachat-ios
- //
- // Created by Bastian van de Wetering on 02.04.19.
- // Copyright © 2019 Jonas Reinsch. All rights reserved.
- //
- import SafariServices
- import UIKit
- import UICircularProgressRing
- class AccountSetupController: UITableViewController {
- weak var coordinator: AccountSetupCoordinator?
- private var backupProgressObserver: Any?
- private var configureProgressObserver: Any?
- private var oauth2Observer: Any?
- lazy var configurationProgress: UICircularProgressRing = {
- let progress = UICircularProgressRing()
- progress.style = UICircularRingStyle.inside
- //progress.backgroundColor = UIColor.white.withAlphaComponent(0)
- progress.maxValue = 100
- progress.outerRingColor = UIColor.init(white: 1, alpha: 0)
- progress.innerRingColor = DCColors.primary
- progress.innerRingWidth = 2
- progress.startAngle = 270
- progress.fontColor = UIColor.lightGray
- progress.font = UIFont.systemFont(ofSize: 12)
- return progress
- }()
- lazy var loginProgressHud: UIAlertController = {
- let alert = UIAlertController(title: "Configuring Account", message: "\n\n\n", preferredStyle: .alert)
- // temp workaround: add 3 newlines to let alertbox grow to fit progress indicator
- let progressView = configurationProgress
- progressView.translatesAutoresizingMaskIntoConstraints = false
- alert.view.addSubview(progressView)
- progressView.centerXAnchor.constraint(equalTo: alert.view.centerXAnchor).isActive = true
- progressView.centerYAnchor.constraint(equalTo: alert.view.centerYAnchor, constant: 0).isActive = true
- progressView.heightAnchor.constraint(equalToConstant: 70).isActive = true
- progressView.widthAnchor.constraint(equalToConstant: 70).isActive = true
- alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
- return alert
- }()
- /*
- private lazy var hudHandler: HudHandler = {
- let hudHandler = HudHandler(parentView: self)
- return hudHandler
- }()
- */
- private lazy var emailCell: TextFieldCell = {
- let cell = TextFieldCell.makeEmailCell(delegate: self)
- cell.textField.tag = 0
- cell.textField.accessibilityIdentifier = "emailTextField" // will be used to eventually show oAuth-Dialogue when pressing return key
- cell.setText(text: MRConfig.addr ?? nil)
- cell.textField.delegate = self
- return cell
- }()
- private lazy var passwordCell: TextFieldCell = {
- let cell = TextFieldCell.makePasswordCell(delegate: self)
- cell.textField.tag = 1
- cell.accessibilityIdentifier = "passwordCell" // will be used to eventually show oAuth-Dialogue when selecting
- cell.setText(text: MRConfig.mailPw ?? nil)
- return cell
- }()
- private lazy var restoreCell: ActionCell = {
- let cell = ActionCell(frame: .zero)
- cell.actionTitle = "Restore from backup"
- cell.accessibilityIdentifier = "restoreCell"
- return cell
- }()
- lazy var imapServerCell: TextFieldCell = {
- let cell = TextFieldCell(description: "IMAP Server", placeholder: MRConfig.mailServer ?? MRConfig.configuredMailServer, delegate: self)
- cell.accessibilityIdentifier = "IMAPServerCell"
- cell.textField.tag = 2
- return cell
- }()
- lazy var imapUserCell: TextFieldCell = {
- let cell = TextFieldCell(description: "IMAP User", placeholder: MRConfig.mailUser ?? MRConfig.configuredMailUser, delegate: self)
- cell.accessibilityIdentifier = "IMAPUserCell"
- cell.textField.tag = 3
- return cell
- }()
- lazy var imapPortCell: UITableViewCell = {
- let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
- cell.textLabel?.text = "IMAP Port"
- cell.accessoryType = .disclosureIndicator
- cell.detailTextLabel?.text = MRConfig.mailPort ?? MRConfig.configuredMailPort
- cell.accessibilityIdentifier = "IMAPPortCell"
- cell.selectionStyle = .none
- return cell
- }()
- lazy var imapSecurityCell: UITableViewCell = {
- let text = "\(MRConfig.getImapSecurity())"
- let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
- cell.textLabel?.text = "IMAP Security"
- // let cell = TextFieldCell(description: "IMAP Security", placeholder: text, delegate: self)
- cell.accessibilityIdentifier = "IMAPSecurityCell"
- cell.accessoryType = .disclosureIndicator
- cell.detailTextLabel?.text = "\(MRConfig.getImapSecurity())"
- cell.selectionStyle = .none
- return cell
- }()
- lazy var smtpServerCell: TextFieldCell = {
- let cell = TextFieldCell(description: "SMTP Server", placeholder: MRConfig.sendServer ?? MRConfig.configuredSendServer, delegate: self)
- cell.accessibilityIdentifier = "SMTPServerCell"
- cell.textField.tag = 4
- return cell
- }()
- lazy var smtpUserCell: TextFieldCell = {
- let cell = TextFieldCell(description: "SMTP User", placeholder: MRConfig.sendUser ?? MRConfig.configuredSendUser, delegate: self)
- cell.accessibilityIdentifier = "SMTPUserCell"
- cell.textField.tag = 5
- return cell
- }()
- lazy var smtpPortCell: UITableViewCell = {
- let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
- cell.textLabel?.text = "SMTP Port"
- cell.accessoryType = .disclosureIndicator
- cell.detailTextLabel?.text = MRConfig.sendPort ?? MRConfig.configuredSendPort
- cell.accessibilityIdentifier = "SMTPPortCell"
- cell.selectionStyle = .none
- return cell
- }()
- lazy var smtpPasswordCell: TextFieldCell = {
- let cell = TextFieldCell(description: "SMTP Password", placeholder: "*************", delegate: self)
- cell.accessibilityIdentifier = "SMTPPasswordCell"
- cell.textField.tag = 6
- return cell
- }()
- lazy var smtpSecurityCell: UITableViewCell = {
- let security = "\(MRConfig.getSmtpSecurity())"
- let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
- cell.textLabel?.text = "SMTP Security"
- cell.detailTextLabel?.text = security
- cell.accessibilityIdentifier = "SMTPSecurityCell"
- cell.accessoryType = .disclosureIndicator
- cell.selectionStyle = .none
- return cell
- }()
- // this loginButton can be enabled and disabled
- let loginButton: UIBarButtonItem = UIBarButtonItem(title: "Login", style: .done, target: self, action: #selector(loginButtonPressed))
- private lazy var basicSectionCells: [UITableViewCell] = [emailCell, passwordCell]
- private lazy var restoreCells: [UITableViewCell] = [restoreCell]
- private lazy var advancedSectionCells: [UITableViewCell] = [
- imapServerCell,
- imapUserCell,
- imapPortCell,
- imapSecurityCell,
- smtpServerCell,
- smtpUserCell,
- smtpPortCell,
- smtpPasswordCell,
- smtpSecurityCell
- ]
- private var advancedSectionShowing: Bool = false
- init() {
- super.init(style: .grouped)
- hidesBottomBarWhenPushed = true
- }
- required init?(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- override func viewDidLoad() {
- super.viewDidLoad()
- title = "Login to your server"
- // navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(closeButtonPressed))
- navigationItem.rightBarButtonItem = loginButton
- }
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- // needs to be changed if returning from portSettingsController
- smtpPortCell.detailTextLabel?.text = MRConfig.sendPort ?? MRConfig.configuredSendPort
- imapPortCell.detailTextLabel?.text = MRConfig.mailPort ?? MRConfig.configuredMailPort
- smtpSecurityCell.detailTextLabel?.text = SecurityConverter.convertHexToString(type: .SMTPSecurity, hex: MRConfig.getSmtpSecurity())
- imapSecurityCell.detailTextLabel?.text = SecurityConverter.convertHexToString(type: .IMAPSecurity, hex: MRConfig.getImapSecurity())
- }
- override func viewDidAppear(_ animated: Bool) {
- super.viewDidAppear(animated)
- addProgressHudEventListener()
- // loginButton.isEnabled = false
- }
- override func viewWillDisappear(_ animated: Bool) {
- resignFirstResponderOnAllCells()
- }
- override func viewDidDisappear(_: Bool) {
- let nc = NotificationCenter.default
- if let backupProgressObserver = self.backupProgressObserver {
- nc.removeObserver(backupProgressObserver)
- }
- if let configureProgressObserver = self.configureProgressObserver {
- nc.removeObserver(configureProgressObserver)
- }
- if let oauth2Observer = self.oauth2Observer {
- nc.removeObserver(oauth2Observer)
- }
- }
- // MARK: - Table view data source
- override func numberOfSections(in _: UITableView) -> Int {
- // #warning Incomplete implementation, return the number of sections
- return 3
- }
- override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
- // #warning Incomplete implementation, return the number of rows
- if section == 0 {
- return basicSectionCells.count
- } else if section == 1 {
- return restoreCells.count
- } else {
- return advancedSectionShowing ? advancedSectionCells.count : 0
- }
- }
- override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
- if section == 2 {
- return "Advanced"
- } else {
- return nil
- }
- }
- override func tableView(_: UITableView, viewForHeaderInSection section: Int) -> UIView? {
- if section == 2 {
- // Advanced Header
- let advancedView = AdvancedSectionHeader()
- advancedView.handleTap = toggleAdvancedSection
- // set tapHandler
- return advancedView
- } else {
- return nil
- }
- }
- override func tableView(_: UITableView, heightForHeaderInSection _: Int) -> CGFloat {
- return 36.0
- }
- override func tableView(_: UITableView, titleForFooterInSection section: Int) -> String? {
- if section == 0 {
- return "There are no Delta Chat servers, your data stays on your device!"
- } else if section == 2 {
- return "For known email providers additional settings are setup automatically. Sometimes IMAP needs to be enabled in the web frontend. Consult your email provider or friends for help"
- } else {
- return nil
- }
- }
- override func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
- let section = indexPath.section
- let row = indexPath.row
- if section == 0 {
- // basicSection
- return basicSectionCells[row]
- } else if section == 1 {
- return restoreCells[row]
- } else {
- // advancedSection
- return advancedSectionCells[row]
- }
- }
- override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
- guard let tappedCell = tableView.cellForRow(at: indexPath) else { return }
- // handle tap on password -> show oAuthDialogue
- if let textFieldCell = tappedCell as? TextFieldCell {
- if textFieldCell.accessibilityIdentifier == "passwordCell" {
- if let emailAdress = textFieldCell.getText() {
- _ = showOAuthAlertIfNeeded(emailAddress: emailAdress, handleCancel: nil)
- }
- }
- }
- if tappedCell.accessibilityIdentifier == "restoreCell" {
- restoreBackup()
- } else if tappedCell.accessibilityIdentifier == "IMAPPortCell" {
- coordinator?.showImapPortOptions()
- } else if tappedCell.accessibilityIdentifier == "SMTPPortCell" {
- coordinator?.showSmtpPortsOptions()
- } else if tappedCell.accessibilityIdentifier == "IMAPSecurityCell" {
- coordinator?.showImapSecurityOptions()
- } else if tappedCell.accessibilityIdentifier == "SMTPSecurityCell" {
- coordinator?.showSmptpSecurityOptions()
- }
- }
- private func toggleAdvancedSection(button: UILabel) {
- let willShow = !advancedSectionShowing
- // extract indexPaths from advancedCells
- let advancedIndexPaths: [IndexPath] = advancedSectionCells.indices.map { IndexPath(row: $0, section: 2) }
- // advancedSectionCells.indices.map({indexPaths.append(IndexPath(row: $0, section: 1))}
- // set flag before delete/insert operation, because cellForRowAt will be triggered and uses this flag
- advancedSectionShowing = willShow
- button.text = willShow ? "Hide" : "Show"
- if willShow {
- tableView.insertRows(at: advancedIndexPaths, with: .fade)
- } else {
- tableView.deleteRows(at: advancedIndexPaths, with: .fade)
- }
- }
- @objc private func loginButtonPressed() {
- guard let emailAddress = emailCell.getText() else {
- return // handle case when either email or pw fields are empty
- }
- let oAuthStarted = showOAuthAlertIfNeeded(emailAddress: emailAddress, handleCancel: loginButtonPressed) // if canceled we will run this method again but this time oAuthStarted will be false
- if oAuthStarted {
- // the loginFlow will be handled by oAuth2
- return
- }
- let password = passwordCell.getText() ?? "" // empty passwords are ok -> for oauth there is no password needed
- login(emailAddress: emailAddress, password: password)
- }
- private func login(emailAddress: String, password: String, skipAdvanceSetup: Bool = false) {
- MRConfig.addr = emailAddress
- MRConfig.mailPw = password
- if !skipAdvanceSetup {
- evaluluateAdvancedSetup() // this will set MRConfig related to advanced fields
- }
- dc_configure(mailboxPointer)
- present(loginProgressHud, animated: true, completion: nil)
- }
- @objc func closeButtonPressed() {
- dismiss(animated: true, completion: nil)
- }
- // returns true if needed
- private func showOAuthAlertIfNeeded(emailAddress: String, handleCancel: (() -> Void)?) -> Bool {
- if MRConfig.getAuthFlags() == 4 {
- // user has previously denied oAuth2-setup
- return false
- }
- guard let oAuth2UrlPointer = dc_get_oauth2_url(mailboxPointer, emailAddress, "chat.delta:/auth") else {
- return false
- }
- let oAuth2Url = String(cString: oAuth2UrlPointer)
- if let url = URL(string: oAuth2Url) {
- let title = "Continue with simplified setup"
- // swiftlint:disable all
- let message = "The entered e-mail address supports a simplified setup (oAuth2).\n\nIn the next step, please allow Delta Chat to act as your Chat with E-Mail app.\n\nThere are no Delta Chat servers, your data stays on your device."
- let oAuthAlertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
- let confirm = UIAlertAction(title: "Confirm", style: .default, handler: {
- [unowned self] _ in
- let nc = NotificationCenter.default
- self.oauth2Observer = nc.addObserver(self, selector: #selector(self.oauthLoginApproved), name: NSNotification.Name("oauthLoginApproved"), object: nil)
- self.launchOAuthBrowserWindow(url: url)
- })
- let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: {
- _ in
- MRConfig.setAuthFlags(flags: Int(DC_LP_AUTH_NORMAL))
- handleCancel?()
- })
- oAuthAlertController.addAction(confirm)
- oAuthAlertController.addAction(cancel)
- present(oAuthAlertController, animated: true, completion: nil)
- return true
- } else {
- return false
- }
- }
- @objc func oauthLoginApproved(notification: Notification) {
- guard let userInfo = notification.userInfo, let token = userInfo["token"] as? String, let emailAddress = emailCell.getText() else {
- return
- }
- passwordCell.setText(text: token)
- MRConfig.setAuthFlags(flags: Int(DC_LP_AUTH_OAUTH2))
- login(emailAddress: emailAddress, password: token, skipAdvanceSetup: true)
- }
- private func launchOAuthBrowserWindow(url: URL) {
- UIApplication.shared.open(url) // this opens safari as seperate app
- }
- private func addProgressHudEventListener() {
- let nc = NotificationCenter.default
- backupProgressObserver = nc.addObserver(
- forName: dcNotificationBackupProgress,
- object: nil,
- queue: nil
- ) {
- notification in
- if let ui = notification.userInfo {
- if ui["error"] as! Bool {
- self.updateProgressHud(error: ui["errorMessage"] as? String)
- // self.hudHandler.setHudError(ui["errorMessage"] as? String)
- } else if ui["done"] as! Bool {
- self.updateProgressHudSuccess(callback: self.handleLoginSuccess)
- // self.hudHandler.setHudDone(callback: self.handleLoginSuccess)
- } else {
- self.updateProgressHudValue(value: ui["progress"] as! Int)
- // self.hudHandler.setHudProgress(ui["progress"] as! Int)
- }
- }
- }
- configureProgressObserver = nc.addObserver(
- forName: dcNotificationConfigureProgress,
- object: nil,
- queue: nil
- ) {
- notification in
- if let ui = notification.userInfo {
- if ui["error"] as! Bool {
- self.updateProgressHud(error: ui["errorMessage"] as? String)
- // self.hudHandler.setHudError(ui["errorMessage"] as? String)
- } else if ui["done"] as! Bool {
- self.updateProgressHudSuccess(callback: self.handleLoginSuccess)
- // self.hudHandler.setHudDone(callback: self.handleLoginSuccess)
- } else {
- self.updateProgressHudValue(value: ui["progress"] as! Int)
- // self.hudHandler.setHudProgress(ui["progress"] as! Int)
- }
- }
- }
- }
- private func evaluluateAdvancedSetup() {
- for cell in advancedSectionCells {
- if let textFieldCell = cell as? TextFieldCell {
- switch cell.accessibilityIdentifier {
- case "IMAPServerCell":
- MRConfig.mailServer = textFieldCell.getText() ?? nil
- case "IMAPUserCell":
- MRConfig.mailUser = textFieldCell.getText() ?? nil
- case "IMAPPortCell":
- MRConfig.mailPort = textFieldCell.getText() ?? nil
- case "IMAPSecurityCell":
- let flag = 0
- MRConfig.setImapSecurity(imapFlags: flag)
- case "SMTPServerCell":
- MRConfig.sendServer = textFieldCell.getText() ?? nil
- case "SMTPSUserCell":
- MRConfig.sendUser = textFieldCell.getText() ?? nil
- case "SMTPPortCell":
- MRConfig.sendPort = textFieldCell.getText() ?? nil
- case "SMTPPasswordCell":
- MRConfig.sendPw = textFieldCell.getText() ?? nil
- case "SMTPSecurityCell":
- let flag = 0
- MRConfig.setSmtpSecurity(smptpFlags: flag)
- default:
- logger.info("unknown identifier", cell.accessibilityIdentifier ?? "")
- }
- }
- }
- }
- private func restoreBackup() {
- logger.info("restoring backup")
- if MRConfig.configured {
- return
- }
- let documents = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
- if !documents.isEmpty {
- logger.info("looking for backup in: \(documents[0])")
- if let file = dc_imex_has_backup(mailboxPointer, documents[0]) {
- logger.info("restoring backup: \(String(cString: file))")
- // hudHandler.showBackupHud("Restoring Backup")
- dc_imex(mailboxPointer, DC_IMEX_IMPORT_BACKUP, file, nil)
- return
- }
- let alert = UIAlertController(title: "Can not restore", message: "No Backup found", preferredStyle: .alert)
- alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { _ in
- }))
- present(alert, animated: true, completion: nil)
- return
- }
- logger.error("no documents directory found")
- }
- private func handleLoginSuccess() {
- // used when login hud successfully went trough
- dismiss(animated: true, completion: nil)
- }
- private func resignFirstResponderOnAllCells() {
- basicSectionCells.map({
- resignCell(cell: $0)
- })
- advancedSectionCells.map({
- resignCell(cell: $0)
- }
- )
- }
- func resignCell(cell: UITableViewCell) {
- if let c = cell as? TextFieldCell {
- c.textField.resignFirstResponder()
- }
- }
- }
- extension AccountSetupController: UITextFieldDelegate {
- func textFieldShouldReturn(_ textField: UITextField) -> Bool {
- let currentTag = textField.tag
- if let nextField = tableView.viewWithTag(currentTag + 1) as? UITextField {
- if nextField.tag > 1, !advancedSectionShowing {
- // gets here when trying to activate a collapsed cell
- return false
- }
- nextField.becomeFirstResponder()
- }
- return false
- }
- func textFieldDidBeginEditing(_ textField: UITextField) {
- if textField.accessibilityIdentifier == "emailTextField" {
- // this will re-enable possible oAuth2-login
- MRConfig.setAuthFlags(flags: Int(DC_LP_AUTH_OAUTH2))
- }
- }
- func textFieldDidEndEditing(_ textField: UITextField) {
- if textField.accessibilityIdentifier == "emailTextField" {
- let _ = showOAuthAlertIfNeeded(emailAddress: textField.text ?? "", handleCancel: {
- self.passwordCell.textField.becomeFirstResponder()
- })
- }
- }
- }
- class AdvancedSectionHeader: UIView {
- var handleTap: ((UILabel) -> Void)?
- private var label: UILabel = {
- let label = UILabel()
- label.text = "ADVANCED"
- label.font = UIFont.systemFont(ofSize: 15)
- label.textColor = UIColor.darkGray
- return label
- }()
- /*
- why UILabel, why no UIButton? For unknown reasons UIButton's target function was not triggered when one of the textfields in the tableview was active -> used label as workaround
- */
- private lazy var toggleButton: UILabel = {
- let label = UILabel()
- label.text = "Show"
- label.font = UIFont.systemFont(ofSize: 15, weight: .medium)
- label.textColor = UIColor.systemBlue
- return label
- }()
- //
- // private var toggleButton:UIButton = {
- // let button = UIButton(type: .system)
- // button.setTitle("Show", for: .normal)
- // button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside )
- // //button.target(forAction: #selector(buttonTapped(_:)), withSender: self)
- // return button
- // }()
- init() {
- super.init(frame: .zero) // will be constraint from tableViewDelegate
- setupSubviews()
- let tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped)) // use this if the whole header is supposed to be clickable
- addGestureRecognizer(tap)
- }
- required init?(coder _: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- func setupSubviews() {
- addSubview(label)
- label.translatesAutoresizingMaskIntoConstraints = false
- label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 15).isActive = true
- label.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0).isActive = true
- addSubview(toggleButton)
- toggleButton.translatesAutoresizingMaskIntoConstraints = false
- toggleButton.leadingAnchor.constraint(equalTo: trailingAnchor, constant: -60).isActive = true // since button will change title it should be left aligned
- toggleButton.centerYAnchor.constraint(equalTo: label.centerYAnchor, constant: 0).isActive = true
- }
- @objc func buttonTapped(_: UIButton) {
- // handleTap?(button)
- }
- @objc func viewTapped() {
- handleTap?(toggleButton)
- }
- }
- extension AccountSetupController {
- func updateProgressHud(error message: String?) {
- }
- func updateProgressHudSuccess(callback: (()->())?) {
- }
- func updateProgressHudValue(value: Int?) {
- if let value = value {
- print(value)
- configurationProgress.value = CGFloat(value / 10)
- } else {
- fatalError()
- }
- }
- }
|