Implement designed Prompts for EIP3085 wallet_addEthereumChain support #2908
parent
0f411a6efc
commit
2094623d8f
@ -0,0 +1,180 @@ |
||||
// |
||||
// SwitchChainRequestViewController.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 23.09.2021. |
||||
// |
||||
|
||||
import UIKit |
||||
import PromiseKit |
||||
|
||||
protocol SwitchChainRequestViewControllerDelegate: class { |
||||
func didClose(in viewController: SwitchChainRequestViewController) |
||||
func didSelectActionButton(in viewController: SwitchChainRequestViewController) |
||||
func didSelectAdditionalButton(in viewController: SwitchChainRequestViewController) |
||||
} |
||||
|
||||
class SwitchChainRequestViewController: ModalViewController { |
||||
weak var _delegate: SwitchChainRequestViewControllerDelegate? |
||||
|
||||
private var titleLabel: UILabel = { |
||||
let v = UILabel() |
||||
v.numberOfLines = 0 |
||||
v.textAlignment = .center |
||||
v.textColor = R.color.black() |
||||
v.font = Fonts.bold(size: 24) |
||||
|
||||
return v |
||||
}() |
||||
|
||||
private var descriptionLabel: UILabel = { |
||||
let v = UILabel() |
||||
v.numberOfLines = 0 |
||||
v.textAlignment = .center |
||||
v.textColor = R.color.mine() |
||||
v.font = Fonts.regular(size: 17) |
||||
|
||||
return v |
||||
}() |
||||
private lazy var enableTestnetButton: Button = { |
||||
let button = Button(size: .normal, style: .system) |
||||
button.setTitle(viewModel.additionalButtonTitle, for: .normal) |
||||
|
||||
return button |
||||
}() |
||||
|
||||
private lazy var buttonsBar: ButtonsBar = { |
||||
let buttonsBar = ButtonsBar(configuration: .green(buttons: 1)) |
||||
return buttonsBar |
||||
}() |
||||
|
||||
private var viewModel: SwitchChainRequestViewModel |
||||
|
||||
init(viewModel: SwitchChainRequestViewModel) { |
||||
self.viewModel = viewModel |
||||
super.init() |
||||
let footerView = ButtonsBarBackgroundView(buttonsBar: buttonsBar, separatorHeight: 0) |
||||
|
||||
footerStackView.addArrangedSubview(footerView) |
||||
generateSubviews() |
||||
presentationDelegate = self |
||||
|
||||
enableTestnetButton.addTarget(self, action: #selector(enableTestnetButtonSelected), for: .touchUpInside) |
||||
} |
||||
|
||||
required init?(coder aDecoder: NSCoder) { |
||||
return nil |
||||
} |
||||
|
||||
func configure(viewModel: SwitchChainRequestViewModel) { |
||||
self.viewModel = viewModel |
||||
generateSubviews() |
||||
|
||||
buttonsBar.configure() |
||||
buttonsBar.buttons[0].setTitle(viewModel.actionButtonTitle, for: .normal) |
||||
buttonsBar.buttons[0].addTarget(self, action: #selector(actionButtonSelected), for: .touchUpInside) |
||||
|
||||
titleLabel.text = viewModel.title |
||||
descriptionLabel.text = viewModel.description |
||||
} |
||||
|
||||
@objc private func actionButtonSelected(_ sender: UIButton) { |
||||
dismissViewAnimated(with: { |
||||
self._delegate?.didSelectActionButton(in: self) |
||||
}) |
||||
} |
||||
|
||||
@objc private func enableTestnetButtonSelected(_ sender: UIButton) { |
||||
dismissViewAnimated(with: { |
||||
self._delegate?.didSelectAdditionalButton(in: self) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
extension SwitchChainRequestViewController: ModalViewControllerDelegate { |
||||
|
||||
func didDismiss(_ controller: ModalViewController) { |
||||
_delegate?.didClose(in: self) |
||||
dismiss(animated: false) |
||||
} |
||||
|
||||
func didClose(_ controller: ModalViewController) { |
||||
dismissViewAnimated(with: { |
||||
self._delegate?.didClose(in: self) |
||||
self.dismiss(animated: false) |
||||
}) |
||||
} |
||||
} |
||||
|
||||
extension SwitchChainRequestViewController { |
||||
private func generateSubviews() { |
||||
stackView.removeAllArrangedSubviews() |
||||
|
||||
var views: [UIView] = [ |
||||
[.spacerWidth(16), titleLabel, .spacerWidth(16)].asStackView(axis: .horizontal), |
||||
.spacer(height: 20), |
||||
[.spacerWidth(16), descriptionLabel, .spacerWidth(16)].asStackView(axis: .horizontal), |
||||
] |
||||
|
||||
switch viewModel.configuration { |
||||
case .promptAndSwitchToExistingServerInBrowser, .promptAndActivateExistingServer: |
||||
break |
||||
case .promptAndAddAndActivateServer: |
||||
views += [ |
||||
.spacer(height: 20), |
||||
enableTestnetButton |
||||
] |
||||
} |
||||
|
||||
stackView.addArrangedSubviews(views) |
||||
} |
||||
} |
||||
|
||||
private class SwitchChainRequestViewControllerBridgeToPromise: NSObject { |
||||
|
||||
private let (promiseToReturn, seal) = Promise<SwitchChainRequestResponse>.pending() |
||||
private var retainCycle: SwitchChainRequestViewControllerBridgeToPromise? |
||||
private let viewController: SwitchChainRequestViewController |
||||
|
||||
init(viewController target: UIViewController, configuration: SwitchChainRequestConfiguration) { |
||||
viewController = SwitchChainRequestViewController(viewModel: .init(configuration: configuration)) |
||||
viewController.configure(viewModel: .init(configuration: configuration)) |
||||
|
||||
super.init() |
||||
retainCycle = self |
||||
|
||||
viewController._delegate = self |
||||
promiseToReturn.ensure { |
||||
// ensure we break the retain cycle |
||||
self.retainCycle = nil |
||||
}.cauterize() |
||||
|
||||
target.present(viewController, animated: false) |
||||
} |
||||
|
||||
var promise: Promise<SwitchChainRequestResponse> { |
||||
return promiseToReturn |
||||
} |
||||
} |
||||
|
||||
extension SwitchChainRequestViewControllerBridgeToPromise: SwitchChainRequestViewControllerDelegate { |
||||
//NOTE: need to update it with more clear solution, passing button index isn't goo idea for that |
||||
func didSelectActionButton(in viewController: SwitchChainRequestViewController) { |
||||
seal.fulfill(.action(0)) |
||||
} |
||||
|
||||
func didSelectAdditionalButton(in viewController: SwitchChainRequestViewController) { |
||||
seal.fulfill(.action(1)) |
||||
} |
||||
|
||||
func didClose(in viewController: SwitchChainRequestViewController) { |
||||
seal.fulfill(.canceled) |
||||
} |
||||
} |
||||
|
||||
extension SwitchChainRequestViewController { |
||||
static func promise(_ viewController: UIViewController, configuration: SwitchChainRequestConfiguration) -> Promise<SwitchChainRequestResponse> { |
||||
return SwitchChainRequestViewControllerBridgeToPromise(viewController: viewController, configuration: configuration).promise |
||||
} |
||||
} |
||||
|
@ -0,0 +1,53 @@ |
||||
// |
||||
// SwitchChainRequestViewModel.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 23.09.2021. |
||||
// |
||||
|
||||
import UIKit |
||||
|
||||
enum SwitchChainRequestConfiguration { |
||||
case promptAndSwitchToExistingServerInBrowser(existingServer: RPCServer) |
||||
case promptAndAddAndActivateServer(customChain: WalletAddEthereumChainObject, customChainId: Int) |
||||
case promptAndActivateExistingServer(existingServer: RPCServer) |
||||
} |
||||
|
||||
enum SwitchChainRequestResponse { |
||||
case action(Int) |
||||
case canceled |
||||
} |
||||
|
||||
struct SwitchChainRequestViewModel { |
||||
let title: String = R.string.localizable.switchChainRequestTitle() |
||||
let configuration: SwitchChainRequestConfiguration |
||||
|
||||
var description: String { |
||||
switch configuration { |
||||
case .promptAndSwitchToExistingServerInBrowser(let existingServer): |
||||
return R.string.localizable.addCustomChainSwitchToExisting(existingServer.displayName, existingServer.chainID) |
||||
case .promptAndAddAndActivateServer(let customChain, let customChainId): |
||||
return R.string.localizable.addCustomChainAddAndSwitch(customChain.chainName ?? R.string.localizable.addCustomChainUnnamed(), customChainId) |
||||
case .promptAndActivateExistingServer(let existingServer): |
||||
return R.string.localizable.addCustomChainEnableExisting(existingServer.displayName, existingServer.chainID) |
||||
} |
||||
} |
||||
|
||||
var actionButtonTitle: String { |
||||
switch configuration { |
||||
case .promptAndSwitchToExistingServerInBrowser: |
||||
// Switch & Reload |
||||
return R.string.localizable.switchChainRequestActionSwitchReload() |
||||
case .promptAndAddAndActivateServer: |
||||
// Add, Switch & Reload Mainnet |
||||
return R.string.localizable.switchChainRequestActionAddSwitchReload(R.string.localizable.settingsEnabledNetworksMainnet()) |
||||
case .promptAndActivateExistingServer: |
||||
// Enable, Switch & Reload |
||||
return R.string.localizable.switchChainRequestActionEnableSwitchReload() |
||||
} |
||||
} |
||||
|
||||
var additionalButtonTitle: String { |
||||
R.string.localizable.switchChainRequestActionAddSwitchReload(R.string.localizable.settingsEnabledNetworksTestnet()) |
||||
} |
||||
} |
Loading…
Reference in new issue