Swiftgram/submodules/WalletUI/Sources/WalletSettingsScreen.swift
2020-03-25 17:59:03 +04:00

204 lines
9.5 KiB
Swift

import Foundation
import UIKit
import AppBundle
import AsyncDisplayKit
import Display
import SolidRoundedButtonNode
import SwiftSignalKit
import OverlayStatusController
import WalletCore
private final class WalletSettingsControllerArguments {
let openConfiguration: () -> Void
let exportWallet: () -> Void
let deleteWallet: () -> Void
init(openConfiguration: @escaping () -> Void, exportWallet: @escaping () -> Void, deleteWallet: @escaping () -> Void) {
self.openConfiguration = openConfiguration
self.exportWallet = exportWallet
self.deleteWallet = deleteWallet
}
}
private enum WalletSettingsSection: Int32 {
case configuration
case exportWallet
case deleteWallet
}
private enum WalletSettingsEntry: ItemListNodeEntry {
case configuration(WalletTheme, String)
case configurationInfo(WalletTheme, String)
case exportWallet(WalletTheme, String)
case deleteWallet(WalletTheme, String)
case deleteWalletInfo(WalletTheme, String)
var section: ItemListSectionId {
switch self {
case .configuration, .configurationInfo:
return WalletSettingsSection.configuration.rawValue
case .exportWallet:
return WalletSettingsSection.exportWallet.rawValue
case .deleteWallet, .deleteWalletInfo:
return WalletSettingsSection.deleteWallet.rawValue
}
}
var stableId: Int32 {
switch self {
case .configuration:
return 0
case .configurationInfo:
return 1
case .exportWallet:
return 2
case .deleteWallet:
return 3
case .deleteWalletInfo:
return 4
}
}
static func <(lhs: WalletSettingsEntry, rhs: WalletSettingsEntry) -> Bool {
return lhs.stableId < rhs.stableId
}
func item(_ arguments: Any) -> ListViewItem {
let arguments = arguments as! WalletSettingsControllerArguments
switch self {
case let .configuration(theme, text):
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.openConfiguration()
})
case let .configurationInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .exportWallet(theme, text):
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.exportWallet()
})
case let .deleteWallet(theme, text):
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
arguments.deleteWallet()
})
case let .deleteWalletInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
}
}
}
private struct WalletSettingsControllerState: Equatable {
}
private func walletSettingsControllerEntries(presentationData: WalletPresentationData, state: WalletSettingsControllerState, supportsCustomConfigurations: Bool) -> [WalletSettingsEntry] {
var entries: [WalletSettingsEntry] = []
if supportsCustomConfigurations {
entries.append(.configuration(presentationData.theme, presentationData.strings.Wallet_Settings_Configuration))
entries.append(.configurationInfo(presentationData.theme, presentationData.strings.Wallet_Settings_ConfigurationInfo))
}
entries.append(.exportWallet(presentationData.theme, presentationData.strings.Wallet_Settings_BackupWallet))
entries.append(.deleteWallet(presentationData.theme, presentationData.strings.Wallet_Settings_DeleteWallet))
entries.append(.deleteWalletInfo(presentationData.theme, presentationData.strings.Wallet_Settings_DeleteWalletInfo))
return entries
}
public func walletSettingsController(context: WalletContext, walletInfo: WalletInfo) -> ViewController {
let statePromise = ValuePromise(WalletSettingsControllerState(), ignoreRepeated: true)
var presentControllerImpl: ((ViewController, Any?) -> Void)?
var pushControllerImpl: ((ViewController) -> Void)?
var replaceAllWalletControllersImpl: ((ViewController) -> Void)?
let arguments = WalletSettingsControllerArguments(openConfiguration: {
let _ = (context.storage.localWalletConfiguration()
|> take(1)
|> deliverOnMainQueue).start(next: { configuration in
pushControllerImpl?(walletConfigurationScreen(context: context, currentConfiguration: configuration))
})
}, exportWallet: {
let presentationData = context.presentationData
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(controller, nil)
let _ = (context.keychain.decrypt(walletInfo.encryptedSecret)
|> deliverOnMainQueue).start(next: { [weak controller] decryptedSecret in
let _ = (context.getServerSalt()
|> deliverOnMainQueue).start(next: { serverSalt in
let _ = (walletRestoreWords(tonInstance: context.tonInstance, publicKey: walletInfo.publicKey, decryptedSecret: decryptedSecret, localPassword: serverSalt)
|> deliverOnMainQueue).start(next: { [weak controller] wordList in
controller?.dismiss()
pushControllerImpl?(WalletWordDisplayScreen(context: context, walletInfo: walletInfo, wordList: wordList, mode: .export, walletCreatedPreloadState: nil))
}, error: { [weak controller] _ in
controller?.dismiss()
})
}, error: { [weak controller] _ in
controller?.dismiss()
})
}, error: { [weak controller] _ in
controller?.dismiss()
})
}, deleteWallet: {
let presentationData = context.presentationData
let actionSheet = ActionSheetController(theme: presentationData.theme.actionSheet)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.Wallet_Settings_DeleteWalletInfo),
ActionSheetButtonItem(title: presentationData.strings.Wallet_Settings_DeleteWallet, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(controller, nil)
let _ = (deleteAllLocalWalletsData(storage: context.storage, tonInstance: context.tonInstance)
|> deliverOnMainQueue).start(error: { [weak controller] _ in
controller?.dismiss()
}, completed: { [weak controller] in
controller?.dismiss()
replaceAllWalletControllersImpl?(WalletSplashScreen(context: context, mode: .intro, walletCreatedPreloadState: nil))
})
})
]), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Wallet_Navigation_Cancel, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
presentControllerImpl?(actionSheet, nil)
})
let signal = combineLatest(queue: .mainQueue(), .single(context.presentationData), statePromise.get())
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Wallet_Settings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Wallet_Navigation_Back), animateChanges: false)
let listState = ItemListNodeState(entries: walletSettingsControllerEntries(presentationData: presentationData, state: state, supportsCustomConfigurations: context.supportsCustomConfigurations), style: .blocks, animateChanges: false)
return (controllerState, (listState, arguments))
}
|> afterDisposed {
}
let controller = ItemListController(theme: context.presentationData.theme, strings: context.presentationData.strings, updatedPresentationData: .single((context.presentationData.theme, context.presentationData.strings)), state: signal, tabBarItem: nil)
controller.navigationPresentation = .modal
controller.enableInteractiveDismiss = true
presentControllerImpl = { [weak controller] c, a in
controller?.present(c, in: .window(.root), with: a)
}
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
replaceAllWalletControllersImpl = { [weak controller] c in
if let navigationController = controller?.navigationController as? NavigationController {
var controllers = navigationController.viewControllers
controllers = controllers.filter { listController in
if listController === controller {
return false
}
if listController is WalletInfoScreen {
return false
}
return true
}
controllers.append(c)
navigationController.setViewControllers(controllers, animated: true)
}
}
return controller
}