802 lines
37 KiB
Swift
802 lines
37 KiB
Swift
//
|
|
// MainControllerRoot.swift
|
|
// List
|
|
//
|
|
// Created by Saveliy Stavitsky on 7/14/20.
|
|
// Copyright © 2020 Igor Danich. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import Branch
|
|
import Alamofire
|
|
import WebKit
|
|
import WalletKit
|
|
import WalletFoundation
|
|
import Combine
|
|
import RealmSwift
|
|
|
|
extension UserDefaults {
|
|
@objc dynamic var chatsReadCount: [String: Int] {
|
|
return (dictionary(forKey: "chatsReadCount") as? [String: Int]) ?? [:]
|
|
}
|
|
}
|
|
|
|
extension UIViewController {
|
|
// swiftlint:disable force_cast
|
|
var mainController: MainController { UIApplication.shared.windows.first?.rootViewController as! MainController }
|
|
}
|
|
|
|
final class MainController: UIViewController {
|
|
|
|
@IBOutlet var headerView: UIView!
|
|
@IBOutlet var accountButton: UIButton!
|
|
@IBOutlet var accountBarButton: UIBarButtonItem!
|
|
@IBOutlet var backButton: UIButton!
|
|
@IBOutlet var barNav: UINavigationBar!
|
|
@IBOutlet weak var resourcesSwitch: CommonSwitch!
|
|
@IBOutlet private weak var resourcesBtn: UIBarButtonItem!
|
|
@IBOutlet weak var settingsGearButton: UIBarButtonItem!
|
|
@IBOutlet private weak var offset: NSLayoutConstraint!
|
|
@IBOutlet var inviteView: MainViewInvite!
|
|
private lazy var interfaceCover: UIView = {
|
|
let view = UIView()
|
|
view.backgroundColor = Asset.snow.color
|
|
view.frame = self.view.bounds
|
|
return view
|
|
}()
|
|
|
|
private let service = Main.Service()
|
|
|
|
private var notificationTokens = [NotificationToken]()
|
|
|
|
private var cancellables = Set<AnyCancellable>()
|
|
|
|
private var hasTitle: Bool {
|
|
guard let barNavItems = self.barNav.items else { return false }
|
|
let titlesOfItems = barNavItems.compactMap { $0.title }
|
|
return !titlesOfItems.isEmpty
|
|
}
|
|
|
|
var content: MainControllerContent { self.child()! }
|
|
|
|
let timerFreeTx = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { timer in
|
|
timer.tolerance = 0.5
|
|
Accounts().fetchQuota()
|
|
}
|
|
|
|
let timerBalances = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { timer in
|
|
timer.tolerance = 0.2
|
|
if Wallet.Service.Tokens.shared.balances.collection.count == 0 {
|
|
Wallet.Service.Tokens.shared.balances.fetch()
|
|
} else {
|
|
timer.invalidate()
|
|
}
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
|
|
super.viewDidLoad()
|
|
|
|
self.accountBarButton.customView = self.accountButton
|
|
self.headerView.layer.shadowColor = Asset.lightGray.color.cgColor
|
|
self.configureAccountButton()
|
|
self.configureQRButton()
|
|
self.inviteView.changeVisibility(Accounts().hasActiveAccounts)
|
|
self.updateMsgCount()
|
|
|
|
// if !UserDefaults.standard.bool(forKey: "isFreeTransactionsOn") {
|
|
// changeFreeSwitchState()
|
|
// }
|
|
|
|
// Network.shared.onReabilityChange = { }
|
|
|
|
self.view.addSubview(self.interfaceCover)
|
|
Loader.show()
|
|
|
|
Accounts().messageShelf.activeBook?.fetch()
|
|
|
|
Account.Service.Authorize.shared.updateAuthPublisher
|
|
.sink { [weak self] in
|
|
|
|
guard let self else { return }
|
|
|
|
self.setupSubscriptions()
|
|
guard let link = self.deepLink else { return }
|
|
self.process(deepLink: link)
|
|
self.deepLink = nil
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
NotificationCenter.default.publisher(for: .didUpdateAccountQuota)
|
|
.sink { [weak self] _ in
|
|
guard let self else { return }
|
|
|
|
self.configureResourcesSwitch()
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
NotificationCenter.default.publisher(for: .didUpdateReachability)
|
|
.sink { _ in
|
|
guard !Network.Service().isReachable else { return }
|
|
Alert.error(text: L10n.Main.NoInternet.text)
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
self.inviteView.didLockedFunds = { [weak self] in
|
|
self?.content.push(P2PLockedFundsController(), animated: true)
|
|
}
|
|
|
|
// Notification.subscribe(name: .didChangeAccount) { [weak self] _ in
|
|
// P2PMainLockedFundsService.shared.fetch {
|
|
// // if P2P.Service.balances.collection.
|
|
// if P2PMyDealsService.shared.deals.count > 0 || P2PMyOrdersService.shared.orders.count > 0 {
|
|
// self?.inviteView.lockedFundsView.isHidden = false
|
|
// let msg = P2PMyOrdersService.shared.orders
|
|
// .reduce("", { $0 + "Order: \($1.id):\($1.volume_balance)" })
|
|
// + P2PMyDealsService.shared.deals
|
|
// .reduce("", { $0 + "Deal: \($1.id):\($1.volume)" })
|
|
// self?.inviteView.lockedFundsLabel.attributedText = msg.attributed
|
|
// .applying(attribute: .font, value: FontFamily.GolosUI.medium.font(size: 20))
|
|
// .applying(attribute: .foregroundColor, value: Asset.textSnow.color)
|
|
// self?.inviteView.lockedFundsLabel.speed = .rate(20.0)
|
|
// } else {
|
|
// self?.inviteView.lockedFundsView.isHidden = true
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
self.resourcesBtn.customView = self.resourcesSwitch
|
|
self.resourcesSwitch.isSelected = Accounts().quota.isEnabled
|
|
|
|
Accounts().activePublisher
|
|
.sink { [weak self] _ in
|
|
|
|
guard let self else { return }
|
|
|
|
self.notificationTokens.removeAll()
|
|
|
|
self.notificationTokens.append(contentsOf: [
|
|
self.service.p2pBalancesService.balances.observe(on: .main) { [weak self] _ in
|
|
|
|
Wallet.Service.Tokens.shared.balances.fetch()
|
|
|
|
if (self?.service.p2pBalancesService.balances.filter("amount > 0 || blockedAmount > 0").count ?? 0) > 0 {
|
|
self?.inviteView.lockedFundsView.isHidden = false
|
|
let msg = L10n.P2p.Main.LockedFunds.headerTitle +
|
|
(self?.service.p2pBalancesService.balances.filter("amount > 0 || blockedAmount > 0")
|
|
.reduce("", { $0 + " \(($1.amount.decimalValue + $1.blockedAmount.decimalValue).toString(max: 5)) \($1.symbol) " }) ?? "")
|
|
+ " "
|
|
self?.inviteView.lockedFundsLabel.attributedText = msg.attributed
|
|
.applying(attribute: .font, value: FontFamily.GolosUI.medium.font(size: 20))
|
|
.applying(attribute: .foregroundColor, value: Asset.textSnow.color)
|
|
self?.inviteView.lockedFundsLabel.speed = .rate(20.0)
|
|
} else {
|
|
self?.inviteView.lockedFundsView.isHidden = true
|
|
}
|
|
}
|
|
].compactMap { $0 })
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
Accounts().activePublisher
|
|
.sink { [weak self] _ in
|
|
Accounts().fetchQuota()
|
|
self?.onAccountChange()
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
Accounts().lockedPublisher
|
|
.sink { [weak self] _ in
|
|
self?.onAccountChange()
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
Account.Service.Update.shared.updatePublisher
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] _ in
|
|
self?.onAccountChange()
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
// TODO: - Here we need handle update notifications
|
|
// Notification.subscribe(name: .socketDidUpdateValue) { [weak self] in
|
|
// print($0)
|
|
// print("\(Date()) - socket update")
|
|
// }
|
|
|
|
NotificationCenter.default.publisher(for: .didUpdateHistory)
|
|
.sink { [weak self] in
|
|
guard let username = Accounts().current?.name,
|
|
username == $0.userInfo?["username"] as? String else { return }
|
|
Wallet.Service.Tokens.shared.balances.fetch()
|
|
self?.updateMsgCount()
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
UserDefaults.standard
|
|
.publisher(for: \.chatsReadCount, options: [.initial, .new])
|
|
.sink { [weak self] _ in
|
|
guard let self else { return }
|
|
guard let username = Accounts().current?.name else {
|
|
self.setChatsBadge(count: 0)
|
|
return
|
|
}
|
|
self.setChatsBadge(count: self.chatsMsgsCount(username: username) - self.chatsRead(by: username))
|
|
}
|
|
.store(in: &self.cancellables)
|
|
|
|
self.inviteView.didClose = { [weak self] in self?.inviteView.isHidden = true }
|
|
}
|
|
|
|
func chatsRead(by username: String) -> Int {
|
|
var chatsRead = 0
|
|
AccountViewAuthorize.showGetPrivateKey(in: self) {
|
|
guard
|
|
let msgsHistoryService = try? CryptoChat.Service.MsgsHistory(
|
|
username: username,
|
|
encryptionKey: $0
|
|
)
|
|
else { return }
|
|
msgsHistoryService.fetchFromLocalHistory()
|
|
chatsRead = msgsHistoryService.readCount
|
|
}
|
|
return chatsRead
|
|
}
|
|
|
|
private func chatsMsgsCount(username: String) -> Int {
|
|
|
|
guard let current = Accounts().messageShelf.activeBook else { return 0 }
|
|
|
|
let contract = ApplicationEnvironment.shared().current.contract(.chat)
|
|
let action = Network.Model.Blockchain.Action.chatSendDm.rawValue
|
|
|
|
return current.actions
|
|
.where {
|
|
$0.username == username
|
|
&& $0.account == contract
|
|
&& $0.name == action
|
|
&& $0.receiver == username
|
|
}
|
|
.count
|
|
}
|
|
|
|
func setChatsBadge(count: Int) {
|
|
DispatchQueue.main.async { [weak self] in
|
|
self?.content.viewControllers?
|
|
.compactMap { $0 as? UINavigationController }
|
|
.compactMap { $0.viewControllers.first }
|
|
.first(where: { $0 is CryptoChatControllerChats })?
|
|
.navigationController?.tabBarItem.badgeValue = count > 0 ? "\(count)" : nil
|
|
}
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
StoreReviewHelper.checkAndAskForReview()
|
|
|
|
Accounts().messageShelf.activeBook?.fetch()
|
|
|
|
let bank = Accounts().bank
|
|
if !bank.active.isExist {
|
|
|
|
if !bank.wallets.isEmpty {
|
|
let ctrl = AccountsListController()
|
|
self.mainController.content.push(ctrl, animated: true)
|
|
} else if Account.Service.isAccountMigrated,
|
|
!(Account.Service.Authorize.shared.password ?? "").isEmpty {
|
|
self.showWalletBoarding()
|
|
}
|
|
|
|
}
|
|
// else if !UserDefaults.standard.bool(forKey: "onboardingOverviewPassed") {
|
|
// present(StoryboardScene.AccountOnboarding.accountOnboardingControllerInterfaceType.instantiate(), animated: true)
|
|
// }
|
|
else if Accounts().isAuthorized {
|
|
|
|
self.interfaceCover.isHidden = true
|
|
Loader.hide()
|
|
|
|
// Show news
|
|
/*Task {
|
|
if let urlString = await service.loadNews().first?.url,
|
|
let url = URL(string: urlString),
|
|
!(AccountOnboarding.Service.Common().newsShowed ?? []).contains(urlString) {
|
|
|
|
let webview = WKWebView()
|
|
webview.load(URLRequest(url: url))
|
|
webview.addHeightConstraint(height: UIScreen.main.bounds.height * 0.8 - 100)
|
|
|
|
Popup.show(
|
|
views: [webview],
|
|
submit: L10n.Common.Button.close,
|
|
in: self
|
|
)
|
|
|
|
AccountOnboarding.Service.Common().newsShowed = (AccountOnboarding.Service.Common().newsShowed ?? []) + [urlString]
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
|
|
func showWalletBoarding() {
|
|
guard self.view.window != nil else { return }
|
|
let ctrl = WalletBoardingViewController {
|
|
if !Accounts().hasActiveAccounts {
|
|
let vc = AccountsListController()
|
|
self.content.push(vc, animated: false)
|
|
}
|
|
}
|
|
ctrl.modalPresentationStyle = .fullScreen
|
|
self.present(ctrl, animated: true)
|
|
}
|
|
|
|
func updateMsgCount() {
|
|
|
|
guard let username = Accounts().current?.name else {
|
|
self.setChatsBadge(count: 0)
|
|
return
|
|
}
|
|
|
|
if UserDefaults.standard.object(forKey: "chatsReadCount") == nil {
|
|
UserDefaults.standard.setValue([username: self.chatsMsgsCount(username: username)], forKey: "chatsReadCount")
|
|
} else if !(UserDefaults.standard.dictionary(forKey: "chatsReadCount")?.keys.contains(username) ?? false) {
|
|
var readDict = (UserDefaults.standard.dictionary(forKey: "chatsReadCount") as? [String: Int]) ?? [:]
|
|
readDict[username] = self.chatsMsgsCount(username: username)
|
|
UserDefaults.standard.setValue(readDict, forKey: "chatsReadCount")
|
|
}
|
|
|
|
self.setChatsBadge(count: self.chatsMsgsCount(username: username) - self.chatsRead(by: username))
|
|
}
|
|
|
|
@objc func onAccountChange() {
|
|
|
|
self.configureAccountButton()
|
|
self.configureQRButton()
|
|
self.configureResourcesSwitch()
|
|
self.setupSubscriptions()
|
|
self.inviteView.changeVisibility(Accounts().hasActiveAccounts)
|
|
|
|
self.updateMsgCount()
|
|
|
|
if Accounts().collection.isEmpty {
|
|
self.showWalletBoarding()
|
|
}
|
|
|
|
DispatchQueue.main.async { [weak self] in
|
|
guard let self,
|
|
self.view.window.isExist else { return }
|
|
self.interfaceCover.isHidden = true
|
|
Loader.hide()
|
|
}
|
|
}
|
|
|
|
func setupSubscriptions() {
|
|
|
|
guard let username = Accounts().current?.name,
|
|
!Network.webSockets.contains(id: "\(username)-sockets2.0") else {
|
|
return
|
|
}
|
|
|
|
Network.webSockets.remove(idSuffix: "-sockets2.0")
|
|
|
|
let timeText = Date().toISODateString
|
|
let signature = Network.Service.Blockchain.signWithK1(privateKey: AccountViewAuthorize.getPrivateKey(),
|
|
data: timeText.data(using: .utf8) ?? Data())
|
|
|
|
let signaturesString = #"""
|
|
{ \\\"username\\\": \\\"$username\\\", \\\"text\\\": \\\"$timeText\\\", \\\"signature\\\": \\\"$signature\\\" }
|
|
"""#
|
|
.replacingOccurrences(of: "$username", with: username)
|
|
.replacingOccurrences(of: "$timeText", with: timeText)
|
|
.replacingOccurrences(of: "$signature", with: signature)
|
|
|
|
let subscription =
|
|
#"""
|
|
{"id":"2","type":"start","payload":{"query":"subscription { notifications(lang: $lang, signature: \"$signature\"){ notificationType state payload previousUid currentUid }}","variables":null}}
|
|
"""#
|
|
.replacingOccurrences(of: "$signature", with: signaturesString)
|
|
.replacingOccurrences(of: "$lang", with: Common.Model.Language.current.rawValue)
|
|
Network.webSockets.open(subscription: subscription, id: "\(username)-sockets2.0")
|
|
|
|
self.service.reloadP2PData(username: Accounts().current?.name ?? "")
|
|
}
|
|
|
|
private func configureAccountButton() {
|
|
|
|
let wallet = Accounts().current
|
|
|
|
let accountButtonTitle = wallet?.isOnActiveState == true ? (wallet?.name ?? L10n.Account.Button.empty)
|
|
: L10n.Account.Button.addAccounts
|
|
self.accountButton.setAttributedTitle(accountButtonTitle.attributed(style: .bold,
|
|
size: 16,
|
|
color: Asset.textSnow.color),
|
|
for: .normal
|
|
)
|
|
|
|
self.accountButton.isEnabled = wallet?.isOnActiveState == true
|
|
self.accountButton.backgroundColor = wallet?.isOnActiveState == true ? Asset.deepWater.color : Asset.disabled.color
|
|
self.accountButton.isUserInteractionEnabled = wallet?.isOnActiveState == true && !Accounts().isLocked
|
|
self.accountButton.setImage(Accounts().isLocked ? Asset.accountLock.image : Asset.commonEos.image, for: .normal)
|
|
}
|
|
|
|
private func configureQRButton() {
|
|
let wallet = Accounts().current
|
|
self.settingsGearButton.isEnabled = wallet?.isOnActiveState == true
|
|
self.settingsGearButton.image = wallet?.isOnActiveState == true ? Asset.commonButtonQr.image : Asset.commonButtonQrDisabled.image
|
|
}
|
|
|
|
private func configureResourcesSwitch() {
|
|
let wallet = Accounts().current
|
|
let quota = Accounts().quota
|
|
self.resourcesSwitch.isActive = wallet?.isOnActiveState == true
|
|
self.resourcesSwitch.lzTextFrontSelected = wallet?.isOnActiveState == true ? "\(quota.count)" : ""
|
|
self.resourcesSwitch.set(isSelected: quota.isEnabled, animated: true)
|
|
}
|
|
|
|
@IBAction func accountPressed(_ sender: Any) {
|
|
// let ctrl = AccountsSelectionViewController()
|
|
let ctrl = AccountsListController()
|
|
self.mainController.content.push(ctrl, animated: true)
|
|
}
|
|
|
|
@IBAction func onResources(_: AnyObject?) {
|
|
let ctrl = StoryboardScene.Resources.setup.instantiate()
|
|
ctrl.shouldHideBackButton = self.hasTitle
|
|
self.content.push(ctrl, animated: true)
|
|
}
|
|
|
|
@IBAction func qrPressed(_ sender: Any) {
|
|
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
|
|
let ctrl = ScannerViewController()
|
|
ctrl.navigationItem.leftBarButtonItem = .close { [weak self] in self?.dismiss(animated: true) }
|
|
ctrl.didCapture = { [weak self] string in
|
|
guard let self else { return }
|
|
self.dismiss(animated: true)
|
|
self.readQrData(string: string)
|
|
}
|
|
let navCtrl = UINavigationController(rootViewController: ctrl)
|
|
navCtrl.modalPresentationStyle = .fullScreen
|
|
present(navCtrl, animated: true)
|
|
return
|
|
}
|
|
Alert.system(
|
|
actions: [
|
|
.init(title: L10n.Wallet.Send.qrCamera, style: .default) { [weak self] _ in
|
|
let ctrl = ScannerViewController()
|
|
ctrl.navigationItem.leftBarButtonItem = .close { [weak ctrl] in ctrl?.dismiss(animated: true) }
|
|
ctrl.didCapture = { string in
|
|
self?.dismiss(animated: true)
|
|
self?.readQrData(string: string)
|
|
}
|
|
let navCtrl = UINavigationController(rootViewController: ctrl)
|
|
navCtrl.modalPresentationStyle = .fullScreen
|
|
UIViewController.topController().present(navCtrl, animated: true)
|
|
},
|
|
.init(title: L10n.Wallet.Send.qrLibrary, style: .default) { [weak self] _ in
|
|
guard let self else { return }
|
|
let ctrl = UIImagePickerController()
|
|
ctrl.delegate = self
|
|
ctrl.sourceType = .photoLibrary
|
|
UIViewController.topController().present(ctrl, animated: true)
|
|
},
|
|
.init(title: L10n.Main.Qr.showMy, style: .default) { [weak self] _ in
|
|
guard let self else { return }
|
|
let ctrl = StoryboardScene.Wallet.receive.instantiate()
|
|
ctrl.isQuickLook = true
|
|
self.mainController.content.push(ctrl, animated: true)
|
|
},
|
|
.init(title: L10n.Common.Button.cancel, style: .cancel)
|
|
],
|
|
style: .actionSheet,
|
|
in: self
|
|
)
|
|
}
|
|
|
|
private func openTransfer(with dictionary: [String: Any]) {
|
|
let viewController = StoryboardScene.Wallet.transfer.instantiate()
|
|
viewController.dictionary = dictionary
|
|
|
|
let navigationController = self.content.selectedViewController as? UINavigationController
|
|
navigationController?.popToRootViewController(animated: true)
|
|
navigationController?.pushViewController(viewController, animated: true)
|
|
}
|
|
|
|
private func readQrData(string: String) {
|
|
if let link = URL(string: string) {
|
|
Branch.getInstance().handleDeepLink(link)
|
|
} else {
|
|
self.openTransfer(with: convertStringToDictionary(text: string) ?? [:])
|
|
}
|
|
}
|
|
|
|
private var deepLink: DeepLink?
|
|
|
|
// swiftlint:disable cyclomatic_complexity function_body_length
|
|
func process(deepLink: DeepLink) {
|
|
|
|
guard Accounts().isAuthorized else {
|
|
self.deepLink = deepLink
|
|
return
|
|
}
|
|
|
|
let navigationController = self.content.selectedViewController as? UINavigationController
|
|
|
|
switch deepLink.action {
|
|
case .walletAuth:
|
|
let dictionary = deepLink.dictionary()
|
|
if let callbackUrl = dictionary["callback_url"] as? String,
|
|
let verificationCode = dictionary["verification_code"] as? String,
|
|
let account = Accounts().current?.name {
|
|
let siteUrl = dictionary["site_url"] as? String ?? ""
|
|
let siteName = ((dictionary["site_name"] as? String) ?? "").isEmpty
|
|
? " " : "\((dictionary["site_name"] as? String) ?? " ")"
|
|
Popup.show(
|
|
title: ((dictionary["site_name"] as? String) ?? "").isEmpty
|
|
? L10n.Main.ListLogin.title : L10n.Main.ListLogin.titleOn(siteName),
|
|
views: [
|
|
.label(
|
|
text: L10n.Main.ListLogin.description(siteName)
|
|
.attributed(style: .regular, size: 16, color: Asset.textCoal.color),
|
|
numberOfLines: 0
|
|
)
|
|
],
|
|
submit: L10n.Common.Button.confirm,
|
|
in: navigationController ?? self
|
|
) { ctrl in
|
|
Loader.show(in: ctrl)
|
|
AccountViewAuthorize.showGetPrivateKey(in: navigationController ?? self) {
|
|
let data = "{\"account\":\"\(account)\",\"verification_code\":\"\(verificationCode)\"}"
|
|
let signature = Network.Service.Blockchain.signWithK1(privateKey: $0, data: data.data(using: .utf8) ?? Data())
|
|
AF.request(
|
|
callbackUrl,
|
|
method: .post,
|
|
parameters: ["signature": signature, "data": data],
|
|
encoding: JSONEncoding.default
|
|
).responseString {
|
|
self.interfaceCover.isHidden = true
|
|
Loader.hide(in: ctrl)
|
|
Popup.hide()
|
|
|
|
guard let statusCode = $0.response?.statusCode else { return }
|
|
|
|
let errorTitle: String?
|
|
if statusCode == 200 {
|
|
// Open URL if it exists
|
|
deepLink.url >>- { UIApplication.shared.open($0) }
|
|
return
|
|
} else if !siteUrl.isEmpty,
|
|
let url = URL(string: siteUrl) {
|
|
url >>- { UIApplication.shared.open($0) }
|
|
return
|
|
} else if let error = ($0.error as NSError?) {
|
|
Alert.notify(error.localizedDescription, dismiss: ctrl)
|
|
return
|
|
} else if statusCode >= 400, statusCode < 500 {
|
|
errorTitle = L10n.tr("Localizable", "main.listLogin.expired")
|
|
} else {
|
|
errorTitle = L10n.tr("Localizable", "main.listLogin.unexpected")
|
|
}
|
|
|
|
errorTitle >>- { Alert.notify($0, dismiss: ctrl) }
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case .transfer, .competitivePrice:
|
|
let viewController = StoryboardScene.Wallet.transfer.instantiate()
|
|
viewController.dictionary = deepLink.dictionary()
|
|
navigationController?.popToRootViewController(animated: true)
|
|
navigationController?.pushViewController(viewController, animated: true)
|
|
case .connect:
|
|
if let model = deepLink.get(AccountModelConnect.self),
|
|
let account = Accounts().collection.filter({ $0.name == model.from }).first {
|
|
Accounts().current = account
|
|
let ctrl = StoryboardScene.Account.connect.instantiate()
|
|
ctrl.service.model = model
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
(self.content.selectedViewController as? UINavigationController)?.pushViewController(ctrl, animated: true)
|
|
}
|
|
case .chat:
|
|
// guard UIApplication.shared.applicationState == .inactive else { return }
|
|
if let model = deepLink.get(CryptoChat.Model.DeepLink.self) {
|
|
AccountViewAuthorize.showGetPrivateKey(in: self) {
|
|
guard
|
|
let user = Accounts().current,
|
|
let msgsHistoryService = try? CryptoChat.Service.MsgsHistory(
|
|
username: user.name,
|
|
encryptionKey: $0
|
|
)
|
|
else { return }
|
|
let ctrl = CryptoChatControllerChat(username: model.account, unreadCount: 0, service: msgsHistoryService)
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
self.content.selectChatViewController()
|
|
guard let selectedNavigation = (self.content.selectedViewController as? UINavigationController),
|
|
!(selectedNavigation.viewControllers.last is CryptoChatControllerChat) else { return }
|
|
selectedNavigation.pushViewController(ctrl, animated: true)
|
|
selectedNavigation.setNavigationBarHidden(false, animated: true)
|
|
}
|
|
}
|
|
case .chatMessage:
|
|
// guard UIApplication.shared.applicationState == .inactive else { return }
|
|
guard let info = deepLink.info,
|
|
let receiver = info["receiver"] as? String,
|
|
let sender = info["sender"] as? String,
|
|
let account = Accounts().collection.filter({ $0.name == receiver }).first
|
|
else { return }
|
|
Accounts().current = account
|
|
AccountViewAuthorize.showGetPrivateKey(in: self) {
|
|
guard
|
|
let user = Accounts().current,
|
|
let msgsHistoryService = try? CryptoChat.Service.MsgsHistory(
|
|
username: user.name,
|
|
encryptionKey: $0
|
|
)
|
|
else { return }
|
|
let controller = CryptoChatControllerChat(username: sender, unreadCount: 0, service: msgsHistoryService)
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
self.content.selectChatViewController()
|
|
guard let selectedNavigation = (self.content.selectedViewController as? UINavigationController),
|
|
!(selectedNavigation.viewControllers.last is CryptoChatControllerChat) else {
|
|
return
|
|
}
|
|
selectedNavigation.pushViewController(controller, animated: true)
|
|
selectedNavigation.setNavigationBarHidden(false, animated: true)
|
|
}
|
|
case .tokenization:
|
|
if let model = deepLink.get(Apartments.Model.Tokenization.self),
|
|
let account = Accounts().collection.filter({
|
|
$0.name == model.permission
|
|
}).first {
|
|
Accounts().current = account
|
|
let ctrl = StoryboardScene.Apartments.request.instantiate()
|
|
ctrl.title = L10n.Apartments.Tokenization.title
|
|
ctrl.popupDescription = L10n.Apartments.Tokenization.popup
|
|
let service = Apartments.Service.Tokenization()
|
|
service.image = Asset.apartmentsTokenization.image
|
|
service.warning = L10n.Apartments.Tokenization.warning
|
|
service.submit = L10n.Apartments.Tokenization.submit
|
|
service.title = L10n.Apartments.Tokenization.description
|
|
service.actionTitle = L10n.Apartments.Tokenization.Emission.title
|
|
service.contract = model.contract
|
|
service.action = model.action
|
|
service.symbol = model.symbol
|
|
service.fetchApartment(id: model.apt_id, contract: model.contract, symbol: model.symbol) { (success) in
|
|
guard success else { return }
|
|
service.receiver = nil
|
|
ctrl.service = service
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
(self.content.selectedViewController as? UINavigationController)?.pushViewController(ctrl, animated: true)
|
|
}
|
|
}
|
|
case .approveBuy:
|
|
if let model = deepLink.get(Apartments.Model.ApproveBuy.self),
|
|
let account = Accounts().collection.filter({
|
|
$0.name == model.permission
|
|
}).first {
|
|
Accounts().current = account
|
|
let ctrl = StoryboardScene.Apartments.request.instantiate()
|
|
ctrl.title = L10n.Apartments.Approve.title
|
|
ctrl.popupDescription = L10n.Apartments.Approve.popup
|
|
let service = Apartments.Service.Approve()
|
|
service.warning = L10n.Apartments.Approve.warning
|
|
service.submit = L10n.Apartments.Approve.submit
|
|
service.title = L10n.Apartments.Approve.description
|
|
service.actionTitle = L10n.Apartments.Approve.Emission.title
|
|
service.contract = model.contract
|
|
service.action = model.action
|
|
service.symbol = model.token
|
|
service.fetchApartment(id: model.apt_id, contract: model.contract, symbol: model.token) { (success) in
|
|
guard success else { return }
|
|
service.receiver = nil
|
|
ctrl.service = service
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
(self.content.selectedViewController as? UINavigationController)?.pushViewController(ctrl, animated: true)
|
|
}
|
|
}
|
|
case .emission:
|
|
if let model = deepLink.get(Apartments.Model.Emission.self),
|
|
let account = Accounts().collection.filter({
|
|
$0.name == model.permission
|
|
}).first {
|
|
Accounts().current = account
|
|
let ctrl = StoryboardScene.Apartments.request.instantiate()
|
|
ctrl.title = L10n.Apartments.Emission.title
|
|
ctrl.popupDescription = L10n.Apartments.Emission.popup
|
|
let service = Apartments.Service.Emission()
|
|
service.image = Asset.apartmentsEmission.image
|
|
service.warning = L10n.Apartments.Emission.warning
|
|
service.title = L10n.Apartments.Emission.description
|
|
service.actionTitle = L10n.Apartments.Tokenization.Emission.title
|
|
service.submit = L10n.Apartments.Emission.submit
|
|
service.contract = model.contract
|
|
service.action = model.action
|
|
service.to = model.to
|
|
service.amount = model.amount
|
|
service.symbol = model.symbol
|
|
service.memo = model.memo
|
|
service.fetchApartment(id: model.apt_id, contract: model.contract, symbol: model.symbol) { (success) in
|
|
guard success else { return }
|
|
ctrl.service = service
|
|
(self.content.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true)
|
|
(self.content.selectedViewController as? UINavigationController)?.pushViewController(ctrl, animated: true)
|
|
}
|
|
}
|
|
case .transactionTransfer, .transactionEmission, .transactionInheritance/*, .cashDealComplete*/:
|
|
if let info = deepLink.info,
|
|
let username = info["receiver"] as? String,
|
|
let symbol = info["currency"] as? String,
|
|
let account = Accounts().collection.filter({ $0.name == username }).first {
|
|
Accounts().current = account
|
|
if let index = self.content.viewControllers?.lastIndex(where: { ($0 as? UINavigationController)?.viewControllers.first is WalletController }) {
|
|
self.content.selectedIndex = index
|
|
let walletController = ((self.content.viewControllers?[index] as? UINavigationController)?.viewControllers.first as? WalletController)
|
|
walletController?.selectedSymbol = symbol
|
|
((self.content.viewControllers?[index] as? UINavigationController)?.viewControllers.first as? WalletController)?.selectedSymbol = symbol
|
|
(self.content.viewControllers?[index] as? UINavigationController)?.popToRootViewController(animated: true)
|
|
}
|
|
|
|
Wallet.Service.Tokens.shared.balances.fetch()
|
|
}
|
|
case .p2pDealNew, .p2pDealComplete, .p2pDealCancel, .p2pDealDispute:
|
|
guard UIApplication.shared.applicationState == .inactive else { return }
|
|
if let info = deepLink.info,
|
|
let username = info["receiver"] as? String,
|
|
(info["currency"] as? String).isExist,
|
|
let account = Accounts().collection.filter({ $0.name == username }).first {
|
|
|
|
Accounts().current = account
|
|
if let index = self.content.viewControllers?.lastIndex(where: { ($0 as? UINavigationController)?.viewControllers.first is P2PControllerDashboard }) {
|
|
self.content.selectedIndex = index
|
|
(self.content.viewControllers?[index] as? UINavigationController)?.popToRootViewController(animated: true)
|
|
// P2P.Service.Dashboard.shared.symbol = symbol
|
|
Wallet.Service.Tokens.shared.balances.fetch()
|
|
}
|
|
}
|
|
/*case .cashDealNew, .cashDealConfirm, .cashDealCancel:
|
|
if let info = deepLink.info,
|
|
let username = info["receiver"] as? String,
|
|
let account = Accounts().collection.filter({ $0.username == username }).first {
|
|
Accounts().current = account
|
|
if let index = content.viewControllers?.lastIndex(where: { ($0 as? UINavigationController)?.viewControllers.first is CCCPMainViewController }) {
|
|
content.selectedIndex = index
|
|
(content.viewControllers?[index] as? UINavigationController)?.popToRootViewController(animated: true)
|
|
if deepLink.action == .cashDealNew || deepLink.action == .cashDealCancel {
|
|
let ctrl = CCCPControllerExchangeRequests()
|
|
ctrl.type = .incomingRequests
|
|
(content.viewControllers?[index] as? UINavigationController)?.pushViewController(ctrl, animated: true)
|
|
}
|
|
}
|
|
}*/
|
|
case .news:
|
|
if let info = deepLink.info,
|
|
let aps = info["aps"] as? [String: Any],
|
|
let alert = aps["alert"] as? [String: String] {
|
|
Popup.show(title: alert["title"], description: alert["body"] ?? "", submit: L10n.Common.Button.ok)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension MainController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
|
|
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
|
|
picker.dismiss(animated: true)
|
|
guard
|
|
let selectedImage = info[.originalImage] as? UIImage,
|
|
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]),
|
|
let ciImage = CIImage(image: selectedImage)
|
|
else { return }
|
|
var qrCodeLink = ""
|
|
for feature in (detector.features(in: ciImage) as? [CIQRCodeFeature]) ?? [] {
|
|
qrCodeLink += feature.messageString ?? ""
|
|
}
|
|
print(qrCodeLink) // Your result from QR Code
|
|
if !qrCodeLink.isEmpty {
|
|
readQrData(string: qrCodeLink)
|
|
} else {
|
|
Alert.error(L10n.Main.Qr.notValidError)
|
|
}
|
|
}
|
|
}
|