Add introduction screen at the start of backing up a HD wallet seed phrase

pull/1411/head
Hwee-Boon Yar 5 years ago
parent 98f8a463b5
commit 0851012d1f
  1. 8
      AlphaWallet.xcodeproj/project.pbxproj
  2. 21
      AlphaWallet/Assets.xcassets/hd-introduction.imageset/Contents.json
  3. BIN
      AlphaWallet/Assets.xcassets/hd-introduction.imageset/hd-introduction.png
  4. 2
      AlphaWallet/Localization/en.lproj/Localizable.strings
  5. 2
      AlphaWallet/Localization/es.lproj/Localizable.strings
  6. 2
      AlphaWallet/Localization/ja.lproj/Localizable.strings
  7. 2
      AlphaWallet/Localization/ko.lproj/Localizable.strings
  8. 2
      AlphaWallet/Localization/zh-Hans.lproj/Localizable.strings
  9. 16
      AlphaWallet/Wallet/Coordinators/BackupSeedPhraseCoordinator.swift
  10. 113
      AlphaWallet/Wallet/ViewControllers/SeedPhraseBackupIntroductionViewController.swift
  11. 46
      AlphaWallet/Wallet/ViewModels/SeedPhraseBackupIntroductionViewModel.swift
  12. 2
      AlphaWalletTests/Coordinators/BackupCoordinatorTests.swift

@ -250,6 +250,7 @@
5E7C7110A4DF17DA65B912AC /* EnterSellTokensCardPriceQuantityViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7ABB1538A0E83EEAEB0C /* EnterSellTokensCardPriceQuantityViewControllerTests.swift */; };
5E7C71145CE952518B3EECE3 /* AccountViewTableSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7E7720DE64069CCF37D5 /* AccountViewTableSectionHeader.swift */; };
5E7C7131E338A806132D989B /* DateEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7CD1FB7D353704EF3389 /* DateEntryField.swift */; };
5E7C7133FCB97894647E2628 /* SeedPhraseBackupIntroductionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C78CF45AA54EF8647C44B /* SeedPhraseBackupIntroductionViewController.swift */; };
5E7C713ACE8C72642B1C9F93 /* SendHeaderViewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7B7A45EDFA8ED1E25863 /* SendHeaderViewViewModel.swift */; };
5E7C71570B651B3B56CAA1CC /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C76D132F4BEA5CE4FFD0A /* StringExtensionTests.swift */; };
5E7C716AB8079EA1283B2317 /* Bookmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7ED293E477AD7C13056C /* Bookmark.swift */; };
@ -453,6 +454,7 @@
5E7C7A9363A9DF11B233F9DC /* Keystore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7DD409C330DA4033F504 /* Keystore.swift */; };
5E7C7A957F0CF58041D4929E /* AssetAttributeSyntaxValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C77EEE333F036B2C3DBD4 /* AssetAttributeSyntaxValue.swift */; };
5E7C7A9628548EB8AB8B7A26 /* TokenCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7C83B57FC8FAE9AF8F26 /* TokenCollection.swift */; };
5E7C7AAC782446EADECEADF1 /* SeedPhraseBackupIntroductionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C77AED5BC29ED8D075D08 /* SeedPhraseBackupIntroductionViewModel.swift */; };
5E7C7AB2ECFB589632F2A26C /* WalletFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7E2DCCE0D775ECF83088 /* WalletFilter.swift */; };
5E7C7AB6950E43BD6E8D0CBE /* TokensViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7B3302309706CA0F972A /* TokensViewController.swift */; };
5E7C7AC88DB7EB58FDAF1B21 /* ConfirmSignMessageViewControllerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7B6380E6EB88AF8810CD /* ConfirmSignMessageViewControllerViewModel.swift */; };
@ -1066,6 +1068,7 @@
5E7C77A1F1399FD7EE2812E8 /* ServerDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerDictionary.swift; sourceTree = "<group>"; };
5E7C77A400E5145C04083FEB /* Dapps.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dapps.swift; sourceTree = "<group>"; };
5E7C77A8710ADB45488DE4E9 /* SendHeaderViewViewModelWithIntroduction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendHeaderViewViewModelWithIntroduction.swift; sourceTree = "<group>"; };
5E7C77AED5BC29ED8D075D08 /* SeedPhraseBackupIntroductionViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeedPhraseBackupIntroductionViewModel.swift; sourceTree = "<group>"; };
5E7C77B790551456E111ED4F /* PeekOpenSeaNonFungibleTokenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeekOpenSeaNonFungibleTokenViewController.swift; sourceTree = "<group>"; };
5E7C77BCBD2C2BE682D384DB /* SeedPhraseCollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeedPhraseCollectionView.swift; sourceTree = "<group>"; };
5E7C77C2844B3579A59C3F2F /* CallSmartContractFunction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSmartContractFunction.swift; sourceTree = "<group>"; };
@ -1090,6 +1093,7 @@
5E7C78B61907C2C1E2BCD478 /* DappsHomeViewControllerViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DappsHomeViewControllerViewModel.swift; sourceTree = "<group>"; };
5E7C78B63FDE2FAF25389260 /* TransferTokensCardViaWalletAddressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransferTokensCardViaWalletAddressViewController.swift; sourceTree = "<group>"; };
5E7C78C073F380B48D5BE94C /* LayoutConstraintsWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LayoutConstraintsWrapper.swift; sourceTree = "<group>"; };
5E7C78CF45AA54EF8647C44B /* SeedPhraseBackupIntroductionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeedPhraseBackupIntroductionViewController.swift; sourceTree = "<group>"; };
5E7C78E5C8FAEA752B32626D /* UIActivityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIActivityViewController.swift; sourceTree = "<group>"; };
5E7C78EFAF641C41F06C46BF /* ServersCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServersCoordinatorTests.swift; sourceTree = "<group>"; };
5E7C78FAB9070B10A476DB29 /* AssetImplicitAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssetImplicitAttributes.swift; sourceTree = "<group>"; };
@ -1898,6 +1902,7 @@
5E7C7F829626688EA50E1B68 /* KeystoreBackupIntroductionViewController.swift */,
5E7C74A5B5B9D8AD0BD913C1 /* CreateInitialWalletViewController.swift */,
5E7C753A2216F043CBDEC07C /* ElevateWalletSecurityViewController.swift */,
5E7C78CF45AA54EF8647C44B /* SeedPhraseBackupIntroductionViewController.swift */,
);
path = ViewControllers;
sourceTree = "<group>";
@ -1916,6 +1921,7 @@
5E7C73BA4FF25754ACB41255 /* CreateInitialWalletViewModel.swift */,
5E7C788BDFBDF222B3F4BEAF /* SeedPhraseCollectionViewModel.swift */,
5E7C77E2559C7C9117C0F75F /* ElevateWalletSecurityViewModel.swift */,
5E7C77AED5BC29ED8D075D08 /* SeedPhraseBackupIntroductionViewModel.swift */,
);
path = ViewModels;
sourceTree = "<group>";
@ -4358,6 +4364,8 @@
5E7C756B31278B71E68D5E10 /* TokensViewControllerCollectiblesCollectionViewHeader.swift in Sources */,
5E7C721B569E1CD1C68295F6 /* LayoutConstraintsWrapper.swift in Sources */,
5E7C779E0415809A7166A85F /* GetERC20BalanceCoordinator.swift in Sources */,
5E7C7133FCB97894647E2628 /* SeedPhraseBackupIntroductionViewController.swift in Sources */,
5E7C7AAC782446EADECEADF1 /* SeedPhraseBackupIntroductionViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "hd-introduction.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

@ -85,6 +85,8 @@
"wallets.backupKeystoreWallet.introduction.title" = "What is Keystore JSON?";
"wallets.backupKeystoreWallet.introduction.description" = "A Keystore is a text file. You can copy its contents when you want to import your wallet. This is a safe way to back up a wallet.";
"wallets.backupHdWallet.alertSheet.title" = "Show Seed Phrase";
wallets.backupHdWallet.introduction.button.title = "Back up my Wallet";
wallets.backupHdWallet.introduction.title = "Back up your Wallet with Seed Phrase";
"wallets.showSeedPhrase.title" = "Seed Phrase";
"wallets.showSeedPhrase.subtitle" = "Making a backup is very simple and safe:";
"wallets.showSeedPhrase.description" = "just write down 12 words and keep them in a safe place, offline";

@ -85,6 +85,8 @@
"wallets.backupKeystoreWallet.introduction.title" = "What is Keystore JSON?";
"wallets.backupKeystoreWallet.introduction.description" = "A Keystore is a text file. You can copy its contents when you want to import your wallet. This is a safe way to back up a wallet.";
"wallets.backupHdWallet.alertSheet.title" = "Show Seed Phrase";
wallets.backupHdWallet.introduction.button.title = "Back up my Wallet";
wallets.backupHdWallet.introduction.title = "Back up your Wallet with Seed Phrase";
"wallets.showSeedPhrase.title" = "Seed Phrase";
"wallets.showSeedPhrase.subtitle" = "Making a backup is very simple and safe:";
"wallets.showSeedPhrase.description" = "just write down 12 words and keep them in a safe place, offline";

@ -85,6 +85,8 @@
"wallets.backupKeystoreWallet.introduction.title" = "What is Keystore JSON?";
"wallets.backupKeystoreWallet.introduction.description" = "A Keystore is a text file. You can copy its contents when you want to import your wallet. This is a safe way to back up a wallet.";
"wallets.backupHdWallet.alertSheet.title" = "Show Seed Phrase";
wallets.backupHdWallet.introduction.button.title = "Back up my Wallet";
wallets.backupHdWallet.introduction.title = "Back up your Wallet with Seed Phrase";
"wallets.showSeedPhrase.title" = "Seed Phrase";
"wallets.showSeedPhrase.subtitle" = "Making a backup is very simple and safe:";
"wallets.showSeedPhrase.description" = "just write down 12 words and keep them in a safe place, offline";

@ -85,6 +85,8 @@
"wallets.backupKeystoreWallet.introduction.title" = "What is Keystore JSON?";
"wallets.backupKeystoreWallet.introduction.description" = "A Keystore is a text file. You can copy its contents when you want to import your wallet. This is a safe way to back up a wallet.";
"wallets.backupHdWallet.alertSheet.title" = "Show Seed Phrase";
wallets.backupHdWallet.introduction.button.title = "Back up my Wallet";
wallets.backupHdWallet.introduction.title = "Back up your Wallet with Seed Phrase";
"wallets.showSeedPhrase.title" = "Seed Phrase";
"wallets.showSeedPhrase.subtitle" = "Making a backup is very simple and safe:";
"wallets.showSeedPhrase.description" = "just write down 12 words and keep them in a safe place, offline";

@ -73,6 +73,8 @@
"wallets.backupKeystoreWallet.introduction.title" = "What is Keystore JSON?";
"wallets.backupKeystoreWallet.introduction.description" = "A Keystore is a text file. You can copy its contents when you want to import your wallet. This is a safe way to back up a wallet.";
"wallets.backupHdWallet.alertSheet.title" = "Show Seed Phrase";
wallets.backupHdWallet.introduction.button.title = "Back up my Wallet";
wallets.backupHdWallet.introduction.title = "Back up your Wallet with Seed Phrase";
"wallets.showSeedPhrase.title" = "Seed Phrase";
"wallets.showSeedPhrase.subtitle" = "Making a backup is very simple and safe:";
"wallets.showSeedPhrase.description" = "just write down 12 words and keep them in a safe place, offline";

@ -9,7 +9,13 @@ protocol BackupSeedPhraseCoordinatorDelegate: class {
}
class BackupSeedPhraseCoordinator: Coordinator {
private lazy var rootViewController: ShowSeedPhraseViewController = {
private lazy var rootViewController: SeedPhraseBackupIntroductionViewController = {
let controller = SeedPhraseBackupIntroductionViewController()
controller.delegate = self
controller.configure()
return controller
}()
private lazy var showSeedPhraseViewController: ShowSeedPhraseViewController = {
let controller = ShowSeedPhraseViewController(keystore: keystore, account: account)
controller.configure()
controller.delegate = self
@ -33,7 +39,7 @@ class BackupSeedPhraseCoordinator: Coordinator {
}
func end() {
rootViewController.markDone()
showSeedPhraseViewController.markDone()
}
func endUserInterface(animated: Bool) {
@ -52,3 +58,9 @@ extension BackupSeedPhraseCoordinator: ShowSeedPhraseViewControllerDelegate {
delegate?.didClose(forAccount: account, inCoordinator: self)
}
}
extension BackupSeedPhraseCoordinator: SeedPhraseBackupIntroductionViewControllerDelegate {
func didTapBackupWallet(inViewController viewController: SeedPhraseBackupIntroductionViewController) {
navigationController.pushViewController(showSeedPhraseViewController, animated: true)
}
}

@ -0,0 +1,113 @@
// Copyright © 2019 Stormbird PTE. LTD.
import UIKit
protocol SeedPhraseBackupIntroductionViewControllerDelegate: class {
func didTapBackupWallet(inViewController viewController: SeedPhraseBackupIntroductionViewController)
}
class SeedPhraseBackupIntroductionViewController: UIViewController {
private var viewModel = SeedPhraseBackupIntroductionViewModel()
private let roundedBackground = RoundedBackground()
private let subtitleLabel = UILabel()
private let imageView = UIImageView()
private let descriptionLabel1 = UILabel()
private let descriptionLabel2 = UILabel()
private let buttonsBar = ButtonsBar(numberOfButtons: 1)
private var imageViewDimension: CGFloat {
if ScreenChecker().isNarrowScreen {
return 180
} else {
return 250
}
}
weak var delegate: SeedPhraseBackupIntroductionViewControllerDelegate?
init() {
super.init(nibName: nil, bundle: nil)
hidesBottomBarWhenPushed = true
roundedBackground.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(roundedBackground)
imageView.contentMode = .scaleAspectFit
let stackView = [
UIView.spacer(height: 30),
subtitleLabel,
UIView.spacer(height: 40),
imageView,
UIView.spacer(height: 40),
descriptionLabel1,
descriptionLabel2,
].asStackView(axis: .vertical)
stackView.translatesAutoresizingMaskIntoConstraints = false
roundedBackground.addSubview(stackView)
let footerBar = UIView()
footerBar.translatesAutoresizingMaskIntoConstraints = false
footerBar.backgroundColor = .clear
roundedBackground.addSubview(footerBar)
footerBar.addSubview(buttonsBar)
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: imageViewDimension),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
stackView.topAnchor.constraint(equalTo: view.topAnchor),
stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor),
buttonsBar.leadingAnchor.constraint(equalTo: footerBar.leadingAnchor),
buttonsBar.trailingAnchor.constraint(equalTo: footerBar.trailingAnchor),
buttonsBar.topAnchor.constraint(equalTo: footerBar.topAnchor),
buttonsBar.heightAnchor.constraint(equalToConstant: ButtonsBar.buttonsHeight),
footerBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
footerBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
footerBar.topAnchor.constraint(equalTo: view.layoutGuide.bottomAnchor, constant: -ButtonsBar.buttonsHeight - ButtonsBar.marginAtBottomScreen),
footerBar.bottomAnchor.constraint(equalTo: view.bottomAnchor),
] + roundedBackground.createConstraintsWithContainer(view: view))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure() {
view.backgroundColor = Colors.appBackground
subtitleLabel.textAlignment = .center
subtitleLabel.numberOfLines = 0
subtitleLabel.textColor = viewModel.subtitleColor
subtitleLabel.font = viewModel.subtitleFont
subtitleLabel.text = viewModel.subtitle
imageView.image = viewModel.imageViewImage
descriptionLabel1.textAlignment = .center
descriptionLabel1.textColor = viewModel.descriptionColor
descriptionLabel1.font = viewModel.descriptionFont
descriptionLabel1.numberOfLines = 0
descriptionLabel1.text = viewModel.description1
descriptionLabel2.textAlignment = .center
descriptionLabel2.textColor = viewModel.descriptionColor
descriptionLabel2.font = viewModel.descriptionFont
descriptionLabel2.numberOfLines = 0
descriptionLabel2.text = viewModel.description2
buttonsBar.configure()
let exportButton = buttonsBar.buttons[0]
exportButton.setTitle(viewModel.title, for: .normal)
exportButton.addTarget(self, action: #selector(tappedExportButton), for: .touchUpInside)
}
@objc private func tappedExportButton() {
delegate?.didTapBackupWallet(inViewController: self)
}
}

@ -0,0 +1,46 @@
// Copyright © 2019 Stormbird PTE. LTD.
import Foundation
import UIKit
struct SeedPhraseBackupIntroductionViewModel {
var backgroundColor: UIColor {
return Colors.appWhite
}
var title: String {
return R.string.localizable.walletsBackupHdWalletIntroductionButtonTitle()
}
var subtitle: String {
return R.string.localizable.walletsBackupHdWalletIntroductionTitle()
}
var subtitleColor: UIColor {
return Colors.appText
}
var subtitleFont: UIFont {
return Fonts.regular(size: 22)!
}
var imageViewImage: UIImage {
return R.image.hdIntroduction()!
}
var description1: String {
return R.string.localizable.walletsShowSeedPhraseSubtitle()
}
var description2: String {
return R.string.localizable.walletsShowSeedPhraseDescription()
}
var descriptionColor: UIColor {
return Colors.darkGray
}
var descriptionFont: UIFont {
return Fonts.regular(size: 18)!
}
}

@ -12,7 +12,7 @@ class BackupCoordinatorTests: XCTestCase {
)
coordinator.start()
XCTAssertTrue(coordinator.navigationController.viewControllers[0] is ShowSeedPhraseViewController)
XCTAssertTrue(coordinator.navigationController.viewControllers[0] is SeedPhraseBackupIntroductionViewController)
}
func testStartWithKeystoreWallet() {

Loading…
Cancel
Save