From 2818ad249e017ddf30c8121c20ddd5e6ee2d179c Mon Sep 17 00:00:00 2001 From: Denis D Date: Wed, 8 May 2019 18:14:29 +0300 Subject: [PATCH] categories in progress --- BeamWallet.xcodeproj/project.pbxproj | 290 ++++++++++++++--- BeamWallet/AppDelegate.swift | 34 +- BeamWallet/BeamSDK/AppModel.h | 14 +- BeamWallet/BeamSDK/AppModel.mm | 167 +++++++++- BeamWallet/BeamSDK/Objects/BMAddress.h | 1 + BeamWallet/BeamSDK/Objects/BMCategory.h | 29 ++ BeamWallet/BeamSDK/Objects/BMCategory.m | 43 +++ BeamWallet/BeamSDK/Objects/BMDuration.h | 28 ++ .../Objects/BMDuration.m} | 10 +- BeamWallet/BeamSDK/Objects/BMTransaction.h | 4 +- BeamWallet/BeamSDK/Settings.m | 2 +- BeamWallet/BeamSDK/WalletModel.mm | 3 +- .../Controls/BMTableHeaderTitleView.swift | 41 +++ BeamWallet/Extensions/Color.swift | 42 +++ BeamWallet/Extensions/Device.swift | 4 + BeamWallet/Extensions/TextView.swift | 98 ++++++ BeamWallet/Extensions/View.swift | 43 +++ BeamWallet/Manager/NotificationManager.swift | 2 +- BeamWallet/Manager/TGBotManager.swift | 46 ++- BeamWallet/Protocols/Configurable.swift | 4 +- BeamWallet/Protocols/LocalizableStrings.swift | 26 ++ .../EnterWalletPasswordViewController.swift | 9 +- .../AddressExpiresPickerViewController.swift | 112 +++++++ .../AddressExpiresPickerViewController.xib | 44 +++ .../Addresses/AddressViewController.swift | 48 ++- .../Main/Addresses/AddressViewController.xib | 23 +- .../Addresses/AddressesViewController.swift | 11 + .../Addresses/Cell/AddressCategoryCell.swift | 45 +++ .../Addresses/Cell/AddressCategoryCell.xib | 100 ++++++ .../Main/Addresses/Cell/AddressCell.swift | 10 +- .../Main/Addresses/Cell/AddressCell.xib | 23 +- .../Addresses/Cell/AddressCommentCell.swift | 32 +- .../Addresses/Cell/AddressCommentCell.xib | 98 +++--- .../Addresses/Cell/AddressDurationCell.swift | 51 +++ .../Addresses/Cell/AddressDurationCell.xib | 77 +++++ .../Main/Addresses/Cell/AddressExpireCell.xib | 118 ------- .../Addresses/Cell/AddressExpiredCell.swift | 45 +++ .../Addresses/Cell/AddressExpiredCell.xib | 81 +++++ ...ireCell.swift => AddressExpiresCell.swift} | 52 +--- .../Addresses/Cell/AddressExpiresCell.xib | 117 +++++++ .../Addresses/Cell/AddressSwitchCell.swift | 8 +- .../Main/Addresses/Cell/AddressSwitchCell.xib | 78 +++-- .../Addresses/EditAddressViewController.swift | 293 ++++++++++-------- .../Addresses/EditAddressViewController.xib | 37 +-- .../Main/Categories/CategoryColorsView.swift | 131 ++++++++ .../CategoryDetailViewController.swift | 199 ++++++++++++ .../CategoryDetailViewController.xib | 68 ++++ .../CategoryEditViewController.swift | 149 +++++++++ .../Categories/CategoryEditViewController.xib | 101 ++++++ .../CategoryPickerViewController.swift | 120 +++++++ .../CategoryPickerViewController.xib | 44 +++ .../Categories/Cells/CategoryNameCell.swift | 39 +++ .../Categories/Cells/CategoryNameCell.xib | 65 ++++ .../Categories/Cells/CategoryPickerCell.swift | 52 ++++ .../Categories/Cells/CategoryPickerCell.xib | 77 +++++ .../Main/Settings/Cells/SettingsCell.swift | 23 +- .../EnterNodeAddressViewController.swift | 2 +- .../EnterNodeAddressViewController.xib | 13 +- .../Settings/Model/SettingsViewModel.swift | 97 ++++-- .../Settings/SettingsViewController.swift | 74 +++-- .../Main/Settings/SettingsViewController.xib | 20 -- .../UnlockPasswordViewController.swift | 2 +- .../Main/UTXO/UTXODetailViewController.swift | 10 +- .../GeneralInfoCell.swift} | 30 +- .../GeneralInfoCell.xib} | 6 +- .../Cell/TransactionPaymentProofCell.swift | 2 +- .../PaymentProofDetailViewController.swift | 22 +- .../TransactionViewController.swift | 24 +- .../Main/Wallet/WalletViewController.swift | 2 +- BeamWalletNotificationView/Info.plist | 2 +- .../tick.imageset/Contents.json | 22 ++ .../Assets.xcassets/tick.imageset/tick.png | Bin 0 -> 675 bytes .../Assets.xcassets/tick.imageset/tick@2x.png | Bin 0 -> 874 bytes Resources/Info.plist | 2 +- Resources/InfoMasternet.plist | 2 +- Resources/InfoTestnet.plist | 2 +- 76 files changed, 3177 insertions(+), 668 deletions(-) create mode 100644 BeamWallet/BeamSDK/Objects/BMCategory.h create mode 100644 BeamWallet/BeamSDK/Objects/BMCategory.m create mode 100644 BeamWallet/BeamSDK/Objects/BMDuration.h rename BeamWallet/{Controls/BMWordSuggestionView.swift => BeamSDK/Objects/BMDuration.m} (86%) create mode 100644 BeamWallet/Controls/BMTableHeaderTitleView.swift create mode 100644 BeamWallet/Extensions/TextView.swift create mode 100644 BeamWallet/Protocols/LocalizableStrings.swift create mode 100644 BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.swift create mode 100644 BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.xib create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.swift create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.xib create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressDurationCell.swift create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressDurationCell.xib delete mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressExpireCell.xib create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressExpiredCell.swift create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressExpiredCell.xib rename BeamWallet/ViewControllers/Main/Addresses/Cell/{AddressExpireCell.swift => AddressExpiresCell.swift} (61%) create mode 100644 BeamWallet/ViewControllers/Main/Addresses/Cell/AddressExpiresCell.xib create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryColorsView.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.xib create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.xib create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.xib create mode 100644 BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.xib create mode 100644 BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.swift create mode 100644 BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.xib rename BeamWallet/ViewControllers/Main/Wallet/{Transaction/Cell/GeneralTransactionInfoCell.swift => Cells/GeneralInfoCell.swift} (78%) rename BeamWallet/ViewControllers/Main/Wallet/{Transaction/Cell/GeneralTransactionInfoCell.xib => Cells/GeneralInfoCell.xib} (97%) create mode 100644 Resources/Assets.xcassets/tick.imageset/Contents.json create mode 100644 Resources/Assets.xcassets/tick.imageset/tick.png create mode 100644 Resources/Assets.xcassets/tick.imageset/tick@2x.png diff --git a/BeamWallet.xcodeproj/project.pbxproj b/BeamWallet.xcodeproj/project.pbxproj index bb93df61..0120bfd7 100644 --- a/BeamWallet.xcodeproj/project.pbxproj +++ b/BeamWallet.xcodeproj/project.pbxproj @@ -24,6 +24,13 @@ 92090D0D223A684000A1CFBB /* bgTestnet.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 92090D0B223A684000A1CFBB /* bgTestnet.jpg */; }; 920F460D223A9EA20048966E /* BMInputCopyBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920F460C223A9EA20048966E /* BMInputCopyBar.swift */; }; 920F460E223A9EA20048966E /* BMInputCopyBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 920F460C223A9EA20048966E /* BMInputCopyBar.swift */; }; + 9219595522821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595422821F9C007E9723 /* BMTableHeaderTitleView.swift */; }; + 9219595622821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595422821F9C007E9723 /* BMTableHeaderTitleView.swift */; }; + 9219595722821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595422821F9C007E9723 /* BMTableHeaderTitleView.swift */; }; + 9219595922823639007E9723 /* LocalizableStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595822823639007E9723 /* LocalizableStrings.swift */; }; + 9219595A22823639007E9723 /* LocalizableStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595822823639007E9723 /* LocalizableStrings.swift */; }; + 9219595B22823639007E9723 /* LocalizableStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595822823639007E9723 /* LocalizableStrings.swift */; }; + 9219595C22823639007E9723 /* LocalizableStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9219595822823639007E9723 /* LocalizableStrings.swift */; }; 921E21F4224B7F77001E2538 /* EditAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E21F2224B7F77001E2538 /* EditAddressViewController.swift */; }; 921E21F5224B7F77001E2538 /* EditAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E21F2224B7F77001E2538 /* EditAddressViewController.swift */; }; 921E21F6224B7F77001E2538 /* EditAddressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E21F3224B7F77001E2538 /* EditAddressViewController.xib */; }; @@ -32,10 +39,10 @@ 921E21FE224B84A4001E2538 /* AddressSwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E21FB224B84A4001E2538 /* AddressSwitchCell.swift */; }; 921E21FF224B84A4001E2538 /* AddressSwitchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E21FC224B84A4001E2538 /* AddressSwitchCell.xib */; }; 921E2200224B84A4001E2538 /* AddressSwitchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E21FC224B84A4001E2538 /* AddressSwitchCell.xib */; }; - 921E2203224B870F001E2538 /* AddressExpireCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpireCell.swift */; }; - 921E2204224B870F001E2538 /* AddressExpireCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpireCell.swift */; }; - 921E2205224B870F001E2538 /* AddressExpireCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpireCell.xib */; }; - 921E2206224B870F001E2538 /* AddressExpireCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpireCell.xib */; }; + 921E2203224B870F001E2538 /* AddressExpiresCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpiresCell.swift */; }; + 921E2204224B870F001E2538 /* AddressExpiresCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpiresCell.swift */; }; + 921E2205224B870F001E2538 /* AddressExpiresCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpiresCell.xib */; }; + 921E2206224B870F001E2538 /* AddressExpiresCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpiresCell.xib */; }; 921E2209224B8B8B001E2538 /* AddressCommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2207224B8B8B001E2538 /* AddressCommentCell.swift */; }; 921E220A224B8B8B001E2538 /* AddressCommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2207224B8B8B001E2538 /* AddressCommentCell.swift */; }; 921E220B224B8B8B001E2538 /* AddressCommentCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2208224B8B8B001E2538 /* AddressCommentCell.xib */; }; @@ -44,6 +51,74 @@ 921FA631227C3BB6008E80A3 /* CurrencyFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 921FA62F227C3BB6008E80A3 /* CurrencyFormatter.m */; }; 921FA632227C3BB6008E80A3 /* CurrencyFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 921FA62F227C3BB6008E80A3 /* CurrencyFormatter.m */; }; 921FA633227C3BB6008E80A3 /* CurrencyFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 921FA62F227C3BB6008E80A3 /* CurrencyFormatter.m */; }; + 92227AF92281981E0070DC68 /* BMCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 92227AF82281981E0070DC68 /* BMCategory.m */; }; + 92227AFA2281981E0070DC68 /* BMCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 92227AF82281981E0070DC68 /* BMCategory.m */; }; + 92227AFB2281981E0070DC68 /* BMCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 92227AF82281981E0070DC68 /* BMCategory.m */; }; + 92227AFC2281981E0070DC68 /* BMCategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 92227AF82281981E0070DC68 /* BMCategory.m */; }; + 92227B002281B1B00070DC68 /* CategoryEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227AFE2281B1B00070DC68 /* CategoryEditViewController.swift */; }; + 92227B012281B1B00070DC68 /* CategoryEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227AFE2281B1B00070DC68 /* CategoryEditViewController.swift */; }; + 92227B022281B1B00070DC68 /* CategoryEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227AFE2281B1B00070DC68 /* CategoryEditViewController.swift */; }; + 92227B032281B1B00070DC68 /* CategoryEditViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92227AFF2281B1B00070DC68 /* CategoryEditViewController.xib */; }; + 92227B042281B1B00070DC68 /* CategoryEditViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92227AFF2281B1B00070DC68 /* CategoryEditViewController.xib */; }; + 92227B052281B1B00070DC68 /* CategoryEditViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92227AFF2281B1B00070DC68 /* CategoryEditViewController.xib */; }; + 92227B072281C28D0070DC68 /* CategoryColorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227B062281C28D0070DC68 /* CategoryColorsView.swift */; }; + 92227B082281C28D0070DC68 /* CategoryColorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227B062281C28D0070DC68 /* CategoryColorsView.swift */; }; + 92227B092281C28D0070DC68 /* CategoryColorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92227B062281C28D0070DC68 /* CategoryColorsView.swift */; }; + 9227AEAF2282C80E00FB221F /* CategoryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEAD2282C80E00FB221F /* CategoryDetailViewController.swift */; }; + 9227AEB02282C80E00FB221F /* CategoryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEAD2282C80E00FB221F /* CategoryDetailViewController.swift */; }; + 9227AEB12282C80E00FB221F /* CategoryDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEAD2282C80E00FB221F /* CategoryDetailViewController.swift */; }; + 9227AEB22282C80E00FB221F /* CategoryDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEAE2282C80E00FB221F /* CategoryDetailViewController.xib */; }; + 9227AEB32282C80E00FB221F /* CategoryDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEAE2282C80E00FB221F /* CategoryDetailViewController.xib */; }; + 9227AEB42282C80E00FB221F /* CategoryDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEAE2282C80E00FB221F /* CategoryDetailViewController.xib */; }; + 9227AEB82282CA7700FB221F /* CategoryNameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEB62282CA7700FB221F /* CategoryNameCell.swift */; }; + 9227AEB92282CA7700FB221F /* CategoryNameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEB62282CA7700FB221F /* CategoryNameCell.swift */; }; + 9227AEBA2282CA7700FB221F /* CategoryNameCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEB62282CA7700FB221F /* CategoryNameCell.swift */; }; + 9227AEBB2282CA7700FB221F /* CategoryNameCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEB72282CA7700FB221F /* CategoryNameCell.xib */; }; + 9227AEBC2282CA7700FB221F /* CategoryNameCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEB72282CA7700FB221F /* CategoryNameCell.xib */; }; + 9227AEBD2282CA7700FB221F /* CategoryNameCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEB72282CA7700FB221F /* CategoryNameCell.xib */; }; + 9227AEC02282D2A000FB221F /* CategoryPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEBE2282D2A000FB221F /* CategoryPickerViewController.swift */; }; + 9227AEC12282D2A000FB221F /* CategoryPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEBE2282D2A000FB221F /* CategoryPickerViewController.swift */; }; + 9227AEC22282D2A000FB221F /* CategoryPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEBE2282D2A000FB221F /* CategoryPickerViewController.swift */; }; + 9227AEC32282D2A000FB221F /* CategoryPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEBF2282D2A000FB221F /* CategoryPickerViewController.xib */; }; + 9227AEC42282D2A000FB221F /* CategoryPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEBF2282D2A000FB221F /* CategoryPickerViewController.xib */; }; + 9227AEC52282D2A000FB221F /* CategoryPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEBF2282D2A000FB221F /* CategoryPickerViewController.xib */; }; + 9227AEC82282D43700FB221F /* CategoryPickerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEC62282D43700FB221F /* CategoryPickerCell.swift */; }; + 9227AEC92282D43700FB221F /* CategoryPickerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEC62282D43700FB221F /* CategoryPickerCell.swift */; }; + 9227AECA2282D43700FB221F /* CategoryPickerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEC62282D43700FB221F /* CategoryPickerCell.swift */; }; + 9227AECB2282D43700FB221F /* CategoryPickerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEC72282D43700FB221F /* CategoryPickerCell.xib */; }; + 9227AECC2282D43700FB221F /* CategoryPickerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEC72282D43700FB221F /* CategoryPickerCell.xib */; }; + 9227AECD2282D43700FB221F /* CategoryPickerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEC72282D43700FB221F /* CategoryPickerCell.xib */; }; + 9227AED02282E4E700FB221F /* AddressExpiredCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AECE2282E4E700FB221F /* AddressExpiredCell.swift */; }; + 9227AED12282E4E700FB221F /* AddressExpiredCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AECE2282E4E700FB221F /* AddressExpiredCell.swift */; }; + 9227AED22282E4E700FB221F /* AddressExpiredCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AECE2282E4E700FB221F /* AddressExpiredCell.swift */; }; + 9227AED32282E4E700FB221F /* AddressExpiredCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AECF2282E4E700FB221F /* AddressExpiredCell.xib */; }; + 9227AED42282E4E700FB221F /* AddressExpiredCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AECF2282E4E700FB221F /* AddressExpiredCell.xib */; }; + 9227AED52282E4E700FB221F /* AddressExpiredCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AECF2282E4E700FB221F /* AddressExpiredCell.xib */; }; + 9227AED82282E7F900FB221F /* AddressCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AED62282E7F900FB221F /* AddressCategoryCell.swift */; }; + 9227AED92282E7F900FB221F /* AddressCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AED62282E7F900FB221F /* AddressCategoryCell.swift */; }; + 9227AEDA2282E7F900FB221F /* AddressCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AED62282E7F900FB221F /* AddressCategoryCell.swift */; }; + 9227AEDB2282E7F900FB221F /* AddressCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AED72282E7F900FB221F /* AddressCategoryCell.xib */; }; + 9227AEDC2282E7F900FB221F /* AddressCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AED72282E7F900FB221F /* AddressCategoryCell.xib */; }; + 9227AEDD2282E7F900FB221F /* AddressCategoryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AED72282E7F900FB221F /* AddressCategoryCell.xib */; }; + 9227AEDF2282EADA00FB221F /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEDE2282EADA00FB221F /* TextView.swift */; }; + 9227AEE02282EADA00FB221F /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEDE2282EADA00FB221F /* TextView.swift */; }; + 9227AEE12282EADA00FB221F /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEDE2282EADA00FB221F /* TextView.swift */; }; + 9227AEE42282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEE22282F54000FB221F /* AddressExpiresPickerViewController.swift */; }; + 9227AEE52282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEE22282F54000FB221F /* AddressExpiresPickerViewController.swift */; }; + 9227AEE62282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEE22282F54000FB221F /* AddressExpiresPickerViewController.swift */; }; + 9227AEE72282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEE32282F54000FB221F /* AddressExpiresPickerViewController.xib */; }; + 9227AEE82282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEE32282F54000FB221F /* AddressExpiresPickerViewController.xib */; }; + 9227AEE92282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEE32282F54000FB221F /* AddressExpiresPickerViewController.xib */; }; + 9227AEEC2282F6F800FB221F /* BMDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEEB2282F6F800FB221F /* BMDuration.m */; }; + 9227AEED2282F6F800FB221F /* BMDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEEB2282F6F800FB221F /* BMDuration.m */; }; + 9227AEEE2282F6F800FB221F /* BMDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEEB2282F6F800FB221F /* BMDuration.m */; }; + 9227AEEF2282F6F800FB221F /* BMDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEEB2282F6F800FB221F /* BMDuration.m */; }; + 9227AEF22282F7A200FB221F /* AddressDurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEF02282F7A200FB221F /* AddressDurationCell.swift */; }; + 9227AEF32282F7A200FB221F /* AddressDurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEF02282F7A200FB221F /* AddressDurationCell.swift */; }; + 9227AEF42282F7A200FB221F /* AddressDurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227AEF02282F7A200FB221F /* AddressDurationCell.swift */; }; + 9227AEF52282F7A200FB221F /* AddressDurationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEF12282F7A200FB221F /* AddressDurationCell.xib */; }; + 9227AEF62282F7A200FB221F /* AddressDurationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEF12282F7A200FB221F /* AddressDurationCell.xib */; }; + 9227AEF72282F7A200FB221F /* AddressDurationCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9227AEF12282F7A200FB221F /* AddressDurationCell.xib */; }; 9231E3F9225CC3A000121B33 /* SF-Pro-Display-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9231E3F7225CC39F00121B33 /* SF-Pro-Display-LightItalic.otf */; }; 9231E3FA225CC3A000121B33 /* SF-Pro-Display-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9231E3F7225CC39F00121B33 /* SF-Pro-Display-LightItalic.otf */; }; 9231E3FB225CC3A000121B33 /* SF-Pro-Display-RegularItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 9231E3F8225CC3A000121B33 /* SF-Pro-Display-RegularItalic.otf */; }; @@ -314,8 +389,6 @@ 92AB832F223BC5D4000ADE86 /* TransactionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AB832C223BC5D4000ADE86 /* TransactionViewController.swift */; }; 92AB8330223BC5D4000ADE86 /* TransactionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92AB832D223BC5D4000ADE86 /* TransactionViewController.xib */; }; 92AB8331223BC5D4000ADE86 /* TransactionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92AB832D223BC5D4000ADE86 /* TransactionViewController.xib */; }; - 92AC2DED225F8DA7000272BF /* BMWordSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AC2DEC225F8DA7000272BF /* BMWordSuggestionView.swift */; }; - 92AC2DEE225F8DA7000272BF /* BMWordSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AC2DEC225F8DA7000272BF /* BMWordSuggestionView.swift */; }; 92ADED812229F213001D0A38 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ADED802229F213001D0A38 /* ViewController.swift */; }; 92AE366C22383D2300E0810B /* WalletQRCodeScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AE366A22383D2300E0810B /* WalletQRCodeScannerViewController.swift */; }; 92AE366D22383D2300E0810B /* WalletQRCodeScannerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92AE366B22383D2300E0810B /* WalletQRCodeScannerViewController.xib */; }; @@ -357,10 +430,10 @@ 92D9C94A2240FB3C00EDE059 /* UTXOBlockCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C9472240FB3C00EDE059 /* UTXOBlockCell.swift */; }; 92D9C94B2240FB3C00EDE059 /* UTXOBlockCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C9482240FB3C00EDE059 /* UTXOBlockCell.xib */; }; 92D9C94C2240FB3C00EDE059 /* UTXOBlockCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C9482240FB3C00EDE059 /* UTXOBlockCell.xib */; }; - 92D9C94F224188A400EDE059 /* GeneralTransactionInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralTransactionInfoCell.swift */; }; - 92D9C950224188A400EDE059 /* GeneralTransactionInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralTransactionInfoCell.swift */; }; - 92D9C951224188A400EDE059 /* GeneralTransactionInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralTransactionInfoCell.xib */; }; - 92D9C952224188A400EDE059 /* GeneralTransactionInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralTransactionInfoCell.xib */; }; + 92D9C94F224188A400EDE059 /* GeneralInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralInfoCell.swift */; }; + 92D9C950224188A400EDE059 /* GeneralInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralInfoCell.swift */; }; + 92D9C951224188A400EDE059 /* GeneralInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralInfoCell.xib */; }; + 92D9C952224188A400EDE059 /* GeneralInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralInfoCell.xib */; }; 92DD900E224A554E0011BE3E /* AddressesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DD900C224A554E0011BE3E /* AddressesViewController.swift */; }; 92DD900F224A554E0011BE3E /* AddressesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92DD900C224A554E0011BE3E /* AddressesViewController.swift */; }; 92DD9010224A554E0011BE3E /* AddressesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92DD900D224A554E0011BE3E /* AddressesViewController.xib */; }; @@ -395,7 +468,6 @@ 92E2EADD226F21C700367928 /* Settings.m in Sources */ = {isa = PBXBuildFile; fileRef = 92365AD8222D3F5E000D7064 /* Settings.m */; }; 92E2EADE226F21C700367928 /* WalletAvailableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 926A856D222E97DF00A3B747 /* WalletAvailableCell.swift */; }; 92E2EADF226F21C700367928 /* CreateWalletPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92FC611A22297EEC00AEABC1 /* CreateWalletPasswordViewController.swift */; }; - 92E2EAE0226F21C700367928 /* BMWordSuggestionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AC2DEC225F8DA7000272BF /* BMWordSuggestionView.swift */; }; 92E2EAE1226F21C700367928 /* WalletConfirmSendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9235447B2254D6B700889C74 /* WalletConfirmSendViewController.swift */; }; 92E2EAE2226F21C700367928 /* UTXOBlockCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C9472240FB3C00EDE059 /* UTXOBlockCell.swift */; }; 92E2EAE3226F21C700367928 /* BMWalletStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 92435242222DED3200A0EF37 /* BMWalletStatus.m */; }; @@ -423,8 +495,8 @@ 92E2EAF9226F21C700367928 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925AD5DB2228254E00DDE66B /* AppDelegate.swift */; }; 92E2EAFA226F21C700367928 /* AddressCommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2207224B8B8B001E2538 /* AddressCommentCell.swift */; }; 92E2EAFB226F21C700367928 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929885F5222B2B1E0038C015 /* Label.swift */; }; - 92E2EAFC226F21C700367928 /* GeneralTransactionInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralTransactionInfoCell.swift */; }; - 92E2EAFD226F21C700367928 /* AddressExpireCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpireCell.swift */; }; + 92E2EAFC226F21C700367928 /* GeneralInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D9C94D224188A400EDE059 /* GeneralInfoCell.swift */; }; + 92E2EAFD226F21C700367928 /* AddressExpiresCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 921E2201224B870F001E2538 /* AddressExpiresCell.swift */; }; 92E2EAFE226F21C700367928 /* UTXOCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92E884C2223FADCD0003D6BB /* UTXOCell.swift */; }; 92E2EAFF226F21C700367928 /* BMNetworkStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92AE366E223845E300E0810B /* BMNetworkStatusView.swift */; }; 92E2EB00226F21C700367928 /* WalletQRCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92A1BA012236920C008135B5 /* WalletQRCodeViewController.swift */; }; @@ -505,7 +577,7 @@ 92E2EB5C226F21C700367928 /* IntroPhraseViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9207FF3E222932DA009D931B /* IntroPhraseViewController.xib */; }; 92E2EB5D226F21C700367928 /* UTXOBlockCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C9482240FB3C00EDE059 /* UTXOBlockCell.xib */; }; 92E2EB5E226F21C700367928 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92435254222E73E900A0EF37 /* SettingsViewController.xib */; }; - 92E2EB5F226F21C700367928 /* AddressExpireCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpireCell.xib */; }; + 92E2EB5F226F21C700367928 /* AddressExpiresCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E2202224B870F001E2538 /* AddressExpiresCell.xib */; }; 92E2EB60226F21C700367928 /* CreateWalletProgressViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92538F60222B5F7E00792A25 /* CreateWalletProgressViewController.xib */; }; 92E2EB61226F21C700367928 /* TransactionPaymentProofCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92790D9D224E4A1500F79D64 /* TransactionPaymentProofCell.xib */; }; 92E2EB62226F21C700367928 /* AddressSwitchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 921E21FC224B84A4001E2538 /* AddressSwitchCell.xib */; }; @@ -513,7 +585,7 @@ 92E2EB64226F21C700367928 /* DisplayPhraseViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9207FF4722293FEB009D931B /* DisplayPhraseViewController.xib */; }; 92E2EB65226F21C700367928 /* AddressesViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92DD900D224A554E0011BE3E /* AddressesViewController.xib */; }; 92E2EB66226F21C700367928 /* UTXOCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92E884C3223FADCD0003D6BB /* UTXOCell.xib */; }; - 92E2EB67226F21C700367928 /* GeneralTransactionInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralTransactionInfoCell.xib */; }; + 92E2EB67226F21C700367928 /* GeneralInfoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92D9C94E224188A400EDE059 /* GeneralInfoCell.xib */; }; 92E2EB68226F21C700367928 /* NewsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92F7ADD3225B79E000D8C46D /* NewsViewController.xib */; }; 92E2EB69226F21C700367928 /* InputPhraseViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 929885F2222A15300038C015 /* InputPhraseViewController.xib */; }; 92E2EB6A226F21C700367928 /* WalletReceiveViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 92A1B9FA22367717008135B5 /* WalletReceiveViewController.xib */; }; @@ -697,16 +769,42 @@ 92090D08223A67D400A1CFBB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreenTestNet.storyboard; sourceTree = ""; }; 92090D0B223A684000A1CFBB /* bgTestnet.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = bgTestnet.jpg; sourceTree = ""; }; 920F460C223A9EA20048966E /* BMInputCopyBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BMInputCopyBar.swift; sourceTree = ""; }; + 9219595422821F9C007E9723 /* BMTableHeaderTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BMTableHeaderTitleView.swift; sourceTree = ""; }; + 9219595822823639007E9723 /* LocalizableStrings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizableStrings.swift; sourceTree = ""; }; 921E21F2224B7F77001E2538 /* EditAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditAddressViewController.swift; sourceTree = ""; }; 921E21F3224B7F77001E2538 /* EditAddressViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EditAddressViewController.xib; sourceTree = ""; }; 921E21FB224B84A4001E2538 /* AddressSwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressSwitchCell.swift; sourceTree = ""; }; 921E21FC224B84A4001E2538 /* AddressSwitchCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressSwitchCell.xib; sourceTree = ""; }; - 921E2201224B870F001E2538 /* AddressExpireCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressExpireCell.swift; sourceTree = ""; }; - 921E2202224B870F001E2538 /* AddressExpireCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressExpireCell.xib; sourceTree = ""; }; + 921E2201224B870F001E2538 /* AddressExpiresCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressExpiresCell.swift; sourceTree = ""; }; + 921E2202224B870F001E2538 /* AddressExpiresCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressExpiresCell.xib; sourceTree = ""; }; 921E2207224B8B8B001E2538 /* AddressCommentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCommentCell.swift; sourceTree = ""; }; 921E2208224B8B8B001E2538 /* AddressCommentCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressCommentCell.xib; sourceTree = ""; }; 921FA62E227C3BB6008E80A3 /* CurrencyFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CurrencyFormatter.h; sourceTree = ""; }; 921FA62F227C3BB6008E80A3 /* CurrencyFormatter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CurrencyFormatter.m; sourceTree = ""; }; + 92227AF72281981E0070DC68 /* BMCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BMCategory.h; sourceTree = ""; }; + 92227AF82281981E0070DC68 /* BMCategory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BMCategory.m; sourceTree = ""; }; + 92227AFE2281B1B00070DC68 /* CategoryEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryEditViewController.swift; sourceTree = ""; }; + 92227AFF2281B1B00070DC68 /* CategoryEditViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryEditViewController.xib; sourceTree = ""; }; + 92227B062281C28D0070DC68 /* CategoryColorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryColorsView.swift; sourceTree = ""; }; + 9227AEAD2282C80E00FB221F /* CategoryDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryDetailViewController.swift; sourceTree = ""; }; + 9227AEAE2282C80E00FB221F /* CategoryDetailViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryDetailViewController.xib; sourceTree = ""; }; + 9227AEB62282CA7700FB221F /* CategoryNameCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryNameCell.swift; sourceTree = ""; }; + 9227AEB72282CA7700FB221F /* CategoryNameCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryNameCell.xib; sourceTree = ""; }; + 9227AEBE2282D2A000FB221F /* CategoryPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryPickerViewController.swift; sourceTree = ""; }; + 9227AEBF2282D2A000FB221F /* CategoryPickerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryPickerViewController.xib; sourceTree = ""; }; + 9227AEC62282D43700FB221F /* CategoryPickerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryPickerCell.swift; sourceTree = ""; }; + 9227AEC72282D43700FB221F /* CategoryPickerCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CategoryPickerCell.xib; sourceTree = ""; }; + 9227AECE2282E4E700FB221F /* AddressExpiredCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressExpiredCell.swift; sourceTree = ""; }; + 9227AECF2282E4E700FB221F /* AddressExpiredCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressExpiredCell.xib; sourceTree = ""; }; + 9227AED62282E7F900FB221F /* AddressCategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCategoryCell.swift; sourceTree = ""; }; + 9227AED72282E7F900FB221F /* AddressCategoryCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressCategoryCell.xib; sourceTree = ""; }; + 9227AEDE2282EADA00FB221F /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = ""; }; + 9227AEE22282F54000FB221F /* AddressExpiresPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressExpiresPickerViewController.swift; sourceTree = ""; }; + 9227AEE32282F54000FB221F /* AddressExpiresPickerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressExpiresPickerViewController.xib; sourceTree = ""; }; + 9227AEEA2282F6F800FB221F /* BMDuration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BMDuration.h; sourceTree = ""; }; + 9227AEEB2282F6F800FB221F /* BMDuration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BMDuration.m; sourceTree = ""; }; + 9227AEF02282F7A200FB221F /* AddressDurationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressDurationCell.swift; sourceTree = ""; }; + 9227AEF12282F7A200FB221F /* AddressDurationCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressDurationCell.xib; sourceTree = ""; }; 9231E3F7225CC39F00121B33 /* SF-Pro-Display-LightItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Pro-Display-LightItalic.otf"; sourceTree = ""; }; 9231E3F8225CC3A000121B33 /* SF-Pro-Display-RegularItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SF-Pro-Display-RegularItalic.otf"; sourceTree = ""; }; 9232EC952267334900A12EEE /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -862,7 +960,6 @@ 92AB8326223BA921000ADE86 /* ShareLogActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareLogActivity.swift; sourceTree = ""; }; 92AB832C223BC5D4000ADE86 /* TransactionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionViewController.swift; sourceTree = ""; }; 92AB832D223BC5D4000ADE86 /* TransactionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TransactionViewController.xib; sourceTree = ""; }; - 92AC2DEC225F8DA7000272BF /* BMWordSuggestionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BMWordSuggestionView.swift; sourceTree = ""; }; 92ADED802229F213001D0A38 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 92AE366A22383D2300E0810B /* WalletQRCodeScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletQRCodeScannerViewController.swift; sourceTree = ""; }; 92AE366B22383D2300E0810B /* WalletQRCodeScannerViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = WalletQRCodeScannerViewController.xib; sourceTree = ""; }; @@ -881,8 +978,8 @@ 92D3CBD02264AB6D007E3C55 /* BiometricAuthorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricAuthorization.swift; sourceTree = ""; }; 92D9C9472240FB3C00EDE059 /* UTXOBlockCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTXOBlockCell.swift; sourceTree = ""; }; 92D9C9482240FB3C00EDE059 /* UTXOBlockCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UTXOBlockCell.xib; sourceTree = ""; }; - 92D9C94D224188A400EDE059 /* GeneralTransactionInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralTransactionInfoCell.swift; sourceTree = ""; }; - 92D9C94E224188A400EDE059 /* GeneralTransactionInfoCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GeneralTransactionInfoCell.xib; sourceTree = ""; }; + 92D9C94D224188A400EDE059 /* GeneralInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralInfoCell.swift; sourceTree = ""; }; + 92D9C94E224188A400EDE059 /* GeneralInfoCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GeneralInfoCell.xib; sourceTree = ""; }; 92DD900C224A554E0011BE3E /* AddressesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressesViewController.swift; sourceTree = ""; }; 92DD900D224A554E0011BE3E /* AddressesViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddressesViewController.xib; sourceTree = ""; }; 92DD9013224A62B40011BE3E /* AddressCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressCell.swift; sourceTree = ""; }; @@ -1081,6 +1178,7 @@ children = ( 9207FF4F222948F3009D931B /* Configurable.swift */, 92AB8326223BA921000ADE86 /* ShareLogActivity.swift */, + 9219595822823639007E9723 /* LocalizableStrings.swift */, ); path = Protocols; sourceTree = ""; @@ -1096,6 +1194,32 @@ path = Cells; sourceTree = ""; }; + 92227AFD2281B1910070DC68 /* Categories */ = { + isa = PBXGroup; + children = ( + 9227AEB52282CA5C00FB221F /* Cells */, + 92227B062281C28D0070DC68 /* CategoryColorsView.swift */, + 92227AFE2281B1B00070DC68 /* CategoryEditViewController.swift */, + 92227AFF2281B1B00070DC68 /* CategoryEditViewController.xib */, + 9227AEAD2282C80E00FB221F /* CategoryDetailViewController.swift */, + 9227AEAE2282C80E00FB221F /* CategoryDetailViewController.xib */, + 9227AEBE2282D2A000FB221F /* CategoryPickerViewController.swift */, + 9227AEBF2282D2A000FB221F /* CategoryPickerViewController.xib */, + ); + path = Categories; + sourceTree = ""; + }; + 9227AEB52282CA5C00FB221F /* Cells */ = { + isa = PBXGroup; + children = ( + 9227AEB62282CA7700FB221F /* CategoryNameCell.swift */, + 9227AEB72282CA7700FB221F /* CategoryNameCell.xib */, + 9227AEC62282D43700FB221F /* CategoryPickerCell.swift */, + 9227AEC72282D43700FB221F /* CategoryPickerCell.xib */, + ); + path = Cells; + sourceTree = ""; + }; 9232EC972267382A00A12EEE /* FirebaseTestnet */ = { isa = PBXGroup; children = ( @@ -1173,6 +1297,10 @@ 92790D95224CD8AE00F79D64 /* BMContact.m */, 926A8577222EB7C600A3B747 /* BMTransaction.h */, 926A8578222EB7C600A3B747 /* BMTransaction.m */, + 92227AF72281981E0070DC68 /* BMCategory.h */, + 92227AF82281981E0070DC68 /* BMCategory.m */, + 9227AEEA2282F6F800FB221F /* BMDuration.h */, + 9227AEEB2282F6F800FB221F /* BMDuration.m */, ); path = Objects; sourceTree = ""; @@ -1184,6 +1312,7 @@ 92DD900B224A553D0011BE3E /* Addresses */, 92435257222E73EC00A0EF37 /* UTXO */, 92435252222E73DF00A0EF37 /* Settings */, + 92227AFD2281B1910070DC68 /* Categories */, 92F7ADD1225B79CB00D8C46D /* News */, 9243524B222E72B500A0EF37 /* MainTabBarController.swift */, ); @@ -1334,7 +1463,7 @@ 928848012243B66500DFC2AD /* BMCopyLabel.swift */, 92BA7EC222520915002D9367 /* BMTextView.swift */, 92D2AE0D22578D2200642789 /* LockScreen.swift */, - 92AC2DEC225F8DA7000272BF /* BMWordSuggestionView.swift */, + 9219595422821F9C007E9723 /* BMTableHeaderTitleView.swift */, ); path = Controls; sourceTree = ""; @@ -1355,6 +1484,7 @@ 92BA4B7722484DCB0044B721 /* Application.swift */, 92FC933322538CE400555DE1 /* Double.swift */, 92708DDB2272398300B30613 /* URL.swift */, + 9227AEDE2282EADA00FB221F /* TextView.swift */, ); path = Extensions; sourceTree = ""; @@ -1371,6 +1501,8 @@ 926A8566222E7FBD00A3B747 /* Cells */ = { isa = PBXGroup; children = ( + 92D9C94D224188A400EDE059 /* GeneralInfoCell.swift */, + 92D9C94E224188A400EDE059 /* GeneralInfoCell.xib */, 926A8567222E7FD900A3B747 /* WalletStatusCell.swift */, 926A8568222E7FD900A3B747 /* WalletStatusCell.xib */, 926A856D222E97DF00A3B747 /* WalletAvailableCell.swift */, @@ -1444,8 +1576,6 @@ 92BE0E60223BD3FC002BF856 /* Cell */ = { isa = PBXGroup; children = ( - 92D9C94D224188A400EDE059 /* GeneralTransactionInfoCell.swift */, - 92D9C94E224188A400EDE059 /* GeneralTransactionInfoCell.xib */, 92790D9C224E4A1500F79D64 /* TransactionPaymentProofCell.swift */, 92790D9D224E4A1500F79D64 /* TransactionPaymentProofCell.xib */, 92790DA2224E59E800F79D64 /* TransactionUTXOCell.swift */, @@ -1515,6 +1645,8 @@ 92DD901A224A77800011BE3E /* AddressViewController.xib */, 921E21F2224B7F77001E2538 /* EditAddressViewController.swift */, 921E21F3224B7F77001E2538 /* EditAddressViewController.xib */, + 9227AEE22282F54000FB221F /* AddressExpiresPickerViewController.swift */, + 9227AEE32282F54000FB221F /* AddressExpiresPickerViewController.xib */, ); path = Addresses; sourceTree = ""; @@ -1526,10 +1658,16 @@ 92DD9014224A62B40011BE3E /* AddressCell.xib */, 921E21FB224B84A4001E2538 /* AddressSwitchCell.swift */, 921E21FC224B84A4001E2538 /* AddressSwitchCell.xib */, - 921E2201224B870F001E2538 /* AddressExpireCell.swift */, - 921E2202224B870F001E2538 /* AddressExpireCell.xib */, + 921E2201224B870F001E2538 /* AddressExpiresCell.swift */, + 921E2202224B870F001E2538 /* AddressExpiresCell.xib */, + 9227AECE2282E4E700FB221F /* AddressExpiredCell.swift */, + 9227AECF2282E4E700FB221F /* AddressExpiredCell.xib */, 921E2207224B8B8B001E2538 /* AddressCommentCell.swift */, 921E2208224B8B8B001E2538 /* AddressCommentCell.xib */, + 9227AED62282E7F900FB221F /* AddressCategoryCell.swift */, + 9227AED72282E7F900FB221F /* AddressCategoryCell.xib */, + 9227AEF02282F7A200FB221F /* AddressDurationCell.swift */, + 9227AEF12282F7A200FB221F /* AddressDurationCell.xib */, ); path = Cell; sourceTree = ""; @@ -1805,8 +1943,11 @@ buildActionMask = 2147483647; files = ( 92FC610A22294F7D00AEABC1 /* ConfirmPhraseViewController.xib in Resources */, + 9227AEC32282D2A000FB221F /* CategoryPickerViewController.xib in Resources */, + 9227AEB22282C80E00FB221F /* CategoryDetailViewController.xib in Resources */, 926A857D222EC10C00A3B747 /* WalletTransactionCell.xib in Resources */, 9235447F2254D6B700889C74 /* WalletConfirmSendViewController.xib in Resources */, + 9227AEBB2282CA7700FB221F /* CategoryNameCell.xib in Resources */, 92DD901D224A77800011BE3E /* AddressViewController.xib in Resources */, 92790DA6224E59E800F79D64 /* TransactionUTXOCell.xib in Resources */, 92B39D6E2260CB97006D27A5 /* phrases.txt in Resources */, @@ -1818,6 +1959,7 @@ 9232EC982267383700A12EEE /* GoogleService-Info.plist in Resources */, 921E21F6224B7F77001E2538 /* EditAddressViewController.xib in Resources */, 92DD9017224A62B40011BE3E /* AddressCell.xib in Resources */, + 92227B032281B1B00070DC68 /* CategoryEditViewController.xib in Resources */, 921E220B224B8B8B001E2538 /* AddressCommentCell.xib in Resources */, 925AD5E32228254F00DDE66B /* Assets.xcassets in Resources */, 92435251222E73DC00A0EF37 /* WalletViewController.xib in Resources */, @@ -1834,16 +1976,18 @@ 9246C95C2268AC9F00646484 /* EnterNodeAddressViewController.xib in Resources */, 9246F75D227C48830091FB0B /* EmptyCell.xib in Resources */, 92435256222E73E900A0EF37 /* SettingsViewController.xib in Resources */, - 921E2205224B870F001E2538 /* AddressExpireCell.xib in Resources */, + 921E2205224B870F001E2538 /* AddressExpiresCell.xib in Resources */, 92538F62222B5F7E00792A25 /* CreateWalletProgressViewController.xib in Resources */, + 9227AEDB2282E7F900FB221F /* AddressCategoryCell.xib in Resources */, 92790DA0224E4A1500F79D64 /* TransactionPaymentProofCell.xib in Resources */, + 9227AECB2282D43700FB221F /* CategoryPickerCell.xib in Resources */, 921E21FF224B84A4001E2538 /* AddressSwitchCell.xib in Resources */, 92790DAC224E6FDE00F79D64 /* PaymentProofDetailViewController.xib in Resources */, 9207FF4922293FEB009D931B /* DisplayPhraseViewController.xib in Resources */, 92E2EAA3226DFC3B00367928 /* ClearDataViewController.xib in Resources */, 92DD9010224A554E0011BE3E /* AddressesViewController.xib in Resources */, 92E884C6223FADCD0003D6BB /* UTXOCell.xib in Resources */, - 92D9C951224188A400EDE059 /* GeneralTransactionInfoCell.xib in Resources */, + 92D9C951224188A400EDE059 /* GeneralInfoCell.xib in Resources */, 92F7ADD6225B79E000D8C46D /* NewsViewController.xib in Resources */, 929885F4222A15300038C015 /* InputPhraseViewController.xib in Resources */, 92A1B9FC22367717008135B5 /* WalletReceiveViewController.xib in Resources */, @@ -1852,6 +1996,7 @@ 926A8576222EA54F00A3B747 /* WalletProgressCell.xib in Resources */, 92A1BA042236920C008135B5 /* WalletQRCodeViewController.xib in Resources */, 926A8570222E97DF00A3B747 /* WalletAvailableCell.xib in Resources */, + 9227AEF52282F7A200FB221F /* AddressDurationCell.xib in Resources */, 926A856A222E7FD900A3B747 /* WalletStatusCell.xib in Resources */, 9243525B222E73FC00A0EF37 /* UTXOViewController.xib in Resources */, 9231E3F9225CC3A000121B33 /* SF-Pro-Display-LightItalic.otf in Resources */, @@ -1859,9 +2004,11 @@ 9207FF442229336E009D931B /* SF-Pro-Display-Semibold.otf in Resources */, 925AD5F4222827A500DDE66B /* LoginViewController.xib in Resources */, 92E2EB89226F222900367928 /* LaunchScreenMasterNet.storyboard in Resources */, + 9227AED32282E4E700FB221F /* AddressExpiredCell.xib in Resources */, 92FC611D22297EEC00AEABC1 /* CreateWalletPasswordViewController.xib in Resources */, 925AD5F9222829A400DDE66B /* ProximaNova-Bold.ttf in Resources */, 92090D09223A67D400A1CFBB /* LaunchScreenTestNet.storyboard in Resources */, + 9227AEE72282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */, 92F68C802244E77500197D4D /* UTXODetailCell.xib in Resources */, 92090D0C223A684000A1CFBB /* bgTestnet.jpg in Resources */, 9235448B2256019C00889C74 /* UnlockPasswordViewController.xib in Resources */, @@ -1883,8 +2030,11 @@ buildActionMask = 2147483647; files = ( 9288DD76223A55410020C501 /* ConfirmPhraseViewController.xib in Resources */, + 9227AEC42282D2A000FB221F /* CategoryPickerViewController.xib in Resources */, + 9227AEB32282C80E00FB221F /* CategoryDetailViewController.xib in Resources */, 9288DD77223A55410020C501 /* WalletTransactionCell.xib in Resources */, 923544802254D6B700889C74 /* WalletConfirmSendViewController.xib in Resources */, + 9227AEBC2282CA7700FB221F /* CategoryNameCell.xib in Resources */, 92DD901E224A77800011BE3E /* AddressViewController.xib in Resources */, 92790DA7224E59E800F79D64 /* TransactionUTXOCell.xib in Resources */, 92B39D6F2260CB97006D27A5 /* phrases.txt in Resources */, @@ -1896,6 +2046,7 @@ 9288DD7B223A55410020C501 /* InputWordCell.xib in Resources */, 9232EC962267334A00A12EEE /* GoogleService-Info.plist in Resources */, 921E21F7224B7F77001E2538 /* EditAddressViewController.xib in Resources */, + 92227B042281B1B00070DC68 /* CategoryEditViewController.xib in Resources */, 92DD9018224A62B40011BE3E /* AddressCell.xib in Resources */, 921E220C224B8B8B001E2538 /* AddressCommentCell.xib in Resources */, 92E2EA9B226DE5F500367928 /* Localizable.strings in Resources */, @@ -1913,15 +2064,17 @@ 9246F75E227C48830091FB0B /* EmptyCell.xib in Resources */, 92D9C94C2240FB3C00EDE059 /* UTXOBlockCell.xib in Resources */, 9288DD84223A55410020C501 /* SettingsViewController.xib in Resources */, - 921E2206224B870F001E2538 /* AddressExpireCell.xib in Resources */, + 921E2206224B870F001E2538 /* AddressExpiresCell.xib in Resources */, + 9227AEDC2282E7F900FB221F /* AddressCategoryCell.xib in Resources */, 9288DD85223A55410020C501 /* CreateWalletProgressViewController.xib in Resources */, + 9227AECC2282D43700FB221F /* CategoryPickerCell.xib in Resources */, 92790DA1224E4A1500F79D64 /* TransactionPaymentProofCell.xib in Resources */, 921E2200224B84A4001E2538 /* AddressSwitchCell.xib in Resources */, 92790DAD224E6FDE00F79D64 /* PaymentProofDetailViewController.xib in Resources */, 9288DD86223A55410020C501 /* DisplayPhraseViewController.xib in Resources */, 92DD9011224A554E0011BE3E /* AddressesViewController.xib in Resources */, 92E884C7223FADCD0003D6BB /* UTXOCell.xib in Resources */, - 92D9C952224188A400EDE059 /* GeneralTransactionInfoCell.xib in Resources */, + 92D9C952224188A400EDE059 /* GeneralInfoCell.xib in Resources */, 92F7ADD7225B79E000D8C46D /* NewsViewController.xib in Resources */, 9288DD87223A55410020C501 /* InputPhraseViewController.xib in Resources */, 9288DD88223A55410020C501 /* WalletReceiveViewController.xib in Resources */, @@ -1930,6 +2083,7 @@ 9288DD89223A55410020C501 /* WalletProgressCell.xib in Resources */, 9288DD8A223A55410020C501 /* WalletQRCodeViewController.xib in Resources */, 9288DD8B223A55410020C501 /* WalletAvailableCell.xib in Resources */, + 9227AEF62282F7A200FB221F /* AddressDurationCell.xib in Resources */, 9288DD8C223A55410020C501 /* WalletStatusCell.xib in Resources */, 92E2EAA4226DFC3B00367928 /* ClearDataViewController.xib in Resources */, 9288DD8D223A55410020C501 /* UTXOViewController.xib in Resources */, @@ -1937,9 +2091,11 @@ 9288DD8E223A55410020C501 /* ProximaNova-Regular.ttf in Resources */, 9288DD8F223A55410020C501 /* SF-Pro-Display-Semibold.otf in Resources */, 9288DD90223A55410020C501 /* LoginViewController.xib in Resources */, + 9227AED42282E4E700FB221F /* AddressExpiredCell.xib in Resources */, 9288DD91223A55410020C501 /* CreateWalletPasswordViewController.xib in Resources */, 9288DD92223A55410020C501 /* ProximaNova-Bold.ttf in Resources */, 92090D0A223A67D400A1CFBB /* LaunchScreenTestNet.storyboard in Resources */, + 9227AEE82282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */, 92F68C812244E77500197D4D /* UTXODetailCell.xib in Resources */, 92090D0D223A684000A1CFBB /* bgTestnet.jpg in Resources */, 9235448C2256019C00889C74 /* UnlockPasswordViewController.xib in Resources */, @@ -1952,10 +2108,14 @@ files = ( 92E2EB42226F21C700367928 /* ConfirmPhraseViewController.xib in Resources */, 92E2EB43226F21C700367928 /* WalletTransactionCell.xib in Resources */, + 92227B052281B1B00070DC68 /* CategoryEditViewController.xib in Resources */, 9246F75F227C48830091FB0B /* EmptyCell.xib in Resources */, + 9227AEBD2282CA7700FB221F /* CategoryNameCell.xib in Resources */, 92B13272227B2CAC0099B86C /* InfoMasternet.plist in Resources */, + 9227AED52282E4E700FB221F /* AddressExpiredCell.xib in Resources */, 92E2EB44226F21C700367928 /* WalletConfirmSendViewController.xib in Resources */, 92E2EB45226F21C700367928 /* AddressViewController.xib in Resources */, + 9227AEE92282F54000FB221F /* AddressExpiresPickerViewController.xib in Resources */, 92E2EB46226F21C700367928 /* TransactionUTXOCell.xib in Resources */, 92E2EB47226F21C700367928 /* phrases.txt in Resources */, 92E2EB48226F21C700367928 /* LaunchScreen.storyboard in Resources */, @@ -1965,6 +2125,7 @@ 92E2EB4C226F21C700367928 /* InputWordCell.xib in Resources */, 92E2EB4D226F21C700367928 /* GoogleService-Info.plist in Resources */, 92E2EB4E226F21C700367928 /* EditAddressViewController.xib in Resources */, + 9227AEDD2282E7F900FB221F /* AddressCategoryCell.xib in Resources */, 92E2EB4F226F21C700367928 /* AddressCell.xib in Resources */, 92E2EB50226F21C700367928 /* AddressCommentCell.xib in Resources */, 92E2EB51226F21C700367928 /* Localizable.strings in Resources */, @@ -1976,13 +2137,15 @@ 92E2EB56226F21C700367928 /* SF-Pro-Display-Regular.otf in Resources */, 92E2EB57226F21C700367928 /* WordCell.xib in Resources */, 92E2EB58226F21C700367928 /* UTXODetailViewController.xib in Resources */, + 9227AEC52282D2A000FB221F /* CategoryPickerViewController.xib in Resources */, 92E2EB59226F21C700367928 /* UTXOTransactionCell.xib in Resources */, 92E2EB5A226F21C700367928 /* WalletQRCodeScannerViewController.xib in Resources */, 92E2EB5B226F21C700367928 /* SF-Pro-Display-Bold.otf in Resources */, 92E2EB5C226F21C700367928 /* IntroPhraseViewController.xib in Resources */, + 9227AEF72282F7A200FB221F /* AddressDurationCell.xib in Resources */, 92E2EB5D226F21C700367928 /* UTXOBlockCell.xib in Resources */, 92E2EB5E226F21C700367928 /* SettingsViewController.xib in Resources */, - 92E2EB5F226F21C700367928 /* AddressExpireCell.xib in Resources */, + 92E2EB5F226F21C700367928 /* AddressExpiresCell.xib in Resources */, 92E2EB60226F21C700367928 /* CreateWalletProgressViewController.xib in Resources */, 92E2EB61226F21C700367928 /* TransactionPaymentProofCell.xib in Resources */, 92E2EB62226F21C700367928 /* AddressSwitchCell.xib in Resources */, @@ -1991,12 +2154,14 @@ 92E2EB64226F21C700367928 /* DisplayPhraseViewController.xib in Resources */, 92E2EB65226F21C700367928 /* AddressesViewController.xib in Resources */, 92E2EB66226F21C700367928 /* UTXOCell.xib in Resources */, - 92E2EB67226F21C700367928 /* GeneralTransactionInfoCell.xib in Resources */, + 92E2EB67226F21C700367928 /* GeneralInfoCell.xib in Resources */, 92E2EB68226F21C700367928 /* NewsViewController.xib in Resources */, 92E2EB69226F21C700367928 /* InputPhraseViewController.xib in Resources */, 92E2EB6A226F21C700367928 /* WalletReceiveViewController.xib in Resources */, + 9227AEB42282C80E00FB221F /* CategoryDetailViewController.xib in Resources */, 92E2EB6B226F21C700367928 /* SFProText-Semibold.otf in Resources */, 92E2EB6C226F21C700367928 /* TransactionViewController.xib in Resources */, + 9227AECD2282D43700FB221F /* CategoryPickerCell.xib in Resources */, 92E2EB6D226F21C700367928 /* WalletProgressCell.xib in Resources */, 92E2EB6E226F21C700367928 /* WalletQRCodeViewController.xib in Resources */, 92E2EB6F226F21C700367928 /* WalletAvailableCell.xib in Resources */, @@ -2264,6 +2429,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9227AEC02282D2A000FB221F /* CategoryPickerViewController.swift in Sources */, 92FC611022295DC100AEABC1 /* BMWordField.swift in Sources */, 926A8579222EB7C600A3B747 /* BMTransaction.m in Sources */, 92365AD1222D3E79000D7064 /* AppModel.mm in Sources */, @@ -2271,20 +2437,23 @@ 92482DFF2237F69700776D38 /* WalletSendViewController.swift in Sources */, 92FC9331225371D400555DE1 /* DiskStatusManager.m in Sources */, 92BA7EC322520915002D9367 /* BMTextView.swift in Sources */, + 9219595522821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */, 92D2AE0E22578D2200642789 /* LockScreen.swift in Sources */, 92708DCF2271B2ED00B30613 /* TGBotManager.swift in Sources */, 92FC611F2229803700AEABC1 /* BMField.swift in Sources */, 929885F8222B32C40038C015 /* Field.swift in Sources */, 926A8575222EA54F00A3B747 /* WalletProgressCell.swift in Sources */, + 92227B002281B1B00070DC68 /* CategoryEditViewController.swift in Sources */, 925AD6032228332A00DDE66B /* Button.swift in Sources */, 92DD9015224A62B40011BE3E /* AddressCell.swift in Sources */, + 92227AF92281981E0070DC68 /* BMCategory.m in Sources */, 92365ADB222D3F5E000D7064 /* Settings.m in Sources */, 926A856F222E97DF00A3B747 /* WalletAvailableCell.swift in Sources */, 92FC611C22297EEC00AEABC1 /* CreateWalletPasswordViewController.swift in Sources */, 92708DD82271FA5100B30613 /* SettingsViewModel.swift in Sources */, - 92AC2DED225F8DA7000272BF /* BMWordSuggestionView.swift in Sources */, 9235447D2254D6B700889C74 /* WalletConfirmSendViewController.swift in Sources */, 92D9C9492240FB3C00EDE059 /* UTXOBlockCell.swift in Sources */, + 9227AED02282E4E700FB221F /* AddressExpiredCell.swift in Sources */, 92435243222DED3200A0EF37 /* BMWalletStatus.m in Sources */, 92FC610D22295A6E00AEABC1 /* InputWordCell.swift in Sources */, 9288DD9F223A55DF0020C501 /* BaseViewController.swift in Sources */, @@ -2294,14 +2463,17 @@ 9243525A222E73FC00A0EF37 /* UTXOViewController.swift in Sources */, 92435250222E73DC00A0EF37 /* WalletViewController.swift in Sources */, 92F68C7E2244E77500197D4D /* UTXODetailCell.swift in Sources */, + 9227AED82282E7F900FB221F /* AddressCategoryCell.swift in Sources */, 92790D9A224E41E800F79D64 /* BMPaymentProof.m in Sources */, 925AD5FF22282AB500DDE66B /* View.swift in Sources */, 92538F61222B5F7E00792A25 /* CreateWalletProgressViewController.swift in Sources */, 92592CA52245296D00050A13 /* KeychainManager.swift in Sources */, 9207FF4822293FEB009D931B /* DisplayPhraseViewController.swift in Sources */, + 9219595922823639007E9723 /* LocalizableStrings.swift in Sources */, 92FC6121222990FE00AEABC1 /* BMStepView.swift in Sources */, 92FC61262229C0C200AEABC1 /* BaseWizardViewController.swift in Sources */, 92365AD3222D3E79000D7064 /* WalletModel.mm in Sources */, + 9227AEAF2282C80E00FB221F /* CategoryDetailViewController.swift in Sources */, 925AD5F3222827A500DDE66B /* LoginViewController.swift in Sources */, 923544832255F45B00889C74 /* SettingsCell.swift in Sources */, 92E884B9223F93FF0003D6BB /* BMUTXO.m in Sources */, @@ -2311,22 +2483,28 @@ 925AD5DC2228254E00DDE66B /* AppDelegate.swift in Sources */, 921E2209224B8B8B001E2538 /* AddressCommentCell.swift in Sources */, 929885F6222B2B1F0038C015 /* Label.swift in Sources */, - 92D9C94F224188A400EDE059 /* GeneralTransactionInfoCell.swift in Sources */, - 921E2203224B870F001E2538 /* AddressExpireCell.swift in Sources */, + 92D9C94F224188A400EDE059 /* GeneralInfoCell.swift in Sources */, + 921E2203224B870F001E2538 /* AddressExpiresCell.swift in Sources */, 92E884C4223FADCD0003D6BB /* UTXOCell.swift in Sources */, 92AE366F223845E300E0810B /* BMNetworkStatusView.swift in Sources */, 92A1BA032236920C008135B5 /* WalletQRCodeViewController.swift in Sources */, + 9227AEE42282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */, + 92227B072281C28D0070DC68 /* CategoryColorsView.swift in Sources */, 925AD5FC22282A7F00DDE66B /* BMButton.swift in Sources */, 92FC610922294F7D00AEABC1 /* ConfirmPhraseViewController.swift in Sources */, 92FC6118222978C400AEABC1 /* PasswordManager.swift in Sources */, 92DD901B224A77800011BE3E /* AddressViewController.swift in Sources */, 92FC612322299A4E00AEABC1 /* Device.swift in Sources */, + 9227AEEC2282F6F800FB221F /* BMDuration.m in Sources */, 926A8569222E7FD900A3B747 /* WalletStatusCell.swift in Sources */, + 9227AEB82282CA7700FB221F /* CategoryNameCell.swift in Sources */, 92E2EAA1226DFC3B00367928 /* ClearDataViewController.swift in Sources */, 92FC611522296F2700AEABC1 /* Color.swift in Sources */, + 9227AEC82282D43700FB221F /* CategoryPickerCell.swift in Sources */, 92708DDC2272398300B30613 /* URL.swift in Sources */, 92790D9E224E4A1500F79D64 /* TransactionPaymentProofCell.swift in Sources */, 921E21F4224B7F77001E2538 /* EditAddressViewController.swift in Sources */, + 9227AEDF2282EADA00FB221F /* TextView.swift in Sources */, 92592CA82245309B00050A13 /* NotificationManager.swift in Sources */, 92F68C8D2245070200197D4D /* UTXOTransactionCell.swift in Sources */, 921E21FD224B84A4001E2538 /* AddressSwitchCell.swift in Sources */, @@ -2338,6 +2516,7 @@ 92BA4B7822484DCB0044B721 /* Application.swift in Sources */, 923544892256019C00889C74 /* UnlockPasswordViewController.swift in Sources */, 9288DDA2223A5A550020C501 /* BaseCell.swift in Sources */, + 9227AEF22282F7A200FB221F /* AddressDurationCell.swift in Sources */, 92A1BA0622369567008135B5 /* QRCodeView.swift in Sources */, 9288DDA5223A5B430020C501 /* BaseView.swift in Sources */, 926A8580222ECD7600A3B747 /* Reachability.m in Sources */, @@ -2380,6 +2559,7 @@ 92C4DBCB227879AE0073AEED /* StringStd.mm in Sources */, 927367272277AB340060CB67 /* NotificationViewController.swift in Sources */, 92C4DBD522788E430073AEED /* Button.swift in Sources */, + 9227AEEF2282F6F800FB221F /* BMDuration.m in Sources */, 9273674E2277C4FD0060CB67 /* String.swift in Sources */, 92C4DBCD227879AE0073AEED /* WalletModel.mm in Sources */, 9273674A2277BFE60060CB67 /* KeychainManager.swift in Sources */, @@ -2389,9 +2569,11 @@ 92C4DBC7227879AE0073AEED /* BMUTXO.m in Sources */, 921FA633227C3BB6008E80A3 /* CurrencyFormatter.m in Sources */, 92C4DBC8227879AE0073AEED /* BMPaymentProof.m in Sources */, + 9219595C22823639007E9723 /* LocalizableStrings.swift in Sources */, 92C4DBC6227879AE0073AEED /* BMAddress.mm in Sources */, 92C4DBC9227879AE0073AEED /* BMContact.m in Sources */, 92C4DBD322787AB80073AEED /* NotificationManager.swift in Sources */, + 92227AFC2281981E0070DC68 /* BMCategory.m in Sources */, 92C4DBD0227879AE0073AEED /* MnemonicModel.mm in Sources */, 92C4DBD2227879AE0073AEED /* DiskStatusManager.m in Sources */, 92C4DBD1227879AE0073AEED /* Reachability.m in Sources */, @@ -2402,6 +2584,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9227AEC12282D2A000FB221F /* CategoryPickerViewController.swift in Sources */, 9288DD2D223A55410020C501 /* BMWordField.swift in Sources */, 9288DD2E223A55410020C501 /* BMTransaction.m in Sources */, 9288DD2F223A55410020C501 /* AppModel.mm in Sources */, @@ -2409,20 +2592,23 @@ 9288DD31223A55410020C501 /* WalletSendViewController.swift in Sources */, 92FC9332225371D400555DE1 /* DiskStatusManager.m in Sources */, 92BA7EC422520915002D9367 /* BMTextView.swift in Sources */, + 9219595622821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */, 92D2AE0F22578D2200642789 /* LockScreen.swift in Sources */, 92708DD02271B2ED00B30613 /* TGBotManager.swift in Sources */, 9288DD32223A55410020C501 /* BMField.swift in Sources */, 9288DD34223A55410020C501 /* Field.swift in Sources */, 9288DD35223A55410020C501 /* WalletProgressCell.swift in Sources */, + 92227B012281B1B00070DC68 /* CategoryEditViewController.swift in Sources */, 9288DD36223A55410020C501 /* Button.swift in Sources */, 92DD9016224A62B40011BE3E /* AddressCell.swift in Sources */, + 92227AFA2281981E0070DC68 /* BMCategory.m in Sources */, 9288DD37223A55410020C501 /* Settings.m in Sources */, 9288DD38223A55410020C501 /* WalletAvailableCell.swift in Sources */, 9288DD39223A55410020C501 /* CreateWalletPasswordViewController.swift in Sources */, 92708DD92271FA5100B30613 /* SettingsViewModel.swift in Sources */, - 92AC2DEE225F8DA7000272BF /* BMWordSuggestionView.swift in Sources */, 9235447E2254D6B700889C74 /* WalletConfirmSendViewController.swift in Sources */, 92D9C94A2240FB3C00EDE059 /* UTXOBlockCell.swift in Sources */, + 9227AED12282E4E700FB221F /* AddressExpiredCell.swift in Sources */, 9288DD3A223A55410020C501 /* BMWalletStatus.m in Sources */, 9288DD3B223A55410020C501 /* InputWordCell.swift in Sources */, 9288DDA0223A56920020C501 /* BaseViewController.swift in Sources */, @@ -2432,14 +2618,17 @@ 9288DD3D223A55410020C501 /* UTXOViewController.swift in Sources */, 9288DD3E223A55410020C501 /* WalletViewController.swift in Sources */, 92F68C7F2244E77500197D4D /* UTXODetailCell.swift in Sources */, + 9227AED92282E7F900FB221F /* AddressCategoryCell.swift in Sources */, 92790D9B224E41E800F79D64 /* BMPaymentProof.m in Sources */, 9288DD3F223A55410020C501 /* View.swift in Sources */, 9288DD40223A55410020C501 /* CreateWalletProgressViewController.swift in Sources */, 92592CA62245296D00050A13 /* KeychainManager.swift in Sources */, 9288DD41223A55410020C501 /* DisplayPhraseViewController.swift in Sources */, + 9219595A22823639007E9723 /* LocalizableStrings.swift in Sources */, 9288DD42223A55410020C501 /* BMStepView.swift in Sources */, 9288DD43223A55410020C501 /* BaseWizardViewController.swift in Sources */, 9288DD44223A55410020C501 /* WalletModel.mm in Sources */, + 9227AEB02282C80E00FB221F /* CategoryDetailViewController.swift in Sources */, 9288DD45223A55410020C501 /* LoginViewController.swift in Sources */, 923544842255F45B00889C74 /* SettingsCell.swift in Sources */, 92E884BA223F93FF0003D6BB /* BMUTXO.m in Sources */, @@ -2449,22 +2638,28 @@ 9288DD47223A55410020C501 /* AppDelegate.swift in Sources */, 921E220A224B8B8B001E2538 /* AddressCommentCell.swift in Sources */, 9288DD48223A55410020C501 /* Label.swift in Sources */, - 92D9C950224188A400EDE059 /* GeneralTransactionInfoCell.swift in Sources */, - 921E2204224B870F001E2538 /* AddressExpireCell.swift in Sources */, + 92D9C950224188A400EDE059 /* GeneralInfoCell.swift in Sources */, + 921E2204224B870F001E2538 /* AddressExpiresCell.swift in Sources */, 92E884C5223FADCD0003D6BB /* UTXOCell.swift in Sources */, 9288DD49223A55410020C501 /* BMNetworkStatusView.swift in Sources */, 9288DD4B223A55410020C501 /* WalletQRCodeViewController.swift in Sources */, + 9227AEE52282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */, + 92227B082281C28D0070DC68 /* CategoryColorsView.swift in Sources */, 9288DD4C223A55410020C501 /* BMButton.swift in Sources */, 9288DD4D223A55410020C501 /* ConfirmPhraseViewController.swift in Sources */, 9288DD4E223A55410020C501 /* PasswordManager.swift in Sources */, 92DD901C224A77800011BE3E /* AddressViewController.swift in Sources */, 9288DD4F223A55410020C501 /* Device.swift in Sources */, + 9227AEED2282F6F800FB221F /* BMDuration.m in Sources */, 9288DD50223A55410020C501 /* WalletStatusCell.swift in Sources */, + 9227AEB92282CA7700FB221F /* CategoryNameCell.swift in Sources */, 92E2EAA2226DFC3B00367928 /* ClearDataViewController.swift in Sources */, 9288DD51223A55410020C501 /* Color.swift in Sources */, + 9227AEC92282D43700FB221F /* CategoryPickerCell.swift in Sources */, 92708DDD2272398300B30613 /* URL.swift in Sources */, 92790D9F224E4A1500F79D64 /* TransactionPaymentProofCell.swift in Sources */, 921E21F5224B7F77001E2538 /* EditAddressViewController.swift in Sources */, + 9227AEE02282EADA00FB221F /* TextView.swift in Sources */, 92592CA92245309B00050A13 /* NotificationManager.swift in Sources */, 92F68C8E2245070200197D4D /* UTXOTransactionCell.swift in Sources */, 921E21FE224B84A4001E2538 /* AddressSwitchCell.swift in Sources */, @@ -2476,6 +2671,7 @@ 92BA4B7922484DCB0044B721 /* Application.swift in Sources */, 9235448A2256019C00889C74 /* UnlockPasswordViewController.swift in Sources */, 9288DDA3223A5A550020C501 /* BaseCell.swift in Sources */, + 9227AEF32282F7A200FB221F /* AddressDurationCell.swift in Sources */, 9288DD54223A55410020C501 /* QRCodeView.swift in Sources */, 9288DDA6223A5B430020C501 /* BaseView.swift in Sources */, 9288DD55223A55410020C501 /* Reachability.m in Sources */, @@ -2510,6 +2706,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 9227AEC22282D2A000FB221F /* CategoryPickerViewController.swift in Sources */, 92E2EAD0226F21C700367928 /* BMWordField.swift in Sources */, 92E2EAD1226F21C700367928 /* BMTransaction.m in Sources */, 92E2EAD2226F21C700367928 /* AppModel.mm in Sources */, @@ -2517,20 +2714,23 @@ 92E2EAD4226F21C700367928 /* WalletSendViewController.swift in Sources */, 92E2EAD5226F21C700367928 /* DiskStatusManager.m in Sources */, 92E2EAD6226F21C700367928 /* BMTextView.swift in Sources */, + 9219595722821F9C007E9723 /* BMTableHeaderTitleView.swift in Sources */, 92E2EAD7226F21C700367928 /* LockScreen.swift in Sources */, 92708DD12271B2ED00B30613 /* TGBotManager.swift in Sources */, 92E2EAD8226F21C700367928 /* BMField.swift in Sources */, 92E2EAD9226F21C700367928 /* Field.swift in Sources */, 92E2EADA226F21C700367928 /* WalletProgressCell.swift in Sources */, + 92227B022281B1B00070DC68 /* CategoryEditViewController.swift in Sources */, 92E2EADB226F21C700367928 /* Button.swift in Sources */, 92E2EADC226F21C700367928 /* AddressCell.swift in Sources */, + 92227AFB2281981E0070DC68 /* BMCategory.m in Sources */, 92E2EADD226F21C700367928 /* Settings.m in Sources */, 92E2EADE226F21C700367928 /* WalletAvailableCell.swift in Sources */, 92E2EADF226F21C700367928 /* CreateWalletPasswordViewController.swift in Sources */, 92708DDA2271FA5100B30613 /* SettingsViewModel.swift in Sources */, - 92E2EAE0226F21C700367928 /* BMWordSuggestionView.swift in Sources */, 92E2EAE1226F21C700367928 /* WalletConfirmSendViewController.swift in Sources */, 92E2EAE2226F21C700367928 /* UTXOBlockCell.swift in Sources */, + 9227AED22282E4E700FB221F /* AddressExpiredCell.swift in Sources */, 92E2EAE3226F21C700367928 /* BMWalletStatus.m in Sources */, 92E2EAE4226F21C700367928 /* InputWordCell.swift in Sources */, 92E2EAE5226F21C700367928 /* BaseViewController.swift in Sources */, @@ -2540,14 +2740,17 @@ 92E2EAE8226F21C700367928 /* UTXOViewController.swift in Sources */, 92E2EAE9226F21C700367928 /* WalletViewController.swift in Sources */, 92E2EAEA226F21C700367928 /* UTXODetailCell.swift in Sources */, + 9227AEDA2282E7F900FB221F /* AddressCategoryCell.swift in Sources */, 92E2EAEB226F21C700367928 /* BMPaymentProof.m in Sources */, 92E2EAEC226F21C700367928 /* View.swift in Sources */, 92E2EAED226F21C700367928 /* CreateWalletProgressViewController.swift in Sources */, 92E2EAEE226F21C700367928 /* KeychainManager.swift in Sources */, 92E2EAEF226F21C700367928 /* DisplayPhraseViewController.swift in Sources */, + 9219595B22823639007E9723 /* LocalizableStrings.swift in Sources */, 92E2EAF0226F21C700367928 /* BMStepView.swift in Sources */, 92E2EAF1226F21C700367928 /* BaseWizardViewController.swift in Sources */, 92E2EAF2226F21C700367928 /* WalletModel.mm in Sources */, + 9227AEB12282C80E00FB221F /* CategoryDetailViewController.swift in Sources */, 92E2EAF3226F21C700367928 /* LoginViewController.swift in Sources */, 92E2EAF4226F21C700367928 /* SettingsCell.swift in Sources */, 92E2EAF5226F21C700367928 /* BMUTXO.m in Sources */, @@ -2557,22 +2760,28 @@ 92E2EAF9226F21C700367928 /* AppDelegate.swift in Sources */, 92E2EAFA226F21C700367928 /* AddressCommentCell.swift in Sources */, 92E2EAFB226F21C700367928 /* Label.swift in Sources */, - 92E2EAFC226F21C700367928 /* GeneralTransactionInfoCell.swift in Sources */, - 92E2EAFD226F21C700367928 /* AddressExpireCell.swift in Sources */, + 92E2EAFC226F21C700367928 /* GeneralInfoCell.swift in Sources */, + 92E2EAFD226F21C700367928 /* AddressExpiresCell.swift in Sources */, 92E2EAFE226F21C700367928 /* UTXOCell.swift in Sources */, 92E2EAFF226F21C700367928 /* BMNetworkStatusView.swift in Sources */, 92E2EB00226F21C700367928 /* WalletQRCodeViewController.swift in Sources */, + 9227AEE62282F54000FB221F /* AddressExpiresPickerViewController.swift in Sources */, + 92227B092281C28D0070DC68 /* CategoryColorsView.swift in Sources */, 92E2EB01226F21C700367928 /* BMButton.swift in Sources */, 92E2EB02226F21C700367928 /* ConfirmPhraseViewController.swift in Sources */, 92E2EB03226F21C700367928 /* PasswordManager.swift in Sources */, 92E2EB04226F21C700367928 /* AddressViewController.swift in Sources */, 92E2EB05226F21C700367928 /* Device.swift in Sources */, + 9227AEEE2282F6F800FB221F /* BMDuration.m in Sources */, 92E2EB06226F21C700367928 /* WalletStatusCell.swift in Sources */, + 9227AEBA2282CA7700FB221F /* CategoryNameCell.swift in Sources */, 92E2EB07226F21C700367928 /* ClearDataViewController.swift in Sources */, 92E2EB08226F21C700367928 /* Color.swift in Sources */, + 9227AECA2282D43700FB221F /* CategoryPickerCell.swift in Sources */, 92708DDE2272398300B30613 /* URL.swift in Sources */, 92E2EB09226F21C700367928 /* TransactionPaymentProofCell.swift in Sources */, 92E2EB0A226F21C700367928 /* EditAddressViewController.swift in Sources */, + 9227AEE12282EADA00FB221F /* TextView.swift in Sources */, 92E2EB0B226F21C700367928 /* NotificationManager.swift in Sources */, 92E2EB0C226F21C700367928 /* UTXOTransactionCell.swift in Sources */, 92E2EB0D226F21C700367928 /* AddressSwitchCell.swift in Sources */, @@ -2584,6 +2793,7 @@ 92E2EB13226F21C700367928 /* Application.swift in Sources */, 92E2EB14226F21C700367928 /* UnlockPasswordViewController.swift in Sources */, 92E2EB15226F21C700367928 /* BaseCell.swift in Sources */, + 9227AEF42282F7A200FB221F /* AddressDurationCell.swift in Sources */, 92E2EB16226F21C700367928 /* QRCodeView.swift in Sources */, 92E2EB17226F21C700367928 /* BaseView.swift in Sources */, 92E2EB18226F21C700367928 /* Reachability.m in Sources */, diff --git a/BeamWallet/AppDelegate.swift b/BeamWallet/AppDelegate.swift index f51f7ea0..36903278 100644 --- a/BeamWallet/AppDelegate.swift +++ b/BeamWallet/AppDelegate.swift @@ -131,23 +131,18 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } private func tryLinkingBot(url:URL) { - if let params = url.queryParameters { - if let id = params["user_id"], let name = params["username"] { - TGBotManager.sharedManager.user.userId = id - TGBotManager.sharedManager.user.userName = name - - if AppModel.sharedManager().isLoggedin { - TGBotManager.sharedManager.startLinking { (_ ) in - - } + if TGBotManager.sharedManager.isValidUserFromUrl(url: url) { + if AppModel.sharedManager().isLoggedin { + TGBotManager.sharedManager.startLinking { (_ ) in + } - else{ - if let vc = UIApplication.getTopMostViewController() { - vc.alert(title: "Telegram bot", message: "Please open wallet to link telegram bot") { (_ ) in - - if let passVC = UIApplication.getTopMostViewController() as? EnterWalletPasswordViewController { - passVC.biometricAuthorization() - } + } + else{ + if let vc = UIApplication.getTopMostViewController() { + vc.alert(title: "Telegram bot", message: "Please open wallet to link telegram bot") { (_ ) in + + if let passVC = UIApplication.getTopMostViewController() as? EnterWalletPasswordViewController { + passVC.biometricAuthorization() } } } @@ -159,12 +154,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if let url = userActivity.webpageURL { if ((UIApplication.getTopMostViewController() as? EnterWalletPasswordViewController) != nil) { - if let params = url.queryParameters { - if let id = params["user_id"], let name = params["username"] { - TGBotManager.sharedManager.user.userId = id - TGBotManager.sharedManager.user.userName = name - } - } + _ = TGBotManager.sharedManager.isValidUserFromUrl(url: url) } else{ tryLinkingBot(url: url) diff --git a/BeamWallet/BeamSDK/AppModel.h b/BeamWallet/BeamSDK/AppModel.h index bb5a9764..e1296a7b 100644 --- a/BeamWallet/BeamSDK/AppModel.h +++ b/BeamWallet/BeamSDK/AppModel.h @@ -25,6 +25,8 @@ #import "BMContact.h" #import "BMPaymentProof.h" #import "Settings.h" +#import "BMCategory.h" +#import "BMDuration.h" @protocol WalletModelDelegate @optional @@ -42,6 +44,7 @@ -(void)onContactsChange:(NSArray*_Nonnull)contacts; -(void)onReceivePaymentProof:(BMPaymentProof*_Nonnull)proof; -(void)onLocalNodeStarted; +-(void)onCategoriesChange; @end @interface AppModel : NSObject @@ -63,6 +66,7 @@ @property (nonatomic,strong) NSMutableArray*_Nullable utxos; @property (nonatomic,strong) NSMutableArray*_Nullable walletAddresses; @property (nonatomic,strong) NSMutableArray*_Nonnull contacts; +@property (nonatomic,strong) NSMutableArray*_Nonnull categories; +(AppModel*_Nonnull)sharedManager; @@ -103,7 +107,6 @@ -(void)deleteAddress:(NSString*_Nullable)address; -(BOOL)isValidAddress:(NSString*_Nullable)address; -(BOOL)isExpiredAddress:(NSString*_Nullable)address; --(BOOL)isAddressDeleted:(NSString*_Nullable)address; -(BOOL)isMyAddress:(NSString*_Nullable)address; -(void)clearAllAddresses; @@ -137,4 +140,13 @@ -(BMContact*_Nullable)getContactFromId:(NSString*_Nonnull)idValue; -(void)clearAllContacts; +//categories +-(void)deleteCategory:(BMCategory*_Nonnull)category; +-(void)editCategory:(BMCategory*_Nonnull)category; +-(void)addCategory:(BMCategory*_Nonnull)category; +-(BOOL)isNameAlreadyExist:(NSString*_Nonnull)name id:(int)ID; +-(BMCategory*_Nullable)findCategoryById:(NSString*_Nonnull)ID; +-(BMCategory*_Nullable)findCategoryByAddress:(NSString*_Nonnull)ID; +-(NSMutableArray*_Nonnull)getAddressFromCategory:(BMCategory*_Nonnull)category; + @end diff --git a/BeamWallet/BeamSDK/AppModel.mm b/BeamWallet/BeamSDK/AppModel.mm index 6f3491b8..19a51270 100644 --- a/BeamWallet/BeamSDK/AppModel.mm +++ b/BeamWallet/BeamSDK/AppModel.mm @@ -54,7 +54,7 @@ using namespace beam::io; static int proofSize = 330; -static NSString *deletedAddressesKEY = @"deletedAddresses"; +static NSString *categoriesKey = @"categoriesKey"; @implementation AppModel { BOOL isStarted; @@ -96,6 +96,8 @@ -(id)init{ _contacts = [[NSMutableArray alloc] init]; + _categories = [[NSMutableArray alloc] initWithArray:[self allCategories]]; + [self checkInternetConnection]; [[NSNotificationCenter defaultCenter] addObserver:self @@ -652,17 +654,6 @@ -(void)deleteAddress:(NSString*_Nullable)address { } } --(BOOL)isAddressDeleted:(NSString*_Nullable)address { - NSMutableArray *deletedAddresses = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults]objectForKey:deletedAddressesKEY]]; - - for (NSString *a in deletedAddresses) { - if ([a isEqualToString:address]){ - return YES; - } - } - - return NO; -} -(void)generateNewWalletAddress { wallet->getAsync()->generateNewAddress(); @@ -704,10 +695,27 @@ -(void)generateNewWalletAddress { } -(void)editAddress:(BMAddress*_Nonnull)address { - WalletID walletID(Zero); if (walletID.FromHex(address.walletId.string)) { + std::vector addresses = walletDb->getAddresses(true); + + for (int i=0; igetAsync()->saveAddress(addresses[i], true); + + break; + } + } + if(address.isNowExpired) { wallet->getAsync()->saveAddressChanges(walletID, address.label.string, false, false, true); } @@ -723,8 +731,8 @@ -(void)editAddress:(BMAddress*_Nonnull)address { if (address.isExpired) { wallet->getAsync()->saveAddressChanges(walletID, address.label.string, false, false, true); } - else{ - wallet->getAsync()->saveAddressChanges(walletID, address.label.string, (address.duration == 0 ? true : false), true, false); + else { + wallet->getAsync()->saveAddressChanges(walletID, address.label.string, (address.duration == 0 ? true : false), address.isChangedDate ? true : false, false); } } } @@ -1133,9 +1141,138 @@ -(BMContact*_Nullable)getContactFromId:(NSString*_Nonnull)idValue { } -(void)clearAllContacts{ + for (BMContact *contact in _contacts) { [self deleteAddress:contact.address.walletId]; } } + +#pragma mark - Categories + +-(BMCategory*_Nullable)findCategoryById:(NSString*)ID { + if (ID.isEmpty) { + return nil; + } + + for (int i=0; i<_categories.count; i++) { + if (_categories[i].ID == ID.intValue) { + return _categories[i]; + } + } + + return nil; +} + +-(BMCategory*_Nullable)findCategoryByAddress:(NSString*_Nonnull)ID { + if (ID.isEmpty) { + return nil; + } + for (BMAddress *address in _walletAddresses) { + if ([address.walletId isEqualToString:ID]) { + return [self findCategoryById:address.category]; + } + } + + return nil; +} + +-(NSUInteger)findCategoryIndex:(int)ID { + for (int i=0; i<_categories.count; i++) { + if (_categories[i].ID == ID) { + return i; + } + } + + return 0; +} + +-(NSMutableArray*_Nonnull)allCategories{ + if ([[NSUserDefaults standardUserDefaults] objectForKey:categoriesKey]) { + NSData *data = [[NSUserDefaults standardUserDefaults] dataForKey:categoriesKey]; + + NSMutableArray *array = [NSMutableArray arrayWithArray:[NSKeyedUnarchiver unarchiveObjectWithData:data]]; + + return array; + } + + return @[].mutableCopy; +} + +-(void)deleteCategory:(BMCategory*_Nonnull)category { + [_categories removeObjectAtIndex:[self findCategoryIndex:category.ID]]; + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_categories]; + [[NSUserDefaults standardUserDefaults] setObject:data forKey:categoriesKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + for(id delegate in [AppModel sharedManager].delegates) + { + if ([delegate respondsToSelector:@selector(onCategoriesChange)]) { + [delegate onCategoriesChange]; + } + } +} + +-(void)editCategory:(BMCategory*_Nonnull)category { + NSUInteger index = [self findCategoryIndex:category.ID]; + + [_categories replaceObjectAtIndex:index withObject:category]; + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_categories]; + [[NSUserDefaults standardUserDefaults] setObject:data forKey:categoriesKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + for(id delegate in [AppModel sharedManager].delegates) + { + if ([delegate respondsToSelector:@selector(onCategoriesChange)]) { + [delegate onCategoriesChange]; + } + } +} + +-(void)addCategory:(BMCategory*_Nonnull)category { + [_categories addObject:category]; + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:_categories]; + [[NSUserDefaults standardUserDefaults] setObject:data forKey:categoriesKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + for(id delegate in [AppModel sharedManager].delegates) + { + if ([delegate respondsToSelector:@selector(onCategoriesChange)]) { + [delegate onCategoriesChange]; + } + } +} + +-(BOOL)isNameAlreadyExist:(NSString*_Nonnull)name id:(int)ID{ + for(BMCategory *category in _categories) { + if (ID == 0) { + if ([category.name isEqualToString:name]) { + return YES; + } + } + else{ + if ([category.name isEqualToString:name] && category.ID != ID) { + return YES; + } + } + } + + return NO; +} + +-(NSMutableArray*_Nonnull)getAddressFromCategory:(BMCategory*_Nonnull)category { + NSMutableArray *addresses = [NSMutableArray array]; + + for (BMAddress *address in _walletAddresses) { + if (address.category.intValue == category.ID) { + [addresses addObject:address]; + } + } + + return addresses; +} + @end diff --git a/BeamWallet/BeamSDK/Objects/BMAddress.h b/BeamWallet/BeamSDK/Objects/BMAddress.h index d1cf2f1c..145e5c7c 100644 --- a/BeamWallet/BeamSDK/Objects/BMAddress.h +++ b/BeamWallet/BeamSDK/Objects/BMAddress.h @@ -34,6 +34,7 @@ @property (nonatomic,assign) BOOL isNowExpired; @property (nonatomic,assign) BOOL isNowActive; @property (nonatomic,assign) UInt64 isNowActiveDuration; +@property (nonatomic,assign) BOOL isChangedDate; -(BOOL)isExpired; -(UInt64)getExpirationTime; diff --git a/BeamWallet/BeamSDK/Objects/BMCategory.h b/BeamWallet/BeamSDK/Objects/BMCategory.h new file mode 100644 index 00000000..ce5f0567 --- /dev/null +++ b/BeamWallet/BeamSDK/Objects/BMCategory.h @@ -0,0 +1,29 @@ +// +// BMCategory.h +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + + +@interface BMCategory : NSObject + +@property (nonatomic,strong) NSString * _Nonnull name; +@property (nonatomic,strong) NSString * _Nonnull color; +@property (nonatomic,assign) int ID; + +@end diff --git a/BeamWallet/BeamSDK/Objects/BMCategory.m b/BeamWallet/BeamSDK/Objects/BMCategory.m new file mode 100644 index 00000000..4129d1f4 --- /dev/null +++ b/BeamWallet/BeamSDK/Objects/BMCategory.m @@ -0,0 +1,43 @@ +// +// BMCategory.m +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "BMCategory.h" + +@implementation BMCategory + +- (void)encodeWithCoder:(NSCoder *)encoder +{ + [encoder encodeObject:[NSNumber numberWithInt:self.ID] forKey: @"ID"]; + [encoder encodeObject:self.name forKey: @"name"]; + [encoder encodeObject:self.color forKey: @"color"]; +} + +-(id)initWithCoder:(NSCoder *)decoder +{ + self = [super init]; + if(self) + { + self.ID = [[decoder decodeObjectForKey: @"ID"] intValue]; + self.name = [decoder decodeObjectForKey: @"name"]; + self.color = [decoder decodeObjectForKey:@"color"]; + } + return self; +} + +@end diff --git a/BeamWallet/BeamSDK/Objects/BMDuration.h b/BeamWallet/BeamSDK/Objects/BMDuration.h new file mode 100644 index 00000000..a1dcb20d --- /dev/null +++ b/BeamWallet/BeamSDK/Objects/BMDuration.h @@ -0,0 +1,28 @@ +// +// BMDuration.h +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +#import + + +@interface BMDuration : NSObject + +@property (nonatomic,strong) NSString * _Nonnull name; +@property (nonatomic,assign) int duration; + +@end + diff --git a/BeamWallet/Controls/BMWordSuggestionView.swift b/BeamWallet/BeamSDK/Objects/BMDuration.m similarity index 86% rename from BeamWallet/Controls/BMWordSuggestionView.swift rename to BeamWallet/BeamSDK/Objects/BMDuration.m index ce3a2976..4386e1f2 100644 --- a/BeamWallet/Controls/BMWordSuggestionView.swift +++ b/BeamWallet/BeamSDK/Objects/BMDuration.m @@ -1,5 +1,5 @@ // -// BMWordSuggestionView.swift +// BMDuration.m // BeamWallet // // Copyright 2018 Beam Development @@ -17,8 +17,8 @@ // limitations under the License. // -import Foundation +#import "BMDuration.h" -class BMWordSuggestionView: UIView { - -} +@implementation BMDuration + +@end diff --git a/BeamWallet/BeamSDK/Objects/BMTransaction.h b/BeamWallet/BeamSDK/Objects/BMTransaction.h index 6ff32172..f3cac809 100644 --- a/BeamWallet/BeamSDK/Objects/BMTransaction.h +++ b/BeamWallet/BeamSDK/Objects/BMTransaction.h @@ -1,6 +1,6 @@ // -// BMTransaction.h -// BeamWallet +// BMTransaction.h +// BeamWallet // // Copyright 2018 Beam Development // diff --git a/BeamWallet/BeamSDK/Settings.m b/BeamWallet/BeamSDK/Settings.m index 589d1165..7dd4219f 100644 --- a/BeamWallet/BeamSDK/Settings.m +++ b/BeamWallet/BeamSDK/Settings.m @@ -104,7 +104,7 @@ -(id)init { _explorerAddress = @"https://testnet.explorer.beam.mw/"; } else if (self.target == Masternet) { - _explorerAddress = @"https://explorer.beam.mw/"; + _explorerAddress = @"https://master-net.explorer.beam.mw/"; } else{ _explorerAddress = @"https://explorer.beam.mw/"; diff --git a/BeamWallet/BeamSDK/WalletModel.mm b/BeamWallet/BeamSDK/WalletModel.mm index 8d36b38f..c345cb78 100644 --- a/BeamWallet/BeamSDK/WalletModel.mm +++ b/BeamWallet/BeamSDK/WalletModel.mm @@ -306,7 +306,8 @@ BMAddress *address = [[BMAddress alloc] init]; address.label = [NSString stringWithUTF8String:walletAddr.m_label.c_str()]; address.walletId = [NSString stringWithUTF8String:to_string(walletAddr.m_walletID).c_str()]; - + address.category = [NSString stringWithUTF8String:walletAddr.m_category.c_str()]; + BMContact *contact = [[BMContact alloc] init]; contact.address = address; contact.name = address.label; diff --git a/BeamWallet/Controls/BMTableHeaderTitleView.swift b/BeamWallet/Controls/BMTableHeaderTitleView.swift new file mode 100644 index 00000000..9c9450c8 --- /dev/null +++ b/BeamWallet/Controls/BMTableHeaderTitleView.swift @@ -0,0 +1,41 @@ +// +// BMTableHeaderTitleView.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +import Foundation + +class BMTableHeaderTitleView: UIView { + + static let height:CGFloat = 50 + + init(title:String) { + super.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: BMTableHeaderTitleView.height)) + + self.backgroundColor = UIColor.main.marine + + let label = UILabel(frame: CGRect(x: 15, y: 25, width: 200, height: 15)) + label.adjustFontSize = true + label.font = UIFont(name: "SFProDisplay-Regular", size: 12) + label.text = title.uppercased() + label.textColor = UIColor.main.blueyGrey + self.addSubview(label) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/BeamWallet/Extensions/Color.swift b/BeamWallet/Extensions/Color.swift index ddd5f8b5..43b6421a 100644 --- a/BeamWallet/Extensions/Color.swift +++ b/BeamWallet/Extensions/Color.swift @@ -22,6 +22,48 @@ import UIKit extension UIColor { + convenience init(hexString: String) { + let hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted) + var int = UInt32() + Scanner(string: hex).scanHexInt32(&int) + let a, r, g, b: UInt32 + switch hex.count { + case 3: // RGB (12-bit) + (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) + case 6: // RGB (24-bit) + (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) + case 8: // ARGB (32-bit) + (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) + default: + (a, r, g, b) = (255, 0, 0, 0) + } + self.init(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255) + } + + func toHexString() -> String { + var r:CGFloat = 0 + var g:CGFloat = 0 + var b:CGFloat = 0 + var a:CGFloat = 0 + + getRed(&r, green: &g, blue: &b, alpha: &a) + + let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0 + + return NSString(format:"#%06x", rgb) as String + } +} + +extension UIColor { + + enum category { + + static var veryLightPink50: UIColor { + return .init(red: 216/255, green: 216/255, blue: 216/255, alpha: 0.5) + } + } + + enum main { static var veryLightPink50: UIColor { diff --git a/BeamWallet/Extensions/Device.swift b/BeamWallet/Extensions/Device.swift index d3b6dc11..2a65bbe7 100644 --- a/BeamWallet/Extensions/Device.swift +++ b/BeamWallet/Extensions/Device.swift @@ -39,6 +39,10 @@ class Device { return UIDevice.current.userInterfaceIdiom == .pad } + static var isLarge: Bool { + return Device.screenType == .iPhone_XSMax || Device.screenType == .iPhones_Plus + } + enum ScreenType: String { case iPhones_4 = "iPhone 4 or iPhone 4S" case iPhones_5 = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE" diff --git a/BeamWallet/Extensions/TextView.swift b/BeamWallet/Extensions/TextView.swift new file mode 100644 index 00000000..af3eb096 --- /dev/null +++ b/BeamWallet/Extensions/TextView.swift @@ -0,0 +1,98 @@ +// +// TextView.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +class UITextViewPlacholder : UITextView +{ + + override open var text: String! { + didSet { + textChanged() + } + } + + /// Resize the placeholder when the UITextView bounds change + override open var bounds: CGRect { + didSet { + self.resizePlaceholder() + } + } + + /// The UITextView placeholder text + public var placeholder: String? { + get { + var placeholderText: String? + + if let placeholderLabel = self.viewWithTag(100) as? UILabel { + placeholderText = placeholderLabel.text + } + + return placeholderText + } + set { + if let placeholderLabel = self.viewWithTag(100) as! UILabel? { + placeholderLabel.text = newValue + placeholderLabel.sizeToFit() + } else { + self.addPlaceholder(newValue!) + } + } + } + + /// When the UITextView did change, show or hide the label based on if the UITextView is empty or not + /// + /// - Parameter textView: The UITextView that got updated + @objc private func textChanged() { + if let placeholderLabel = self.viewWithTag(100) as? UILabel { + placeholderLabel.isHidden = self.text.lengthOfBytes(using: .utf8) > 0 + } + } + + /// Resize the placeholder UILabel to make sure it's in the same position as the UITextView text + private func resizePlaceholder() { + if let placeholderLabel = self.viewWithTag(100) as! UILabel? { + let labelX = self.textContainer.lineFragmentPadding + let labelY = self.textContainerInset.top - 2 + let labelWidth = self.frame.width - (labelX * 2) + let labelHeight = placeholderLabel.frame.height + + placeholderLabel.frame = CGRect(x: labelX, y: labelY, width: labelWidth, height: labelHeight) + } + } + + /// Adds a placeholder UILabel to this UITextView + private func addPlaceholder(_ placeholderText: String) { + NotificationCenter.default.addObserver(self, selector: #selector(textChanged), name: UITextView.textDidChangeNotification, object: nil) + + let placeholderLabel = UILabel() + + placeholderLabel.text = placeholderText + placeholderLabel.sizeToFit() + + placeholderLabel.font = self.font + placeholderLabel.textColor = UIColor.init(red: 112/255, green: 128/255, blue: 138/255, alpha: 1) + placeholderLabel.tag = 100 + + placeholderLabel.isHidden = self.text.lengthOfBytes(using: .utf8) > 0 + + self.addSubview(placeholderLabel) + self.resizePlaceholder() + } +} diff --git a/BeamWallet/Extensions/View.swift b/BeamWallet/Extensions/View.swift index 84c9f9d4..a2a66b25 100644 --- a/BeamWallet/Extensions/View.swift +++ b/BeamWallet/Extensions/View.swift @@ -20,6 +20,38 @@ import Foundation import UIKit +extension UIView { + + struct Constants { + static let ExternalBorderName = "externalBorder" + } + + func addExternalBorder(borderWidth: CGFloat = 2.0, borderColor: UIColor = UIColor.white) -> CALayer { + let externalBorder = CALayer() + externalBorder.frame = CGRect(x:-borderWidth, y:-borderWidth, width:frame.size.width + 2 * borderWidth, height:frame.size.height + 2 * borderWidth) + externalBorder.borderColor = borderColor.cgColor + externalBorder.borderWidth = borderWidth + externalBorder.name = Constants.ExternalBorderName + + layer.insertSublayer(externalBorder, at: 0) + layer.masksToBounds = false + + return externalBorder + } + + func removeExternalBorders() { + layer.sublayers?.filter() { $0.name == Constants.ExternalBorderName }.forEach() { + $0.removeFromSuperlayer() + } + } + + func removeExternalBorder(externalBorder: CALayer) { + guard externalBorder.name == Constants.ExternalBorderName else { return } + externalBorder.removeFromSuperlayer() + } + +} + extension UIView { func shake() { let animation = CAKeyframeAnimation(keyPath: "transform.translation.x") @@ -32,6 +64,17 @@ extension UIView { extension UIView { + var width: CGFloat { + get { + return frame.size.width + } + set { + var f = frame + f.size.width = newValue + frame = f + } + } + var x: CGFloat { get { return frame.origin.x diff --git a/BeamWallet/Manager/NotificationManager.swift b/BeamWallet/Manager/NotificationManager.swift index b23bc853..ad632de7 100644 --- a/BeamWallet/Manager/NotificationManager.swift +++ b/BeamWallet/Manager/NotificationManager.swift @@ -546,7 +546,7 @@ extension NotificationManager : WalletModelDelegate { } } } - else if connected && TGBotManager.sharedManager.user.userId.isEmpty == false { + else if connected && TGBotManager.sharedManager.isNeedLinking() { TGBotManager.sharedManager.startLinking(completion: { (_ ) in }) diff --git a/BeamWallet/Manager/TGBotManager.swift b/BeamWallet/Manager/TGBotManager.swift index f864c88f..a336a351 100644 --- a/BeamWallet/Manager/TGBotManager.swift +++ b/BeamWallet/Manager/TGBotManager.swift @@ -29,12 +29,50 @@ class TGBotManager : NSObject { static let sharedManager = TGBotManager() private static var mainApi = "https://anywhere.beam.mw/api" - - public var user = TGUser() private var isStartLinking = false private var completion : ((Bool) -> Void)? + private var user = TGUser() + + public func isNeedLinking()->Bool { + if user.userName.isEmpty { + return false + } + return true + } + + public func isValidUserFromUrl(url:URL)->Bool { + if let params = url.queryParameters { + if let id = params["user_id"], let name = params["username"] { + + user.userId = id + user.userName = name + + return true + } + } + + return false + } + + public func isValidUserFromJson(value:String)->Bool { + if let json = try? JSONSerialization.jsonObject(with: value.data(using: .utf8)!, options: .mutableContainers) as? [String: Any] { + + if let id = json["_id"] as? u_quad_t, let name = json["username"] as? String { + + user.userId = String(id) + user.userName = name + + return true + } + } + + return false; + } + + //MARK: - HTTP methods + public func startLinking(completion:@escaping ((Bool) -> Void)) { #if EXTENSION print("ignore") @@ -114,6 +152,8 @@ class TGBotManager : NSObject { } } + //MARK: - Requests + private static func sendRequest(url:URL, parameters:[String:Any], method:String, completion: @escaping ((Error?) -> Void)) { let session = URLSession.shared @@ -161,7 +201,7 @@ extension TGBotManager : WalletModelDelegate { func onGeneratedNewAddress(_ address: BMAddress) { #if EXTENSION - print("ignore") + print("ignore") #else DispatchQueue.main.async { if self.isStartLinking { diff --git a/BeamWallet/Protocols/Configurable.swift b/BeamWallet/Protocols/Configurable.swift index 27e12db5..fbab10c0 100644 --- a/BeamWallet/Protocols/Configurable.swift +++ b/BeamWallet/Protocols/Configurable.swift @@ -1,6 +1,6 @@ // -// Configurable.swift -// BeamWallet +// Configurable.swift +// BeamWallet // // Copyright 2018 Beam Development // diff --git a/BeamWallet/Protocols/LocalizableStrings.swift b/BeamWallet/Protocols/LocalizableStrings.swift new file mode 100644 index 00000000..9f543fbe --- /dev/null +++ b/BeamWallet/Protocols/LocalizableStrings.swift @@ -0,0 +1,26 @@ +// +// LocalizableStrings.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct LocalizableStrings { + + static let testnet_logs = "testnet_logs".localized + static let main_logs = "main_logs".localized +} diff --git a/BeamWallet/ViewControllers/Login/EnterWalletPasswordViewController.swift b/BeamWallet/ViewControllers/Login/EnterWalletPasswordViewController.swift index 0e66f8d1..535f53e7 100644 --- a/BeamWallet/ViewControllers/Login/EnterWalletPasswordViewController.swift +++ b/BeamWallet/ViewControllers/Login/EnterWalletPasswordViewController.swift @@ -62,9 +62,14 @@ class EnterWalletPasswordViewController: BaseWizardViewController { } else{ - if isRequestedAuthorization == false && TGBotManager.sharedManager.user.userId.isEmpty == true && UIApplication.shared.applicationState == .active { +// if let password = KeychainManager.getPassword() { +// passField.text = password +// onLogin(sender: UIButton()) +// } + + if isRequestedAuthorization == false && TGBotManager.sharedManager.isNeedLinking() == false && UIApplication.shared.applicationState == .active { isRequestedAuthorization = true - + biometricAuthorization() } } diff --git a/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.swift b/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.swift new file mode 100644 index 00000000..01a77537 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.swift @@ -0,0 +1,112 @@ +// +// AddressExpiresPickerViewController.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + +class AddressExpiresPickerViewController: BaseViewController { + + public var completion : ((Int) -> Void)? + + private var items:[BMDuration] = [] + private var selectedDuration:Int! + private var currentDuration:Int! + + @IBOutlet private weak var tableView: UITableView! + + init(duration:Int) { + super.init(nibName: nil, bundle: nil) + + let h24 = BMDuration() + h24.duration = 24 + h24.name = "In 24 hours" + + let never = BMDuration() + never.duration = 0 + never.name = "Never" + + items.append(h24) + items.append(never) + + self.currentDuration = duration + self.selectedDuration = duration + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Address expires" + + tableView.register(AddressDurationCell.self) + + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(onSave)) + navigationItem.rightBarButtonItem?.tintColor = UIColor.main.brightTeal + navigationItem.rightBarButtonItem?.isEnabled = false + } + + @objc private func onSave(sender:UIBarButtonItem) { + self.completion?(selectedDuration) + self.navigationController?.popViewController(animated: true) + } +} + +extension AddressExpiresPickerViewController : UITableViewDelegate { + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 50 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + selectedDuration = (indexPath.row == 0) ? 24 : 0 + + if selectedDuration == currentDuration { + navigationItem.rightBarButtonItem?.isEnabled = false + } + else{ + navigationItem.rightBarButtonItem?.isEnabled = true + } + + tableView.reloadData() + } +} + +extension AddressExpiresPickerViewController : UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return items.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + let cell = tableView + .dequeueReusableCell(withType: AddressDurationCell.self, for: indexPath) + .configured(with: (duration: items[indexPath.row], selected: selectedDuration == items[indexPath.row].duration)) + return cell + } +} + diff --git a/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.xib b/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.xib new file mode 100644 index 00000000..f7dcdf55 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Addresses/AddressExpiresPickerViewController.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.swift b/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.swift index f86a6799..06928387 100644 --- a/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.swift +++ b/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.swift @@ -22,7 +22,9 @@ import UIKit class AddressViewController: BaseViewController { private var address:BMAddress! - private var transactions:[BMTransaction]! + private var transactions = [BMTransaction]() + private var details = [TransactionViewController.TransactionGeneralInfo]() + private var isContact = false @IBOutlet private weak var tableView: UITableView! @@ -44,10 +46,12 @@ class AddressViewController: BaseViewController { self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "iconMore"), style: .plain, target: self, action: #selector(onMore)) - tableView.register(AddressCell.self) - tableView.register(WalletTransactionCell.self) - getTransactions() + fillDetails() + + tableView.register(GeneralInfoCell.self) + tableView.register(WalletTransactionCell.self) + tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: 10)) title = "Address" @@ -63,6 +67,28 @@ class AddressViewController: BaseViewController { } } + private func fillDetails() { + details.removeAll() + + details.append(TransactionViewController.TransactionGeneralInfo(text: "Address ID:", detail: self.address.walletId, failed: false, canCopy:true, color: UIColor.white)) + + if !isContact { + details.append(TransactionViewController.TransactionGeneralInfo(text: "Expiration date:", detail: self.address.formattedDate(), failed: false, canCopy:true, color: UIColor.white)) + + if !self.address.category.isEmpty { + if let category = AppModel.sharedManager().findCategory(byId: self.address.category) { + details.append(TransactionViewController.TransactionGeneralInfo(text: "Category:", detail: category.name, failed: false, canCopy:true, color: UIColor.init(hexString: category.color))) + } + } + } + + + if !self.address.label.isEmpty { + details.append(TransactionViewController.TransactionGeneralInfo(text: "Annotation:", detail: self.address.label, failed: false, canCopy:true, color: UIColor.white)) + } + + } + @objc private func onMore(sender:UIBarButtonItem) { let frame = CGRect(x: UIScreen.main.bounds.size.width-80, y: 44, width: 60, height: 40) var items = [BMPopoverMenu.BMPopoverMenuItem(name: "Show QR code", icon: "iconScanQr", id:1), BMPopoverMenu.BMPopoverMenuItem(name: "Copy address", icon: "iconCopyWhite24", id:2), BMPopoverMenu.BMPopoverMenuItem(name: "Edit address", icon: "iconEdit", id:3), BMPopoverMenu.BMPopoverMenuItem(name: "Delete address", icon: "iconDelete", id:4)] @@ -150,7 +176,7 @@ extension AddressViewController : UITableViewDelegate { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { if section == 1 { - return 40 + return 75 } return 0 @@ -160,7 +186,7 @@ extension AddressViewController : UITableViewDelegate { if indexPath.section == 1 { return 86 } - return 90 + return UITableView.automaticDimension } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -188,15 +214,15 @@ extension AddressViewController : UITableViewDataSource { if section == 1 { return transactions.count } - return 1 + return self.details.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath.section == 0 { - let cell = tableView - .dequeueReusableCell(withType: AddressCell.self, for: indexPath) - .configured(with: (row: indexPath.row, address: address, single:true)) + let cell = tableView + .dequeueReusableCell(withType: GeneralInfoCell.self, for: indexPath) + .configured(with: details[indexPath.row]) return cell } else{ @@ -233,6 +259,8 @@ extension AddressViewController : WalletModelDelegate { if let address = walletAddresses.first(where: { $0.walletId == self.address.walletId }) { self.address = address + self.fillDetails() + UIView.performWithoutAnimation { self.tableView.reloadData() } diff --git a/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.xib b/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.xib index c626866b..a255fd62 100644 --- a/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.xib +++ b/BeamWallet/ViewControllers/Main/Addresses/AddressViewController.xib @@ -1,11 +1,11 @@ - + - + @@ -46,36 +46,23 @@ - + - - - - - + - - - diff --git a/BeamWallet/ViewControllers/Main/Addresses/AddressesViewController.swift b/BeamWallet/ViewControllers/Main/Addresses/AddressesViewController.swift index e665849c..5e3f0ed9 100644 --- a/BeamWallet/ViewControllers/Main/Addresses/AddressesViewController.swift +++ b/BeamWallet/ViewControllers/Main/Addresses/AddressesViewController.swift @@ -50,6 +50,8 @@ class AddressesViewController: BaseViewController { NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) } + + @objc private func didBecomeActive() { filterAddresses() tableView.reloadData() @@ -165,4 +167,13 @@ extension AddressesViewController : WalletModelDelegate { } } } + + func onCategoriesChange() { + DispatchQueue.main.async { + self.filterAddresses() + UIView.performWithoutAnimation { + self.tableView.reloadData() + } + } + } } diff --git a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.swift b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.swift new file mode 100644 index 00000000..1267b02a --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.swift @@ -0,0 +1,45 @@ +// +// AddressCategoryCell.swift +// BeamWallet +// +// Created by Denis on 5/8/19. +// Copyright © 2019 Denis. All rights reserved. +// + +import UIKit + +class AddressCategoryCell: UITableViewCell { + + @IBOutlet weak private var categoryLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + + self.backgroundColor = UIColor.main.marineTwo + + selectionStyle = .default + + let selectedView = UIView() + selectedView.backgroundColor = UIColor.main.marineTwo.withAlphaComponent(0.6) + self.selectedBackgroundView = selectedView + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + } + +} + +extension AddressCategoryCell: Configurable { + + func configure(with address: BMAddress) { + if let category = AppModel.sharedManager().findCategory(byId: address.category) { + categoryLabel.text = category.name + categoryLabel.textColor = UIColor.init(hexString: category.color) + } + else{ + categoryLabel.text = "" + } + } +} + diff --git a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.xib b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.xib new file mode 100644 index 00000000..adf84139 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCategoryCell.xib @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + SFProDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.swift b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.swift index 9a7b1769..4a5cd6ef 100644 --- a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.swift +++ b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.swift @@ -26,10 +26,10 @@ class AddressCell: UITableViewCell { @IBOutlet weak private var nameLabel: UILabel! @IBOutlet weak private var idLabel: UILabel! @IBOutlet weak private var expiredLabel: UILabel! + @IBOutlet weak private var categoryLabel: UILabel! override func awakeFromNib() { super.awakeFromNib() - } } @@ -74,5 +74,13 @@ extension AddressCell: Configurable { selectedView.backgroundColor = mainView.backgroundColor?.withAlphaComponent(0.9) self.selectedBackgroundView = selectedView } + + if let category = AppModel.sharedManager().findCategory(byId: options.address.category) { + categoryLabel.textColor = UIColor.init(hexString: category.color) + categoryLabel.text = category.name + } + else{ + categoryLabel.text = "" + } } } diff --git a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.xib b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.xib index 690e85db..7e94d8d1 100644 --- a/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.xib +++ b/BeamWallet/ViewControllers/Main/Addresses/Cell/AddressCell.xib @@ -1,11 +1,11 @@ - + - + @@ -35,9 +35,9 @@ + diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryColorsView.swift b/BeamWallet/ViewControllers/Main/Categories/CategoryColorsView.swift new file mode 100644 index 00000000..01d81abe --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryColorsView.swift @@ -0,0 +1,131 @@ +// +// CategoryColorsView.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +protocol ColorViewDelegate: AnyObject { + func onSelectColor(color:UIColor) +} + +class CategoryColorsView: UIView { + + class ColorView: UIView { + + weak var delegate: ColorViewDelegate? + + public var color:UIColor! + private var circleView:UIView! + + init(color:UIColor, frame:CGRect) { + + super.init(frame: frame) + + self.color = color + + let button = UIButton(frame: CGRect(x: 4, y: 4, width: frame.size.width-8, height: frame.size.height - 8)) + button.cornerRadius = button.frame.size.width/2 + button.setBackgroundColor(color: color, forState: .normal) + button.addTarget(self, action: #selector(onSelectColor), for: .touchUpInside) + self.addSubview(button) + + circleView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)) + circleView.backgroundColor = UIColor.clear + circleView.layer.cornerRadius = circleView.frame.size.width/2 + circleView.layer.borderWidth = 2 + circleView.layer.borderColor = UIColor.main.brightTeal.cgColor + circleView.alpha = 0 + self.addSubview(circleView) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func onSelectColor() { + self.delegate?.onSelectColor(color: self.color) + } + + public var selected:Bool = false { + didSet{ + UIView.animate(withDuration: 0.3) { + self.circleView.alpha = self.selected ? 1 : 0 + } + } + } + } + + weak var delegate: ColorViewDelegate? + + public var colors:[UIColor] = [] { + didSet{ + fillColorView() + } + } + + public var selectedColor:UIColor = UIColor.clear { + didSet{ + selectColor() + } + } + + private func selectColor() { + for view in self.subviews { + if let colorView = view as? ColorView { + if colorView.color.toHexString() == selectedColor.toHexString() { + colorView.selected = true + } + else{ + colorView.selected = false + } + } + } + } + + private func fillColorView() { + + let size:CGFloat = Device.isLarge ? 38 : 30 + let space:CGFloat = Device.isLarge ? 30 : 20 + var x:CGFloat = 0 + + for color in colors { + + let colorView = ColorView(color: color, frame: CGRect(x: x, y: 0, width: size, height: size)) + colorView.delegate = self + self.addSubview(colorView) + + x = x + (size + space) + } + } + + public func colorsWidht()->CGFloat { + if self.subviews.count > 0 { + if let last = self.subviews.last { + return last.frame.origin.x + last.frame.size.width + } + } + return 0 + } +} + +extension CategoryColorsView : ColorViewDelegate { + + func onSelectColor(color: UIColor) { + self.delegate?.onSelectColor(color: color) + } +} diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.swift b/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.swift new file mode 100644 index 00000000..b4d019cd --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.swift @@ -0,0 +1,199 @@ +// +// CategoryDetailViewController.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +import UIKit + +class CategoryDetailViewController: BaseViewController { + + @IBOutlet private weak var tableView: UITableView! + @IBOutlet private var headerView: UIView! + + private var category:BMCategory! + private var addresses = [BMAddress]() + + init(category:BMCategory?) { + super.init(nibName: nil, bundle: nil) + + self.category = category + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Category" + + loadAddresses() + + tableView.register(AddressCell.self) + tableView.register(CategoryNameCell.self) + tableView.register(EmptyCell.self) + + self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "iconMore"), style: .plain, target: self, action: #selector(onMore)) + + AppModel.sharedManager().addDelegate(self) + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + if isMovingFromParent + { + AppModel.sharedManager().removeDelegate(self) + } + } + + private func loadAddresses() { + addresses = AppModel.sharedManager().getAddressFrom(self.category) as! [BMAddress] + } + + @objc private func onMore(sender:UIBarButtonItem) { + let frame = CGRect(x: UIScreen.main.bounds.size.width-80, y: 44, width: 60, height: 40) + + let items = [BMPopoverMenu.BMPopoverMenuItem(name: "Edit", icon: "iconScanQr", id:1), BMPopoverMenu.BMPopoverMenuItem(name: "Delete", icon: "iconCopyWhite24", id:2)] + + BMPopoverMenu.showForSenderFrame(senderFrame: frame, with: items, done: { (selectedItem) in + if let item = selectedItem { + switch (item.id) { + case 1: + let vc = CategoryEditViewController(category: self.category) + vc.hidesBottomBarWhenPushed = true + self.pushViewController(vc: vc) + case 2 : + AppModel.sharedManager().removeDelegate(self) + + AppModel.sharedManager().deleteCategory(self.category) + self.navigationController?.popViewController(animated: true) + default: + return + } + } + }, cancel: { + + }) + } +} + +extension CategoryDetailViewController : UITableViewDelegate { + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if section == 1 { + return 50 + } + + return 0 + } + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + if indexPath.section == 0 { + return 80 + } + return 90 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + if indexPath.section == 1 && addresses.count > 0 { + let vc = AddressViewController(address: addresses[indexPath.row], isContact:false) + vc.hidesBottomBarWhenPushed = true + pushViewController(vc: vc) + } + } +} + +extension CategoryDetailViewController : UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if section == 1 { + if addresses.count == 0 { + return 1 + } + return addresses.count + } + return 1 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + if indexPath.section == 1 { + if addresses.count == 0 { + let cell = tableView + .dequeueReusableCell(withType: EmptyCell.self, for: indexPath) + .configured(with: "there are no addresses associated with this category") + return cell + } + else{ + let cell = tableView + .dequeueReusableCell(withType: AddressCell.self, for: indexPath) + .configured(with: (row: indexPath.row, address: addresses[indexPath.row], single:false)) + return cell + } + + } + else{ + let cell = tableView + .dequeueReusableCell(withType: CategoryNameCell.self, for: indexPath) + .configured(with: self.category) + return cell + } + + } + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + if section == 1 { + return headerView + } + + return nil + } +} + +extension CategoryDetailViewController : WalletModelDelegate { + + func onWalletAddresses(_ walletAddresses: [BMAddress]) { + DispatchQueue.main.async { + self.loadAddresses() + UIView.performWithoutAnimation { + self.tableView.reloadData() + } + } + } + func onCategoriesChange() { + DispatchQueue.main.async { + let categories = AppModel.sharedManager().categories as! [BMCategory] + if let category = categories.first(where: { $0.id == self.category.id }) { + self.category = category + self.loadAddresses() + + UIView.performWithoutAnimation { + self.tableView.reloadData() + } + } + } + } +} diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.xib b/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.xib new file mode 100644 index 00000000..218679dc --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryDetailViewController.xib @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + SFProDisplay-Bold + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.swift b/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.swift new file mode 100644 index 00000000..28fe2f26 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.swift @@ -0,0 +1,149 @@ +// +// CategoryEditViewController.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + + +import UIKit + +class CategoryEditViewController: BaseViewController { + + public var completion : ((BMCategory?) -> Void)? + + @IBOutlet private weak var nameField: UITextField! + @IBOutlet private weak var nameView: UIView! + + @IBOutlet private weak var colorsView: CategoryColorsView! + @IBOutlet private var colorsWidth: NSLayoutConstraint! + + private var category:BMCategory! + private let colors = [UIColor.init(hexString: "#ff746b"), UIColor.init(hexString: "#ffba55"), + UIColor.init(hexString: "#fee65a"), UIColor.init(hexString: "#73ff7c"), + UIColor.init(hexString: "#4fa5ff"), UIColor.init(hexString: "#d785ff")] + + private var selectedColor:String! + + init(category:BMCategory?) { + super.init(nibName: nil, bundle: nil) + + if category != nil { + self.category = category + + self.selectedColor = self.category.color + } + else{ + self.selectedColor = self.colors.randomElement()?.toHexString() + + self.category = BMCategory() + self.category.name = "" + self.category.id = 0 + self.category.color = self.selectedColor + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + hideKeyboardWhenTappedAround() + + title = category.id == 0 ? "New category" : "Edit Category" + + nameField.text = category.name + + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(onSave)) + navigationItem.rightBarButtonItem?.tintColor = UIColor.main.brightTeal + navigationItem.rightBarButtonItem?.isEnabled = false + + nameView.backgroundColor = UIColor.main.marineTwo + nameField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) + + colorsView.colors = colors + colorsView.selectedColor = UIColor.init(hexString: category.color) + colorsView.delegate = self + colorsWidth.constant = colorsView.colorsWidht() + } + + private func canSave(name:String, color:String) -> Bool { + if name.isEmpty { + return false + } + else if(name != category.name || color != category.color) { + return true + } + else{ + return false + } + } + + @objc func textFieldDidChange(_ textField: UITextField) { + if let name = nameField.text { + + navigationItem.rightBarButtonItem?.isEnabled = self.canSave(name: name, color: selectedColor) + } + } + + @objc private func onSave() { + if let name = nameField.text { + + if AppModel.sharedManager().isNameAlreadyExist(name, id: category.id) { + self.alert(message: "This category name already exists") + } + else{ + category.name = name + category.color = selectedColor + + if category.id == 0 { + category.id = Int32(Int.random(in: 1 ... 10024)) + + AppModel.sharedManager().addCategory(category) + } + else{ + AppModel.sharedManager().editCategory(category) + } + + self.completion?(category) + + navigationController?.popViewController(animated: true) + } + } + } +} + +extension CategoryEditViewController : UITextFieldDelegate { + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + + return true + } +} + +extension CategoryEditViewController: ColorViewDelegate { + func onSelectColor(color: UIColor) { + + self.selectedColor = color.toHexString() + self.colorsView.selectedColor = UIColor.init(hexString: self.selectedColor) + + if let name = self.nameField.text { + self.navigationItem.rightBarButtonItem?.isEnabled = self.canSave(name: name, color: self.selectedColor) + } + } +} diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.xib b/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.xib new file mode 100644 index 00000000..54a0c785 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryEditViewController.xib @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + SFProDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.swift b/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.swift new file mode 100644 index 00000000..71cfd3ad --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.swift @@ -0,0 +1,120 @@ +// +// CategoryPickerViewController.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + +import UIKit + +class CategoryPickerViewController: BaseViewController { + + public var completion : ((BMCategory?) -> Void)? + + private var categories:[BMCategory]! + private var selectedCategory:BMCategory? + private var currentCategory:BMCategory? + + @IBOutlet private weak var tableView: UITableView! + + init(category:BMCategory?) { + super.init(nibName: nil, bundle: nil) + + self.currentCategory = category + self.selectedCategory = category + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = "Category" + + categories = (AppModel.sharedManager().categories as! [BMCategory]) + + tableView.register(CategoryPickerCell.self) + tableView.register(EmptyCell.self) + + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(onSave)) + navigationItem.rightBarButtonItem?.tintColor = UIColor.main.brightTeal + navigationItem.rightBarButtonItem?.isEnabled = false + } + + + @objc private func onSave(sender:UIBarButtonItem) { + self.completion?(selectedCategory) + self.navigationController?.popViewController(animated: true) + } +} + +extension CategoryPickerViewController : UITableViewDelegate { + + func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 50 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + selectedCategory = categories[indexPath.row] + + if currentCategory != nil { + if currentCategory?.id == selectedCategory?.id { + navigationItem.rightBarButtonItem?.isEnabled = false + } + else{ + navigationItem.rightBarButtonItem?.isEnabled = true + } + } + else{ + navigationItem.rightBarButtonItem?.isEnabled = true + } + + tableView.reloadData() + } +} + +extension CategoryPickerViewController : UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return categories.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + + if categories.count == 0 { + let cell = tableView + .dequeueReusableCell(withType: EmptyCell.self, for: indexPath) + .configured(with: "categories not found") + return cell + } + else{ + let cell = tableView + .dequeueReusableCell(withType: CategoryPickerCell.self, for: indexPath) + .configured(with: (category: categories[indexPath.row], selected: categories[indexPath.row].id == selectedCategory?.id)) + return cell + } + } +} + diff --git a/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.xib b/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.xib new file mode 100644 index 00000000..1289b798 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/CategoryPickerViewController.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.swift b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.swift new file mode 100644 index 00000000..398ef899 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.swift @@ -0,0 +1,39 @@ +// +// CategoryNameCell.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + +class CategoryNameCell: BaseCell { + + @IBOutlet weak private var nameLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + + selectionStyle = .none + } +} + +extension CategoryNameCell: Configurable { + + func configure(with category:BMCategory) { + nameLabel.text = category.name + nameLabel.textColor = UIColor.init(hexString: category.color) + } +} diff --git a/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.xib b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.xib new file mode 100644 index 00000000..b69faee1 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryNameCell.xib @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + SFProDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.swift b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.swift new file mode 100644 index 00000000..cd09c670 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.swift @@ -0,0 +1,52 @@ +// +// CategoryPickerCell.swift +// BeamWallet +// +// Copyright 2018 Beam Development +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit + + +class CategoryPickerCell: BaseCell { + + @IBOutlet weak private var nameLabel: UILabel! + @IBOutlet private weak var mainView: UIView! + @IBOutlet private weak var arrowView: UIImageView! + + override func awakeFromNib() { + super.awakeFromNib() + + backgroundColor = UIColor.main.marineTwo + contentView.backgroundColor = UIColor.main.marineTwo + mainView.backgroundColor = UIColor.main.marineTwo + + let selectedView = UIView() + selectedView.backgroundColor = UIColor.main.marineTwo.withAlphaComponent(0.6) + self.selectedBackgroundView = selectedView + + arrowView.image = UIImage.init(named: "tick")?.withRenderingMode(.alwaysTemplate) + arrowView.tintColor = UIColor.main.brightTeal + } +} + +extension CategoryPickerCell: Configurable { + + func configure(with options: (category: BMCategory, selected:Bool)) { + arrowView.isHidden = !options.selected + nameLabel.text = options.category.name + nameLabel.textColor = UIColor.init(hexString: options.category.color) + } +} diff --git a/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.xib b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.xib new file mode 100644 index 00000000..9556eec9 --- /dev/null +++ b/BeamWallet/ViewControllers/Main/Categories/Cells/CategoryPickerCell.xib @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + SFProDisplay-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Settings/Cells/SettingsCell.swift b/BeamWallet/ViewControllers/Main/Settings/Cells/SettingsCell.swift index e3774e18..c077f1a7 100644 --- a/BeamWallet/ViewControllers/Main/Settings/Cells/SettingsCell.swift +++ b/BeamWallet/ViewControllers/Main/Settings/Cells/SettingsCell.swift @@ -30,6 +30,10 @@ class SettingsCell: BaseCell { backgroundColor = UIColor.clear mainView.backgroundColor = UIColor.main.marineTwo + + let selectedView = UIView() + selectedView.backgroundColor = UIColor.main.marineTwo.withAlphaComponent(0.6) + self.selectedBackgroundView = selectedView } override func setSelected(_ selected: Bool, animated: Bool) { @@ -45,6 +49,8 @@ extension SettingsCell: Configurable { func configure(with item:SettingsViewModel.SettingsItem) { + titleLabel.textColor = UIColor.white + titleLabel?.text = item.title detailLabel?.text = item.detail @@ -60,16 +66,23 @@ extension SettingsCell: Configurable { selectionStyle = item.id == 0 ? .none : .default } - if item.id == 5 || item.id == 6 || item.id == 7 || item.id == 2 || item.id == 1 - || item.id == 8 { + if let category = item.category { arrowView.isHidden = false titleXOffset.constant = 25 + titleLabel.textColor = UIColor.init(hexString: category.color) } else{ - arrowView.isHidden = true - titleXOffset.constant = 15 + if item.id == 5 || item.id == 6 || item.id == 7 || item.id == 2 || item.id == 1 + || item.id == 8 { + arrowView.isHidden = false + titleXOffset.constant = 25 + } + else{ + arrowView.isHidden = true + titleXOffset.constant = 15 + } } - + botLineView.isHidden = item.position == SettingsViewModel.SettingsItem.Position.midle } } diff --git a/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.swift b/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.swift index 29280ce5..ec3cb960 100644 --- a/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.swift +++ b/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.swift @@ -51,7 +51,7 @@ class EnterNodeAddressViewController: BaseViewController { super.viewDidDisappear(animated) } - @objc func textFieldDidChange(_ textField: BMField) { + @objc func textFieldDidChange(_ textField: UITextField) { if let address = nodeAddressField.text { if address.isEmpty { diff --git a/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.xib b/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.xib index f1466c2e..7cf6d60a 100644 --- a/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.xib +++ b/BeamWallet/ViewControllers/Main/Settings/EnterNodeAddressViewController.xib @@ -41,26 +41,37 @@ - + + + + + + + + + + + + diff --git a/BeamWallet/ViewControllers/Main/Settings/Model/SettingsViewModel.swift b/BeamWallet/ViewControllers/Main/Settings/Model/SettingsViewModel.swift index 8ac9d301..e17e9336 100644 --- a/BeamWallet/ViewControllers/Main/Settings/Model/SettingsViewModel.swift +++ b/BeamWallet/ViewControllers/Main/Settings/Model/SettingsViewModel.swift @@ -26,8 +26,9 @@ protocol SettingsActions { func onClearData(controller:UIViewController) func onSwitch(controller:UIViewController, indexPath:IndexPath) func onOpenTgBot() - + func onCategory(controller:UIViewController, category:BMCategory?) } + extension SettingsViewModel: SettingsActions { func onOpenTgBot() { @@ -101,11 +102,20 @@ extension SettingsViewModel: SettingsActions { controller.present(vc, animated: true) } + + func onCategory(controller:UIViewController, category:BMCategory?) { + + let vc = CategoryEditViewController(category: category) + vc.hidesBottomBarWhenPushed = true + controller.pushViewController(vc: vc) + } } -class SettingsViewModel { +class SettingsViewModel : NSObject { public var items = [[SettingsItem]]() + + public var needReloadTable : (() -> Void)? class SettingsItem { enum Position { @@ -118,7 +128,8 @@ class SettingsViewModel { public var isSwitch:Bool? public var id:Int! public var position:Position! - + public var category:BMCategory? + init(title: String?, detail: String?, isSwitch: Bool?, id:Int, position:Position) { self.title = title self.detail = detail @@ -126,41 +137,71 @@ class SettingsViewModel { self.id = id self.position = position } + + init(title: String?, detail: String?, isSwitch: Bool?, id:Int, position:Position, category:BMCategory?) { + self.title = title + self.detail = detail + self.isSwitch = isSwitch + self.id = id + self.position = position + self.category = category + } } - init() { + override init() { + super.init() + initItems() + + AppModel.sharedManager().addDelegate(self) } private func initItems() { - var first = [SettingsItem]() - first.append(SettingsItem(title: "ip:port:", detail: Settings.sharedManager().nodeAddress, isSwitch: nil, id: 5, position: .one)) - var second = [SettingsItem]() - second.append(SettingsItem(title: "Ask for password on every Send", detail: nil, isSwitch: Settings.sharedManager().isNeedaskPasswordForSend, id: 3, position: .midle)) + var node = [SettingsItem]() + node.append(SettingsItem(title: "ip:port:", detail: Settings.sharedManager().nodeAddress, isSwitch: nil, id: 5, position: .one)) + + var security = [SettingsItem]() + security.append(SettingsItem(title: "Ask for password on every Send", detail: nil, isSwitch: Settings.sharedManager().isNeedaskPasswordForSend, id: 3, position: .midle)) if BiometricAuthorization.shared.canAuthenticate() { - second.append(SettingsItem(title: BiometricAuthorization.shared.faceIDAvailable() ? "Enable Face ID" : "Enable Touch ID", detail: nil, isSwitch: Settings.sharedManager().isEnableBiometric, id: 4, position: .midle)) + security.append(SettingsItem(title: BiometricAuthorization.shared.faceIDAvailable() ? "Enable Face ID" : "Enable Touch ID", detail: nil, isSwitch: Settings.sharedManager().isEnableBiometric, id: 4, position: .midle)) } - second.append(SettingsItem(title: "Allow open external link", detail: nil, isSwitch: Settings.sharedManager().isAllowOpenLink, id: 9, position: .midle)) + security.append(SettingsItem(title: "Allow open external link", detail: nil, isSwitch: Settings.sharedManager().isAllowOpenLink, id: 9, position: .midle)) - var three = [SettingsItem]() - three.append(SettingsItem(title: "Change wallet password", detail: nil, isSwitch: nil, id: 1, position: .midle)) - three.append(SettingsItem(title: "Clear data", detail: nil, isSwitch: nil, id: 6, position: .midle)) + var info = [SettingsItem]() + info.append(SettingsItem(title: "Change wallet password", detail: nil, isSwitch: nil, id: 1, position: .midle)) + info.append(SettingsItem(title: "Clear data", detail: nil, isSwitch: nil, id: 6, position: .midle)) - var four = [SettingsItem]() - four.append(SettingsItem(title: "Report a problem", detail: nil, isSwitch: nil, id: 2, position: .one)) + var categories = [SettingsItem]() + if AppModel.sharedManager().categories.count > 0 { + for category in AppModel.sharedManager().categories as! [BMCategory] { + categories.append(SettingsItem(title: category.name, detail: nil, isSwitch: nil, id: Int(category.id), position: .midle, category: category)) + } + } + else{ + categories.append(SettingsItem(title: "Create new category", detail: nil, isSwitch: nil, id: 10, position: AppModel.sharedManager().categories.count > 0 ? .midle : .one)) + } + + var report = [SettingsItem]() + report.append(SettingsItem(title: "Report a problem", detail: nil, isSwitch: nil, id: 2, position: .one)) - items.append(first) - items.append(second) - items.append(three) - items.append(four) + items.append(node) + items.append(security) + items.append(info) + items.append(categories) + if AppModel.sharedManager().categories.count > 0 { + var categories = [SettingsItem]() + categories.append(SettingsItem(title: "Create new category", detail: nil, isSwitch: nil, id: 10, position: .one)) + items.append(categories) + } + items.append(report) if !NotificationManager.disableApns { - var four = [SettingsItem]() - four.append(SettingsItem(title: "Open telegram bot", detail: nil, isSwitch: nil, id: 8, position: .midle)) - four.append(SettingsItem(title: "Linking telegram bot", detail: nil, isSwitch: nil, id: 7, position: .one)) - items.append(four) + var bots = [SettingsItem]() + bots.append(SettingsItem(title: "Open telegram bot", detail: nil, isSwitch: nil, id: 8, position: .midle)) + bots.append(SettingsItem(title: "Linking telegram bot", detail: nil, isSwitch: nil, id: 7, position: .one)) + items.append(bots) } } @@ -168,3 +209,13 @@ class SettingsViewModel { return items[indexPath.section][indexPath.row] } } + +extension SettingsViewModel : WalletModelDelegate { + + func onCategoriesChange() { + //temp solution + self.items.removeAll() + self.initItems() + self.needReloadTable?() + } +} diff --git a/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.swift b/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.swift index 49747628..e7913752 100644 --- a/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.swift +++ b/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.swift @@ -25,15 +25,19 @@ class SettingsViewController: BaseViewController { @IBOutlet private weak var versionLabel:UILabel! @IBOutlet private var versionView:UIView! @IBOutlet private var headerView:UIView! - @IBOutlet private var nodeTitleHeaderView:UIView! - - private var viewModel = SettingsViewModel() + + private var viewModel:SettingsViewModel! override func viewDidLoad() { super.viewDidLoad() self.navigationItem.title = "Settings" + viewModel = SettingsViewModel() + viewModel.needReloadTable = { + self.talbeView.reloadData() + } + versionLabel.text = UIApplication.version() talbeView.register(SettingsCell.self) @@ -51,7 +55,7 @@ extension SettingsViewController : UITableViewDelegate { func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return 40 + return BMTableHeaderTitleView.height } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -60,27 +64,36 @@ extension SettingsViewController : UITableViewDelegate { let item = viewModel.getItem(indexPath: indexPath) - switch item.id { - case 2: - self.viewModel.onClickReport(controller: self) - case 1: - self.viewModel.onChangePassword(controller: self) - case 5: - self.viewModel.onChangeNode(controller: self) { (_) in - self.talbeView.reloadData() - } - case 6: - self.viewModel.onClearData(controller: self) - case 7: - let vc = WalletQRCodeScannerViewController() - vc.delegate = self - vc.isBotScanner = true + if item.category != nil { + let vc = CategoryDetailViewController(category: item.category!) vc.hidesBottomBarWhenPushed = true self.pushViewController(vc: vc) - case 8: - self.viewModel.onOpenTgBot() - default: - return + } + else{ + switch item.id { + case 2: + self.viewModel.onClickReport(controller: self) + case 1: + self.viewModel.onChangePassword(controller: self) + case 5: + self.viewModel.onChangeNode(controller: self) { (_) in + self.talbeView.reloadData() + } + case 6: + self.viewModel.onClearData(controller: self) + case 7: + let vc = WalletQRCodeScannerViewController() + vc.delegate = self + vc.isBotScanner = true + vc.hidesBottomBarWhenPushed = true + self.pushViewController(vc: vc) + case 8: + self.viewModel.onOpenTgBot() + case 10: + self.viewModel.onCategory(controller: self, category: nil) + default: + return + } } } @@ -91,7 +104,10 @@ extension SettingsViewController : UITableViewDataSource { func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { if section == 0 { - return nodeTitleHeaderView + return BMTableHeaderTitleView(title: "node") + } + else if section == 3 { + return BMTableHeaderTitleView(title: "categories") } let view = UIView() @@ -183,15 +199,9 @@ extension SettingsViewController : SettingsCellDelegate { extension SettingsViewController : WalletQRCodeScannerViewControllerDelegate { func didScanQRCode(value:String, amount:String?) { - if let json = try? JSONSerialization.jsonObject(with: value.data(using: .utf8)!, options: .mutableContainers) as? [String: Any] { - - if let id = json["_id"] as? u_quad_t, let name = json["username"] as? String { + if TGBotManager.sharedManager.isValidUserFromJson(value: value) { + TGBotManager.sharedManager.startLinking { (_ ) in - TGBotManager.sharedManager.user.userId = String(id) - TGBotManager.sharedManager.user.userName = name - TGBotManager.sharedManager.startLinking { (_ ) in - - } } } } diff --git a/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.xib b/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.xib index 648fa786..5c332a0a 100644 --- a/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.xib +++ b/BeamWallet/ViewControllers/Main/Settings/SettingsViewController.xib @@ -18,7 +18,6 @@ - @@ -71,25 +70,6 @@ - - - - - - - - - - - - - - diff --git a/BeamWallet/ViewControllers/Main/Settings/UnlockPasswordViewController.swift b/BeamWallet/ViewControllers/Main/Settings/UnlockPasswordViewController.swift index 8a58c793..9753a068 100644 --- a/BeamWallet/ViewControllers/Main/Settings/UnlockPasswordViewController.swift +++ b/BeamWallet/ViewControllers/Main/Settings/UnlockPasswordViewController.swift @@ -52,7 +52,7 @@ class UnlockPasswordViewController: BaseWizardViewController { title = event == .unlock ? "Your password" : "Change password" - if Device.isZoomed{ + if Device.isZoomed { heightConstraint.constant = 250 } diff --git a/BeamWallet/ViewControllers/Main/UTXO/UTXODetailViewController.swift b/BeamWallet/ViewControllers/Main/UTXO/UTXODetailViewController.swift index 87296c79..d2bec868 100644 --- a/BeamWallet/ViewControllers/Main/UTXO/UTXODetailViewController.swift +++ b/BeamWallet/ViewControllers/Main/UTXO/UTXODetailViewController.swift @@ -46,7 +46,7 @@ class UTXODetailViewController: BaseViewController { fillDetailInfo() tableView.register(UTXODetailCell.self) - tableView.register(GeneralTransactionInfoCell.self) + tableView.register(GeneralInfoCell.self) tableView.register(UTXOTransactionCell.self) title = "UTXO Details" @@ -70,16 +70,16 @@ class UTXODetailViewController: BaseViewController { details.removeAll() if let kernel = history.first?.kernelId { - details.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: kernel, failed: false, canCopy:true)) + details.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: kernel, failed: false, canCopy:true, color: UIColor.white)) } - details.append(TransactionViewController.TransactionGeneralInfo(text: "UTXO type:", detail: utxo.typeString, failed: false, canCopy:true)) + details.append(TransactionViewController.TransactionGeneralInfo(text: "UTXO type:", detail: utxo.typeString, failed: false, canCopy:true, color: UIColor.white)) // for transaction in history { // if let contact = AppModel.sharedManager().getContactFromId(transaction.receiverAddress) // { // let value = contact.name.isEmpty ? contact.address.walletId : contact.name + "\n" + contact.address.walletId -// details.append(TransactionViewController.TransactionGeneralInfo(text: "Contact:", detail: value, failed: false, canCopy:true)) +// details.append(TransactionViewController.TransactionGeneralInfo(text: "Contact:", detail: value, failed: false, canCopy:true, color: UIColor.white)) // } // } } @@ -139,7 +139,7 @@ extension UTXODetailViewController : UITableViewDataSource { } else if indexPath.section == 1{ let cell = tableView - .dequeueReusableCell(withType: GeneralTransactionInfoCell.self, for: indexPath) + .dequeueReusableCell(withType: GeneralInfoCell.self, for: indexPath) .configured(with: details[indexPath.row]) return cell diff --git a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.swift b/BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.swift similarity index 78% rename from BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.swift rename to BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.swift index 32848459..0d3769d2 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.swift +++ b/BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.swift @@ -1,5 +1,5 @@ // -// GeneralTransactionInfoCell.swift +// GeneralInfoCell.swift // BeamWallet // // Copyright 2018 Beam Development @@ -19,13 +19,13 @@ import UIKit -protocol GeneralTransactionInfoCellDelegate: AnyObject { +protocol GeneralInfoCellDelegate: AnyObject { func onClickToCell(cell:UITableViewCell) } -class GeneralTransactionInfoCell: BaseCell { +class GeneralInfoCell: BaseCell { - weak var delegate: GeneralTransactionInfoCellDelegate? + weak var delegate: GeneralInfoCellDelegate? @IBOutlet weak private var titleLabel: UILabel! @IBOutlet weak private var detailLabel: BMCopyLabel! @@ -69,14 +69,14 @@ class GeneralTransactionInfoCell: BaseCell { } } -extension GeneralTransactionInfoCell: Configurable { +extension GeneralInfoCell: Configurable { func configure(with info:TransactionViewController.TransactionGeneralInfo) { titleLabel.text = info.text detailLabel.text = info.detail detailLabel.copyText = nil detailLabel.isUserInteractionEnabled = info.canCopy - + if info.failed { titleLabel.textColor = UIColor.main.red detailLabel.textColor = UIColor.main.red @@ -84,9 +84,25 @@ extension GeneralTransactionInfoCell: Configurable { else{ titleLabel.textColor = UIColor.main.blueyGrey detailLabel.textColor = UIColor.white + detailLabel.textColor = info.color } - if info.text == "Contact:" { + if info.text == "Sending address:" || info.text == "Receiving address:" { + if let category = AppModel.sharedManager().findCategory(byAddress: info.detail) + { + detailLabel.copyText = info.detail + + let text = info.detail + "\n" + category.name + let range = (text as NSString).range(of: String(category.name)) + + let attributedString = NSMutableAttributedString(string:text) + attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.init(hexString: category.color) , range: range) + attributedString.addAttribute(NSAttributedString.Key.font, value: UIFont(name: "SFProDisplay-Italic", size: 14) ?? UIFont.italicSystemFont(ofSize: 14) , range: range) + + detailLabel.attributedText = attributedString + } + } + else if info.text == "Contact:" { let split = info.detail.split(separator: "\n") if split.count == 2 { let contact = split[0] diff --git a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.xib b/BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.xib similarity index 97% rename from BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.xib rename to BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.xib index 2865312d..b57aa65f 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/GeneralTransactionInfoCell.xib +++ b/BeamWallet/ViewControllers/Main/Wallet/Cells/GeneralInfoCell.xib @@ -1,11 +1,11 @@ - + - + @@ -17,7 +17,7 @@ - + diff --git a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/TransactionPaymentProofCell.swift b/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/TransactionPaymentProofCell.swift index 5da9b2c5..579fac0d 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/TransactionPaymentProofCell.swift +++ b/BeamWallet/ViewControllers/Main/Wallet/Transaction/Cell/TransactionPaymentProofCell.swift @@ -1,5 +1,5 @@ // -// GeneralTransactionInfoCell.swift +// GeneralInfoCell.swift // BeamWallet // // Copyright 2018 Beam Development diff --git a/BeamWallet/ViewControllers/Main/Wallet/Transaction/PaymentProofDetailViewController.swift b/BeamWallet/ViewControllers/Main/Wallet/Transaction/PaymentProofDetailViewController.swift index 2c96880b..4fd41111 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/Transaction/PaymentProofDetailViewController.swift +++ b/BeamWallet/ViewControllers/Main/Wallet/Transaction/PaymentProofDetailViewController.swift @@ -53,7 +53,7 @@ class PaymentProofDetailViewController: BaseViewController { title = paymentProof == nil ? "Payment proof verification" : "Payment proof" - tableView.register(GeneralTransactionInfoCell.self) + tableView.register(GeneralInfoCell.self) fillTransactionInfo() @@ -95,13 +95,13 @@ class PaymentProofDetailViewController: BaseViewController { if let paymentProof = self.paymentProof, let transaction = self.transaction { var section_1 = [TransactionViewController.TransactionGeneralInfo]() - section_1.append(TransactionViewController.TransactionGeneralInfo(text: "Code:", detail: paymentProof.code, failed: false, canCopy:true)) + section_1.append(TransactionViewController.TransactionGeneralInfo(text: "Code:", detail: paymentProof.code, failed: false, canCopy:true, color: UIColor.white)) var section_2 = [TransactionViewController.TransactionGeneralInfo]() - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Sender:", detail: transaction.senderAddress, failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Receiver:", detail: transaction.receiverAddress, failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Amount:", detail: String.currency(value: transaction.realAmount) + " BEAM", failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Sender:", detail: transaction.senderAddress, failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Receiver:", detail: transaction.receiverAddress, failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Amount:", detail: String.currency(value: transaction.realAmount) + " BEAM", failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true, color: UIColor.white)) details.append(section_1) details.append(section_2) @@ -110,10 +110,10 @@ class PaymentProofDetailViewController: BaseViewController { } else if let transaction = self.transaction { var section_2 = [TransactionViewController.TransactionGeneralInfo]() - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Sender:", detail: transaction.senderAddress, failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Receiver:", detail: transaction.receiverAddress, failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Amount:", detail: String.currency(value: transaction.realAmount) + " BEAM", failed: false, canCopy:true)) - section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Sender:", detail: transaction.senderAddress, failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Receiver:", detail: transaction.receiverAddress, failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Amount:", detail: String.currency(value: transaction.realAmount) + " BEAM", failed: false, canCopy:true, color: UIColor.white)) + section_2.append(TransactionViewController.TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true, color: UIColor.white)) details.append(section_2) @@ -169,7 +169,7 @@ extension PaymentProofDetailViewController : UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView - .dequeueReusableCell(withType: GeneralTransactionInfoCell.self, for: indexPath) + .dequeueReusableCell(withType: GeneralInfoCell.self, for: indexPath) .configured(with: details[indexPath.section][indexPath.row]) return cell diff --git a/BeamWallet/ViewControllers/Main/Wallet/Transaction/TransactionViewController.swift b/BeamWallet/ViewControllers/Main/Wallet/Transaction/TransactionViewController.swift index 7a41ac54..be0f3e76 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/Transaction/TransactionViewController.swift +++ b/BeamWallet/ViewControllers/Main/Wallet/Transaction/TransactionViewController.swift @@ -32,6 +32,7 @@ class TransactionViewController: BaseViewController { var detail:String! var failed:Bool! var canCopy:Bool! + var color = UIColor.white } private var paymentProof:BMPaymentProof? @@ -45,7 +46,7 @@ class TransactionViewController: BaseViewController { title = "Transaction details" - tableView.register(GeneralTransactionInfoCell.self) + tableView.register(GeneralInfoCell.self) tableView.register(WalletTransactionCell.self) tableView.register(TransactionPaymentProofCell.self) tableView.register(TransactionUTXOCell.self) @@ -88,20 +89,23 @@ class TransactionViewController: BaseViewController { } details = [TransactionGeneralInfo]() - details.append(TransactionGeneralInfo(text: "Sending address:", detail: transaction.senderAddress, failed: false, canCopy:true)) - details.append(TransactionGeneralInfo(text: "Receiving address:", detail: transaction.receiverAddress, failed: false, canCopy:true)) - details.append(TransactionGeneralInfo(text: "Transaction fee:", detail: String.currency(value: transaction.fee), failed: false, canCopy:true)) - details.append(TransactionGeneralInfo(text: "Transaction ID: ", detail: transaction.id, failed: false, canCopy:true)) + details.append(TransactionGeneralInfo(text: "Sending address:", detail: transaction.senderAddress, failed: false, canCopy:true, color: UIColor.white)) - details.append(TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true)) + details.append(TransactionGeneralInfo(text: "Receiving address:", detail: transaction.receiverAddress, failed: false, canCopy:true, color: UIColor.white)) + + details.append(TransactionGeneralInfo(text: "Transaction fee:", detail: String.currency(value: transaction.fee), failed: false, canCopy:true, color: UIColor.white)) + + details.append(TransactionGeneralInfo(text: "Transaction ID: ", detail: transaction.id, failed: false, canCopy:true, color: UIColor.white)) + + details.append(TransactionGeneralInfo(text: "Kernel ID:", detail: transaction.kernelId, failed: false, canCopy:true, color: UIColor.white)) if !transaction.comment.isEmpty { - details.append(TransactionGeneralInfo(text: "Comment:", detail: transaction.comment, failed: false, canCopy:true)) + details.append(TransactionGeneralInfo(text: "Comment:", detail: transaction.comment, failed: false, canCopy:true, color: UIColor.white)) } if transaction.isFailed() { - details.append(TransactionGeneralInfo(text: "Failure reason:", detail: transaction.failureReason, failed: true, canCopy:true)) + details.append(TransactionGeneralInfo(text: "Failure reason:", detail: transaction.failureReason, failed: true, canCopy:true, color: UIColor.white)) } //utxos @@ -206,7 +210,7 @@ extension TransactionViewController : UITableViewDataSource { } else if indexPath.section == 1 { let cell = tableView - .dequeueReusableCell(withType: GeneralTransactionInfoCell.self, for: indexPath) + .dequeueReusableCell(withType: GeneralInfoCell.self, for: indexPath) .configured(with: details[indexPath.row]) cell.delegate = self return cell @@ -300,7 +304,7 @@ extension TransactionViewController: TransactionPaymentProofCellDelegate { } } -extension TransactionViewController : GeneralTransactionInfoCellDelegate { +extension TransactionViewController : GeneralInfoCellDelegate { func onClickToCell(cell: UITableViewCell) { if let path = tableView.indexPath(for: cell) { diff --git a/BeamWallet/ViewControllers/Main/Wallet/WalletViewController.swift b/BeamWallet/ViewControllers/Main/Wallet/WalletViewController.swift index 8563b2f8..6f4ac031 100644 --- a/BeamWallet/ViewControllers/Main/Wallet/WalletViewController.swift +++ b/BeamWallet/ViewControllers/Main/Wallet/WalletViewController.swift @@ -73,7 +73,7 @@ class WalletViewController: BaseViewController { rightButton() - if TGBotManager.sharedManager.user.userName.isEmpty == false { + if TGBotManager.sharedManager.isNeedLinking() { TGBotManager.sharedManager.startLinking { (_ ) in } diff --git a/BeamWalletNotificationView/Info.plist b/BeamWalletNotificationView/Info.plist index e0d6f4d4..a7b6ca51 100644 --- a/BeamWalletNotificationView/Info.plist +++ b/BeamWalletNotificationView/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 2.2 CFBundleVersion - 5 + 8 NSExtension NSExtensionAttributes diff --git a/Resources/Assets.xcassets/tick.imageset/Contents.json b/Resources/Assets.xcassets/tick.imageset/Contents.json new file mode 100644 index 00000000..d49af08a --- /dev/null +++ b/Resources/Assets.xcassets/tick.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tick.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tick@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/Assets.xcassets/tick.imageset/tick.png b/Resources/Assets.xcassets/tick.imageset/tick.png new file mode 100644 index 0000000000000000000000000000000000000000..e88d5252d506bcf9db665b7ae85b79140276b508 GIT binary patch literal 675 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2?f>5jgR3=A9lx&I`x0{IHb9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSzC zHb_`sNdc^+B->Ug!Z$#{Ilm}X!Bo#g&p^qJOF==wrYI%ND#*nRsvXF)RmvzSDX`Ml zFE20GD>v55FG|-pw6wI;H!#vSGSUUA&@HaaD@m--%_~-h7y>iLCAB!YD6^m>Ge1uO zWNuBXVDcO3ScPxhE2xv|lG^0(S0zQL#Z^Y(2m`o<%$ z<7A`kgzqg~^#Lq>GvYI}SM=X{C*8;_$C&*^^rA@d`v(UCuJE1ZU0+_BkoufC`tsZ- zUB|Xv+<3Kd=~a1$uROLFczY)}1z(ch<6NmKdt^p{%|*$#fi)%C4|12!&^JAB{zhIK q+ky)YVyR)ZtxNY$w|F+gyu&=;hxqfE8?4kpNx{?A&t;ucLK6UV*yCdW literal 0 HcmV?d00001 diff --git a/Resources/Assets.xcassets/tick.imageset/tick@2x.png b/Resources/Assets.xcassets/tick.imageset/tick@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..403b83ce01b78d05271a6603de029a233698aaf6 GIT binary patch literal 874 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8X6a5n0T@z;^_M8K-LV zNi#4oMrMXYltlRYSS9D@>LsS+C#C9DVstT4fPE4;bsH1+JHo@{EISEfi{E8 zw==W>t3(ll+GC>+vK+}V5TAlYfnK%aveAbJn;n)! z^{kkoQktch5)&triU7O96QMgT9BL_T(gls3oF^DI?qC11zbdL%{LZo^`QL+L&xfY& zUiI(fG`43N|BQY~P1-!+$SDVvqkmmyzmU;&m?^&Tsz7S{Z{47qa)+We&eq=Id&F9$ zqolQKred_q93|&tJ?374F?x<_oGBqvi;9lUyklT~CFBundleShortVersionString 2.2 CFBundleVersion - 4 + 8 Fabric APIKey diff --git a/Resources/InfoMasternet.plist b/Resources/InfoMasternet.plist index 280e731b..d80022f0 100644 --- a/Resources/InfoMasternet.plist +++ b/Resources/InfoMasternet.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString 2.2 CFBundleVersion - 6 + 8 Fabric APIKey diff --git a/Resources/InfoTestnet.plist b/Resources/InfoTestnet.plist index b0734301..ea9dd3d0 100644 --- a/Resources/InfoTestnet.plist +++ b/Resources/InfoTestnet.plist @@ -30,7 +30,7 @@ CFBundleVersion - 5 + 8 Fabric APIKey