From e0f408cc8acf4dfcbdca2fca007315d658b445f1 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 14:27:59 +0300 Subject: [PATCH 01/13] Removed Base localization --- Adamant.xcodeproj/project.pbxproj | 55 ++-- Adamant/Assets/en.lproj/InfoPlist.strings | 15 + Adamant/Assets/en.lproj/Localizable.strings | 304 ++++++++++++++++++ .../Localizable.stringsdict | 0 .../Account.storyboard | 0 .../Account/ru.lproj/Account.storyboard | 170 ++++++++++ .../Stories/Account/ru.lproj/Account.strings | 18 -- .../{Base.lproj => en.lproj}/Chats.storyboard | 0 .../Stories/Chats/ru.lproj/Chats.storyboard | 144 +++++++++ Adamant/Stories/Chats/ru.lproj/Chats.strings | 12 - .../{Base.lproj => en.lproj}/Login.storyboard | 0 .../Stories/Login/ru.lproj/Login.storyboard | 28 ++ Adamant/Stories/Login/ru.lproj/Login.strings | 1 - .../{Base.lproj => }/Settings.storyboard | 0 .../Settings/SettingsViewController.xib | 22 ++ .../Settings/ru.lproj/Settings.strings | 9 - 16 files changed, 709 insertions(+), 69 deletions(-) create mode 100644 Adamant/Assets/en.lproj/InfoPlist.strings create mode 100644 Adamant/Assets/en.lproj/Localizable.strings rename Adamant/Assets/{Base.lproj => en.lproj}/Localizable.stringsdict (100%) rename Adamant/Stories/Account/{Base.lproj => en.lproj}/Account.storyboard (100%) create mode 100644 Adamant/Stories/Account/ru.lproj/Account.storyboard delete mode 100644 Adamant/Stories/Account/ru.lproj/Account.strings rename Adamant/Stories/Chats/{Base.lproj => en.lproj}/Chats.storyboard (100%) create mode 100644 Adamant/Stories/Chats/ru.lproj/Chats.storyboard delete mode 100644 Adamant/Stories/Chats/ru.lproj/Chats.strings rename Adamant/Stories/Login/{Base.lproj => en.lproj}/Login.storyboard (100%) create mode 100644 Adamant/Stories/Login/ru.lproj/Login.storyboard delete mode 100644 Adamant/Stories/Login/ru.lproj/Login.strings rename Adamant/Stories/Settings/{Base.lproj => }/Settings.storyboard (100%) create mode 100644 Adamant/Stories/Settings/SettingsViewController.xib delete mode 100644 Adamant/Stories/Settings/ru.lproj/Settings.strings diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 65d927ded..1d186e22e 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -30,7 +30,6 @@ E91947B420002809001362F8 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91947B320002809001362F8 /* Account.swift */; }; E9256F5F2034C21100DE86E9 /* String+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9256F5E2034C21100DE86E9 /* String+localized.swift */; }; E9256F602034E0E100DE86E9 /* Chats.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F622034E0E100DE86E9 /* Chats.storyboard */; }; - E9256F632034E7DE00DE86E9 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F652034E7DE00DE86E9 /* Settings.storyboard */; }; E9256F692034E98700DE86E9 /* Login.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F6B2034E98700DE86E9 /* Login.storyboard */; }; E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9256F6C20357B1700DE86E9 /* LoginHeader.xib */; }; E9256F762039A9A200DE86E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */; }; @@ -52,6 +51,8 @@ E948E0482024F02700975D6B /* LoginFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = E948E0472024F02700975D6B /* LoginFooter.xib */; }; E948E04C2027679300975D6B /* AdamantExportTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E04B2027679300975D6B /* AdamantExportTools.swift */; }; E948E04E20278D5600975D6B /* SettingsDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E04D20278D5600975D6B /* SettingsDependencies.swift */; }; + E94E7AF5205D309B0042B639 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E94E7AF4205D309B0042B639 /* Settings.storyboard */; }; + E94E7AFB205D30F60042B639 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7AFA205D30F60042B639 /* SettingsViewController.xib */; }; E9502740202E257E002C1098 /* RepeaterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950273F202E257E002C1098 /* RepeaterService.swift */; }; E950652120404BF0008352E5 /* AdamantUriBuilding.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652020404BF0008352E5 /* AdamantUriBuilding.swift */; }; E950652320404C84008352E5 /* AdamantUriTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652220404C84008352E5 /* AdamantUriTools.swift */; }; @@ -205,14 +206,7 @@ E91947B12000246A001362F8 /* AdamantError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantError.swift; sourceTree = ""; }; E91947B320002809001362F8 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; E9256F5E2034C21100DE86E9 /* String+localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+localized.swift"; sourceTree = ""; }; - E9256F612034E0E100DE86E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Chats.storyboard; sourceTree = ""; }; - E9256F642034E7DE00DE86E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Settings.storyboard; sourceTree = ""; }; - E9256F6A2034E98700DE86E9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Login.storyboard; sourceTree = ""; }; E9256F6C20357B1700DE86E9 /* LoginHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LoginHeader.xib; sourceTree = ""; }; - E9256F6E2039A7E800DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Account.strings; sourceTree = ""; }; - E9256F6F2039A7E900DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Chats.strings; sourceTree = ""; }; - E9256F702039A7E900DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Login.strings; sourceTree = ""; }; - E9256F712039A7E900DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Settings.strings; sourceTree = ""; }; E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; E9256F7A2039B29A00DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; E9256F7F2039B29D00DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -224,15 +218,15 @@ E93D7ABF2052CF63005D19DC /* AdamantNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantNotificationService.swift; sourceTree = ""; }; E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SettingsViewController+StayIn.swift"; sourceTree = ""; }; E93D7AC620530F76005D19DC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; - E93D7AC920530F8E005D19DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = Base; path = Base.lproj/Localizable.stringsdict; sourceTree = ""; }; E93EFE12200D1156000BB482 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = ""; }; - E9452A4D20344834005BA34C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Account.storyboard; sourceTree = ""; }; E94883E6203F07CD00F6E1B0 /* PassphraseValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassphraseValidation.swift; sourceTree = ""; }; E948E03A20235E2300975D6B /* SettingsRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRoutes.swift; sourceTree = ""; }; E948E0452024DAE800975D6B /* AdamantUserInfoKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUserInfoKeys.swift; sourceTree = ""; }; E948E0472024F02700975D6B /* LoginFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoginFooter.xib; sourceTree = ""; }; E948E04B2027679300975D6B /* AdamantExportTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantExportTools.swift; sourceTree = ""; }; E948E04D20278D5600975D6B /* SettingsDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDependencies.swift; sourceTree = ""; }; + E94E7AF4205D309B0042B639 /* Settings.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; + E94E7AFA205D30F60042B639 /* SettingsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = ""; }; E950273F202E257E002C1098 /* RepeaterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeaterService.swift; sourceTree = ""; }; E950652020404BF0008352E5 /* AdamantUriBuilding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriBuilding.swift; sourceTree = ""; }; E950652220404C84008352E5 /* AdamantUriTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriTools.swift; sourceTree = ""; }; @@ -263,6 +257,15 @@ E9722065201F42BB004F2AAD /* CoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = ""; }; E9722067201F42CC004F2AAD /* InMemoryCoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InMemoryCoreDataStack.swift; sourceTree = ""; }; E972206A201F44CA004F2AAD /* TransfersProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransfersProvider.swift; sourceTree = ""; }; + E982A8D2205D2A5D0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Login.storyboard; sourceTree = ""; }; + E982A8D3205D2A5D0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Chats.storyboard; sourceTree = ""; }; + E982A8D5205D2A5F0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Account.storyboard; sourceTree = ""; }; + E982A8D6205D2A610097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + E982A8D7205D2A910097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; + E982A8D8205D2AA70097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Login.storyboard; sourceTree = ""; }; + E982A8D9205D2AA70097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Chats.storyboard; sourceTree = ""; }; + E982A8DB205D2AA80097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Account.storyboard; sourceTree = ""; }; + E982A8DC205D2AB40097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; E982F69B20235B4D00566AC7 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; E9942B7F203C058C00C163AF /* QRGeneratorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRGeneratorViewController.swift; sourceTree = ""; }; E9942B83203CBFCE00C163AF /* AdamantQRTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantQRTools.swift; sourceTree = ""; }; @@ -585,9 +588,10 @@ E982F69820235AF000566AC7 /* Settings */ = { isa = PBXGroup; children = ( - E9256F652034E7DE00DE86E9 /* Settings.storyboard */, + E94E7AF4205D309B0042B639 /* Settings.storyboard */, E948E04D20278D5600975D6B /* SettingsDependencies.swift */, E948E03A20235E2300975D6B /* SettingsRoutes.swift */, + E94E7AFA205D30F60042B639 /* SettingsViewController.xib */, E982F69B20235B4D00566AC7 /* SettingsViewController.swift */, E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */, E9942B7F203C058C00C163AF /* QRGeneratorViewController.swift */, @@ -779,7 +783,6 @@ hasScannedForEncodings = 0; knownRegions = ( en, - Base, ); mainGroup = E913C8E51FFFA51D001A83F7; productRefGroup = E913C8EF1FFFA51D001A83F7 /* Products */; @@ -806,6 +809,7 @@ E9256F692034E98700DE86E9 /* Login.storyboard in Resources */, E9942B89203D9ECA00C163AF /* QrCell.xib in Resources */, E9C51EED2011416E00385EB7 /* adamant-core.js in Resources */, + E94E7AF5205D309B0042B639 /* Settings.storyboard in Resources */, E90A4945204C6204009F6A65 /* PassphraseCell.xib in Resources */, E9E7CDC82003F6D200DFC4DB /* TransactionTableViewCell.xib in Resources */, E9EC3417200524CA00C0E546 /* Exo+2_400_italic.ttf in Resources */, @@ -814,7 +818,6 @@ E9256F7E2039B29D00DE86E9 /* InfoPlist.strings in Resources */, E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */, E9EC3416200524CA00C0E546 /* Exo+2_300_normal.ttf in Resources */, - E9256F632034E7DE00DE86E9 /* Settings.storyboard in Resources */, E9EC341C200524CA00C0E546 /* Roboto_400_italic.ttf in Resources */, E9256F792039B29A00DE86E9 /* Localizable.strings in Resources */, E93D7AC520530F76005D19DC /* Localizable.stringsdict in Resources */, @@ -822,6 +825,7 @@ E9EC341A200524CA00C0E546 /* Exo+2_700_normal.ttf in Resources */, E9EC341D200524CA00C0E546 /* Roboto_400_normal.ttf in Resources */, E9A174B920587B84003667CD /* notification.mp3 in Resources */, + E94E7AFB205D30F60042B639 /* SettingsViewController.xib in Resources */, E9256F602034E0E100DE86E9 /* Chats.storyboard in Resources */, E9EC3418200524CA00C0E546 /* Exo+2_400_normal.ttf in Resources */, E948E0482024F02700975D6B /* LoginFooter.xib in Resources */, @@ -1059,26 +1063,17 @@ E9256F622034E0E100DE86E9 /* Chats.storyboard */ = { isa = PBXVariantGroup; children = ( - E9256F612034E0E100DE86E9 /* Base */, - E9256F6F2039A7E900DE86E9 /* ru */, + E982A8D3205D2A5D0097FAE7 /* ru */, + E982A8D9205D2AA70097FAE7 /* en */, ); name = Chats.storyboard; sourceTree = ""; }; - E9256F652034E7DE00DE86E9 /* Settings.storyboard */ = { - isa = PBXVariantGroup; - children = ( - E9256F642034E7DE00DE86E9 /* Base */, - E9256F712039A7E900DE86E9 /* ru */, - ); - name = Settings.storyboard; - sourceTree = ""; - }; E9256F6B2034E98700DE86E9 /* Login.storyboard */ = { isa = PBXVariantGroup; children = ( - E9256F6A2034E98700DE86E9 /* Base */, - E9256F702039A7E900DE86E9 /* ru */, + E982A8D2205D2A5D0097FAE7 /* ru */, + E982A8D8205D2AA70097FAE7 /* en */, ); name = Login.storyboard; sourceTree = ""; @@ -1087,6 +1082,7 @@ isa = PBXVariantGroup; children = ( E9256F7A2039B29A00DE86E9 /* ru */, + E982A8D6205D2A610097FAE7 /* en */, ); name = Localizable.strings; sourceTree = ""; @@ -1095,6 +1091,7 @@ isa = PBXVariantGroup; children = ( E9256F7F2039B29D00DE86E9 /* ru */, + E982A8DC205D2AB40097FAE7 /* en */, ); name = InfoPlist.strings; sourceTree = ""; @@ -1103,7 +1100,7 @@ isa = PBXVariantGroup; children = ( E93D7AC620530F76005D19DC /* ru */, - E93D7AC920530F8E005D19DC /* Base */, + E982A8D7205D2A910097FAE7 /* en */, ); name = Localizable.stringsdict; sourceTree = ""; @@ -1111,8 +1108,8 @@ E9452A4E20344834005BA34C /* Account.storyboard */ = { isa = PBXVariantGroup; children = ( - E9452A4D20344834005BA34C /* Base */, - E9256F6E2039A7E800DE86E9 /* ru */, + E982A8D5205D2A5F0097FAE7 /* ru */, + E982A8DB205D2AA80097FAE7 /* en */, ); name = Account.storyboard; sourceTree = ""; diff --git a/Adamant/Assets/en.lproj/InfoPlist.strings b/Adamant/Assets/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..2cd714a50 --- /dev/null +++ b/Adamant/Assets/en.lproj/InfoPlist.strings @@ -0,0 +1,15 @@ +/* (No Comment) */ +"CFBundleDisplayName" = "Адамант"; + +/* (No Comment) */ +"CFBundleName" = ""; + +/* (No Comment) */ +"NSCameraUsageDescription" = "Необходим доступ к Камере для чтения QR-кодов с адресами и паролями"; + +/* (No Comment) */ +"NSPhotoLibraryAddUsageDescription" = "Необходим доступ к Фотографиям для сохранения созданных QR-кодов"; + +/* (No Comment) */ +"NSPhotoLibraryUsageDescription" = "Необходим доступ к Фотографиям для сканирования QR-кодов с адресами и паролями со сделанных ранее фотографий"; + diff --git a/Adamant/Assets/en.lproj/Localizable.strings b/Adamant/Assets/en.lproj/Localizable.strings new file mode 100644 index 000000000..cb7448de4 --- /dev/null +++ b/Adamant/Assets/en.lproj/Localizable.strings @@ -0,0 +1,304 @@ +/* New chat: Remote server returned an error. */ +"%@" = "%@"; + +/* Product name */ +"ADAMANT" = "АДАМАНТ"; + +/* Wallet page: Account section title. */ +"Account" = "Аккаунт"; + +/* ApiService: Account not found error, appending account info. */ +"Account not found: %@" = "Аккаунт не найден: %@"; + +/* Wallet page: Actions section title */ +"Actions" = "Действия"; + +/* Transfer: recipient address */ +"Address" = "Адрес"; + +/* New chat: Notify user that specified address (%@) not found */ +"Address %@ not found" = "Адрес %@ не найден"; + +/* Transfer: Address not found error */ +"Address not found" = "Такой адрес не найден"; + +/* Transaction details: amount row. + Transfer: amount of adamant to transfer. */ +"Amount" = "Количество"; + +/* Config: Application Info section */ +"Application info" = "Приложение"; + +/* Transfer: logged user balance. + Wallet page: Balance row title */ +"Balance" = "Баланс"; + +/* Transaction details: Block id row. */ +"Block" = "Блок"; + +/* Shared alert 'Cancel' button. Used anywhere */ +"Cancel" = "Отмена"; + +/* Transaction details: confirmations row. */ +"Confirmations" = "Подтверждений"; + +/* Shared alert notification: message about item copied to pasteboard. */ +"Copied to Pasteboard" = "Скопировано!"; + +/* Shared alert 'Copy' button. Used anywhere. Used for copy-paste info. */ +"Copy to Pasteboard" = "Копировать"; + +/* Transaction details: date row. */ +"Date" = "Дата"; + +/* Config: turn off 'Stay Logged In' confirmation */ +"Do not stay logged in" = "Выходить из системы при выходе из приложения"; + +/* Config: Authorization reason for turning biometry off */ +"Do not use biometry to log in" = "Отключить вход с биометрией"; + +/* Shared alert Done message. Used anywhere */ +"Done" = "Готово"; + +/* Wallet page: Inform user that sending tokens not allowed by Apple until the end of ICO */ +"Due to Apple restrictions, sending tokens is not allowed until the end of the ICO. For now, you can send tokens using WebApp at msg.adamant.im" = "Ввиду ограничений Apple, отправка токенов отключена до конца ICO. В данный момент вы можете отправлять токены с помощью WebApp по адресу msg.adamant.im"; + +/* Login: notify user that he is trying to login without a passphrase */ +"Enter a passphrase!" = "Введите пароль"; + +/* QRGenerator: user typed in wrong invalid */ +"Enter correct passphrase" = "Введите корректный пароль"; + +/* Pinpad: Ask user to create new pin */ +"Enter new pin" = "Введите новый пин"; + +/* Shared alert 'Error' title. Used anywhere */ +"Error" = "Ошибка"; + +/* Chat: input bar: Estimated fee */ +"~%@" = "~%@"; + +/* Transaction details: fee row. */ +"Fee" = "Комиссия"; + +/* Transaction details: sender row. */ +"From" = "Отправитель"; + +/* Transfer: Tokens transfered successfully message */ +"Funds sended!" = "Токены переведены!"; + +/* Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere. */ +"Generate QR Code" = "Создать QR-код"; + +/* Config: Generate QR with passphrase row */ +"Generate QR with passphrase" = "Создать QR-код с паролем"; + +/* Login: generate new passphrase button */ +"Generate new passphrase" = "Создать новый"; + +/* Wallet page: 'Transfer not allowed' alert 'go to WebApp button' */ +"Go to msg.adamant.im" = "Открыть msg.adamant.im"; + +/* Transaction details: Id row. */ +"Id" = "Номер"; + +/* Wallet page: 'Invest in ICO' button */ +"Invest in ICO" = "Инвестировать в ICO"; + +/* Login: notify user that we a logging in */ +"Logging in" = "Входим..."; + +/* Login: Login button + Login: login with existing passphrase section */ +"Login" = "Вход"; + +/* Login: Login into previous account with biometry or pincode */ +"Login into Adamant" = "Вход в Адамант"; + +/* Wallet page: 'Logout' button + Wallet page: Confirm logout alert: Logout (Ok) button */ +"Logout" = "Выход"; + +/* Wallet page: Confirm logout alert */ +"Logout from %@?" = "Выйти из %@?"; + +/* Transfer: maximum amount to transfer: available account money substracting transfer fee. */ +"Max to transfer" = "Доступно для перевода"; + +/* Chat: Notify user that message cannot be empty */ +"Message is empty" = "Сообщение пусто!"; + +/* Chat: Message is too long */ +"Message is too long" = "Сообщение слишком длинное"; + +/* Login: Create new account section */ +"New account" = "Новый аккаунт"; + +/* Chat: message input placeholder + Notifications: New message notification title */ +"New message" = "Новое сообщение"; + +/* Notifications: New transfer transaction title */ +"New transfer" = "Новый перевод"; + +/* ApiService: No connection message. Generally bad network. */ +"No connection" = "Нет соединения с интернетом"; + +/* Login: No network error. */ +"No connection with The Internet" = "Нет соединения с сетью"; + +/* Config: Show notifications */ +"Notifications" = "Уведомления"; + +/* Notifications: User has disabled notifications. Head him into settings */ +"Notifications disabled. You can reenable notifications in Settings" = "Уведомления отключены. Вы можете включить их в Настройках"; + +/* Shared alert 'Ok' button. Used anywhere */ +"Ok" = "Ок"; + +/* Transaction details: 'Open transaction in explorer' row. */ +"Open in Explorer" = "Открыть в Explorer"; + +/* Login: Passphrase placeholder + QRGenerator: Passphrase textview placeholder */ +"Passphrase" = "Пароль"; + +/* Login: Login with pincode button */ +"Login with Pincode" = "Войти с pin-кодом"; + +/* Transfer: Address validation error */ +"Please enter a valid recipient address" = "Введите корректный адрес получателя"; + +/* New chat: Notify user that he did enter invalid address */ +"Please specify valid recipient address" = "Неверный адрес"; + +/* Login: Login with QR button. */ +"Login with QR" = "Войти с QR-кодом"; + +/* New Chat: Notify user that scanned QR doesn't contains an address */ +"QR code does not contains a valid adamant address" = "QR код не содержит адреса"; + +/* Login: Notify user that scanned QR doesn't contains a passphrase. */ +"QR code does not contains a valid passphrase" = "QR код не содержит пароля"; + +/* Login: Notify user that device not supported by QR reader */ +"QR codes reading not supported by the current device" = "На этом устройстве не поддерживается чтение QR кодов"; + +/* Pinpad: Ask user to repeat new pin */ +"Re-enter new pin" = "Введите пин ещё раз"; + +/* Shared alert 'Save' button. Used anywhere */ +"Save" = "Сохранить"; + +/* Login: security alert, notify user that he must save his new passphrase */ +"Save the passphrase for new Wallet and Messenger account. There is no login to enter Wallet, only the passphrase needed. If lost, no way to recover it" = "Это пароль для нового Кошелька и Мессенджера. Сохраните его! Для входа в Кошелек не нужно логина, только этот пароль. Восстановление пароля невозможно."; + +/* New chat: Scan QR with address button */ +"Scan QR" = "Сканировать QR код"; + +/* Chat: Send message button + Transfer: Confirm transfer alert: Send tokens button */ +"Send" = "Отправить"; + +/* Transfer: Confirm transfer X tokens to Y message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'. */ +"Send %1$@ to %2$@?" = "Отправить %1$@ получателю %2$@?"; + +/* Transfer: Send button */ +"Send Funds" = "Отправить токены"; + +/* Wallet page: 'Send tokens' button */ +"Send Tokens" = "Отправить токены"; + +/* Transfer: Processing message */ +"Sending funds..." = "Отправляем токены..."; + +/* Config: Settings section + Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title. */ +"Settings" = "Настройки"; + +/* Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu. */ +"Share" = "Поделиться"; + +/* Wallet page: 'Transfer not allowed' alert title */ +"Sorry!" = "Ой!"; + +/* Config: Stay logged option */ +"Stay Logged in" = "Оставаться в сети"; + +/* Export transaction: 'Share transaction summary' button */ +"Summary" = "Сводка"; + +/* Login: a small hint for a user, that he can tap on passphrase to save it + QRGenerator: small 'Tap to save' tooltip under generated QR */ +"Tap to save" = "Нажмите для сохранения"; + +/* Transaction details: recipient row. */ +"To" = "Получатель"; + +/* Transfer: total amount of transaction: money to transfer adding fee */ +"Total" = "Итого"; + +/* Transfer: transfer fee */ +"Transaction fee" = "Комиссия"; + +/* Transfer: 'Transfer info' section */ +"Transfer Info" = "Перевод"; + +/* Export transaction: 'Share transaction URL' button */ +"URL" = "URL"; + +/* Unknown internal error */ +"Unknown error" = "Неизвестная ошибка"; + +/* Config: Authorization reason for turning biometry on */ +"Use biometry to log in" = "Использовать биометрию для входа в систему"; + +/* ApiService: User not logged error + Login: user not logged error */ +"User not logged" = "Не выполнен вход"; + +/* Config: Utilities section */ +"Utilities" = "Утилиты"; + +/* Config: Version row */ +"Version" = "Версия"; + +/* Wallet page: Wallet section title */ +"Wallet" = "Кошелёк"; + +/* Known contacts: Adamant welcome message */ +"Welcome to ADAMANT, the most secure and anonymous messenger. You are credited with bounty tokens, which you can use to get acquainted with the messenger.\nRemember, your security and anonymity is up to you also. Do not follow links you receive, otherwise your IP can be compromised. Do not trust browser extensions. Better to share your ADM address personally, but not using other messengers. Keep your secret passphrase secure. Set a password on your device or logout before leaving.\nLearn more about security and anonymity at https://adamant.im/staysecured/.\n\nDo not reply to this message, it is a system account." = "Добро пожаловать в самый анонимный и безопасный мессенджер АДАМАНТ. Вам начислены приветственные токены, которые вы можете использовать для ознакомления с мессенджером.\nПомните, что безопасность и анонимность зависит и от вас самих. Не переходите по ссылкам, которые вы получаете в чатах, иначе ваш IP-адрес может быть определен. Не доверяйте расширениям браузера. Лучше всего передавать ваш ADM-адрес собеседникам лично, а не через другие мессенджеры. Храните вашу секретную фразу (пароль) от аккаунта в тайне. Установите на ваше устройство пароль или закрываете вкладку браузера после завершения диалогов.\nБолее полную информацию о безопасности и анонимности читайте на странице https://adamant.im/ru-staysecured/\n\nНе отвечайте на это сообщение, этот адрес служебный."; + +/* Login: user typed in wrong passphrase */ +"Wrong passphrase!" = "Неправильный пароль"; + +/* Chat: Notify user that he doesn't have money to pay a message fee */ +"You don't have enough money to send a message" = "Недостаточно токенов для отправки сообщения"; + +/* Transfer: Amount is hiegher that user's total money notification */ +"You don't have that much money" = "У вас нет столько токенов"; + +/* New chat: Notify user that he can't start chat with himself */ +"You don't need an encrypted anonymous chat to talk to yourself" = "Вам не нужен анонимный чат, чтобы говорить с самим собой"; + +/* Known contacts: Adamant pre ICO message */ +"You have a possibility to invest in ADAMANT, the most secure and anonymous messenger. Now is a Pre-ICO stage — the most profitable for investors. Learn more on Adamant.im website or in the Whitepaper. To participate just reply to this message and we will assist. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "Сегодня последний день, когда мы принимаем инвестиции по минимальной цене 0.001 ETH за токен ADM до начала публичного сейла ICO — 30.01. Это самые выгодные условия для инвесторов. Минимальная инвестиция — эквивалент 2 ETH (на этапе публичного сейла ограничений по минимальной сумме нет, но цена токена начинается с 0.002 ETH). Подробная информация о проекте АДАМАНТ на сайте Adamant.im и в Белой книге. Для участия достаточно ответить на это сообщение, и мы вам поможем."; + +/* Known contacts: Adamant ICO message */ +"You have a possibility to invest in ICO of ADAMANT, the most secure and anonymous messenger. Earlier you participate, better offer you will get. Learn more on Adamant.im website or in the Whitepaper. To invest, go to Wallet→Invest in the ICO, or follow a website page Adamant.im/ico/. If you still have any questions, you can ask them by replying to this message. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "У вас есть возможность инвестировать в ICO самого защищенного мессенджера АДАМАНТ. Более раннее участие — более выгодные условия. Подробная информация об условиях на сайте Adamant.im и в Белой книге проекта. Если вы уже ознакомились с нашим сайтом и Белой книгой, но у вас остались вопросы, вы можете задать их, ответив на это сообщение. Мы стараемся реагировать быстро, но иногда возможны задержки до нескольких часов.\nВажно! Пожалуйста, убедитесь, что вы сохранили пароль к этому аккаунту — выйдите из аккаунта и войдите в него снова. Лучше всего иметь запись пароля и на бумаге. Однако помните, только вы несете ответственность за сохранность вашего пароля. Его невозможно восстановить. А если он попадет в другие руки, ваши деньги будут украдены. Отнеситесь к этому вопросу так серьезно, как если бы цена токенов на вашем кошельке когда-то станет равна миллиарду долларов.\nЧтобы инвестировать, перейдите в этом месседжере на вкладку Кошелек и нажмите кнопку Инвестировать в ICO, или откройте в браузере веб-страницу Adamant.im/ico/. В форме для инвестирования укажите ваш адрес АДАМАНТа — на него будут перечислены токены ADM. При переходе из мессенджера он будет вставлен автоматически, в другом случае вернитесь в мессенджер и кликните на блок Ваш адрес, он будет скопирован в буфер обмена. Укажите криптовалюту, в которой вы хотите инвестировать, и какую сумму. Вы увидите сколько ADM-токенов вы получите, с учетом скидки за объем: 20–30 ETH: +20%, 30–50 ETH: +30%, 50–90 ETH: +40%, 90+ ETH: +50%. Нажмите кнопку Купить токены АДАМАНТ. Вы получите уникальный адрес, на который необходимо выполнить перевод. Как только на него поступит ожидаемая сумма и транзакция будет подтверждена, вы получите токены ADM. Транзакцию можно выполнить с любого кошелька, включая биржи. Необязятельно переводить точную сумму с учетом комиссии, платеж все равно будет засчитан. Остались вопросы? Спрашивайте.\nПосле того, как вы инвестируете и получите токены ADM, мы рекомендуем вам хранить их в кошельке как можно дольше. Ежемесячно все нераспроданные на ICO токены будут распределяться по кошелькам пользователей, увеличивая балансы на 5%. Подробную информацию можно получить на сайте Adamant.im и в Белой книге Проекта."; + +/* Login: Notify user, that he disabled camera in settings, and need to authorize application. */ +"You need to authorize Adamant to use device's Camera" = "Для чтения QR кодов необходимо разрешить доступ к камере"; + +/* Transfer: Amount is zero, or even negative notification */ +"You should send more money" = "Нужно отправить больше токенов"; + +/* Transfer: 'Your wallet' section */ +"Your wallet" = "Ваш кошелёк"; + +/* Transfer: recipient address placeholder */ +"of the recipient" = "получателя"; + +/* Transfer: transfer amount placeholder */ +"to send" = "для перевода"; + diff --git a/Adamant/Assets/Base.lproj/Localizable.stringsdict b/Adamant/Assets/en.lproj/Localizable.stringsdict similarity index 100% rename from Adamant/Assets/Base.lproj/Localizable.stringsdict rename to Adamant/Assets/en.lproj/Localizable.stringsdict diff --git a/Adamant/Stories/Account/Base.lproj/Account.storyboard b/Adamant/Stories/Account/en.lproj/Account.storyboard similarity index 100% rename from Adamant/Stories/Account/Base.lproj/Account.storyboard rename to Adamant/Stories/Account/en.lproj/Account.storyboard diff --git a/Adamant/Stories/Account/ru.lproj/Account.storyboard b/Adamant/Stories/Account/ru.lproj/Account.storyboard new file mode 100644 index 000000000..e4b16c796 --- /dev/null +++ b/Adamant/Stories/Account/ru.lproj/Account.storyboard @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Account/ru.lproj/Account.strings b/Adamant/Stories/Account/ru.lproj/Account.strings deleted file mode 100644 index 6c30b60b6..000000000 --- a/Adamant/Stories/Account/ru.lproj/Account.strings +++ /dev/null @@ -1,18 +0,0 @@ -/* Class = "UINavigationItem"; title = "Transactions"; ObjectID = "63z-aT-Hem"; */ -"63z-aT-Hem.title" = "Транзакции"; - -/* Class = "UIBarButtonItem"; title = "Send"; ObjectID = "EEV-td-OPY"; */ -"EEV-td-OPY.title" = "Отправить"; - -/* Class = "UINavigationItem"; title = "Transaction"; ObjectID = "FG4-t0-tQk"; */ -"FG4-t0-tQk.title" = "Транзакция"; - -/* Class = "UITabBarItem"; title = "Wallet"; ObjectID = "OLR-zA-lhu"; */ -"OLR-zA-lhu.title" = "Кошелёк"; - -/* Class = "UINavigationItem"; title = "Account"; ObjectID = "dte-Ko-zLE"; */ -"dte-Ko-zLE.title" = "Аккаунт"; - -/* Class = "UINavigationItem"; title = "Send Tokens"; ObjectID = "qwn-Er-hr0"; */ -"qwn-Er-hr0.title" = "Отправить токены"; - diff --git a/Adamant/Stories/Chats/Base.lproj/Chats.storyboard b/Adamant/Stories/Chats/en.lproj/Chats.storyboard similarity index 100% rename from Adamant/Stories/Chats/Base.lproj/Chats.storyboard rename to Adamant/Stories/Chats/en.lproj/Chats.storyboard diff --git a/Adamant/Stories/Chats/ru.lproj/Chats.storyboard b/Adamant/Stories/Chats/ru.lproj/Chats.storyboard new file mode 100644 index 000000000..f2f134f5d --- /dev/null +++ b/Adamant/Stories/Chats/ru.lproj/Chats.storyboard @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Chats/ru.lproj/Chats.strings b/Adamant/Stories/Chats/ru.lproj/Chats.strings deleted file mode 100644 index 2e64e06a6..000000000 --- a/Adamant/Stories/Chats/ru.lproj/Chats.strings +++ /dev/null @@ -1,12 +0,0 @@ -/* Class = "UITabBarItem"; title = "Chats"; ObjectID = "Kcp-hK-Mxk"; */ -"Kcp-hK-Mxk.title" = "Чаты"; - -/* Class = "UINavigationItem"; title = "Chats"; ObjectID = "NNn-vk-aSk"; */ -"NNn-vk-aSk.title" = "Чаты"; - -/* Class = "UINavigationItem"; title = "New Chat"; ObjectID = "R9S-0N-t3f"; */ -"R9S-0N-t3f.title" = "Новый чат"; - -/* Class = "UIBarButtonItem"; title = "•••"; ObjectID = "v2Z-hT-nNQ"; */ -"v2Z-hT-nNQ.title" = "•••"; - diff --git a/Adamant/Stories/Login/Base.lproj/Login.storyboard b/Adamant/Stories/Login/en.lproj/Login.storyboard similarity index 100% rename from Adamant/Stories/Login/Base.lproj/Login.storyboard rename to Adamant/Stories/Login/en.lproj/Login.storyboard diff --git a/Adamant/Stories/Login/ru.lproj/Login.storyboard b/Adamant/Stories/Login/ru.lproj/Login.storyboard new file mode 100644 index 000000000..7a8b3862e --- /dev/null +++ b/Adamant/Stories/Login/ru.lproj/Login.storyboard @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Login/ru.lproj/Login.strings b/Adamant/Stories/Login/ru.lproj/Login.strings deleted file mode 100644 index 874e8a453..000000000 --- a/Adamant/Stories/Login/ru.lproj/Login.strings +++ /dev/null @@ -1 +0,0 @@ -/* No Localized Strings */ diff --git a/Adamant/Stories/Settings/Base.lproj/Settings.storyboard b/Adamant/Stories/Settings/Settings.storyboard similarity index 100% rename from Adamant/Stories/Settings/Base.lproj/Settings.storyboard rename to Adamant/Stories/Settings/Settings.storyboard diff --git a/Adamant/Stories/Settings/SettingsViewController.xib b/Adamant/Stories/Settings/SettingsViewController.xib new file mode 100644 index 000000000..f0eedefa9 --- /dev/null +++ b/Adamant/Stories/Settings/SettingsViewController.xib @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Settings/ru.lproj/Settings.strings b/Adamant/Stories/Settings/ru.lproj/Settings.strings deleted file mode 100644 index dd861a520..000000000 --- a/Adamant/Stories/Settings/ru.lproj/Settings.strings +++ /dev/null @@ -1,9 +0,0 @@ -/* Class = "UINavigationItem"; title = "Settings"; ObjectID = "81x-yd-4F2"; */ -"81x-yd-4F2.title" = "Настройки"; - -/* Class = "UITabBarItem"; title = "Settings"; ObjectID = "Igt-Ig-iLK"; */ -"Igt-Ig-iLK.title" = "Настройки"; - -/* Class = "UINavigationItem"; title = "QR Passphrase"; ObjectID = "YBG-RB-W62"; */ -"YBG-RB-W62.title" = "QR-пароль"; - From c4a3dcbc44c399bb9788dcc15fd59f14ea58a3eb Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 17:46:47 +0300 Subject: [PATCH 02/13] Storyboards to xib grand refactoring. Router refactored. pod 'SwinjectStoryboard' removed. --- Adamant.xcodeproj/project.pbxproj | 112 ++++-------- Adamant/AppDelegate.swift | 46 +++-- Adamant/ServiceProtocols/Router.swift | 34 +--- Adamant/Services/SwinjectedRouter.swift | 16 +- .../Stories/Account/AccountDependencies.swift | 31 ---- Adamant/Stories/Account/AccountRoutes.swift | 25 ++- .../Account/AccountViewController.swift | 27 +-- .../Stories/Account/AccountViewController.xib | 39 ++++ .../Account/en.lproj/Account.storyboard | 170 ------------------ .../Account/ru.lproj/Account.storyboard | 170 ------------------ ...ler.swift => ChatListViewController.swift} | 71 ++++---- .../Stories/Chats/ChatListViewController.xib | 39 ++++ .../Stories/Chats/ChatViewController.swift | 1 + Adamant/Stories/Chats/ChatsDependencies.swift | 31 ---- Adamant/Stories/Chats/ChatsRoutes.swift | 39 +++- .../Stories/Chats/NewChatViewController.swift | 5 + .../Stories/Chats/en.lproj/Chats.storyboard | 144 --------------- .../Stories/Chats/ru.lproj/Chats.storyboard | 144 --------------- Adamant/Stories/Login/LoginDependencies.swift | 20 --- Adamant/Stories/Login/LoginRoutes.swift | 17 +- .../Stories/Login/en.lproj/Login.storyboard | 28 --- .../Stories/Login/ru.lproj/Login.storyboard | 28 --- .../Settings/QRGeneratorViewController.swift | 2 + Adamant/Stories/Settings/Settings.storyboard | 72 -------- .../Settings/SettingsDependencies.swift | 24 --- Adamant/Stories/Settings/SettingsRoutes.swift | 27 ++- .../Settings/SettingsViewController.swift | 11 +- .../Settings/SettingsViewController.xib | 22 --- Adamant/Stories/Shared/SharedRoutes.swift | 17 ++ .../TransactionDetailsViewController.swift | 2 +- .../TransactionDetailsViewController.xib | 39 ++++ .../Transactions/TransactionsRoutes.swift | 27 +++ .../TransactionsViewController.swift | 17 +- .../TransactionsViewController.xib | 39 ++++ Adamant/SwinjectDependencies.swift | 9 +- Podfile | 5 +- Podfile.lock | 10 +- 37 files changed, 432 insertions(+), 1128 deletions(-) delete mode 100644 Adamant/Stories/Account/AccountDependencies.swift create mode 100644 Adamant/Stories/Account/AccountViewController.xib delete mode 100644 Adamant/Stories/Account/en.lproj/Account.storyboard delete mode 100644 Adamant/Stories/Account/ru.lproj/Account.storyboard rename Adamant/Stories/Chats/{ChatsListViewController.swift => ChatListViewController.swift} (83%) create mode 100644 Adamant/Stories/Chats/ChatListViewController.xib delete mode 100644 Adamant/Stories/Chats/ChatsDependencies.swift delete mode 100644 Adamant/Stories/Chats/en.lproj/Chats.storyboard delete mode 100644 Adamant/Stories/Chats/ru.lproj/Chats.storyboard delete mode 100644 Adamant/Stories/Login/LoginDependencies.swift delete mode 100644 Adamant/Stories/Login/en.lproj/Login.storyboard delete mode 100644 Adamant/Stories/Login/ru.lproj/Login.storyboard delete mode 100644 Adamant/Stories/Settings/Settings.storyboard delete mode 100644 Adamant/Stories/Settings/SettingsDependencies.swift delete mode 100644 Adamant/Stories/Settings/SettingsViewController.xib create mode 100644 Adamant/Stories/Shared/SharedRoutes.swift rename Adamant/Stories/{Account => Transactions}/TransactionDetailsViewController.swift (98%) create mode 100644 Adamant/Stories/Transactions/TransactionDetailsViewController.xib create mode 100644 Adamant/Stories/Transactions/TransactionsRoutes.swift rename Adamant/Stories/{Account => Transactions}/TransactionsViewController.swift (91%) create mode 100644 Adamant/Stories/Transactions/TransactionsViewController.xib diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 1d186e22e..777cead9a 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -29,8 +29,6 @@ E91947B22000246A001362F8 /* AdamantError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91947B12000246A001362F8 /* AdamantError.swift */; }; E91947B420002809001362F8 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = E91947B320002809001362F8 /* Account.swift */; }; E9256F5F2034C21100DE86E9 /* String+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9256F5E2034C21100DE86E9 /* String+localized.swift */; }; - E9256F602034E0E100DE86E9 /* Chats.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F622034E0E100DE86E9 /* Chats.storyboard */; }; - E9256F692034E98700DE86E9 /* Login.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F6B2034E98700DE86E9 /* Login.storyboard */; }; E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9256F6C20357B1700DE86E9 /* LoginHeader.xib */; }; E9256F762039A9A200DE86E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */; }; E9256F792039B29A00DE86E9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E9256F7B2039B29A00DE86E9 /* Localizable.strings */; }; @@ -44,15 +42,17 @@ E93D7AC22052EE21005D19DC /* SettingsViewController+StayIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */; }; E93D7AC520530F76005D19DC /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = E93D7AC720530F76005D19DC /* Localizable.stringsdict */; }; E93EFE13200D1156000BB482 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93EFE12200D1156000BB482 /* ChatViewController.swift */; }; - E9452A4C20344834005BA34C /* Account.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9452A4E20344834005BA34C /* Account.storyboard */; }; E94883E7203F07CD00F6E1B0 /* PassphraseValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94883E6203F07CD00F6E1B0 /* PassphraseValidation.swift */; }; E948E03B20235E2300975D6B /* SettingsRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E03A20235E2300975D6B /* SettingsRoutes.swift */; }; E948E0462024DAE800975D6B /* AdamantUserInfoKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E0452024DAE800975D6B /* AdamantUserInfoKeys.swift */; }; E948E0482024F02700975D6B /* LoginFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = E948E0472024F02700975D6B /* LoginFooter.xib */; }; E948E04C2027679300975D6B /* AdamantExportTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E04B2027679300975D6B /* AdamantExportTools.swift */; }; - E948E04E20278D5600975D6B /* SettingsDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E04D20278D5600975D6B /* SettingsDependencies.swift */; }; - E94E7AF5205D309B0042B639 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E94E7AF4205D309B0042B639 /* Settings.storyboard */; }; - E94E7AFB205D30F60042B639 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7AFA205D30F60042B639 /* SettingsViewController.xib */; }; + E94E7B01205D3F090042B639 /* ChatListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7B00205D3F090042B639 /* ChatListViewController.xib */; }; + E94E7B06205D48B20042B639 /* TransactionsRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94E7B05205D48B20042B639 /* TransactionsRoutes.swift */; }; + E94E7B08205D4CB80042B639 /* SharedRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94E7B07205D4CB80042B639 /* SharedRoutes.swift */; }; + E94E7B0A205D59F50042B639 /* AccountViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7B09205D59F50042B639 /* AccountViewController.xib */; }; + E94E7B0C205D5E4A0042B639 /* TransactionsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7B0B205D5E4A0042B639 /* TransactionsViewController.xib */; }; + E94E7B0E205D5EA80042B639 /* TransactionDetailsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94E7B0D205D5EA80042B639 /* TransactionDetailsViewController.xib */; }; E9502740202E257E002C1098 /* RepeaterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950273F202E257E002C1098 /* RepeaterService.swift */; }; E950652120404BF0008352E5 /* AdamantUriBuilding.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652020404BF0008352E5 /* AdamantUriBuilding.swift */; }; E950652320404C84008352E5 /* AdamantUriTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652220404C84008352E5 /* AdamantUriTools.swift */; }; @@ -65,8 +65,7 @@ E95F85772007E8EC0070534A /* JSAdamantCoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85762007E8EC0070534A /* JSAdamantCoreTests.swift */; }; E95F857A2007F0260070534A /* ServerResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85792007F0260070534A /* ServerResponse.swift */; }; E95F85802008C8D70070534A /* ChatsRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F857E2008C8D60070534A /* ChatsRoutes.swift */; }; - E95F85812008C8D70070534A /* ChatsDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F857F2008C8D70070534A /* ChatsDependencies.swift */; }; - E95F85852008CB3A0070534A /* ChatsListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85842008CB3A0070534A /* ChatsListViewController.swift */; }; + E95F85852008CB3A0070534A /* ChatListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85842008CB3A0070534A /* ChatListViewController.swift */; }; E95F85872008FDBF0070534A /* Chat.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85862008FDBF0070534A /* Chat.swift */; }; E95F8589200900B10070534A /* ChatType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F8588200900B10070534A /* ChatType.swift */; }; E95F858B200931410070534A /* TransactionAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F858A200931410070534A /* TransactionAsset.swift */; }; @@ -120,8 +119,6 @@ E9E7CD8F20026CD300DFC4DB /* AdamantDialogService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CD8E20026CD300DFC4DB /* AdamantDialogService.swift */; }; E9E7CD9120026FA100DFC4DB /* SwinjectDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CD9020026FA100DFC4DB /* SwinjectDependencies.swift */; }; E9E7CD932002740500DFC4DB /* AdamantAccountService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CD922002740500DFC4DB /* AdamantAccountService.swift */; }; - E9E7CD952002812400DFC4DB /* LoginDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CD942002812400DFC4DB /* LoginDependencies.swift */; }; - E9E7CDA92002AF1E00DFC4DB /* AccountDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDA82002AF1E00DFC4DB /* AccountDependencies.swift */; }; E9E7CDAC2002AFA500DFC4DB /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDAA2002AFA500DFC4DB /* AccountViewController.swift */; }; E9E7CDAF2002B8A100DFC4DB /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDAE2002B8A100DFC4DB /* Router.swift */; }; E9E7CDB12002B97B00DFC4DB /* AccountRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDB02002B97B00DFC4DB /* AccountRoutes.swift */; }; @@ -224,9 +221,12 @@ E948E0452024DAE800975D6B /* AdamantUserInfoKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUserInfoKeys.swift; sourceTree = ""; }; E948E0472024F02700975D6B /* LoginFooter.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoginFooter.xib; sourceTree = ""; }; E948E04B2027679300975D6B /* AdamantExportTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantExportTools.swift; sourceTree = ""; }; - E948E04D20278D5600975D6B /* SettingsDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDependencies.swift; sourceTree = ""; }; - E94E7AF4205D309B0042B639 /* Settings.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = ""; }; - E94E7AFA205D30F60042B639 /* SettingsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = ""; }; + E94E7B00205D3F090042B639 /* ChatListViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ChatListViewController.xib; sourceTree = ""; }; + E94E7B05205D48B20042B639 /* TransactionsRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsRoutes.swift; sourceTree = ""; }; + E94E7B07205D4CB80042B639 /* SharedRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedRoutes.swift; sourceTree = ""; }; + E94E7B09205D59F50042B639 /* AccountViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountViewController.xib; sourceTree = ""; }; + E94E7B0B205D5E4A0042B639 /* TransactionsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TransactionsViewController.xib; sourceTree = ""; }; + E94E7B0D205D5EA80042B639 /* TransactionDetailsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TransactionDetailsViewController.xib; sourceTree = ""; }; E950273F202E257E002C1098 /* RepeaterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeaterService.swift; sourceTree = ""; }; E950652020404BF0008352E5 /* AdamantUriBuilding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriBuilding.swift; sourceTree = ""; }; E950652220404C84008352E5 /* AdamantUriTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriTools.swift; sourceTree = ""; }; @@ -239,8 +239,7 @@ E95F85762007E8EC0070534A /* JSAdamantCoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSAdamantCoreTests.swift; sourceTree = ""; }; E95F85792007F0260070534A /* ServerResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerResponse.swift; sourceTree = ""; }; E95F857E2008C8D60070534A /* ChatsRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsRoutes.swift; sourceTree = ""; }; - E95F857F2008C8D70070534A /* ChatsDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsDependencies.swift; sourceTree = ""; }; - E95F85842008CB3A0070534A /* ChatsListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsListViewController.swift; sourceTree = ""; }; + E95F85842008CB3A0070534A /* ChatListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListViewController.swift; sourceTree = ""; }; E95F85862008FDBF0070534A /* Chat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Chat.swift; sourceTree = ""; }; E95F8588200900B10070534A /* ChatType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatType.swift; sourceTree = ""; }; E95F858A200931410070534A /* TransactionAsset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionAsset.swift; sourceTree = ""; }; @@ -257,14 +256,8 @@ E9722065201F42BB004F2AAD /* CoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = ""; }; E9722067201F42CC004F2AAD /* InMemoryCoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InMemoryCoreDataStack.swift; sourceTree = ""; }; E972206A201F44CA004F2AAD /* TransfersProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransfersProvider.swift; sourceTree = ""; }; - E982A8D2205D2A5D0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Login.storyboard; sourceTree = ""; }; - E982A8D3205D2A5D0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Chats.storyboard; sourceTree = ""; }; - E982A8D5205D2A5F0097FAE7 /* ru */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = ru; path = ru.lproj/Account.storyboard; sourceTree = ""; }; E982A8D6205D2A610097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; E982A8D7205D2A910097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; - E982A8D8205D2AA70097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Login.storyboard; sourceTree = ""; }; - E982A8D9205D2AA70097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Chats.storyboard; sourceTree = ""; }; - E982A8DB205D2AA80097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Account.storyboard; sourceTree = ""; }; E982A8DC205D2AB40097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; E982F69B20235B4D00566AC7 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; E9942B7F203C058C00C163AF /* QRGeneratorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRGeneratorViewController.swift; sourceTree = ""; }; @@ -303,8 +296,6 @@ E9E7CD8E20026CD300DFC4DB /* AdamantDialogService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdamantDialogService.swift; sourceTree = ""; }; E9E7CD9020026FA100DFC4DB /* SwinjectDependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwinjectDependencies.swift; sourceTree = ""; }; E9E7CD922002740500DFC4DB /* AdamantAccountService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantAccountService.swift; sourceTree = ""; }; - E9E7CD942002812400DFC4DB /* LoginDependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginDependencies.swift; sourceTree = ""; }; - E9E7CDA82002AF1E00DFC4DB /* AccountDependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDependencies.swift; sourceTree = ""; }; E9E7CDAA2002AFA500DFC4DB /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = ""; }; E9E7CDAE2002B8A100DFC4DB /* Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; E9E7CDB02002B97B00DFC4DB /* AccountRoutes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountRoutes.swift; sourceTree = ""; }; @@ -496,6 +487,7 @@ children = ( E9FAE5DB203ECD41008D3A6B /* Shared */, E9E7CDA52002AE1C00DFC4DB /* Account */, + E94E7B04205D48950042B639 /* Transactions */, E95F857B2008C8B20070534A /* Chats */, E919479A20001007001362F8 /* Login */, E982F69820235AF000566AC7 /* Settings */, @@ -506,8 +498,6 @@ E919479A20001007001362F8 /* Login */ = { isa = PBXGroup; children = ( - E9256F6B2034E98700DE86E9 /* Login.storyboard */, - E9E7CD942002812400DFC4DB /* LoginDependencies.swift */, E9E7CDB22002B9FB00DFC4DB /* LoginRoutes.swift */, E905D39E204C281400DDB504 /* LoginViewController.swift */, E9147B602050599000145913 /* LoginViewController+QR.swift */, @@ -530,6 +520,18 @@ path = ServerResponses; sourceTree = ""; }; + E94E7B04205D48950042B639 /* Transactions */ = { + isa = PBXGroup; + children = ( + E94E7B05205D48B20042B639 /* TransactionsRoutes.swift */, + E94E7B0B205D5E4A0042B639 /* TransactionsViewController.xib */, + E9E7CDC12003F5A400DFC4DB /* TransactionsViewController.swift */, + E94E7B0D205D5EA80042B639 /* TransactionDetailsViewController.xib */, + E9EC34132005178500C0E546 /* TransactionDetailsViewController.swift */, + ); + path = Transactions; + sourceTree = ""; + }; E950651F20404997008352E5 /* Utilities */ = { isa = PBXGroup; children = ( @@ -544,10 +546,9 @@ E95F857B2008C8B20070534A /* Chats */ = { isa = PBXGroup; children = ( - E9256F622034E0E100DE86E9 /* Chats.storyboard */, - E95F857F2008C8D70070534A /* ChatsDependencies.swift */, E95F857E2008C8D60070534A /* ChatsRoutes.swift */, - E95F85842008CB3A0070534A /* ChatsListViewController.swift */, + E94E7B00205D3F090042B639 /* ChatListViewController.xib */, + E95F85842008CB3A0070534A /* ChatListViewController.swift */, E93EFE12200D1156000BB482 /* ChatViewController.swift */, E9C51EF02013F18000385EB7 /* NewChatViewController.swift */, ); @@ -588,10 +589,7 @@ E982F69820235AF000566AC7 /* Settings */ = { isa = PBXGroup; children = ( - E94E7AF4205D309B0042B639 /* Settings.storyboard */, - E948E04D20278D5600975D6B /* SettingsDependencies.swift */, E948E03A20235E2300975D6B /* SettingsRoutes.swift */, - E94E7AFA205D30F60042B639 /* SettingsViewController.xib */, E982F69B20235B4D00566AC7 /* SettingsViewController.swift */, E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */, E9942B7F203C058C00C163AF /* QRGeneratorViewController.swift */, @@ -658,12 +656,9 @@ E9E7CDA52002AE1C00DFC4DB /* Account */ = { isa = PBXGroup; children = ( - E9452A4E20344834005BA34C /* Account.storyboard */, - E9E7CDA82002AF1E00DFC4DB /* AccountDependencies.swift */, E9E7CDB02002B97B00DFC4DB /* AccountRoutes.swift */, + E94E7B09205D59F50042B639 /* AccountViewController.xib */, E9E7CDAA2002AFA500DFC4DB /* AccountViewController.swift */, - E9E7CDC12003F5A400DFC4DB /* TransactionsViewController.swift */, - E9EC34132005178500C0E546 /* TransactionDetailsViewController.swift */, E9EC342020052ABB00C0E546 /* TransferViewController.swift */, ); path = Account; @@ -706,6 +701,7 @@ children = ( E9FAE5E1203ED1AE008D3A6B /* ShareQrViewController.xib */, E9FAE5E0203ED1AE008D3A6B /* ShareQrViewController.swift */, + E94E7B07205D4CB80042B639 /* SharedRoutes.swift */, ); path = Shared; sourceTree = ""; @@ -806,30 +802,29 @@ E95F85C8200A9B070070534A /* ChatTableViewCell.xib in Resources */, E913C8F91FFFA51D001A83F7 /* Assets.xcassets in Resources */, E9EC341F200524CA00C0E546 /* Roboto_700_normal.ttf in Resources */, - E9256F692034E98700DE86E9 /* Login.storyboard in Resources */, E9942B89203D9ECA00C163AF /* QrCell.xib in Resources */, E9C51EED2011416E00385EB7 /* adamant-core.js in Resources */, - E94E7AF5205D309B0042B639 /* Settings.storyboard in Resources */, E90A4945204C6204009F6A65 /* PassphraseCell.xib in Resources */, E9E7CDC82003F6D200DFC4DB /* TransactionTableViewCell.xib in Resources */, E9EC3417200524CA00C0E546 /* Exo+2_400_italic.ttf in Resources */, + E94E7B01205D3F090042B639 /* ChatListViewController.xib in Resources */, E9EC341E200524CA00C0E546 /* Roboto_500_normal.ttf in Resources */, E9EC3419200524CA00C0E546 /* Exo+2_500_normal.ttf in Resources */, E9256F7E2039B29D00DE86E9 /* InfoPlist.strings in Resources */, E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */, E9EC3416200524CA00C0E546 /* Exo+2_300_normal.ttf in Resources */, E9EC341C200524CA00C0E546 /* Roboto_400_italic.ttf in Resources */, + E94E7B0C205D5E4A0042B639 /* TransactionsViewController.xib in Resources */, E9256F792039B29A00DE86E9 /* Localizable.strings in Resources */, E93D7AC520530F76005D19DC /* Localizable.stringsdict in Resources */, E9EC3415200524CA00C0E546 /* Exo+2_100_normal.ttf in Resources */, E9EC341A200524CA00C0E546 /* Exo+2_700_normal.ttf in Resources */, + E94E7B0A205D59F50042B639 /* AccountViewController.xib in Resources */, + E94E7B0E205D5EA80042B639 /* TransactionDetailsViewController.xib in Resources */, E9EC341D200524CA00C0E546 /* Roboto_400_normal.ttf in Resources */, E9A174B920587B84003667CD /* notification.mp3 in Resources */, - E94E7AFB205D30F60042B639 /* SettingsViewController.xib in Resources */, - E9256F602034E0E100DE86E9 /* Chats.storyboard in Resources */, E9EC3418200524CA00C0E546 /* Exo+2_400_normal.ttf in Resources */, E948E0482024F02700975D6B /* LoginFooter.xib in Resources */, - E9452A4C20344834005BA34C /* Account.storyboard in Resources */, E9FAE5E3203ED1AE008D3A6B /* ShareQrViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -867,7 +862,6 @@ "${BUILT_PRODUCTS_DIR}/QRCodeReader.swift/QRCodeReader.framework", "${BUILT_PRODUCTS_DIR}/RNCryptor/RNCryptor.framework", "${BUILT_PRODUCTS_DIR}/Swinject/Swinject.framework", - "${BUILT_PRODUCTS_DIR}/SwinjectStoryboard/SwinjectStoryboard.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( @@ -882,7 +876,6 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QRCodeReader.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNCryptor.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Swinject.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwinjectStoryboard.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -929,6 +922,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E94E7B08205D4CB80042B639 /* SharedRoutes.swift in Sources */, E9256F5F2034C21100DE86E9 /* String+localized.swift in Sources */, E9CAE8D22018AA7700345E76 /* AdamantApi+Accounts.swift in Sources */, E9942B84203CBFCE00C163AF /* AdamantQRTools.swift in Sources */, @@ -952,15 +946,14 @@ E982F69C20235B4D00566AC7 /* SettingsViewController.swift in Sources */, E9147B6F205088DE00145913 /* LoginViewController+Pinpad.swift in Sources */, E9FAE5E2203ED1AE008D3A6B /* ShareQrViewController.swift in Sources */, + E94E7B06205D48B20042B639 /* TransactionsRoutes.swift in Sources */, E9CE778E202B9DC2009CF70D /* TransferTransaction+CoreDataProperties.swift in Sources */, E95F85B3200954D00070534A /* ChatModels.xcdatamodeld in Sources */, E95F858B200931410070534A /* TransactionAsset.swift in Sources */, E90A494B204D9EB8009F6A65 /* AdamantAuthentication.swift in Sources */, E9E7CDAC2002AFA500DFC4DB /* AccountViewController.swift in Sources */, - E95F85812008C8D70070534A /* ChatsDependencies.swift in Sources */, E91947B420002809001362F8 /* Account.swift in Sources */, E9E7CDC22003F5A400DFC4DB /* TransactionsViewController.swift in Sources */, - E9E7CDA92002AF1E00DFC4DB /* AccountDependencies.swift in Sources */, E905D39F204C281400DDB504 /* LoginViewController.swift in Sources */, E9CE7785202B9DC2009CF70D /* Chatroom+CoreDataClass.swift in Sources */, E9CE7786202B9DC2009CF70D /* Chatroom+CoreDataProperties.swift in Sources */, @@ -975,7 +968,6 @@ E9E7CDC72003F6D200DFC4DB /* TransactionTableViewCell.swift in Sources */, E9B3D3A9202082450019EB36 /* AdamantTransfersProvider.swift in Sources */, E9A174B72057F1B3003667CD /* AdamantChatsProvider+backgroundFetch.swift in Sources */, - E948E04E20278D5600975D6B /* SettingsDependencies.swift in Sources */, E9E7CDB32002B9FB00DFC4DB /* LoginRoutes.swift in Sources */, E91947B22000246A001362F8 /* AdamantError.swift in Sources */, E95F85802008C8D70070534A /* ChatsRoutes.swift in Sources */, @@ -995,9 +987,8 @@ E913C90D1FFFA99B001A83F7 /* Keypair.swift in Sources */, E948E03B20235E2300975D6B /* SettingsRoutes.swift in Sources */, E9CAE8D82018ACA700345E76 /* AdamantApi+Transfers.swift in Sources */, - E9E7CD952002812400DFC4DB /* LoginDependencies.swift in Sources */, E9E7CDCC20040FDC00DFC4DB /* TransactionType.swift in Sources */, - E95F85852008CB3A0070534A /* ChatsListViewController.swift in Sources */, + E95F85852008CB3A0070534A /* ChatListViewController.swift in Sources */, E91947AC20001A9A001362F8 /* ApiService.swift in Sources */, E9B3D3A1201FA26B0019EB36 /* AdamantAccountsProvider.swift in Sources */, E9FAE5DA203DBFEF008D3A6B /* Comparable+Clamped.swift in Sources */, @@ -1060,24 +1051,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - E9256F622034E0E100DE86E9 /* Chats.storyboard */ = { - isa = PBXVariantGroup; - children = ( - E982A8D3205D2A5D0097FAE7 /* ru */, - E982A8D9205D2AA70097FAE7 /* en */, - ); - name = Chats.storyboard; - sourceTree = ""; - }; - E9256F6B2034E98700DE86E9 /* Login.storyboard */ = { - isa = PBXVariantGroup; - children = ( - E982A8D2205D2A5D0097FAE7 /* ru */, - E982A8D8205D2AA70097FAE7 /* en */, - ); - name = Login.storyboard; - sourceTree = ""; - }; E9256F7B2039B29A00DE86E9 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( @@ -1105,15 +1078,6 @@ name = Localizable.stringsdict; sourceTree = ""; }; - E9452A4E20344834005BA34C /* Account.storyboard */ = { - isa = PBXVariantGroup; - children = ( - E982A8D5205D2A5F0097FAE7 /* ru */, - E982A8DB205D2AA80097FAE7 /* en */, - ); - name = Account.storyboard; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index eee8b92f8..545c21a50 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -8,13 +8,20 @@ import UIKit import Swinject -import SwinjectStoryboard + +extension String.adamantLocalized { + struct tabItems { + static let account = NSLocalizedString("Tabs.Account", comment: "Main tab bar: Account/Wallet page") + static let chats = NSLocalizedString("Tabs.Chats", comment: "Main tab bar: Chats page") + static let settings = NSLocalizedString("Tabs.Settings", comment: "Main tab bar: Settings page") + } +} @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { - var window: UIWindow? var repeater: RepeaterService! + var container: Container! weak var accountService: AccountService? weak var notificationService: NotificationsService? @@ -23,14 +30,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // MARK: 1. Initiating Swinject - let container = SwinjectStoryboard.defaultContainer - Container.loggingFunction = nil // Logging currently not supported with SwinjectStoryboards. + container = Container() container.registerAdamantServices() - container.registerAdamantAccountStory() - container.registerAdamantLoginStory() - container.registerAdamantChatsStory() - container.registerAdamantSettingsStory() - accountService = container.resolve(AccountService.self) notificationService = container.resolve(NotificationsService.self) @@ -48,20 +49,33 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } if let tabbar = self.window!.rootViewController as? UITabBarController { - let account = router.get(story: .Account).instantiateInitialViewController()! - let chats = router.get(story: .Chats).instantiateInitialViewController()! - let settings = router.get(story: .Settings).instantiateInitialViewController()! - + let accountRoot = router.get(scene: AdamantScene.Account.account) + let account = UINavigationController(rootViewController: accountRoot) + account.tabBarItem.title = String.adamantLocalized.tabItems.account + account.tabBarItem.image = #imageLiteral(resourceName: "wallet_tab") + + let chatListRoot = router.get(scene: AdamantScene.Chats.chatList) + let chatList = UINavigationController(rootViewController: chatListRoot) + chatList.tabBarItem.title = String.adamantLocalized.tabItems.chats + chatList.tabBarItem.image = #imageLiteral(resourceName: "chats_tab") + + let settingsRoot = router.get(scene: AdamantScene.Settings.settings) + let settings = UINavigationController(rootViewController: settingsRoot) + settings.tabBarItem.title = String.adamantLocalized.tabItems.settings + settings.tabBarItem.image = #imageLiteral(resourceName: "settings_tab") + + account.tabBarItem.badgeColor = UIColor.adamantPrimary - chats.tabBarItem.badgeColor = UIColor.adamantPrimary + chatList.tabBarItem.badgeColor = UIColor.adamantPrimary settings.tabBarItem.badgeColor = UIColor.adamantPrimary - tabbar.setViewControllers([account, chats, settings], animated: false) + tabbar.setViewControllers([account, chatList, settings], animated: false) } // MARK: 3. Initiate login - self.window!.rootViewController?.present(router.get(scene: .Login), animated: false, completion: nil) + let login = router.get(scene: AdamantScene.Login.login) + self.window!.rootViewController?.present(login, animated: false, completion: nil) // MARK: 4 Autoupdate diff --git a/Adamant/ServiceProtocols/Router.swift b/Adamant/ServiceProtocols/Router.swift index 87c14d426..78ff7a3f3 100644 --- a/Adamant/ServiceProtocols/Router.swift +++ b/Adamant/ServiceProtocols/Router.swift @@ -7,46 +7,22 @@ // import UIKit +import Swinject -// MARK: - Adamant Story struct -struct AdamantStory: Equatable, Hashable { - let name: String - - init(_ name: String) { - self.name = name - } - - static func ==(lhs: AdamantStory, rhs: AdamantStory) -> Bool { - return lhs.name == rhs.name - } - - var hashValue: Int { - return name.hashValue &* 171717 - } -} // MARK: - Adamant Scene -struct AdamantScene: Equatable, Hashable { +struct AdamantScene { let identifier: String - let story: AdamantStory + let factory: (Resolver) -> UIViewController - init(story: AdamantStory, identifier: String) { - self.story = story + init(identifier: String, factory: @escaping (Resolver) -> UIViewController) { self.identifier = identifier - } - - static func ==(lhs: AdamantScene, rhs: AdamantScene) -> Bool { - return lhs.identifier == rhs.identifier - } - - var hashValue: Int { - return identifier.hashValue ^ story.hashValue &* 717171 + self.factory = factory } } // MARK: - Adamant Router protocol Router: class { - func get(story: AdamantStory) -> UIStoryboard func get(scene: AdamantScene) -> UIViewController } diff --git a/Adamant/Services/SwinjectedRouter.swift b/Adamant/Services/SwinjectedRouter.swift index 45ac7a72f..1103b59ec 100644 --- a/Adamant/Services/SwinjectedRouter.swift +++ b/Adamant/Services/SwinjectedRouter.swift @@ -7,22 +7,12 @@ // import UIKit -import SwinjectStoryboard +import Swinject class SwinjectedRouter: Router { - private var storyboards = [AdamantStory: UIStoryboard]() - - func get(story: AdamantStory) -> UIStoryboard { - if let storyboard = storyboards[story] { - return storyboard - } else { - let storyboard = SwinjectStoryboard.create(name: story.name, bundle: nil) - storyboards[story] = storyboard - return storyboard - } - } + weak var container: Container? func get(scene: AdamantScene) -> UIViewController { - return get(story: scene.story).instantiateViewController(withIdentifier: scene.identifier) + return scene.factory(container!) } } diff --git a/Adamant/Stories/Account/AccountDependencies.swift b/Adamant/Stories/Account/AccountDependencies.swift deleted file mode 100644 index 314d8b4a2..000000000 --- a/Adamant/Stories/Account/AccountDependencies.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// AccountDependencies.swift -// Adamant -// -// Created by Anokhov Pavel on 07.01.2018. -// Copyright © 2018 Adamant. All rights reserved. -// - -import Swinject - -extension Container { - func registerAdamantAccountStory() { - self.storyboardInitCompleted(AccountViewController.self) { r, c in - c.accountService = r.resolve(AccountService.self) - c.dialogService = r.resolve(DialogService.self) - c.router = r.resolve(Router.self) - } - self.storyboardInitCompleted(TransactionsViewController.self) { (r, c) in - c.cellFactory = r.resolve(CellFactory.self) - c.transfersProvider = r.resolve(TransfersProvider.self) - } - self.storyboardInitCompleted(TransferViewController.self) { (r, c) in - c.apiService = r.resolve(ApiService.self) - c.accountService = r.resolve(AccountService.self) - c.dialogService = r.resolve(DialogService.self) - } - self.storyboardInitCompleted(TransactionDetailsViewController.self) { (r, c) in - c.dialogService = r.resolve(DialogService.self) - } - } -} diff --git a/Adamant/Stories/Account/AccountRoutes.swift b/Adamant/Stories/Account/AccountRoutes.swift index a9539e552..8e782c2be 100644 --- a/Adamant/Stories/Account/AccountRoutes.swift +++ b/Adamant/Stories/Account/AccountRoutes.swift @@ -8,13 +8,22 @@ import Foundation -extension AdamantStory { - static let Account = AdamantStory("Account") -} - extension AdamantScene { - static let AccountDetails = AdamantScene(story: .Account, identifier: "AccountViewController") - static let TransactionsList = AdamantScene(story: .Account, identifier: "TransactionsViewController") - static let TransactionDetails = AdamantScene(story: .Account, identifier: "TransactionDetailsViewController") - static let Transfer = AdamantScene(story: .Account, identifier: "TransferViewController") + struct Account { + static let account = AdamantScene(identifier: "AccountViewController", factory: { r in + let c = AccountViewController() + c.accountService = r.resolve(AccountService.self) + c.dialogService = r.resolve(DialogService.self) + c.router = r.resolve(Router.self) + return c + }) + + static let transfer = AdamantScene(identifier: "TransferViewController", factory: { r in + let c = TransferViewController() + c.apiService = r.resolve(ApiService.self) + c.accountService = r.resolve(AccountService.self) + c.dialogService = r.resolve(DialogService.self) + return c + }) + } } diff --git a/Adamant/Stories/Account/AccountViewController.swift b/Adamant/Stories/Account/AccountViewController.swift index 8ea338780..76636d4b4 100644 --- a/Adamant/Stories/Account/AccountViewController.swift +++ b/Adamant/Stories/Account/AccountViewController.swift @@ -13,6 +13,8 @@ import SafariServices // MARK: - Localization extension String.adamantLocalized { struct account { + static let title = NSLocalizedString("Wallet.title", comment: "Wallet page: scene title") + static let rowBalance = NSLocalizedString("Balance", comment: "Wallet page: Balance row title") static let rowSendTokens = NSLocalizedString("Send Tokens", comment: "Wallet page: 'Send tokens' button") static let rowInvest = NSLocalizedString("Invest in ICO", comment: "Wallet page: 'Invest in ICO' button") @@ -40,8 +42,6 @@ fileprivate extension String.adamantLocalized.alert { class AccountViewController: UIViewController { // MARK: - Constants private let cellIdentifier = "cell" - private let showTransactionsSegue = "showTransactions" - private let showTransferSegue = "showTransfer" private let webAppUrl = URL.init(string: "https://msg.adamant.im") @@ -72,6 +72,7 @@ class AccountViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.title = String.adamantLocalized.account.title tableView.delegate = self tableView.dataSource = self @@ -103,22 +104,6 @@ class AccountViewController: UIViewController { } } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - guard let identifier = segue.identifier else { - return - } - - switch identifier { - case showTransferSegue: - if let account = accountService.account, let vc = segue.destination as? TransferViewController { - vc.account = account - } - - default: - return - } - } - deinit { NotificationCenter.default.removeObserver(self) } @@ -189,10 +174,10 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate { switch row { case .balance: - performSegue(withIdentifier: showTransactionsSegue, sender: nil) + let vc = router.get(scene: AdamantScene.Transactions.transactions) + navigationController?.pushViewController(vc, animated: true) case .sendTokens: -// performSegue(withIdentifier: showTransferSegue, sender: nil) // let alert = UIAlertController(title: String.adamantLocalized.account.sorryAlert, message: String.adamantLocalized.account.transferNotAllowed, preferredStyle: .alert) @@ -234,7 +219,7 @@ extension AccountViewController: UITableViewDataSource, UITableViewDelegate { } let logout = UIAlertAction(title: String.adamantLocalized.alert.logoutButton, style: .default) { [weak self] _ in self?.accountService.logout() - if let vc = self?.router.get(scene: .Login) { + if let vc = self?.router.get(scene: AdamantScene.Login.login) { self?.dialogService.present(vc, animated: true, completion: nil) } } diff --git a/Adamant/Stories/Account/AccountViewController.xib b/Adamant/Stories/Account/AccountViewController.xib new file mode 100644 index 000000000..0dc66efdf --- /dev/null +++ b/Adamant/Stories/Account/AccountViewController.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Account/en.lproj/Account.storyboard b/Adamant/Stories/Account/en.lproj/Account.storyboard deleted file mode 100644 index e4b16c796..000000000 --- a/Adamant/Stories/Account/en.lproj/Account.storyboard +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Account/ru.lproj/Account.storyboard b/Adamant/Stories/Account/ru.lproj/Account.storyboard deleted file mode 100644 index e4b16c796..000000000 --- a/Adamant/Stories/Account/ru.lproj/Account.storyboard +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Chats/ChatsListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift similarity index 83% rename from Adamant/Stories/Chats/ChatsListViewController.swift rename to Adamant/Stories/Chats/ChatListViewController.swift index bbe97f47a..f54066147 100644 --- a/Adamant/Stories/Chats/ChatsListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -1,5 +1,5 @@ // -// ChatsListViewController.swift +// ChatListViewController.swift // Adamant // // Created by Anokhov Pavel on 12.01.2018. @@ -9,7 +9,15 @@ import UIKit import CoreData -class ChatsListViewController: UIViewController { +extension String.adamantLocalized { + struct chatList { + static let title = NSLocalizedString("ChatList.title", comment: "ChatList: scene title") + + private init() {} + } +} + +class ChatListViewController: UIViewController { // MARK: Dependencies var accountService: AccountService! var chatsProvider: ChatsProvider! @@ -21,8 +29,6 @@ class ChatsListViewController: UIViewController { @IBOutlet weak var newChatButton: UIBarButtonItem! // MARK: Properties - let showChatSegue = "showChat" - let newChatSegue = "newChat" var chatsController: NSFetchedResultsController? var unreadController: NSFetchedResultsController? @@ -33,6 +39,8 @@ class ChatsListViewController: UIViewController { // MARK: Lifecycle override func viewDidLoad() { super.viewDidLoad() + navigationItem.title = String.adamantLocalized.chatList.title + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(newChat)) // MARK: TableView tableView.dataSource = self @@ -73,29 +81,22 @@ class ChatsListViewController: UIViewController { } } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - guard let identifier = segue.identifier else { - return - } + + // MARK: IB Actions + @IBAction func newChat(sender: Any) { + let controller = router.get(scene: AdamantScene.Chats.newChat) - switch identifier { - case showChatSegue: - if let chatroom = sender as? Chatroom, let vc = segue.destination as? ChatViewController { - prepareChatViewController(vc, chatroom: chatroom) - } - - case newChatSegue: - if let vc = segue.destination as? NewChatViewController { - vc.delegate = self - } else if let nav = segue.destination as? UINavigationController, let vc = nav.viewControllers.first as? NewChatViewController { - vc.delegate = self - } - - default: - return + if let c = controller as? NewChatViewController { + c.delegate = self + } else if let nav = controller as? UINavigationController, let c = nav.viewControllers.last as? NewChatViewController { + c.delegate = self } + + present(controller, animated: true, completion: nil) } + + // MARK: Helpers private func prepareChatViewController(_ vc: ChatViewController, chatroom: Chatroom) { if let account = accountService.account { vc.account = account @@ -109,7 +110,7 @@ class ChatsListViewController: UIViewController { // MARK: - UITableView -extension ChatsListViewController: UITableViewDelegate, UITableViewDataSource { +extension ChatListViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if let f = chatsController?.fetchedObjects { return f.count @@ -127,15 +128,21 @@ extension ChatsListViewController: UITableViewDelegate, UITableViewDataSource { } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if let chatroom = chatsController?.object(at: indexPath) { - performSegue(withIdentifier: showChatSegue, sender: chatroom) + if let chatroom = chatsController?.object(at: indexPath), let c = router.get(scene: AdamantScene.Chats.chat) as? ChatViewController { + prepareChatViewController(c, chatroom: chatroom) + + if let nav = navigationController { + nav.pushViewController(c, animated: true) + } else { + present(c, animated: true) + } } } } // MARK: - UITableView Cells -extension ChatsListViewController { +extension ChatListViewController { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: chatCell, for: indexPath) as! ChatTableViewCell @@ -186,7 +193,7 @@ extension ChatsListViewController { // MARK: - NSFetchedResultsControllerDelegate -extension ChatsListViewController: NSFetchedResultsControllerDelegate { +extension ChatListViewController: NSFetchedResultsControllerDelegate { func controllerWillChangeContent(_ controller: NSFetchedResultsController) { if controller == chatsController { tableView.beginUpdates() @@ -255,12 +262,12 @@ extension ChatsListViewController: NSFetchedResultsControllerDelegate { // MARK: - NewChatViewControllerDelegate -extension ChatsListViewController: NewChatViewControllerDelegate { +extension ChatListViewController: NewChatViewControllerDelegate { func newChatController(_ controller: NewChatViewController, didSelectAccount account: CoreDataAccount) { let chatroom = self.chatsProvider.chatroomWith(account) DispatchQueue.main.async { - if let vc = self.router.get(scene: .Chat) as? ChatViewController { + if let vc = self.router.get(scene: AdamantScene.Chats.chat) as? ChatViewController { self.prepareChatViewController(vc, chatroom: chatroom) self.navigationController?.pushViewController(vc, animated: false) @@ -292,7 +299,7 @@ extension ChatsListViewController: NewChatViewControllerDelegate { // MARK: - ChatViewControllerDelegate -extension ChatsListViewController: ChatViewControllerDelegate { +extension ChatListViewController: ChatViewControllerDelegate { func preserveMessage(_ message: String, forAddress address: String) { preservedMessagess[address] = message } @@ -312,7 +319,7 @@ extension ChatsListViewController: ChatViewControllerDelegate { // MARK: - Current chat -extension ChatsListViewController { +extension ChatListViewController { func presentedChatroom() -> Chatroom? { // Showing another page guard tabBarController?.selectedViewController == self else { diff --git a/Adamant/Stories/Chats/ChatListViewController.xib b/Adamant/Stories/Chats/ChatListViewController.xib new file mode 100644 index 000000000..ff82632dd --- /dev/null +++ b/Adamant/Stories/Chats/ChatListViewController.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 9083e91a9..9f6dd554b 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -66,6 +66,7 @@ class ChatViewController: MessagesViewController { // MARK: Lifecycle override func viewDidLoad() { super.viewDidLoad() + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "•••", style: .plain, target: self, action: #selector(properties)) // MARK: 1. Initial configuration diff --git a/Adamant/Stories/Chats/ChatsDependencies.swift b/Adamant/Stories/Chats/ChatsDependencies.swift deleted file mode 100644 index 88cbb367c..000000000 --- a/Adamant/Stories/Chats/ChatsDependencies.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// ChatsDependencies.swift -// Adamant -// -// Created by Anokhov Pavel on 12.01.2018. -// Copyright © 2018 Adamant. All rights reserved. -// - -import Swinject - -extension Container { - func registerAdamantChatsStory() { - self.storyboardInitCompleted(ChatsListViewController.self) { r, c in - c.accountService = r.resolve(AccountService.self) - c.chatsProvider = r.resolve(ChatsProvider.self) - c.cellFactory = r.resolve(CellFactory.self) - c.router = r.resolve(Router.self) - } - - self.storyboardInitCompleted(ChatViewController.self) { r, c in - c.chatsProvider = r.resolve(ChatsProvider.self) - c.dialogService = r.resolve(DialogService.self) - } - - self.storyboardInitCompleted(NewChatViewController.self) { r, c in - c.dialogService = r.resolve(DialogService.self) - c.accountService = r.resolve(AccountService.self) - c.accountsProvider = r.resolve(AccountsProvider.self) - } - } -} diff --git a/Adamant/Stories/Chats/ChatsRoutes.swift b/Adamant/Stories/Chats/ChatsRoutes.swift index f896bf0d9..8f9c6d253 100644 --- a/Adamant/Stories/Chats/ChatsRoutes.swift +++ b/Adamant/Stories/Chats/ChatsRoutes.swift @@ -6,14 +6,37 @@ // Copyright © 2018 Adamant. All rights reserved. // -import Foundation - -extension AdamantStory { - static let Chats = AdamantStory("Chats") -} +import UIKit extension AdamantScene { - static let ChatsList = AdamantScene(story: .Chats, identifier: "ChatsListViewController") - static let Chat = AdamantScene(story: .Chats, identifier: "ChatViewController") - static let NewChat = AdamantScene(story: .Chats, identifier: "NewChatViewController") + struct Chats { + static let chatList = AdamantScene(identifier: "ChatListViewController", factory: { r in + let c = ChatListViewController(nibName: "ChatListViewController", bundle: nil) + c.accountService = r.resolve(AccountService.self) + c.chatsProvider = r.resolve(ChatsProvider.self) + c.cellFactory = r.resolve(CellFactory.self) + c.router = r.resolve(Router.self) + return c + }) + + static let chat = AdamantScene(identifier: "ChatViewController", factory: { r in + let c = ChatViewController() + c.chatsProvider = r.resolve(ChatsProvider.self) + c.dialogService = r.resolve(DialogService.self) + return c + }) + + static let newChat = AdamantScene(identifier: "NewChatViewController", factory: { r in + let c = NewChatViewController() + c.dialogService = r.resolve(DialogService.self) + c.accountService = r.resolve(AccountService.self) + c.accountsProvider = r.resolve(AccountsProvider.self) + + let navigator = UINavigationController(rootViewController: c) + + return navigator + }) + + private init() {} + } } diff --git a/Adamant/Stories/Chats/NewChatViewController.swift b/Adamant/Stories/Chats/NewChatViewController.swift index 912f2d5ed..abee171a8 100644 --- a/Adamant/Stories/Chats/NewChatViewController.swift +++ b/Adamant/Stories/Chats/NewChatViewController.swift @@ -14,6 +14,8 @@ import AVFoundation // MARK: - Localization extension String.adamantLocalized { struct newChat { + static let title = NSLocalizedString("NewChat.title", comment: "New chat: scene title") + static let addressPlaceholder = NSLocalizedString("", comment: "New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank.") static let scanQrButton = NSLocalizedString("Scan QR", comment: "New chat: Scan QR with address button") @@ -80,6 +82,9 @@ class NewChatViewController: FormViewController { override func viewDidLoad() { super.viewDidLoad() + navigationItem.title = String.adamantLocalized.newChat.title + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done)) + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancel)) navigationOptions = .Disabled diff --git a/Adamant/Stories/Chats/en.lproj/Chats.storyboard b/Adamant/Stories/Chats/en.lproj/Chats.storyboard deleted file mode 100644 index f2f134f5d..000000000 --- a/Adamant/Stories/Chats/en.lproj/Chats.storyboard +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Chats/ru.lproj/Chats.storyboard b/Adamant/Stories/Chats/ru.lproj/Chats.storyboard deleted file mode 100644 index f2f134f5d..000000000 --- a/Adamant/Stories/Chats/ru.lproj/Chats.storyboard +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Login/LoginDependencies.swift b/Adamant/Stories/Login/LoginDependencies.swift deleted file mode 100644 index e622b9b4d..000000000 --- a/Adamant/Stories/Login/LoginDependencies.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// LoginDependencies.swift -// Adamant -// -// Created by Anokhov Pavel on 07.01.2018. -// Copyright © 2018 Adamant. All rights reserved. -// - -import Swinject - -extension Container { - func registerAdamantLoginStory() { - self.storyboardInitCompleted(LoginViewController.self) { r, c in - c.accountService = r.resolve(AccountService.self) - c.adamantCore = r.resolve(AdamantCore.self) - c.dialogService = r.resolve(DialogService.self) - c.localAuth = r.resolve(LocalAuthentication.self) - } - } -} diff --git a/Adamant/Stories/Login/LoginRoutes.swift b/Adamant/Stories/Login/LoginRoutes.swift index 2824be56a..979374a4e 100644 --- a/Adamant/Stories/Login/LoginRoutes.swift +++ b/Adamant/Stories/Login/LoginRoutes.swift @@ -8,10 +8,17 @@ import Foundation -extension AdamantStory { - static let Login = AdamantStory("Login") -} - extension AdamantScene { - static let Login = AdamantScene(story: .Login, identifier: "LoginViewController") + struct Login { + static let login = AdamantScene(identifier: "LoginViewController", factory: { r in + let c = LoginViewController() + c.accountService = r.resolve(AccountService.self) + c.adamantCore = r.resolve(AdamantCore.self) + c.dialogService = r.resolve(DialogService.self) + c.localAuth = r.resolve(LocalAuthentication.self) + return c + }) + + private init() {} + } } diff --git a/Adamant/Stories/Login/en.lproj/Login.storyboard b/Adamant/Stories/Login/en.lproj/Login.storyboard deleted file mode 100644 index 7a8b3862e..000000000 --- a/Adamant/Stories/Login/en.lproj/Login.storyboard +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Login/ru.lproj/Login.storyboard b/Adamant/Stories/Login/ru.lproj/Login.storyboard deleted file mode 100644 index 7a8b3862e..000000000 --- a/Adamant/Stories/Login/ru.lproj/Login.storyboard +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Settings/QRGeneratorViewController.swift b/Adamant/Stories/Settings/QRGeneratorViewController.swift index f0a2388cd..7bff199ca 100644 --- a/Adamant/Stories/Settings/QRGeneratorViewController.swift +++ b/Adamant/Stories/Settings/QRGeneratorViewController.swift @@ -14,6 +14,8 @@ import Photos // MARK: - Localization extension String.adamantLocalized { struct qrGenerator { + static let title = NSLocalizedString("QrGenerator.title", comment: "QRGenerator: scene title") + static let tapToSaveTip = NSLocalizedString("Tap to save", comment: "QRGenerator: small 'Tap to save' tooltip under generated QR") static let passphrasePlaceholder = NSLocalizedString("Passphrase", comment: "QRGenerator: Passphrase textview placeholder") diff --git a/Adamant/Stories/Settings/Settings.storyboard b/Adamant/Stories/Settings/Settings.storyboard deleted file mode 100644 index b9631eff8..000000000 --- a/Adamant/Stories/Settings/Settings.storyboard +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Settings/SettingsDependencies.swift b/Adamant/Stories/Settings/SettingsDependencies.swift deleted file mode 100644 index 9a26090f9..000000000 --- a/Adamant/Stories/Settings/SettingsDependencies.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// SettingsDependencies.swift -// Adamant -// -// Created by Anokhov Pavel on 04.02.2018. -// Copyright © 2018 Adamant. All rights reserved. -// - -import Swinject - -extension Container { - func registerAdamantSettingsStory() { - self.storyboardInitCompleted(SettingsViewController.self) { r, c in - c.dialogService = r.resolve(DialogService.self) - c.accountService = r.resolve(AccountService.self) - c.localAuth = r.resolve(LocalAuthentication.self) - c.notificationsService = r.resolve(NotificationsService.self) - } - - self.storyboardInitCompleted(QRGeneratorViewController.self) { r, c in - c.dialogService = r.resolve(DialogService.self) - } - } -} diff --git a/Adamant/Stories/Settings/SettingsRoutes.swift b/Adamant/Stories/Settings/SettingsRoutes.swift index a63dd939a..7cc5772b4 100644 --- a/Adamant/Stories/Settings/SettingsRoutes.swift +++ b/Adamant/Stories/Settings/SettingsRoutes.swift @@ -6,13 +6,26 @@ // Copyright © 2018 Adamant. All rights reserved. // -import Foundation - -extension AdamantStory { - static let Settings = AdamantStory("Settings") -} +import UIKit extension AdamantScene { - static let SettingsPage = AdamantScene(story: .Settings, identifier: "SettingsTableViewController") - static let QRGenerator = AdamantScene(story: .Settings, identifier: "QRGeneratorViewController") + struct Settings { + static let settings = AdamantScene(identifier: "SettingsTableViewController", factory: { r in + let c = SettingsViewController() + c.dialogService = r.resolve(DialogService.self) + c.accountService = r.resolve(AccountService.self) + c.localAuth = r.resolve(LocalAuthentication.self) + c.notificationsService = r.resolve(NotificationsService.self) + c.router = r.resolve(Router.self) + return c + }) + + static let qRGenerator = AdamantScene(identifier: "QRGeneratorViewController", factory: { r in + let c = QRGeneratorViewController() + c.dialogService = r.resolve(DialogService.self) + return c + }) + + private init() {} + } } diff --git a/Adamant/Stories/Settings/SettingsViewController.swift b/Adamant/Stories/Settings/SettingsViewController.swift index 3844876e0..d7bab053d 100644 --- a/Adamant/Stories/Settings/SettingsViewController.swift +++ b/Adamant/Stories/Settings/SettingsViewController.swift @@ -12,6 +12,8 @@ import MyLittlePinpad extension String.adamantLocalized { struct settings { + static let title = NSLocalizedString("Config.title", comment: "Config: scene title") + static let stayInTurnOff = NSLocalizedString("Do not stay logged in", comment: "Config: turn off 'Stay Logged In' confirmation") static let biometryOnReason = NSLocalizedString("Use biometry to log in", comment: "Config: Authorization reason for turning biometry on") static let biometryOffReason = NSLocalizedString("Do not use biometry to log in", comment: "Config: Authorization reason for turning biometry off") @@ -19,9 +21,6 @@ extension String.adamantLocalized { } class SettingsViewController: FormViewController { - - private let qrGeneratorSegue = "passphraseToQR" - // MARK: Sections & Rows enum Sections { case settings @@ -85,6 +84,7 @@ class SettingsViewController: FormViewController { var dialogService: DialogService! var localAuth: LocalAuthentication! var notificationsService: NotificationsService! + var router: Router! // MARK: Properties @@ -95,6 +95,7 @@ class SettingsViewController: FormViewController { // MARK: Lifetime override func viewDidLoad() { super.viewDidLoad() + self.navigationItem.title = String.adamantLocalized.settings.title navigationOptions = .Disabled showBiometryRow = accountService.hasStayInAccount @@ -174,10 +175,10 @@ class SettingsViewController: FormViewController { }.cellSetup({ (cell, _) in cell.selectionStyle = .gray }).onCellSelection({ [weak self] (_, _) in - guard let segue = self?.qrGeneratorSegue else { + guard let nav = self?.navigationController, let vc = self?.router.get(scene: AdamantScene.Settings.qRGenerator) else { return } - self?.performSegue(withIdentifier: segue, sender: nil) + nav.pushViewController(vc, animated: true) }).cellUpdate({ (cell, _) in if let label = cell.textLabel { label.font = UIFont.adamantPrimary(size: 17) diff --git a/Adamant/Stories/Settings/SettingsViewController.xib b/Adamant/Stories/Settings/SettingsViewController.xib deleted file mode 100644 index f0eedefa9..000000000 --- a/Adamant/Stories/Settings/SettingsViewController.xib +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Shared/SharedRoutes.swift b/Adamant/Stories/Shared/SharedRoutes.swift new file mode 100644 index 000000000..92f49d411 --- /dev/null +++ b/Adamant/Stories/Shared/SharedRoutes.swift @@ -0,0 +1,17 @@ +// +// SharedRoutes.swift +// Adamant +// +// Created by Anokhov Pavel on 17.03.2018. +// Copyright © 2018 Adamant. All rights reserved. +// + +import Foundation + +extension AdamantScene { + struct Shared { + static let shareQr = AdamantScene(identifier: "ShareQrViewController", factory: { _ in + return ShareQrViewController(nibName: "ShareQrViewController", bundle: nil) + }) + } +} diff --git a/Adamant/Stories/Account/TransactionDetailsViewController.swift b/Adamant/Stories/Transactions/TransactionDetailsViewController.swift similarity index 98% rename from Adamant/Stories/Account/TransactionDetailsViewController.swift rename to Adamant/Stories/Transactions/TransactionDetailsViewController.swift index 40e7d7bab..1b5c7aa49 100644 --- a/Adamant/Stories/Account/TransactionDetailsViewController.swift +++ b/Adamant/Stories/Transactions/TransactionDetailsViewController.swift @@ -57,9 +57,9 @@ class TransactionDetailsViewController: UIViewController { // MARK: - IBOutlets @IBOutlet weak var tableView: UITableView! - @IBOutlet weak var shareButton: UIBarButtonItem! override func viewDidLoad() { + navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(share)) tableView.dataSource = self tableView.delegate = self diff --git a/Adamant/Stories/Transactions/TransactionDetailsViewController.xib b/Adamant/Stories/Transactions/TransactionDetailsViewController.xib new file mode 100644 index 000000000..6f359e85e --- /dev/null +++ b/Adamant/Stories/Transactions/TransactionDetailsViewController.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/Stories/Transactions/TransactionsRoutes.swift b/Adamant/Stories/Transactions/TransactionsRoutes.swift new file mode 100644 index 000000000..62d664a66 --- /dev/null +++ b/Adamant/Stories/Transactions/TransactionsRoutes.swift @@ -0,0 +1,27 @@ +// +// TransactionsRoutes.swift +// Adamant +// +// Created by Anokhov Pavel on 17.03.2018. +// Copyright © 2018 Adamant. All rights reserved. +// + +import Foundation + +extension AdamantScene { + struct Transactions { + static let transactions = AdamantScene(identifier: "TransactionsViewController", factory: { r in + let c = TransactionsViewController(nibName: "TransactionsViewController", bundle: nil) + c.cellFactory = r.resolve(CellFactory.self) + c.transfersProvider = r.resolve(TransfersProvider.self) + c.router = r.resolve(Router.self) + return c + }) + + static let transactionDetails = AdamantScene(identifier: "TransactionDetailsViewController", factory: { r in + let c = TransactionDetailsViewController(nibName: "TransactionDetailsViewController", bundle: nil) + c.dialogService = r.resolve(DialogService.self) + return c + }) + } +} diff --git a/Adamant/Stories/Account/TransactionsViewController.swift b/Adamant/Stories/Transactions/TransactionsViewController.swift similarity index 91% rename from Adamant/Stories/Account/TransactionsViewController.swift rename to Adamant/Stories/Transactions/TransactionsViewController.swift index e95474c71..fec6826b0 100644 --- a/Adamant/Stories/Account/TransactionsViewController.swift +++ b/Adamant/Stories/Transactions/TransactionsViewController.swift @@ -13,10 +13,10 @@ class TransactionsViewController: UIViewController { // MARK: - Dependencies var cellFactory: CellFactory! var transfersProvider: TransfersProvider! + var router: Router! // MARK: - Properties var controller: NSFetchedResultsController? - let transactionDetailsSegue = "showTransactionDetails" // MARK: - IBOutlets @@ -45,14 +45,6 @@ class TransactionsViewController: UIViewController { tableView.deselectRow(at: indexPath, animated: animated) } } - - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if segue.identifier == transactionDetailsSegue, - let vc = segue.destination as? TransactionDetailsViewController, - let transaction = sender as? TransferTransaction { - vc.transaction = transaction - } - } } // MARK: - UITableView Cells @@ -110,7 +102,12 @@ extension TransactionsViewController: UITableViewDataSource, UITableViewDelegate return } - performSegue(withIdentifier: transactionDetailsSegue, sender: transaction) + guard let controller = router.get(scene: AdamantScene.Transactions.transactionDetails) as? TransactionDetailsViewController else { + return + } + + controller.transaction = transaction + navigationController?.pushViewController(controller, animated: true) } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { diff --git a/Adamant/Stories/Transactions/TransactionsViewController.xib b/Adamant/Stories/Transactions/TransactionsViewController.xib new file mode 100644 index 000000000..08b854797 --- /dev/null +++ b/Adamant/Stories/Transactions/TransactionsViewController.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/SwinjectDependencies.swift b/Adamant/SwinjectDependencies.swift index ede87f41c..5f2340cd7 100644 --- a/Adamant/SwinjectDependencies.swift +++ b/Adamant/SwinjectDependencies.swift @@ -7,7 +7,6 @@ // import Swinject -import SwinjectStoryboard // MARK: - Resources private struct AdamantResources { @@ -22,8 +21,6 @@ private struct AdamantResources { // MARK: - Services extension Container { func registerAdamantServices() { - - // MARK: - Standalone services // MARK: AdamantCore self.register(AdamantCore.self) { _ in @@ -35,7 +32,11 @@ extension Container { }.inObjectScope(.container) // MARK: Router - self.register(Router.self) { _ in SwinjectedRouter() }.inObjectScope(.container) + self.register(Router.self) { _ in + let router = SwinjectedRouter() + router.container = self + return router + }.inObjectScope(.container) // MARK: CellFactory self.register(CellFactory.self) { _ in AdamantCellFactory() }.inObjectScope(.container) diff --git a/Podfile b/Podfile index be3ce2d3d..d8882353c 100644 --- a/Podfile +++ b/Podfile @@ -7,11 +7,8 @@ target 'Adamant' do pod 'Alamofire' # Network pod 'KeychainAccess' # Keychain pod 'RNCryptor' # Cryptor + pod 'Swinject' # Swinject DI - # Swinject DI - pod 'Swinject' - pod 'SwinjectStoryboard' - # UI pod 'FreakingSimpleRoundImageView' # Round avatars pod 'FTIndicator' # Notifications and activity indicator diff --git a/Podfile.lock b/Podfile.lock index a42e597cc..ce4dbbc91 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,7 +1,7 @@ PODS: - Alamofire (4.7.0) - EFQRCode (4.2.1) - - Eureka (4.1.0) + - Eureka (4.1.1) - FreakingSimpleRoundImageView (1.0.2) - FTIndicator (1.2.6): - FTIndicator/FTNotificationIndicator (= 1.2.6) @@ -16,8 +16,6 @@ PODS: - QRCodeReader.swift (8.1.1) - RNCryptor (5.0.2) - Swinject (2.2.0) - - SwinjectStoryboard (1.1.2): - - Swinject (~> 2.1) DEPENDENCIES: - Alamofire @@ -31,12 +29,11 @@ DEPENDENCIES: - QRCodeReader.swift - RNCryptor - Swinject - - SwinjectStoryboard SPEC CHECKSUMS: Alamofire: 907e0a98eb68cdb7f9d1f541a563d6ac5dc77b25 EFQRCode: f3fd67049faa07adb575495c05d72a34e407a940 - Eureka: 5770ef95bbbbe52f8abbc0d9bea6ee8282c50209 + Eureka: b88fb930e42c79f8c03c373d0fcdc28c1d6c50ed FreakingSimpleRoundImageView: e87b0ef24c9b95b74b1c2cab5b03832dbabd4873 FTIndicator: d2a7c204341b7b0165b6dbeb5bf6979c6d7d4bb7 KeychainAccess: 94c5540b32eabf7bc32bfb976a268e8ea05fd6da @@ -45,8 +42,7 @@ SPEC CHECKSUMS: QRCodeReader.swift: b164a681887de276d405ff02bce854d82cd6360b RNCryptor: 59b9f92e9fa8a1af74c32dc6b1af5e30ff5e1b64 Swinject: 4ca48bca7de5f398229a26abe1ac902b9f3ee541 - SwinjectStoryboard: 92e75763c3299cdf627bef98a5180dc894864336 -PODFILE CHECKSUM: f56801713dedd8f5b2d1ec95f822fbbce22dc294 +PODFILE CHECKSUM: 870cc099d296984357fb6053beeb8a6ff5acc92c COCOAPODS: 1.4.0 From 4af3c8f7d6c9e0f6f46ceae049cfa6afb7b2d692 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 19:15:54 +0300 Subject: [PATCH 03/13] Localization keys updated. --- Adamant/AppDelegate.swift | 2 +- Adamant/Helpers/MyLittlePinpad+adamant.swift | 4 +- Adamant/Helpers/String+localized.swift | 14 +++---- Adamant/Info.plist | 6 +-- Adamant/ServiceProtocols/AccountService.swift | 8 ++-- Adamant/ServiceProtocols/ApiService.swift | 10 ++--- Adamant/ServiceProtocols/DialogService.swift | 6 +-- .../NotificationsService.swift | 10 ++--- .../ApiService/AdamantApiService.swift | 8 ++-- .../AdamantAccountsProvider.swift | 6 +-- .../RoundAvatarTableViewCell.swift | 4 +- .../Account/AccountViewController.swift | 26 ++++++------- .../Account/TransferViewController.swift | 38 +++++++++---------- .../Chats/ChatListViewController.swift | 2 +- .../Stories/Chats/ChatViewController.swift | 17 ++++----- .../Stories/Chats/NewChatViewController.swift | 16 ++++---- .../Stories/Login/LoginViewController.swift | 32 ++++++++-------- .../Settings/QRGeneratorViewController.swift | 11 +++--- .../Settings/SettingsViewController.swift | 22 +++++------ .../TransactionDetailsViewController.swift | 22 +++++------ 20 files changed, 132 insertions(+), 132 deletions(-) diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index 545c21a50..4b81807e0 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -11,7 +11,7 @@ import Swinject extension String.adamantLocalized { struct tabItems { - static let account = NSLocalizedString("Tabs.Account", comment: "Main tab bar: Account/Wallet page") + static let account = NSLocalizedString("Tabs.Account", comment: "Main tab bar: Account page") static let chats = NSLocalizedString("Tabs.Chats", comment: "Main tab bar: Chats page") static let settings = NSLocalizedString("Tabs.Settings", comment: "Main tab bar: Settings page") } diff --git a/Adamant/Helpers/MyLittlePinpad+adamant.swift b/Adamant/Helpers/MyLittlePinpad+adamant.swift index 000d2d0d9..f1fe8ed06 100644 --- a/Adamant/Helpers/MyLittlePinpad+adamant.swift +++ b/Adamant/Helpers/MyLittlePinpad+adamant.swift @@ -11,8 +11,8 @@ import MyLittlePinpad extension String.adamantLocalized { struct pinpad { - static let createPin = NSLocalizedString("Enter new pin", comment: "Pinpad: Ask user to create new pin") - static let reenterPin = NSLocalizedString("Re-enter new pin", comment: "Pinpad: Ask user to repeat new pin") + static let createPin = NSLocalizedString("Pinpad.EnterNewPin", comment: "Pinpad: Ask user to create new pin") + static let reenterPin = NSLocalizedString("Pinpad.ReenterPin", comment: "Pinpad: Ask user to repeat new pin") } } diff --git a/Adamant/Helpers/String+localized.swift b/Adamant/Helpers/String+localized.swift index c43e2252c..607db518f 100644 --- a/Adamant/Helpers/String+localized.swift +++ b/Adamant/Helpers/String+localized.swift @@ -18,17 +18,17 @@ extension String { struct alert { // MARK: Buttons - static let cancel = NSLocalizedString("Cancel", comment: "Shared alert 'Cancel' button. Used anywhere") - static let ok = NSLocalizedString("Ok", comment: "Shared alert 'Ok' button. Used anywhere") - static let save = NSLocalizedString("Save", comment: "Shared alert 'Save' button. Used anywhere") - static let settings = NSLocalizedString("Settings", comment: "Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title.") + static let cancel = NSLocalizedString("Shared.Cancel", comment: "Shared alert 'Cancel' button. Used anywhere") + static let ok = NSLocalizedString("Shared.Ok", comment: "Shared alert 'Ok' button. Used anywhere") + static let save = NSLocalizedString("Shared.Save", comment: "Shared alert 'Save' button. Used anywhere") + static let settings = NSLocalizedString("Shared.Settings", comment: "Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title.") // MARK: Titles and messages - static let error = NSLocalizedString("Error", comment: "Shared alert 'Error' title. Used anywhere") - static let done = NSLocalizedString("Done", comment: "Shared alert Done message. Used anywhere") + static let error = NSLocalizedString("Shared.Error", comment: "Shared alert 'Error' title. Used anywhere") + static let done = NSLocalizedString("Shared.Done", comment: "Shared alert Done message. Used anywhere") // MARK: Notifications - static let copiedToPasteboardNotification = NSLocalizedString("Copied to Pasteboard", comment: "Shared alert notification: message about item copied to pasteboard.") + static let copiedToPasteboardNotification = NSLocalizedString("Shared.CopiedToPasteboard", comment: "Shared alert notification: message about item copied to pasteboard.") } private init() { } diff --git a/Adamant/Info.plist b/Adamant/Info.plist index c1429a287..0d5a1c703 100644 --- a/Adamant/Info.plist +++ b/Adamant/Info.plist @@ -23,11 +23,11 @@ LSRequiresIPhoneOS NSCameraUsageDescription - The camera needed to scan QR codes - addresses and passphrases + The camera needed to scan QR codes for addresses and passphrases NSPhotoLibraryAddUsageDescription - Saving generated QR codes - passphrases and addresses + Saving generated QR codes with passphrases and addresses NSPhotoLibraryUsageDescription - Reading QR codes - passphrases and addresses + Reading QR codes with passphrases and addresses UIAppFonts Exo+2_100_normal.ttf diff --git a/Adamant/ServiceProtocols/AccountService.swift b/Adamant/ServiceProtocols/AccountService.swift index 10cf8010c..a9e4efc65 100644 --- a/Adamant/ServiceProtocols/AccountService.swift +++ b/Adamant/ServiceProtocols/AccountService.swift @@ -55,19 +55,19 @@ enum AccountServiceError { var localized: String { switch self { case .userNotLogged: - return NSLocalizedString("User not logged", comment: "Login: user not logged error") + return NSLocalizedString("AccountServiceError.UserNotLogged", comment: "Login: user not logged error") case .invalidPassphrase: - return NSLocalizedString("Wrong passphrase", comment: "Login: user typed in wrong passphrase") + return NSLocalizedString("AccountServiceError.InvalidPassphrase", comment: "Login: user typed in invalid passphrase") case .wrongPassphrase: - return NSLocalizedString("Wrong passphrase", comment: "Login: user typed in wrong passphrase") + return NSLocalizedString("AccountServiceError.WrongPassphrase", comment: "Login: user typed in wrong passphrase") case .apiError(let error): return error.localized case .internalError(let message, _): - return String.localizedStringWithFormat(NSLocalizedString("Internal error: %@, report this as a bug", comment: "ApiService: Bad internal application error, report a bug"), message) + return String.localizedStringWithFormat(NSLocalizedString("AccountServiceError.Internal errorFormat", comment: "ApiService: Bad internal application error, report a bug. Using %@ as error description"), message) } } } diff --git a/Adamant/ServiceProtocols/ApiService.swift b/Adamant/ServiceProtocols/ApiService.swift index fa233e451..4243c3b26 100644 --- a/Adamant/ServiceProtocols/ApiService.swift +++ b/Adamant/ServiceProtocols/ApiService.swift @@ -23,13 +23,13 @@ enum ApiServiceError: Error { var localized: String { switch self { case .notLogged: - return NSLocalizedString("User not logged", comment: "ApiService: User not logged error") + return NSLocalizedString("ApiService.Error.UserNotLogged", comment: "ApiService: User not logged error") case .accountNotFound: - return NSLocalizedString("Account not found: %@", comment: "ApiService: Account not found error, appending account info.") + return NSLocalizedString("ApiService.Error.AccountNotFoundFormat", comment: "ApiService: Account not found error. Using %@ for address.") case .serverError(error: let error): - return String.localizedStringWithFormat(NSLocalizedString("Remote Server error: %@", comment: "ApiService: Remote server returned an error"), error) + return String.localizedStringWithFormat(NSLocalizedString("ApiService.Error.RemoteServerErrorFormat", comment: "ApiService: Remote server returned an error. Using %@ for error description"), error) case .internalError(let msg, let error): let message: String @@ -41,10 +41,10 @@ enum ApiServiceError: Error { message = msg } - return String.localizedStringWithFormat(NSLocalizedString("Internal error: %@, report this as a bug", comment: "ApiService: Bad internal application error, report a bug"), message) + return String.localizedStringWithFormat(NSLocalizedString("ApiService.Error.InternalErrorFormat", comment: "ApiService: Bad internal application error, report a bug. Using %@ for error description"), message) case .networkError(error: _): - return NSLocalizedString("No connection", comment: "ApiService: No connection message. Generally bad network.") + return NSLocalizedString("ApiService.Error.NoConnection", comment: "ApiService: No connection message. Generally bad network.") } } } diff --git a/Adamant/ServiceProtocols/DialogService.swift b/Adamant/ServiceProtocols/DialogService.swift index 8761577f0..59e142419 100644 --- a/Adamant/ServiceProtocols/DialogService.swift +++ b/Adamant/ServiceProtocols/DialogService.swift @@ -28,9 +28,9 @@ enum ShareType { } extension String.adamantLocalized.alert { - static let copyToPasteboard = NSLocalizedString("Copy to Pasteboard", comment: "Shared alert 'Copy' button. Used anywhere. Used for copy-paste info.") - static let share = NSLocalizedString("Share", comment: "Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu.") - static let generateQr = NSLocalizedString("Generate QR Code", comment: "Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere.") + static let copyToPasteboard = NSLocalizedString("Shared.CopyToPasteboard", comment: "Shared alert 'Copy' button. Used anywhere. Used for copy-paste info.") + static let share = NSLocalizedString("Shared.Share", comment: "Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu.") + static let generateQr = NSLocalizedString("Shared.GenerateQRCode", comment: "Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere.") } enum ShareContentType { diff --git a/Adamant/ServiceProtocols/NotificationsService.swift b/Adamant/ServiceProtocols/NotificationsService.swift index f922e5bbc..8b7d1e649 100644 --- a/Adamant/ServiceProtocols/NotificationsService.swift +++ b/Adamant/ServiceProtocols/NotificationsService.swift @@ -10,13 +10,13 @@ import Foundation extension String.adamantLocalized { struct notifications { - static let notificationsDisabled = NSLocalizedString("Notifications disabled. You can reenable notifications in Settings", comment: "Notifications: User has disabled notifications. Head him into settings") + static let notificationsDisabled = NSLocalizedString("NotificationsService.NotificationsDisabled", comment: "Notifications: User has disabled notifications. Head him into settings") - static let newMessageTitle = NSLocalizedString("New message", comment: "Notifications: New message notification title") - static let newMessageBody = NSLocalizedString("You have %d new message(s)", comment: "Notifications: new messages notification body") + static let newMessageTitle = NSLocalizedString("NotificationsService.NewMessage.Title", comment: "Notifications: New message notification title") + static let newMessageBody = NSLocalizedString("NotificationsService.NewMessage.BodyFormat", comment: "Notifications: new messages notification body. Using %d for amount") - static let newTransferTitle = NSLocalizedString("New transfer", comment: "Notifications: New transfer transaction title") - static let newTransferBody = NSLocalizedString("You have %d new transfer(s)", comment: "Notifications: New transfer notification body") + static let newTransferTitle = NSLocalizedString("NotificationsService.NewTransfer.Title", comment: "Notifications: New transfer transaction title") + static let newTransferBody = NSLocalizedString("NotificationsService.NewTransferFormat", comment: "Notifications: New transfer notification body. Using %d for amount") private init() {} } diff --git a/Adamant/Services/ApiService/AdamantApiService.swift b/Adamant/Services/ApiService/AdamantApiService.swift index 03d1c0a33..f1d30783f 100644 --- a/Adamant/Services/ApiService/AdamantApiService.swift +++ b/Adamant/Services/ApiService/AdamantApiService.swift @@ -33,16 +33,16 @@ class AdamantApiService: ApiService { var localized: String { switch self { case .endpointBuildFailed: - return NSLocalizedString("Endpoint build failed", comment: "Serious internal error: Failed to build endpoint url") + return NSLocalizedString("ApiService.InternalError.EndpointBuildFailed", comment: "Serious internal error: Failed to build endpoint url") case .signTransactionFailed: - return NSLocalizedString("Failed transaction signing", comment: "Serious internal error: Failed to sign transaction") + return NSLocalizedString("ApiService.InternalError.FailedTransactionSigning", comment: "Serious internal error: Failed to sign transaction") case .parsingFailed: - return NSLocalizedString("Parsing failed", comment: "Serious internal error: Error parsing response") + return NSLocalizedString("ApiService.InternalError.ParsingFailed", comment: "Serious internal error: Error parsing response") case .unknownError: - return NSLocalizedString("Unknown error", comment: "Unknown internal error") + return NSLocalizedString("ApiService.InternalError.UnknownError", comment: "Unknown internal error") } } } diff --git a/Adamant/Services/DataProviders/AdamantAccountsProvider.swift b/Adamant/Services/DataProviders/AdamantAccountsProvider.swift index 67fa6da68..65ce214ef 100644 --- a/Adamant/Services/DataProviders/AdamantAccountsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantAccountsProvider.swift @@ -34,12 +34,12 @@ private enum Contacts { var messages: [String:String] { switch self { case .adamantBountyWallet: - return ["chats.welcome_message": NSLocalizedString("Welcome to ADAMANT, the most secure and anonymous messenger. You are credited with bounty tokens, which you can use to get acquainted with the messenger.\nRemember, your security and anonymity is up to you also. Do not follow links you receive, otherwise your IP can be compromised. Do not trust browser extensions. Better to share your ADM address personally, but not using other messengers. Keep your secret passphrase secure. Set a password on your device or logout before leaving.\nLearn more about security and anonymity at https://adamant.im/staysecured/.\n\nDo not reply to this message, it is a system account.", comment: "Known contacts: Adamant welcome message")] + return ["chats.welcome_message": NSLocalizedString("Chats.WelcomeMessage", comment: "Known contacts: Adamant welcome message")] case .adamantIco: return [ - "chats.preico_message": NSLocalizedString("You have a possibility to invest in ADAMANT, the most secure and anonymous messenger. Now is a Pre-ICO stage — the most profitable for investors. Learn more on Adamant.im website or in the Whitepaper. To participate just reply to this message and we will assist. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper.", comment: "Known contacts: Adamant pre ICO message"), - "chats.ico_message": NSLocalizedString("You have a possibility to invest in ICO of ADAMANT, the most secure and anonymous messenger. Earlier you participate, better offer you will get. Learn more on Adamant.im website or in the Whitepaper. To invest, go to Wallet→Invest in the ICO, or follow a website page Adamant.im/ico/. If you still have any questions, you can ask them by replying to this message. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper.", comment: "Known contacts: Adamant ICO message") + "chats.preico_message": NSLocalizedString("Chats.PreIcoMessage", comment: "Known contacts: Adamant pre ICO message"), + "chats.ico_message": NSLocalizedString("Chats.IcoMessage", comment: "Known contacts: Adamant ICO message") ] } } diff --git a/Adamant/SharedCells/RoundAvatarTableViewCell.swift b/Adamant/SharedCells/RoundAvatarTableViewCell.swift index 140efdbf9..b094ed53f 100644 --- a/Adamant/SharedCells/RoundAvatarTableViewCell.swift +++ b/Adamant/SharedCells/RoundAvatarTableViewCell.swift @@ -10,8 +10,8 @@ import UIKit extension SharedCell { static let RoundAvatarCell = SharedCell(cellIdentifier: "roundAvatar", - xibName: "RoundAvatarTableViewCell", - rowHeight: 72) + xibName: "RoundAvatarTableViewCell", + rowHeight: 72) } class RoundAvatarTableViewCell: UITableViewCell { diff --git a/Adamant/Stories/Account/AccountViewController.swift b/Adamant/Stories/Account/AccountViewController.swift index 76636d4b4..2aa41e770 100644 --- a/Adamant/Stories/Account/AccountViewController.swift +++ b/Adamant/Stories/Account/AccountViewController.swift @@ -13,28 +13,28 @@ import SafariServices // MARK: - Localization extension String.adamantLocalized { struct account { - static let title = NSLocalizedString("Wallet.title", comment: "Wallet page: scene title") + static let title = NSLocalizedString("AccountTab.title", comment: "Account page: scene title") - static let rowBalance = NSLocalizedString("Balance", comment: "Wallet page: Balance row title") - static let rowSendTokens = NSLocalizedString("Send Tokens", comment: "Wallet page: 'Send tokens' button") - static let rowInvest = NSLocalizedString("Invest in ICO", comment: "Wallet page: 'Invest in ICO' button") - static let rowLogout = NSLocalizedString("Logout", comment: "Wallet page: 'Logout' button") + static let rowBalance = NSLocalizedString("AccountTab.Row.Balance", comment: "Account tab: Balance row title") + static let rowSendTokens = NSLocalizedString("AccountTab.Row.SendTokens", comment: "Account tab: 'Send tokens' button") + static let rowInvest = NSLocalizedString("AccountTab.Row.JoinIco", comment: "Account tab: 'Invest in ICO' button") + static let rowLogout = NSLocalizedString("AccountTab.Row.Logout", comment: "Account tab: 'Logout' button") - static let sorryAlert = NSLocalizedString("Sorry!", comment: "Wallet page: 'Transfer not allowed' alert title") - static let webApp = NSLocalizedString("Go to msg.adamant.im", comment: "Wallet page: 'Transfer not allowed' alert 'go to WebApp button'") - static let transferNotAllowed = NSLocalizedString("Due to Apple restrictions, sending tokens is not allowed until the end of the ICO. For now, you can send tokens using WebApp at msg.adamant.im", comment: "Wallet page: Inform user that sending tokens not allowed by Apple until the end of ICO") + static let sorryAlert = NSLocalizedString("AccountTab.TransferBlocked.Title", comment: "Account tab: 'Transfer not allowed' alert title") + static let webApp = NSLocalizedString("AccountTab.TransferBlocked.GoToPWA", comment: "Account tab: 'Transfer not allowed' alert 'go to WebApp button'") + static let transferNotAllowed = NSLocalizedString("AccountTab.Message", comment: "Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO") - static let sectionAccount = NSLocalizedString("Account", comment: "Wallet page: Account section title.") - static let sectionWallet = NSLocalizedString("Wallet", comment: "Wallet page: Wallet section title") - static let sectionActions = NSLocalizedString("Actions", comment: "Wallet page: Actions section title") + static let sectionAccount = NSLocalizedString("AccountTab.Section.Account", comment: "Account tab: Account section title.") + static let sectionWallet = NSLocalizedString("AccountTab.Section.Wallet", comment: "Account tab: Wallet section title") + static let sectionActions = NSLocalizedString("AccountTab.Section.Actions", comment: "Account tab: Actions section title") private init() { } } } fileprivate extension String.adamantLocalized.alert { - static let logoutMessageFormat = NSLocalizedString("Logout from %@?", comment: "Wallet page: Confirm logout alert") - static let logoutButton = NSLocalizedString("Logout", comment: "Wallet page: Confirm logout alert: Logout (Ok) button") + static let logoutMessageFormat = NSLocalizedString("AccountTab.ConfirmLogout.MessageFormat", comment: "Account tab: Confirm logout alert") + static let logoutButton = NSLocalizedString("AccountTab.ConfirmLogout.Logout", comment: "Account tab: Confirm logout alert: Logout (Ok) button") } diff --git a/Adamant/Stories/Account/TransferViewController.swift b/Adamant/Stories/Account/TransferViewController.swift index 5cbc9370d..d10661728 100644 --- a/Adamant/Stories/Account/TransferViewController.swift +++ b/Adamant/Stories/Account/TransferViewController.swift @@ -13,24 +13,24 @@ import Eureka // MARK: - Localization extension String.adamantLocalized { struct transfer { - static let addressPlaceholder = NSLocalizedString("of the recipient", comment: "Transfer: recipient address placeholder") - static let amountPlaceholder = NSLocalizedString("to send", comment: "Transfer: transfer amount placeholder") + static let addressPlaceholder = NSLocalizedString("TransferScene.Recipient.Placeholder", comment: "Transfer: recipient address placeholder") + static let amountPlaceholder = NSLocalizedString("TransferScene.Amount.Placeholder", comment: "Transfer: transfer amount placeholder") - static let addressValidationError = NSLocalizedString("Please enter a valid recipient address", comment: "Transfer: Address validation error") - static let amountZeroError = NSLocalizedString("You should send more money", comment: "Transfer: Amount is zero, or even negative notification") - static let amountTooHigh = NSLocalizedString("You don't have that much money", comment: "Transfer: Amount is hiegher that user's total money notification") - static let accountNotFound = NSLocalizedString("Address not found", comment: "Transfer: Address not found error") + static let addressValidationError = NSLocalizedString("TransferScene.Error.InvalidAddress", comment: "Transfer: Address validation error") + static let amountZeroError = NSLocalizedString("TransferScene.Error.TooLittleMoney", comment: "Transfer: Amount is zero, or even negative notification") + static let amountTooHigh = NSLocalizedString("TransferScene.Error.NotEnoughtMoney", comment: "Transfer: Amount is hiegher that user's total money notification") + static let accountNotFound = NSLocalizedString("TransferScene.Error.AddressNotFound", comment: "Transfer: Address not found error") - static let transferProcessingMessage = NSLocalizedString("Sending funds...", comment: "Transfer: Processing message") - static let transferSuccess = NSLocalizedString("Funds sended!", comment: "Transfer: Tokens transfered successfully message") + static let transferProcessingMessage = NSLocalizedString("TransferScene.SendingFundsProgress", comment: "Transfer: Processing message") + static let transferSuccess = NSLocalizedString("TransferScene.TransferSuccessMessage", comment: "Transfer: Tokens transfered successfully message") private init() { } } } fileprivate extension String.adamantLocalized.alert { - static let confirmSendMessageFormat = NSLocalizedString("Send %1$@ to %2$@?", comment: "Transfer: Confirm transfer X tokens to Y message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'.") - static let send = NSLocalizedString("Send", comment: "Transfer: Confirm transfer alert: Send tokens button") + static let confirmSendMessageFormat = NSLocalizedString("TransferScene.SendConfirmFormat", comment: "Transfer: Confirm transfer %1$@ tokens to %2$@ message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'.") + static let send = NSLocalizedString("TransferScene.Send", comment: "Transfer: Confirm transfer alert: Send tokens button") } @@ -62,13 +62,13 @@ class TransferViewController: FormViewController { var localized: String { switch self { - case .balance: return NSLocalizedString("Balance", comment: "Transfer: logged user balance.") - case .amount: return NSLocalizedString("Amount", comment: "Transfer: amount of adamant to transfer.") - case .maxToTransfer: return NSLocalizedString("Max to transfer", comment: "Transfer: maximum amount to transfer: available account money substracting transfer fee.") - case .address: return NSLocalizedString("Address", comment: "Transfer: recipient address") - case .fee: return NSLocalizedString("Transaction fee", comment: "Transfer: transfer fee") - case .total: return NSLocalizedString("Total", comment: "Transfer: total amount of transaction: money to transfer adding fee") - case .sendButton: return NSLocalizedString("Send Funds", comment: "Transfer: Send button") + case .balance: return NSLocalizedString("TransferScene.Row.Balance", comment: "Transfer: logged user balance.") + case .amount: return NSLocalizedString("TransferScene.Row.Amount", comment: "Transfer: amount of adamant to transfer.") + case .maxToTransfer: return NSLocalizedString("TransferScene.Row.MaxToTransfer", comment: "Transfer: maximum amount to transfer: available account money substracting transfer fee.") + case .address: return NSLocalizedString("TransferScene.Row.Recipient", comment: "Transfer: recipient address") + case .fee: return NSLocalizedString("TransferScene.Row.TransactionFee", comment: "Transfer: transfer fee") + case .total: return NSLocalizedString("TransferScene.Row.Total", comment: "Transfer: total amount of transaction: money to transfer adding fee") + case .sendButton: return NSLocalizedString("TransferScene.Row.Send", comment: "Transfer: Send button") } } } @@ -79,8 +79,8 @@ class TransferViewController: FormViewController { var localized: String { switch self { - case .wallet: return NSLocalizedString("Your wallet", comment: "Transfer: 'Your wallet' section") - case .transferInfo: return NSLocalizedString("Transfer Info", comment: "Transfer: 'Transfer info' section") + case .wallet: return NSLocalizedString("TransferScene.Section.YourWallet", comment: "Transfer: 'Your wallet' section") + case .transferInfo: return NSLocalizedString("TransferScene.Section.TransferInfo", comment: "Transfer: 'Transfer info' section") } } } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index f54066147..4f1ec9b82 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -11,7 +11,7 @@ import CoreData extension String.adamantLocalized { struct chatList { - static let title = NSLocalizedString("ChatList.title", comment: "ChatList: scene title") + static let title = NSLocalizedString("ChatListPage.Title", comment: "ChatList: scene title") private init() {} } diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 9f6dd554b..0256d29e1 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -13,16 +13,15 @@ import CoreData // MARK: - Localization extension String.adamantLocalized { struct chat { - static let sendButton = NSLocalizedString("Send", comment: "Chat: Send message button") - static let messageInputPlaceholder = NSLocalizedString("New message", comment: "Chat: message input placeholder") - static let estimatedFeeFormat = NSLocalizedString("~%@", comment: "Chat: input bar: Estimated fee") + static let sendButton = NSLocalizedString("ChatScene.Send", comment: "Chat: Send message button") + static let messageInputPlaceholder = NSLocalizedString("ChatScene.NewMessage.Placeholder", comment: "Chat: message input placeholder") - static let messageIsEmpty = NSLocalizedString("Message is empty", comment: "Chat: Notify user that message cannot be empty") - static let messageTooLong = NSLocalizedString("Message is too long", comment: "Chat: Message is too long") - static let notEnoughMoney = NSLocalizedString("You don't have enough money to send a message", comment: "Chat: Notify user that he doesn't have money to pay a message fee") + static let messageIsEmpty = NSLocalizedString("ChatScene.Error.MessageIsEmpty", comment: "Chat: Notify user that message cannot be empty") + static let messageTooLong = NSLocalizedString("ChatScene.Error.MessageTooLong", comment: "Chat: Message is too long") + static let notEnoughMoney = NSLocalizedString("ChatScene.Error.NotEnoughMoney", comment: "Chat: Notify user that he doesn't have money to pay a message fee") - static let internalErrorFormat = NSLocalizedString("Internal error: %@. You should report this bug.", comment: "Chat: Notify user about bad internal error. Usually this should be reported as a bug.") - static let serverErrorFormat = NSLocalizedString("Remote server error: %@", comment: "Chat: Notify user about server error.") + static let internalErrorFormat = NSLocalizedString("ChatScene.Error.InternalErrorFormat", comment: "Chat: Notify user about bad internal error. Usually this should be reported as a bug. Using %@ for error description") + static let serverErrorFormat = NSLocalizedString("ChatScene.Error.RemoteServerError", comment: "Chat: Notify user about server error. Using %@ for error description") private init() { } } @@ -194,7 +193,7 @@ extension ChatViewController { return } - let text = String.localizedStringWithFormat(String.adamantLocalized.chat.estimatedFeeFormat, AdamantUtilities.format(balance: fee)) + let text = "~\(AdamantUtilities.format(balance: fee))" prevFee = fee feeLabel.title = text diff --git a/Adamant/Stories/Chats/NewChatViewController.swift b/Adamant/Stories/Chats/NewChatViewController.swift index abee171a8..2ae308c10 100644 --- a/Adamant/Stories/Chats/NewChatViewController.swift +++ b/Adamant/Stories/Chats/NewChatViewController.swift @@ -14,17 +14,17 @@ import AVFoundation // MARK: - Localization extension String.adamantLocalized { struct newChat { - static let title = NSLocalizedString("NewChat.title", comment: "New chat: scene title") + static let title = NSLocalizedString("NewChatScene.Title", comment: "New chat: scene title") - static let addressPlaceholder = NSLocalizedString("", comment: "New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank.") - static let scanQrButton = NSLocalizedString("Scan QR", comment: "New chat: Scan QR with address button") + static let addressPlaceholder = NSLocalizedString(NewChatScene.Address.Placeholder, comment: "New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank.") + static let scanQrButton = NSLocalizedString("NewChatScene.ScanQr", comment: "New chat: Scan QR with address button") - static let specifyValidAddressMessage = NSLocalizedString("Please specify valid recipient address", comment: "New chat: Notify user that he did enter invalid address") - static let loggedUserAddressMessage = NSLocalizedString("You don't need an encrypted anonymous chat to talk to yourself", comment: "New chat: Notify user that he can't start chat with himself") + static let specifyValidAddressMessage = NSLocalizedString("NewChatScene.Error.InvalidAddress", comment: "New chat: Notify user that he did enter invalid address") + static let loggedUserAddressMessage = NSLocalizedString("NewChatScene.Error.OwnAddress", comment: "New chat: Notify user that he can't start chat with himself") - static let wrongQrError = NSLocalizedString("QR code does not contains a valid adamant address", comment: "New Chat: Notify user that scanned QR doesn't contains an address") - static let addressNotFoundFormat = NSLocalizedString("Address %@ not found", comment: "New chat: Notify user that specified address (%@) not found") - static let serverErrorFormat = NSLocalizedString("%@", comment: "New chat: Remote server returned an error.") + static let wrongQrError = NSLocalizedString("NewChatScene.Error.WrongQr", comment: "New Chat: Notify user that scanned QR doesn't contains an address") + static let addressNotFoundFormat = NSLocalizedString("NewChatScene.Error.AddressNotFoundFormat", comment: "New chat: Notify user that specified address (%@) not found. Using %@ for address") + static let serverErrorFormat = NSLocalizedString("NewChatScene.Error.RemoteServerFormat", comment: "New chat: Remote server returned an error. Using %@ for error description") private init() { } } diff --git a/Adamant/Stories/Login/LoginViewController.swift b/Adamant/Stories/Login/LoginViewController.swift index 484df670d..8d07f146c 100644 --- a/Adamant/Stories/Login/LoginViewController.swift +++ b/Adamant/Stories/Login/LoginViewController.swift @@ -13,17 +13,17 @@ import MyLittlePinpad // MARK: - Localization extension String.adamantLocalized { struct login { - static let loggingInProgressMessage = NSLocalizedString("Logging in", comment: "Login: notify user that we a logging in") + static let loggingInProgressMessage = NSLocalizedString("LoginScene.LoggingInProgress", comment: "Login: notify user that we are trying to log in") - static let loginIntoPrevAccount = NSLocalizedString("Login into Adamant", comment: "Login: Login into previous account with biometry or pincode") + static let loginIntoPrevAccount = NSLocalizedString("LoginScene.LoginIntoAdamant", comment: "Login: Login into previous account with biometry or pincode") - static let wrongQrError = NSLocalizedString("QR code does not contains a valid passphrase", comment: "Login: Notify user that scanned QR doesn't contains a passphrase.") - static let noNetworkError = NSLocalizedString("No connection with The Internet", comment: "Login: No network error.") + static let wrongQrError = NSLocalizedString("LoginScene.Error.WrongQr", comment: "Login: Notify user that scanned QR doesn't contains a passphrase.") + static let noNetworkError = NSLocalizedString("LoginScene.Error.NoInternet", comment: "Login: No network error.") - static let cameraNotAuthorized = NSLocalizedString("You need to authorize Adamant to use device's Camera", comment: "Login: Notify user, that he disabled camera in settings, and need to authorize application.") - static let cameraNotSupported = NSLocalizedString("QR codes reading not supported by the current device", comment: "Login: Notify user that device not supported by QR reader") + static let cameraNotAuthorized = NSLocalizedString("LoginScene.Error.AuthorizeCamera", comment: "Login: Notify user, that he disabled camera in settings, and need to authorize application.") + static let cameraNotSupported = NSLocalizedString("LoginScene.Error.QrNotSupported", comment: "Login: Notify user that device not supported by QR reader") - static let emptyPassphraseAlert = NSLocalizedString("Enter a passphrase!", comment: "Login: notify user that he is trying to login without a passphrase") + static let emptyPassphraseAlert = NSLocalizedString("LoginScene.Error.NoPassphrase", comment: "Login: notify user that he is trying to login without a passphrase") private init() {} } @@ -42,10 +42,10 @@ class LoginViewController: FormViewController { var localized: String { switch self { case .login: - return NSLocalizedString("Login", comment: "Login: login with existing passphrase section") + return NSLocalizedString("LoginScene.Section.Login", comment: "Login: login with existing passphrase section") case .newAccount: - return NSLocalizedString("New account", comment: "Login: Create new account section") + return NSLocalizedString("LoginScene.Section.NewAccount", comment: "Login: Create new account section") } } @@ -70,25 +70,25 @@ class LoginViewController: FormViewController { var localized: String { switch self { case .passphrase: - return NSLocalizedString("Passphrase", comment: "Login: Passphrase placeholder") + return NSLocalizedString("LoginScene.Row.Passphrase.Placeholder", comment: "Login: Passphrase placeholder") case .loginButton: - return NSLocalizedString("Login", comment: "Login: Login button") + return NSLocalizedString("LoginScene.Row.Login", comment: "Login: Login button") case .loginWithQr: - return NSLocalizedString("Login with QR", comment: "Login: Login with QR button.") + return NSLocalizedString("LoginScene.Row.Qr", comment: "Login: Login with QR button.") case .loginWithPin: - return NSLocalizedString("Login with Pincode", comment: "Login: Login with pincode button") + return NSLocalizedString("LoginScene.Row.Pincode", comment: "Login: Login with pincode button") case .saveYourPassphraseAlert: - return NSLocalizedString("Save the passphrase for new Wallet and Messenger account. There is no login to enter Wallet, only the passphrase needed. If lost, no way to recover it", comment: "Login: security alert, notify user that he must save his new passphrase") + return NSLocalizedString("LoginScene.Row.SavePassphraseAlert", comment: "Login: security alert, notify user that he must save his new passphrase") case .generateNewPassphraseButton: - return NSLocalizedString("Generate new passphrase", comment: "Login: generate new passphrase button") + return NSLocalizedString("LoginScene.Row.Generate", comment: "Login: generate new passphrase button") case .tapToSaveHint: - return NSLocalizedString("Tap to save", comment: "Login: a small hint for a user, that he can tap on passphrase to save it") + return NSLocalizedString("LoginScene.Row.TapToSave", comment: "Login: a small hint for a user, that he can tap on passphrase to save it") case .newPassphrase: return "" diff --git a/Adamant/Stories/Settings/QRGeneratorViewController.swift b/Adamant/Stories/Settings/QRGeneratorViewController.swift index 7bff199ca..dfeb5ab5f 100644 --- a/Adamant/Stories/Settings/QRGeneratorViewController.swift +++ b/Adamant/Stories/Settings/QRGeneratorViewController.swift @@ -14,13 +14,13 @@ import Photos // MARK: - Localization extension String.adamantLocalized { struct qrGenerator { - static let title = NSLocalizedString("QrGenerator.title", comment: "QRGenerator: scene title") + static let title = NSLocalizedString("QrGeneratorScene.Title", comment: "QRGenerator: scene title") - static let tapToSaveTip = NSLocalizedString("Tap to save", comment: "QRGenerator: small 'Tap to save' tooltip under generated QR") - static let passphrasePlaceholder = NSLocalizedString("Passphrase", comment: "QRGenerator: Passphrase textview placeholder") + static let tapToSaveTip = NSLocalizedString("QrGeneratorScene.TapToSave", comment: "QRGenerator: small 'Tap to save' tooltip under generated QR") + static let passphrasePlaceholder = NSLocalizedString("QrGeneratorScene.Passphrase.Placeholder", comment: "QRGenerator: Passphrase textview placeholder") - static let wrongPassphraseError = NSLocalizedString("Enter correct passphrase", comment: "QRGenerator: user typed in wrong invalid") - static let internalError = NSLocalizedString("Internal error: %@", comment: "QRGenerator: Bad Internal generator error message format") + static let wrongPassphraseError = NSLocalizedString("QrGeneratorScene.Error.InvalidPassphrase", comment: "QRGenerator: user typed in wrong invalid") + static let internalError = NSLocalizedString("QrGeneratorScene.ErrorInternalError", comment: "QRGenerator: Bad Internal generator error message format. Using %@ for error description") private init() {} } @@ -62,6 +62,7 @@ class QRGeneratorViewController: FormViewController { // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() + navigationItem.title = String.adamantLocalized.qrGenerator.title navigationOptions = .Disabled self.tableView.showsVerticalScrollIndicator = false diff --git a/Adamant/Stories/Settings/SettingsViewController.swift b/Adamant/Stories/Settings/SettingsViewController.swift index d7bab053d..f96663e66 100644 --- a/Adamant/Stories/Settings/SettingsViewController.swift +++ b/Adamant/Stories/Settings/SettingsViewController.swift @@ -12,11 +12,11 @@ import MyLittlePinpad extension String.adamantLocalized { struct settings { - static let title = NSLocalizedString("Config.title", comment: "Config: scene title") + static let title = NSLocalizedString("SettingsPage.Title", comment: "Config: scene title") - static let stayInTurnOff = NSLocalizedString("Do not stay logged in", comment: "Config: turn off 'Stay Logged In' confirmation") - static let biometryOnReason = NSLocalizedString("Use biometry to log in", comment: "Config: Authorization reason for turning biometry on") - static let biometryOffReason = NSLocalizedString("Do not use biometry to log in", comment: "Config: Authorization reason for turning biometry off") + static let stayInTurnOff = NSLocalizedString("SettingsPage.DoNotStayLoggedIn", comment: "Config: turn off 'Stay Logged In' confirmation") + static let biometryOnReason = NSLocalizedString("SettingsPage.UseBiometry", comment: "Config: Authorization reason for turning biometry on") + static let biometryOffReason = NSLocalizedString("SettingsPage.DoNotUseBiometry", comment: "Config: Authorization reason for turning biometry off") } } @@ -30,13 +30,13 @@ class SettingsViewController: FormViewController { var localized: String { switch self { case .settings: - return NSLocalizedString("Settings", comment: "Config: Settings section") + return NSLocalizedString("SettingsPage.Section.Settings", comment: "Config: Settings section") case .applicationInfo: - return NSLocalizedString("Application info", comment: "Config: Application Info section") + return NSLocalizedString("SettingsPage.Section.ApplicationInfo", comment: "Config: Application Info section") case .utilities: - return NSLocalizedString("Utilities", comment: "Config: Utilities section") + return NSLocalizedString("SettingsPage.Section.Utilities", comment: "Config: Utilities section") } } } @@ -51,19 +51,19 @@ class SettingsViewController: FormViewController { var localized: String { switch self { case .version: - return NSLocalizedString("Version", comment: "Config: Version row") + return NSLocalizedString("SettingsPage.Row.Version", comment: "Config: Version row") case .qrPassphraseGenerator: - return NSLocalizedString("Generate QR with passphrase", comment: "Config: Generate QR with passphrase row") + return NSLocalizedString("SettingsPage.Row.GenerateQr", comment: "Config: Generate QR with passphrase row") case .stayLoggedIn: - return NSLocalizedString("Stay Logged in", comment: "Config: Stay logged option") + return NSLocalizedString("SettingsPage.Row.StayLoggedIn", comment: "Config: Stay logged option") case .biometry: return "" case .notifications: - return NSLocalizedString("Notifications", comment: "Config: Show notifications") + return NSLocalizedString("SettingsPage.Row.Notifications", comment: "Config: Show notifications") } } diff --git a/Adamant/Stories/Transactions/TransactionDetailsViewController.swift b/Adamant/Stories/Transactions/TransactionDetailsViewController.swift index 1b5c7aa49..d071af1db 100644 --- a/Adamant/Stories/Transactions/TransactionDetailsViewController.swift +++ b/Adamant/Stories/Transactions/TransactionDetailsViewController.swift @@ -12,8 +12,8 @@ import SafariServices // MARK: - Localization extension String.adamantLocalized.alert { - static let exportUrlButton = NSLocalizedString("URL", comment: "Export transaction: 'Share transaction URL' button") - static let exportSummaryButton = NSLocalizedString("Summary", comment: "Export transaction: 'Share transaction summary' button") + static let exportUrlButton = NSLocalizedString("TransactionDetailsScene.Share.URL", comment: "Export transaction: 'Share transaction URL' button") + static let exportSummaryButton = NSLocalizedString("TransactionDetailsScene.Share.Summary", comment: "Export transaction: 'Share transaction summary' button") } @@ -34,15 +34,15 @@ class TransactionDetailsViewController: UIViewController { var localized: String { switch self { - case .transactionNumber: return NSLocalizedString("Id", comment: "Transaction details: Id row.") - case .from: return NSLocalizedString("From", comment: "Transaction details: sender row.") - case .to: return NSLocalizedString("To", comment: "Transaction details: recipient row.") - case .date: return NSLocalizedString("Date", comment: "Transaction details: date row.") - case .amount: return NSLocalizedString("Amount", comment: "Transaction details: amount row.") - case .fee: return NSLocalizedString("Fee", comment: "Transaction details: fee row.") - case .confirmations: return NSLocalizedString("Confirmations", comment: "Transaction details: confirmations row.") - case .block: return NSLocalizedString("Block", comment: "Transaction details: Block id row.") - case .openInExplorer: return NSLocalizedString("Open in Explorer", comment: "Transaction details: 'Open transaction in explorer' row.") + case .transactionNumber: return NSLocalizedString("TransactionDetailsScene.Row.Id", comment: "Transaction details: Id row.") + case .from: return NSLocalizedString("TransactionDetailsScene.Row.From", comment: "Transaction details: sender row.") + case .to: return NSLocalizedString("TransactionDetailsScene.Row.To", comment: "Transaction details: recipient row.") + case .date: return NSLocalizedString("TransactionDetailsScene.Row.Date", comment: "Transaction details: date row.") + case .amount: return NSLocalizedString("TransactionDetailsScene.Row.Amount", comment: "Transaction details: amount row.") + case .fee: return NSLocalizedString("TransactionDetailsScene.Row.Fee", comment: "Transaction details: fee row.") + case .confirmations: return NSLocalizedString("TransactionDetailsScene.Row.Confirmations", comment: "Transaction details: confirmations row.") + case .block: return NSLocalizedString("TransactionDetailsScene.Row.Block", comment: "Transaction details: Block id row.") + case .openInExplorer: return NSLocalizedString("TransactionDetailsScene.Row.Explorer", comment: "Transaction details: 'Open transaction in explorer' row.") } } } From 03adc67e29ea5c9e82156947cfd4e32e07e4fdd2 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 20:12:45 +0300 Subject: [PATCH 04/13] Refactored localization. --- Adamant.xcodeproj/project.pbxproj | 61 +-- Adamant/AppDelegate.swift | 2 + Adamant/Assets/en.lproj/InfoPlist.strings | 15 - Adamant/Assets/en.lproj/Localizable.strings | 304 -------------- .../Assets/l18n/en.lproj/InfoPlist.strings | 15 + .../Assets/l18n/en.lproj/Localizable.strings | 377 ++++++++++++++++++ .../en.lproj/Localizable.stringsdict | 4 +- .../Assets/l18n/ru.lproj/InfoPlist.strings | 15 + .../Assets/l18n/ru.lproj/Localizable.strings | 377 ++++++++++++++++++ .../ru.lproj/Localizable.stringsdict | 4 +- Adamant/Assets/ru.lproj/InfoPlist.strings | 15 - Adamant/Assets/ru.lproj/Localizable.strings | 304 -------------- .../NotificationsService.swift | 2 +- .../Account/AccountViewController.swift | 4 +- .../Stories/Chats/ChatViewController.swift | 2 +- .../Stories/Chats/NewChatViewController.swift | 2 +- .../Settings/QRGeneratorViewController.swift | 2 +- 17 files changed, 831 insertions(+), 674 deletions(-) delete mode 100644 Adamant/Assets/en.lproj/InfoPlist.strings delete mode 100644 Adamant/Assets/en.lproj/Localizable.strings create mode 100644 Adamant/Assets/l18n/en.lproj/InfoPlist.strings create mode 100644 Adamant/Assets/l18n/en.lproj/Localizable.strings rename Adamant/Assets/{ => l18n}/en.lproj/Localizable.stringsdict (89%) create mode 100644 Adamant/Assets/l18n/ru.lproj/InfoPlist.strings create mode 100644 Adamant/Assets/l18n/ru.lproj/Localizable.strings rename Adamant/Assets/{ => l18n}/ru.lproj/Localizable.stringsdict (91%) delete mode 100644 Adamant/Assets/ru.lproj/InfoPlist.strings delete mode 100644 Adamant/Assets/ru.lproj/Localizable.strings diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 777cead9a..86f0e5c79 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -31,8 +31,6 @@ E9256F5F2034C21100DE86E9 /* String+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9256F5E2034C21100DE86E9 /* String+localized.swift */; }; E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9256F6C20357B1700DE86E9 /* LoginHeader.xib */; }; E9256F762039A9A200DE86E9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */; }; - E9256F792039B29A00DE86E9 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E9256F7B2039B29A00DE86E9 /* Localizable.strings */; }; - E9256F7E2039B29D00DE86E9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E9256F802039B29D00DE86E9 /* InfoPlist.strings */; }; E9393FA82055C92700EE6F30 /* Decimal+adamant.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9393FA72055C92700EE6F30 /* Decimal+adamant.swift */; }; E9393FAA2055D03300EE6F30 /* AdamantMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9393FA92055D03300EE6F30 /* AdamantMessage.swift */; }; E93B0D742028B21400126346 /* ChatsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93B0D732028B21400126346 /* ChatsProvider.swift */; }; @@ -40,7 +38,6 @@ E93D7ABE2052CEE1005D19DC /* NotificationsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93D7ABD2052CEE1005D19DC /* NotificationsService.swift */; }; E93D7AC02052CF63005D19DC /* AdamantNotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93D7ABF2052CF63005D19DC /* AdamantNotificationService.swift */; }; E93D7AC22052EE21005D19DC /* SettingsViewController+StayIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */; }; - E93D7AC520530F76005D19DC /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = E93D7AC720530F76005D19DC /* Localizable.stringsdict */; }; E93EFE13200D1156000BB482 /* ChatViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E93EFE12200D1156000BB482 /* ChatViewController.swift */; }; E94883E7203F07CD00F6E1B0 /* PassphraseValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94883E6203F07CD00F6E1B0 /* PassphraseValidation.swift */; }; E948E03B20235E2300975D6B /* SettingsRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E948E03A20235E2300975D6B /* SettingsRoutes.swift */; }; @@ -56,6 +53,9 @@ E9502740202E257E002C1098 /* RepeaterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950273F202E257E002C1098 /* RepeaterService.swift */; }; E950652120404BF0008352E5 /* AdamantUriBuilding.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652020404BF0008352E5 /* AdamantUriBuilding.swift */; }; E950652320404C84008352E5 /* AdamantUriTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E950652220404C84008352E5 /* AdamantUriTools.swift */; }; + E95CB451205D77B200A7218E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E95CB453205D77B200A7218E /* InfoPlist.strings */; }; + E95CB456205D77B500A7218E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E95CB458205D77B500A7218E /* Localizable.strings */; }; + E95CB45E205D7F9600A7218E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = E95CB460205D7F9600A7218E /* Localizable.stringsdict */; }; E95F856520067A030070534A /* GlobalConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F856420067A030070534A /* GlobalConstants.swift */; }; E95F85692006AB9D0070534A /* NormalizedTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85682006AB9D0070534A /* NormalizedTransaction.swift */; }; E95F856B200789450070534A /* JSModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F856A200789450070534A /* JSModels.swift */; }; @@ -205,8 +205,6 @@ E9256F5E2034C21100DE86E9 /* String+localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+localized.swift"; sourceTree = ""; }; E9256F6C20357B1700DE86E9 /* LoginHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LoginHeader.xib; sourceTree = ""; }; E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; - E9256F7A2039B29A00DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; - E9256F7F2039B29D00DE86E9 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; E9393FA72055C92700EE6F30 /* Decimal+adamant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Decimal+adamant.swift"; sourceTree = ""; }; E9393FA92055D03300EE6F30 /* AdamantMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantMessage.swift; sourceTree = ""; }; E93B0D732028B21400126346 /* ChatsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatsProvider.swift; sourceTree = ""; }; @@ -214,7 +212,6 @@ E93D7ABD2052CEE1005D19DC /* NotificationsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsService.swift; sourceTree = ""; }; E93D7ABF2052CF63005D19DC /* AdamantNotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantNotificationService.swift; sourceTree = ""; }; E93D7AC12052EE21005D19DC /* SettingsViewController+StayIn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SettingsViewController+StayIn.swift"; sourceTree = ""; }; - E93D7AC620530F76005D19DC /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; E93EFE12200D1156000BB482 /* ChatViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatViewController.swift; sourceTree = ""; }; E94883E6203F07CD00F6E1B0 /* PassphraseValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassphraseValidation.swift; sourceTree = ""; }; E948E03A20235E2300975D6B /* SettingsRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsRoutes.swift; sourceTree = ""; }; @@ -230,6 +227,12 @@ E950273F202E257E002C1098 /* RepeaterService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeaterService.swift; sourceTree = ""; }; E950652020404BF0008352E5 /* AdamantUriBuilding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriBuilding.swift; sourceTree = ""; }; E950652220404C84008352E5 /* AdamantUriTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUriTools.swift; sourceTree = ""; }; + E95CB452205D77B200A7218E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + E95CB457205D77B500A7218E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + E95CB459205D77DC00A7218E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + E95CB45A205D77DD00A7218E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; + E95CB45F205D7F9600A7218E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; + E95CB461205D7FD000A7218E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; E95F856420067A030070534A /* GlobalConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConstants.swift; sourceTree = ""; }; E95F85682006AB9D0070534A /* NormalizedTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NormalizedTransaction.swift; sourceTree = ""; }; E95F856A200789450070534A /* JSModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSModels.swift; sourceTree = ""; }; @@ -256,9 +259,6 @@ E9722065201F42BB004F2AAD /* CoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = ""; }; E9722067201F42CC004F2AAD /* InMemoryCoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InMemoryCoreDataStack.swift; sourceTree = ""; }; E972206A201F44CA004F2AAD /* TransfersProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransfersProvider.swift; sourceTree = ""; }; - E982A8D6205D2A610097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - E982A8D7205D2A910097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; - E982A8DC205D2AB40097FAE7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; E982F69B20235B4D00566AC7 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; E9942B7F203C058C00C163AF /* QRGeneratorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRGeneratorViewController.swift; sourceTree = ""; }; E9942B83203CBFCE00C163AF /* AdamantQRTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantQRTools.swift; sourceTree = ""; }; @@ -470,12 +470,10 @@ E913C9111FFFAB05001A83F7 /* Assets */ = { isa = PBXGroup; children = ( + E95CB45B205D7DFD00A7218E /* l18n */, E9E7CDA42002A6EB00DFC4DB /* Fonts */, E913C8F81FFFA51D001A83F7 /* Assets.xcassets */, E9A174B820587B83003667CD /* notification.mp3 */, - E9256F802039B29D00DE86E9 /* InfoPlist.strings */, - E9256F7B2039B29A00DE86E9 /* Localizable.strings */, - E93D7AC720530F76005D19DC /* Localizable.stringsdict */, E9256F752039A9A200DE86E9 /* LaunchScreen.storyboard */, E9C51EEC2011416E00385EB7 /* adamant-core.js */, ); @@ -543,6 +541,16 @@ path = Utilities; sourceTree = ""; }; + E95CB45B205D7DFD00A7218E /* l18n */ = { + isa = PBXGroup; + children = ( + E95CB460205D7F9600A7218E /* Localizable.stringsdict */, + E95CB458205D77B500A7218E /* Localizable.strings */, + E95CB453205D77B200A7218E /* InfoPlist.strings */, + ); + path = l18n; + sourceTree = ""; + }; E95F857B2008C8B20070534A /* Chats */ = { isa = PBXGroup; children = ( @@ -779,6 +787,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + ru, ); mainGroup = E913C8E51FFFA51D001A83F7; productRefGroup = E913C8EF1FFFA51D001A83F7 /* Products */; @@ -797,6 +806,7 @@ buildActionMask = 2147483647; files = ( E9256F762039A9A200DE86E9 /* LaunchScreen.storyboard in Resources */, + E95CB451205D77B200A7218E /* InfoPlist.strings in Resources */, E9EC341B200524CA00C0E546 /* Roboto_300_normal.ttf in Resources */, E9E7CDBC2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib in Resources */, E95F85C8200A9B070070534A /* ChatTableViewCell.xib in Resources */, @@ -810,16 +820,15 @@ E94E7B01205D3F090042B639 /* ChatListViewController.xib in Resources */, E9EC341E200524CA00C0E546 /* Roboto_500_normal.ttf in Resources */, E9EC3419200524CA00C0E546 /* Exo+2_500_normal.ttf in Resources */, - E9256F7E2039B29D00DE86E9 /* InfoPlist.strings in Resources */, E9256F6D20357B1700DE86E9 /* LoginHeader.xib in Resources */, E9EC3416200524CA00C0E546 /* Exo+2_300_normal.ttf in Resources */, E9EC341C200524CA00C0E546 /* Roboto_400_italic.ttf in Resources */, E94E7B0C205D5E4A0042B639 /* TransactionsViewController.xib in Resources */, - E9256F792039B29A00DE86E9 /* Localizable.strings in Resources */, - E93D7AC520530F76005D19DC /* Localizable.stringsdict in Resources */, E9EC3415200524CA00C0E546 /* Exo+2_100_normal.ttf in Resources */, E9EC341A200524CA00C0E546 /* Exo+2_700_normal.ttf in Resources */, E94E7B0A205D59F50042B639 /* AccountViewController.xib in Resources */, + E95CB456205D77B500A7218E /* Localizable.strings in Resources */, + E95CB45E205D7F9600A7218E /* Localizable.stringsdict in Resources */, E94E7B0E205D5EA80042B639 /* TransactionDetailsViewController.xib in Resources */, E9EC341D200524CA00C0E546 /* Roboto_400_normal.ttf in Resources */, E9A174B920587B84003667CD /* notification.mp3 in Resources */, @@ -1051,29 +1060,29 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - E9256F7B2039B29A00DE86E9 /* Localizable.strings */ = { + E95CB453205D77B200A7218E /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( - E9256F7A2039B29A00DE86E9 /* ru */, - E982A8D6205D2A610097FAE7 /* en */, + E95CB452205D77B200A7218E /* en */, + E95CB45A205D77DD00A7218E /* ru */, ); - name = Localizable.strings; + name = InfoPlist.strings; sourceTree = ""; }; - E9256F802039B29D00DE86E9 /* InfoPlist.strings */ = { + E95CB458205D77B500A7218E /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - E9256F7F2039B29D00DE86E9 /* ru */, - E982A8DC205D2AB40097FAE7 /* en */, + E95CB457205D77B500A7218E /* en */, + E95CB459205D77DC00A7218E /* ru */, ); - name = InfoPlist.strings; + name = Localizable.strings; sourceTree = ""; }; - E93D7AC720530F76005D19DC /* Localizable.stringsdict */ = { + E95CB460205D7F9600A7218E /* Localizable.stringsdict */ = { isa = PBXVariantGroup; children = ( - E93D7AC620530F76005D19DC /* ru */, - E982A8D7205D2A910097FAE7 /* en */, + E95CB45F205D7F9600A7218E /* en */, + E95CB461205D7FD000A7218E /* ru */, ); name = Localizable.stringsdict; sourceTree = ""; diff --git a/Adamant/AppDelegate.swift b/Adamant/AppDelegate.swift index 4b81807e0..581fca8e3 100644 --- a/Adamant/AppDelegate.swift +++ b/Adamant/AppDelegate.swift @@ -194,4 +194,6 @@ extension AppDelegate { return } } + + completionHandler(.noData) }} diff --git a/Adamant/Assets/en.lproj/InfoPlist.strings b/Adamant/Assets/en.lproj/InfoPlist.strings deleted file mode 100644 index 2cd714a50..000000000 --- a/Adamant/Assets/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,15 +0,0 @@ -/* (No Comment) */ -"CFBundleDisplayName" = "Адамант"; - -/* (No Comment) */ -"CFBundleName" = ""; - -/* (No Comment) */ -"NSCameraUsageDescription" = "Необходим доступ к Камере для чтения QR-кодов с адресами и паролями"; - -/* (No Comment) */ -"NSPhotoLibraryAddUsageDescription" = "Необходим доступ к Фотографиям для сохранения созданных QR-кодов"; - -/* (No Comment) */ -"NSPhotoLibraryUsageDescription" = "Необходим доступ к Фотографиям для сканирования QR-кодов с адресами и паролями со сделанных ранее фотографий"; - diff --git a/Adamant/Assets/en.lproj/Localizable.strings b/Adamant/Assets/en.lproj/Localizable.strings deleted file mode 100644 index cb7448de4..000000000 --- a/Adamant/Assets/en.lproj/Localizable.strings +++ /dev/null @@ -1,304 +0,0 @@ -/* New chat: Remote server returned an error. */ -"%@" = "%@"; - -/* Product name */ -"ADAMANT" = "АДАМАНТ"; - -/* Wallet page: Account section title. */ -"Account" = "Аккаунт"; - -/* ApiService: Account not found error, appending account info. */ -"Account not found: %@" = "Аккаунт не найден: %@"; - -/* Wallet page: Actions section title */ -"Actions" = "Действия"; - -/* Transfer: recipient address */ -"Address" = "Адрес"; - -/* New chat: Notify user that specified address (%@) not found */ -"Address %@ not found" = "Адрес %@ не найден"; - -/* Transfer: Address not found error */ -"Address not found" = "Такой адрес не найден"; - -/* Transaction details: amount row. - Transfer: amount of adamant to transfer. */ -"Amount" = "Количество"; - -/* Config: Application Info section */ -"Application info" = "Приложение"; - -/* Transfer: logged user balance. - Wallet page: Balance row title */ -"Balance" = "Баланс"; - -/* Transaction details: Block id row. */ -"Block" = "Блок"; - -/* Shared alert 'Cancel' button. Used anywhere */ -"Cancel" = "Отмена"; - -/* Transaction details: confirmations row. */ -"Confirmations" = "Подтверждений"; - -/* Shared alert notification: message about item copied to pasteboard. */ -"Copied to Pasteboard" = "Скопировано!"; - -/* Shared alert 'Copy' button. Used anywhere. Used for copy-paste info. */ -"Copy to Pasteboard" = "Копировать"; - -/* Transaction details: date row. */ -"Date" = "Дата"; - -/* Config: turn off 'Stay Logged In' confirmation */ -"Do not stay logged in" = "Выходить из системы при выходе из приложения"; - -/* Config: Authorization reason for turning biometry off */ -"Do not use biometry to log in" = "Отключить вход с биометрией"; - -/* Shared alert Done message. Used anywhere */ -"Done" = "Готово"; - -/* Wallet page: Inform user that sending tokens not allowed by Apple until the end of ICO */ -"Due to Apple restrictions, sending tokens is not allowed until the end of the ICO. For now, you can send tokens using WebApp at msg.adamant.im" = "Ввиду ограничений Apple, отправка токенов отключена до конца ICO. В данный момент вы можете отправлять токены с помощью WebApp по адресу msg.adamant.im"; - -/* Login: notify user that he is trying to login without a passphrase */ -"Enter a passphrase!" = "Введите пароль"; - -/* QRGenerator: user typed in wrong invalid */ -"Enter correct passphrase" = "Введите корректный пароль"; - -/* Pinpad: Ask user to create new pin */ -"Enter new pin" = "Введите новый пин"; - -/* Shared alert 'Error' title. Used anywhere */ -"Error" = "Ошибка"; - -/* Chat: input bar: Estimated fee */ -"~%@" = "~%@"; - -/* Transaction details: fee row. */ -"Fee" = "Комиссия"; - -/* Transaction details: sender row. */ -"From" = "Отправитель"; - -/* Transfer: Tokens transfered successfully message */ -"Funds sended!" = "Токены переведены!"; - -/* Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere. */ -"Generate QR Code" = "Создать QR-код"; - -/* Config: Generate QR with passphrase row */ -"Generate QR with passphrase" = "Создать QR-код с паролем"; - -/* Login: generate new passphrase button */ -"Generate new passphrase" = "Создать новый"; - -/* Wallet page: 'Transfer not allowed' alert 'go to WebApp button' */ -"Go to msg.adamant.im" = "Открыть msg.adamant.im"; - -/* Transaction details: Id row. */ -"Id" = "Номер"; - -/* Wallet page: 'Invest in ICO' button */ -"Invest in ICO" = "Инвестировать в ICO"; - -/* Login: notify user that we a logging in */ -"Logging in" = "Входим..."; - -/* Login: Login button - Login: login with existing passphrase section */ -"Login" = "Вход"; - -/* Login: Login into previous account with biometry or pincode */ -"Login into Adamant" = "Вход в Адамант"; - -/* Wallet page: 'Logout' button - Wallet page: Confirm logout alert: Logout (Ok) button */ -"Logout" = "Выход"; - -/* Wallet page: Confirm logout alert */ -"Logout from %@?" = "Выйти из %@?"; - -/* Transfer: maximum amount to transfer: available account money substracting transfer fee. */ -"Max to transfer" = "Доступно для перевода"; - -/* Chat: Notify user that message cannot be empty */ -"Message is empty" = "Сообщение пусто!"; - -/* Chat: Message is too long */ -"Message is too long" = "Сообщение слишком длинное"; - -/* Login: Create new account section */ -"New account" = "Новый аккаунт"; - -/* Chat: message input placeholder - Notifications: New message notification title */ -"New message" = "Новое сообщение"; - -/* Notifications: New transfer transaction title */ -"New transfer" = "Новый перевод"; - -/* ApiService: No connection message. Generally bad network. */ -"No connection" = "Нет соединения с интернетом"; - -/* Login: No network error. */ -"No connection with The Internet" = "Нет соединения с сетью"; - -/* Config: Show notifications */ -"Notifications" = "Уведомления"; - -/* Notifications: User has disabled notifications. Head him into settings */ -"Notifications disabled. You can reenable notifications in Settings" = "Уведомления отключены. Вы можете включить их в Настройках"; - -/* Shared alert 'Ok' button. Used anywhere */ -"Ok" = "Ок"; - -/* Transaction details: 'Open transaction in explorer' row. */ -"Open in Explorer" = "Открыть в Explorer"; - -/* Login: Passphrase placeholder - QRGenerator: Passphrase textview placeholder */ -"Passphrase" = "Пароль"; - -/* Login: Login with pincode button */ -"Login with Pincode" = "Войти с pin-кодом"; - -/* Transfer: Address validation error */ -"Please enter a valid recipient address" = "Введите корректный адрес получателя"; - -/* New chat: Notify user that he did enter invalid address */ -"Please specify valid recipient address" = "Неверный адрес"; - -/* Login: Login with QR button. */ -"Login with QR" = "Войти с QR-кодом"; - -/* New Chat: Notify user that scanned QR doesn't contains an address */ -"QR code does not contains a valid adamant address" = "QR код не содержит адреса"; - -/* Login: Notify user that scanned QR doesn't contains a passphrase. */ -"QR code does not contains a valid passphrase" = "QR код не содержит пароля"; - -/* Login: Notify user that device not supported by QR reader */ -"QR codes reading not supported by the current device" = "На этом устройстве не поддерживается чтение QR кодов"; - -/* Pinpad: Ask user to repeat new pin */ -"Re-enter new pin" = "Введите пин ещё раз"; - -/* Shared alert 'Save' button. Used anywhere */ -"Save" = "Сохранить"; - -/* Login: security alert, notify user that he must save his new passphrase */ -"Save the passphrase for new Wallet and Messenger account. There is no login to enter Wallet, only the passphrase needed. If lost, no way to recover it" = "Это пароль для нового Кошелька и Мессенджера. Сохраните его! Для входа в Кошелек не нужно логина, только этот пароль. Восстановление пароля невозможно."; - -/* New chat: Scan QR with address button */ -"Scan QR" = "Сканировать QR код"; - -/* Chat: Send message button - Transfer: Confirm transfer alert: Send tokens button */ -"Send" = "Отправить"; - -/* Transfer: Confirm transfer X tokens to Y message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'. */ -"Send %1$@ to %2$@?" = "Отправить %1$@ получателю %2$@?"; - -/* Transfer: Send button */ -"Send Funds" = "Отправить токены"; - -/* Wallet page: 'Send tokens' button */ -"Send Tokens" = "Отправить токены"; - -/* Transfer: Processing message */ -"Sending funds..." = "Отправляем токены..."; - -/* Config: Settings section - Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title. */ -"Settings" = "Настройки"; - -/* Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu. */ -"Share" = "Поделиться"; - -/* Wallet page: 'Transfer not allowed' alert title */ -"Sorry!" = "Ой!"; - -/* Config: Stay logged option */ -"Stay Logged in" = "Оставаться в сети"; - -/* Export transaction: 'Share transaction summary' button */ -"Summary" = "Сводка"; - -/* Login: a small hint for a user, that he can tap on passphrase to save it - QRGenerator: small 'Tap to save' tooltip under generated QR */ -"Tap to save" = "Нажмите для сохранения"; - -/* Transaction details: recipient row. */ -"To" = "Получатель"; - -/* Transfer: total amount of transaction: money to transfer adding fee */ -"Total" = "Итого"; - -/* Transfer: transfer fee */ -"Transaction fee" = "Комиссия"; - -/* Transfer: 'Transfer info' section */ -"Transfer Info" = "Перевод"; - -/* Export transaction: 'Share transaction URL' button */ -"URL" = "URL"; - -/* Unknown internal error */ -"Unknown error" = "Неизвестная ошибка"; - -/* Config: Authorization reason for turning biometry on */ -"Use biometry to log in" = "Использовать биометрию для входа в систему"; - -/* ApiService: User not logged error - Login: user not logged error */ -"User not logged" = "Не выполнен вход"; - -/* Config: Utilities section */ -"Utilities" = "Утилиты"; - -/* Config: Version row */ -"Version" = "Версия"; - -/* Wallet page: Wallet section title */ -"Wallet" = "Кошелёк"; - -/* Known contacts: Adamant welcome message */ -"Welcome to ADAMANT, the most secure and anonymous messenger. You are credited with bounty tokens, which you can use to get acquainted with the messenger.\nRemember, your security and anonymity is up to you also. Do not follow links you receive, otherwise your IP can be compromised. Do not trust browser extensions. Better to share your ADM address personally, but not using other messengers. Keep your secret passphrase secure. Set a password on your device or logout before leaving.\nLearn more about security and anonymity at https://adamant.im/staysecured/.\n\nDo not reply to this message, it is a system account." = "Добро пожаловать в самый анонимный и безопасный мессенджер АДАМАНТ. Вам начислены приветственные токены, которые вы можете использовать для ознакомления с мессенджером.\nПомните, что безопасность и анонимность зависит и от вас самих. Не переходите по ссылкам, которые вы получаете в чатах, иначе ваш IP-адрес может быть определен. Не доверяйте расширениям браузера. Лучше всего передавать ваш ADM-адрес собеседникам лично, а не через другие мессенджеры. Храните вашу секретную фразу (пароль) от аккаунта в тайне. Установите на ваше устройство пароль или закрываете вкладку браузера после завершения диалогов.\nБолее полную информацию о безопасности и анонимности читайте на странице https://adamant.im/ru-staysecured/\n\nНе отвечайте на это сообщение, этот адрес служебный."; - -/* Login: user typed in wrong passphrase */ -"Wrong passphrase!" = "Неправильный пароль"; - -/* Chat: Notify user that he doesn't have money to pay a message fee */ -"You don't have enough money to send a message" = "Недостаточно токенов для отправки сообщения"; - -/* Transfer: Amount is hiegher that user's total money notification */ -"You don't have that much money" = "У вас нет столько токенов"; - -/* New chat: Notify user that he can't start chat with himself */ -"You don't need an encrypted anonymous chat to talk to yourself" = "Вам не нужен анонимный чат, чтобы говорить с самим собой"; - -/* Known contacts: Adamant pre ICO message */ -"You have a possibility to invest in ADAMANT, the most secure and anonymous messenger. Now is a Pre-ICO stage — the most profitable for investors. Learn more on Adamant.im website or in the Whitepaper. To participate just reply to this message and we will assist. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "Сегодня последний день, когда мы принимаем инвестиции по минимальной цене 0.001 ETH за токен ADM до начала публичного сейла ICO — 30.01. Это самые выгодные условия для инвесторов. Минимальная инвестиция — эквивалент 2 ETH (на этапе публичного сейла ограничений по минимальной сумме нет, но цена токена начинается с 0.002 ETH). Подробная информация о проекте АДАМАНТ на сайте Adamant.im и в Белой книге. Для участия достаточно ответить на это сообщение, и мы вам поможем."; - -/* Known contacts: Adamant ICO message */ -"You have a possibility to invest in ICO of ADAMANT, the most secure and anonymous messenger. Earlier you participate, better offer you will get. Learn more on Adamant.im website or in the Whitepaper. To invest, go to Wallet→Invest in the ICO, or follow a website page Adamant.im/ico/. If you still have any questions, you can ask them by replying to this message. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "У вас есть возможность инвестировать в ICO самого защищенного мессенджера АДАМАНТ. Более раннее участие — более выгодные условия. Подробная информация об условиях на сайте Adamant.im и в Белой книге проекта. Если вы уже ознакомились с нашим сайтом и Белой книгой, но у вас остались вопросы, вы можете задать их, ответив на это сообщение. Мы стараемся реагировать быстро, но иногда возможны задержки до нескольких часов.\nВажно! Пожалуйста, убедитесь, что вы сохранили пароль к этому аккаунту — выйдите из аккаунта и войдите в него снова. Лучше всего иметь запись пароля и на бумаге. Однако помните, только вы несете ответственность за сохранность вашего пароля. Его невозможно восстановить. А если он попадет в другие руки, ваши деньги будут украдены. Отнеситесь к этому вопросу так серьезно, как если бы цена токенов на вашем кошельке когда-то станет равна миллиарду долларов.\nЧтобы инвестировать, перейдите в этом месседжере на вкладку Кошелек и нажмите кнопку Инвестировать в ICO, или откройте в браузере веб-страницу Adamant.im/ico/. В форме для инвестирования укажите ваш адрес АДАМАНТа — на него будут перечислены токены ADM. При переходе из мессенджера он будет вставлен автоматически, в другом случае вернитесь в мессенджер и кликните на блок Ваш адрес, он будет скопирован в буфер обмена. Укажите криптовалюту, в которой вы хотите инвестировать, и какую сумму. Вы увидите сколько ADM-токенов вы получите, с учетом скидки за объем: 20–30 ETH: +20%, 30–50 ETH: +30%, 50–90 ETH: +40%, 90+ ETH: +50%. Нажмите кнопку Купить токены АДАМАНТ. Вы получите уникальный адрес, на который необходимо выполнить перевод. Как только на него поступит ожидаемая сумма и транзакция будет подтверждена, вы получите токены ADM. Транзакцию можно выполнить с любого кошелька, включая биржи. Необязятельно переводить точную сумму с учетом комиссии, платеж все равно будет засчитан. Остались вопросы? Спрашивайте.\nПосле того, как вы инвестируете и получите токены ADM, мы рекомендуем вам хранить их в кошельке как можно дольше. Ежемесячно все нераспроданные на ICO токены будут распределяться по кошелькам пользователей, увеличивая балансы на 5%. Подробную информацию можно получить на сайте Adamant.im и в Белой книге Проекта."; - -/* Login: Notify user, that he disabled camera in settings, and need to authorize application. */ -"You need to authorize Adamant to use device's Camera" = "Для чтения QR кодов необходимо разрешить доступ к камере"; - -/* Transfer: Amount is zero, or even negative notification */ -"You should send more money" = "Нужно отправить больше токенов"; - -/* Transfer: 'Your wallet' section */ -"Your wallet" = "Ваш кошелёк"; - -/* Transfer: recipient address placeholder */ -"of the recipient" = "получателя"; - -/* Transfer: transfer amount placeholder */ -"to send" = "для перевода"; - diff --git a/Adamant/Assets/l18n/en.lproj/InfoPlist.strings b/Adamant/Assets/l18n/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..721f889b9 --- /dev/null +++ b/Adamant/Assets/l18n/en.lproj/InfoPlist.strings @@ -0,0 +1,15 @@ +/* (No Comment) */ +"CFBundleDisplayName" = "Adamant"; + +/* (No Comment) */ +"CFBundleName" = "Adamant"; + +/* (No Comment) */ +"NSCameraUsageDescription" = "The camera needed to scan QR codes for addresses and passphrases"; + +/* (No Comment) */ +"NSPhotoLibraryAddUsageDescription" = "Saving generated QR codes with passphrases and addresses"; + +/* (No Comment) */ +"NSPhotoLibraryUsageDescription" = "Reading QR codes with passphrases and addresses"; + diff --git a/Adamant/Assets/l18n/en.lproj/Localizable.strings b/Adamant/Assets/l18n/en.lproj/Localizable.strings new file mode 100644 index 000000000..38bfb3f46 --- /dev/null +++ b/Adamant/Assets/l18n/en.lproj/Localizable.strings @@ -0,0 +1,377 @@ +/* Product name */ +"ADAMANT" = "ADAMANT"; + +/* ApiService: Bad internal application error, report a bug. Using %@ as error description */ +"AccountServiceError.Internal errorFormat" = "Internal error: %@"; + +/* Login: user typed in invalid passphrase */ +"AccountServiceError.InvalidPassphrase" = "Wrong passphrase"; + +/* Login: user not logged error */ +"AccountServiceError.UserNotLogged" = "User not logged"; + +/* Login: user typed in wrong passphrase */ +"AccountServiceError.WrongPassphrase" = "Wrong passphrase: %@"; + +/* Account tab: Confirm logout alert: Logout (Ok) button */ +"AccountTab.ConfirmLogout.Logout" = "Logout"; + +/* Account tab: Confirm logout alert */ +"AccountTab.ConfirmLogout.MessageFormat" = "Logout from %@?"; + +/* Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO */ +"AccountTab.TransferBlocked.Message" = "Due to Apple restrictions, sending tokens is not allowed until the end of the ICO. For now, you can send tokens using WebApp at msg.adamant.im"; + +/* Account tab: Balance row title */ +"AccountTab.Row.Balance" = "Balance"; + +/* Account tab: 'Invest in ICO' button */ +"AccountTab.Row.JoinIco" = "Join the ICO"; + +/* Account tab: 'Logout' button */ +"AccountTab.Row.Logout" = "Logout"; + +/* Account tab: 'Send tokens' button */ +"AccountTab.Row.SendTokens" = "Send Tokens"; + +/* Account tab: Account section title. */ +"AccountTab.Section.Account" = "Account"; + +/* Account tab: Actions section title */ +"AccountTab.Section.Actions" = "Actions"; + +/* Account tab: Wallet section title */ +"AccountTab.Section.Wallet" = "Wallet"; + +/* Account tab: 'Transfer not allowed' alert 'go to WebApp button' */ +"AccountTab.TransferBlocked.GoToPWA" = "msg.adamant.im"; + +/* Account tab: 'Transfer not allowed' alert title */ +"AccountTab.TransferBlocked.Title" = "Sorry!"; + +/* Account page: scene title */ +"AccountTab.Title" = "Account"; + +/* ApiService: Account not found error. Using %@ for address. */ +"ApiService.Error.AccountNotFoundFormat" = "Account not found: %@"; + +/* ApiService: Bad internal application error, report a bug. Using %@ for error description */ +"ApiService.Error.InternalErrorFormat" = "Internal error: %@"; + +/* ApiService: No connection message. Generally bad network. */ +"ApiService.Error.NoConnection" = "No connection to the Internet"; + +/* ApiService: Remote server returned an error. Using %@ for error description */ +"ApiService.Error.RemoteServerErrorFormat" = "Remote server error: %@"; + +/* ApiService: User not logged error */ +"ApiService.Error.UserNotLogged" = "User not logged"; + +/* Serious internal error: Failed to build endpoint url */ +"ApiService.InternalError.EndpointBuildFailed" = "Endpoint build failed. Report a bug"; + +/* Serious internal error: Failed to sign transaction */ +"ApiService.InternalError.FailedTransactionSigning" = "Transaction failed"; + +/* Serious internal error: Error parsing response */ +"ApiService.InternalError.ParsingFailed" = "Parsing failed. Report a bug"; + +/* Unknown internal error */ +"ApiService.InternalError.UnknownError" = "Unknown error. Report a bug"; + +/* ChatList: scene title */ +"ChatListPage.Title" = "Chats"; + +/* Chat: Notify user about bad internal error. Usually this should be reported as a bug. Using %@ for error description */ +"ChatScene.Error.InternalErrorFormat" = "Internal error: %@. Report a bug"; + +/* Chat: Notify user that message cannot be empty */ +"ChatScene.Error.MessageIsEmpty" = "Message is empty!"; + +/* Chat: Message is too long */ +"ChatScene.Error.MessageTooLong" = "Message is too long"; + +/* Chat: Notify user that he doesn't have money to pay a message fee */ +"ChatScene.Error.NotEnoughMoney" = "You don't have enought money to send a message"; + +/* Chat: Notify user about server error. Using %@ for error description */ +"ChatScene.Error.RemoteServerErrorFormat" = "Remote error: %@. Report a bug"; + +/* Chat: message input placeholder */ +"ChatScene.NewMessage.Placeholder" = "New message"; + +/* Chat: Send message button */ +"ChatScene.Send" = "Send"; + +/* Known contacts: Adamant ICO message */ +"Chats.IcoMessage" = "ou have a possibility to invest in ICO of ADAMANT, the most secure and anonymous messenger. Earlier you participate, better offer you will get. Learn more on Adamant.im website or in the Whitepaper. To invest, go to Wallet→Invest in the ICO, or follow a website page Adamant.im/ico/. If you still have any questions, you can ask them by replying to this message. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper."; + +/* Known contacts: Adamant pre ICO message */ +"Chats.PreIcoMessage" = "You have a possibility to invest in ADAMANT, the most secure and anonymous messenger. Now is a Pre-ICO stage — the most profitable for investors. Learn more on Adamant.im website or in the Whitepaper. To participate just reply to this message and we will assist. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper."; + +/* Known contacts: Adamant welcome message */ +"Chats.WelcomeMessage" = "Welcome to ADAMANT, the most secure and anonymous messenger. You are credited with bounty tokens, which you can use to get acquainted with the messenger.\\nRemember, your security and anonymity is up to you also. Do not follow links you receive, otherwise your IP can be compromised. Do not trust browser extensions. Better to share your ADM address personally, but not using other messengers. Keep your secret passphrase secure. Set a password on your device or logout before leaving.\\nLearn more about security and anonymity at https://adamant.im/staysecured/.\\n\\nDo not reply to this message, it is a system account."; + +/* Login: Notify user, that he disabled camera in settings, and need to authorize application. */ +"LoginScene.Error.AuthorizeCamera" = "You need to authorize Adamant to use device's Camera"; + +/* Login: No network error. */ +"LoginScene.Error.NoInternet" = "No connection to the Internet"; + +/* Login: notify user that he is trying to login without a passphrase */ +"LoginScene.Error.NoPassphrase" = "Enter a passphrase"; + +/* Login: Notify user that device not supported by QR reader */ +"LoginScene.Error.QrNotSupported" = "QR code reading not supported by the device"; + +/* Login: Notify user that scanned QR doesn't contains a passphrase. */ +"LoginScene.Error.WrongQr" = "QR code does not contains a valid passphrase"; + +/* Login: notify user that we are trying to log in */ +"LoginScene.LoggingInProgress" = "Logging in..."; + +/* Login: Login into previous account with biometry or pincode */ +"LoginScene.LoginIntoAdamant" = "Login into Adamant"; + +/* Login: generate new passphrase button */ +"LoginScene.Row.Generate" = "Generate new passphrase"; + +/* Login: Login button */ +"LoginScene.Row.Login" = "Login"; + +/* Login: Passphrase placeholder */ +"LoginScene.Row.Passphrase.Placeholder" = "Passphrase"; + +/* Login: Login with pincode button */ +"LoginScene.Row.Pincode" = "Login with PIN-code"; + +/* Login: Login with QR button. */ +"LoginScene.Row.Qr" = "Login with QR-code"; + +/* Login: security alert, notify user that he must save his new passphrase */ +"LoginScene.Row.SavePassphraseAlert" = "Save the passphrase for new Wallet and Messenger account. There is no login to enter Wallet, only the passphrase needed. If lost, no way to recover it."; + +/* Login: a small hint for a user, that he can tap on passphrase to save it */ +"LoginScene.Row.TapToSave" = "Tap to save"; + +/* Login: login with existing passphrase section */ +"LoginScene.Section.Login" = "Login"; + +/* Login: Create new account section */ +"LoginScene.Section.NewAccount" = "New account"; + +/* New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank. */ +"NewChatScene.Address.Placeholder" = ""; + +/* New chat: Notify user that specified address (%@) not found. Using %@ for address */ +"NewChatScene.Error.AddressNotFoundFormat" = "Address not found: %@"; + +/* New chat: Notify user that he did enter invalid address */ +"NewChatScene.Error.InvalidAddress" = "Enter a valid address"; + +/* New chat: Notify user that he can't start chat with himself */ +"NewChatScene.Error.OwnAddress" = "You don't need an encrypted anonymous chat to talk to yourself"; + +/* New chat: Remote server returned an error. Using %@ for error description */ +"NewChatScene.Error.RemoteServerFormat" = "Remote server error: %@. Report a bug"; + +/* New Chat: Notify user that scanned QR doesn't contains an address */ +"NewChatScene.Error.WrongQr" = "QR code does not contains a valid address"; + +/* New chat: Scan QR with address button */ +"NewChatScene.ScanQr" = "Scan QR-code"; + +/* New chat: scene title */ +"NewChatScene.Title" = "New Chat"; + +/* Notifications: New message notification title */ +"NotificationsService.NewMessage.Title" = "New Message"; + +/* Notifications: New transfer transaction title */ +"NotificationsService.NewTransfer.Title" = "New Transfer"; + +/* Notifications: User has disabled notifications. Head him into settings */ +"NotificationsService.NotificationsDisabled" = "Notifications disabled. You can enable notifications in Settings"; + +/* Pinpad: Ask user to create new pin */ +"Pinpad.EnterNewPin" = "Enter new pin-code"; + +/* Pinpad: Ask user to repeat new pin */ +"Pinpad.ReenterPin" = "Re-enter your pin-code"; + +/* QRGenerator: user typed in wrong invalid */ +"QrGeneratorScene.Error.InvalidPassphrase" = "Enter a valid passphrase"; + +/* QRGenerator: Bad Internal generator error message format. Using %@ for error description */ +"QrGeneratorScene.Error.InternalErrorFormat" = "Internal error: %@. Report a bug"; + +/* QRGenerator: Passphrase textview placeholder */ +"QrGeneratorScene.Passphrase.Placeholder" = "Passphrase"; + +/* QRGenerator: small 'Tap to save' tooltip under generated QR */ +"QrGeneratorScene.TapToSave" = "Tap to save"; + +/* QRGenerator: scene title */ +"QrGeneratorScene.Title" = "QR Generator"; + +/* Config: turn off 'Stay Logged In' confirmation */ +"SettingsPage.DoNotStayLoggedIn" = "Do not stay logged in"; + +/* Config: Authorization reason for turning biometry off */ +"SettingsPage.DoNotUseBiometry" = "Do not use biometry to log in"; + +/* Config: Generate QR with passphrase row */ +"SettingsPage.Row.GenerateQr" = "Generate QR with passphrase"; + +/* Config: Show notifications */ +"SettingsPage.Row.Notifications" = "Notifications"; + +/* Config: Stay logged option */ +"SettingsPage.Row.StayLoggedIn" = "Stay logged in"; + +/* Config: Version row */ +"SettingsPage.Row.Version" = "Version"; + +/* Config: Application Info section */ +"SettingsPage.Section.ApplicationInfo" = "Application"; + +/* Config: Settings section */ +"SettingsPage.Section.Settings" = "Settings"; + +/* Config: Utilities section */ +"SettingsPage.Section.Utilities" = "Utilities"; + +/* Config: scene title */ +"SettingsPage.Title" = "Settings"; + +/* Config: Authorization reason for turning biometry on */ +"SettingsPage.UseBiometry" = "Use biometry"; + +/* Shared alert 'Cancel' button. Used anywhere */ +"Shared.Cancel" = "Cancel"; + +/* Shared alert notification: message about item copied to pasteboard. */ +"Shared.CopiedToPasteboard" = "Copied to Pasteboard!"; + +/* Shared alert 'Copy' button. Used anywhere. Used for copy-paste info. */ +"Shared.CopyToPasteboard" = "Copy to Pasteboard"; + +/* Shared alert Done message. Used anywhere */ +"Shared.Done" = "Done"; + +/* Shared alert 'Error' title. Used anywhere */ +"Shared.Error" = "Error"; + +/* Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere. */ +"Shared.GenerateQRCode" = "Generate QR code"; + +/* Shared alert 'Ok' button. Used anywhere */ +"Shared.Ok" = "Ok"; + +/* Shared alert 'Save' button. Used anywhere */ +"Shared.Save" = "Save"; + +/* Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title. */ +"Shared.Settings" = "Settings"; + +/* Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu. */ +"Shared.Share" = "Share"; + +/* Main tab bar: Account page */ +"Tabs.Account" = "Account"; + +/* Main tab bar: Chats page */ +"Tabs.Chats" = "Chats"; + +/* Main tab bar: Settings page */ +"Tabs.Settings" = "Settings"; + +/* Transaction details: amount row. */ +"TransactionDetailsScene.Row.Amount" = "Amount"; + +/* Transaction details: Block id row. */ +"TransactionDetailsScene.Row.Block" = "Block"; + +/* Transaction details: confirmations row. */ +"TransactionDetailsScene.Row.Confirmations" = "Confirmations"; + +/* Transaction details: date row. */ +"TransactionDetailsScene.Row.Date" = "Date"; + +/* Transaction details: 'Open transaction in explorer' row. */ +"TransactionDetailsScene.Row.Explorer" = "Open in Explorer"; + +/* Transaction details: fee row. */ +"TransactionDetailsScene.Row.Fee" = "Fee"; + +/* Transaction details: sender row. */ +"TransactionDetailsScene.Row.From" = "From"; + +/* Transaction details: Id row. */ +"TransactionDetailsScene.Row.Id" = "Id"; + +/* Transaction details: recipient row. */ +"TransactionDetailsScene.Row.To" = "To"; + +/* Export transaction: 'Share transaction summary' button */ +"TransactionDetailsScene.Share.Summary" = "Summary"; + +/* Export transaction: 'Share transaction URL' button */ +"TransactionDetailsScene.Share.URL" = "URL"; + +/* Transfer: transfer amount placeholder */ +"TransferScene.Amount.Placeholder" = "to send"; + +/* Transfer: Address not found error */ +"TransferScene.Error.AddressNotFound" = "Address not found"; + +/* Transfer: Address validation error */ +"TransferScene.Error.InvalidAddress" = "Enter a valid address"; + +/* Transfer: Amount is hiegher that user's total money notification */ +"TransferScene.Error.NotEnoughtMoney" = "You don't have that money"; + +/* Transfer: Amount is zero, or even negative notification */ +"TransferScene.Error.TooLittleMoney" = "You should send more money"; + +/* Transfer: recipient address placeholder */ +"TransferScene.Recipient.Placeholder" = "of the recipient"; + +/* Transfer: amount of adamant to transfer. */ +"TransferScene.Row.Amount" = "Amount"; + +/* Transfer: logged user balance. */ +"TransferScene.Row.Balance" = "Balance"; + +/* Transfer: maximum amount to transfer: available account money substracting transfer fee. */ +"TransferScene.Row.MaxToTransfer" = "Max to transfer"; + +/* Transfer: recipient address */ +"TransferScene.Row.Recipient" = "Address"; + +/* Transfer: Send button */ +"TransferScene.Row.Send" = "Send"; + +/* Transfer: total amount of transaction: money to transfer adding fee */ +"TransferScene.Row.Total" = "Total"; + +/* Transfer: transfer fee */ +"TransferScene.Row.TransactionFee" = "Fee"; + +/* Transfer: 'Transfer info' section */ +"TransferScene.Section.TransferInfo" = "Transfer Info"; + +/* Transfer: 'Your wallet' section */ +"TransferScene.Section.YourWallet" = "Your Wallet"; + +/* Transfer: Confirm transfer alert: Send tokens button */ +"TransferScene.Send" = "Send"; + +/* Transfer: Confirm transfer %1$@ tokens to %2$@ message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'. */ +"TransferScene.SendConfirmFormat" = "Send %1$@ to %2$@?"; + +/* Transfer: Processing message */ +"TransferScene.SendingFundsProgress" = "Sending funds..."; + +/* Transfer: Tokens transfered successfully message */ +"TransferScene.TransferSuccessMessage" = "Done!"; diff --git a/Adamant/Assets/en.lproj/Localizable.stringsdict b/Adamant/Assets/l18n/en.lproj/Localizable.stringsdict similarity index 89% rename from Adamant/Assets/en.lproj/Localizable.stringsdict rename to Adamant/Assets/l18n/en.lproj/Localizable.stringsdict index 7c8e3072f..df7859949 100644 --- a/Adamant/Assets/en.lproj/Localizable.stringsdict +++ b/Adamant/Assets/l18n/en.lproj/Localizable.stringsdict @@ -2,7 +2,7 @@ - You have %d new message(s) + NotificationsService.NewMessage.BodyFormat NSStringLocalizedFormatKey You have %#@messages@ @@ -18,7 +18,7 @@ %d new messages - You have %d new transfer(s) + NotificationsService.NewTransfer.BodyFormat NSStringLocalizedFormatKey You have %#@transfers@ diff --git a/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings new file mode 100644 index 000000000..6d1e286a6 --- /dev/null +++ b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings @@ -0,0 +1,15 @@ +/* (No Comment) */ +"CFBundleDisplayName" = "Адамант"; + +/* (No Comment) */ +"CFBundleName" = "Адамант"; + +/* (No Comment) */ +"NSCameraUsageDescription" = "Чтения QR-кодов с адресами и паролями"; + +/* (No Comment) */ +"NSPhotoLibraryAddUsageDescription" = "Сохранение созданных QR-кодов"; + +/* (No Comment) */ +"NSPhotoLibraryUsageDescription" = "Сканирование QR-кодов с адресами и паролями со сделанных ранее фотографий"; + diff --git a/Adamant/Assets/l18n/ru.lproj/Localizable.strings b/Adamant/Assets/l18n/ru.lproj/Localizable.strings new file mode 100644 index 000000000..1f85acb36 --- /dev/null +++ b/Adamant/Assets/l18n/ru.lproj/Localizable.strings @@ -0,0 +1,377 @@ +/* Product name */ +"ADAMANT" = "АДАМАНТ"; + +/* ApiService: Bad internal application error, report a bug. Using %@ as error description */ +"AccountServiceError.Internal errorFormat" = "Внутренняя ошибка: %@"; + +/* Login: user typed in invalid passphrase */ +"AccountServiceError.InvalidPassphrase" = "Неправильный пароль"; + +/* Login: user not logged error */ +"AccountServiceError.UserNotLogged" = "Не выполнен вход"; + +/* Login: user typed in wrong passphrase */ +"AccountServiceError.WrongPassphrase" = "Неправильный пароль: %@"; + +/* Account tab: Confirm logout alert: Logout (Ok) button */ +"AccountTab.ConfirmLogout.Logout" = "Выход"; + +/* Account tab: Confirm logout alert */ +"AccountTab.ConfirmLogout.MessageFormat" = "Выйти из %@?"; + +/* Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO */ +"AccountTab.TransferBlocked.Message" = "Ввиду ограничений Apple, отправка токенов отключена до конца ICO. В данный момент вы можете отправлять токены с помощью WebApp по адресу msg.adamant.im"; + +/* Account tab: Balance row title */ +"AccountTab.Row.Balance" = "Баланс"; + +/* Account tab: 'Invest in ICO' button */ +"AccountTab.Row.JoinIco" = "Учавствовать в ICO"; + +/* Account tab: 'Logout' button */ +"AccountTab.Row.Logout" = "Выход"; + +/* Account tab: 'Send tokens' button */ +"AccountTab.Row.SendTokens" = "Отправить токены"; + +/* Account tab: Account section title. */ +"AccountTab.Section.Account" = "Аккаунт"; + +/* Account tab: Actions section title */ +"AccountTab.Section.Actions" = "Действия"; + +/* Account tab: Wallet section title */ +"AccountTab.Section.Wallet" = "Кошелёк"; + +/* Account tab: 'Transfer not allowed' alert 'go to WebApp button' */ +"AccountTab.TransferBlocked.GoToPWA" = "msg.adamant.im"; + +/* Account tab: 'Transfer not allowed' alert title */ +"AccountTab.TransferBlocked.Title" = "Ой!"; + +/* Account page: scene title */ +"AccountTab.Title" = "Аккаунт"; + +/* ApiService: Account not found error. Using %@ for address. */ +"ApiService.Error.AccountNotFoundFormat" = "Аккаун не найден: %@"; + +/* ApiService: Bad internal application error, report a bug. Using %@ for error description */ +"ApiService.Error.InternalErrorFormat" = "Внутренняя ошибка: %@"; + +/* ApiService: No connection message. Generally bad network. */ +"ApiService.Error.NoConnection" = "Нет соединения с сетью"; + +/* ApiService: Remote server returned an error. Using %@ for error description */ +"ApiService.Error.RemoteServerErrorFormat" = "Ошибка на сервере: %@"; + +/* ApiService: User not logged error */ +"ApiService.Error.UserNotLogged" = "Не выполнен вход"; + +/* Serious internal error: Failed to build endpoint url */ +"ApiService.InternalError.EndpointBuildFailed" = "Endpoint build failed. Report a bug"; + +/* Serious internal error: Failed to sign transaction */ +"ApiService.InternalError.FailedTransactionSigning" = "Transaction failed"; + +/* Serious internal error: Error parsing response */ +"ApiService.InternalError.ParsingFailed" = "Parsing failed. Report a bug"; + +/* Unknown internal error */ +"ApiService.InternalError.UnknownError" = "Неизвестная ошибка"; + +/* ChatList: scene title */ +"ChatListPage.Title" = "Чаты"; + +/* Chat: Notify user about bad internal error. Usually this should be reported as a bug. Using %@ for error description */ +"ChatScene.Error.InternalErrorFormat" = "Internal error: %@. Report a bug"; + +/* Chat: Notify user that message cannot be empty */ +"ChatScene.Error.MessageIsEmpty" = "Сообщение пустое!"; + +/* Chat: Message is too long */ +"ChatScene.Error.MessageTooLong" = "Сообщение слишком длинное"; + +/* Chat: Notify user that he doesn't have money to pay a message fee */ +"ChatScene.Error.NotEnoughMoney" = "Недостаточно токенов для отправки сообщения"; + +/* Chat: Notify user about server error. Using %@ for error description */ +"ChatScene.Error.RemoteServerErrorFormat" = "Remote error: %@. Report a bug"; + +/* Chat: message input placeholder */ +"ChatScene.NewMessage.Placeholder" = "Сообщение"; + +/* Chat: Send message button */ +"ChatScene.Send" = "Отправить"; + +/* Known contacts: Adamant ICO message */ +"Chats.IcoMessage" = "У вас есть возможность инвестировать в ICO самого защищенного мессенджера АДАМАНТ. Более раннее участие — более выгодные условия. Подробная информация об условиях на сайте Adamant.im и в Белой книге проекта. Если вы уже ознакомились с нашим сайтом и Белой книгой, но у вас остались вопросы, вы можете задать их, ответив на это сообщение. Мы стараемся реагировать быстро, но иногда возможны задержки до нескольких часов.\\nВажно! Пожалуйста, убедитесь, что вы сохранили пароль к этому аккаунту — выйдите из аккаунта и войдите в него снова. Лучше всего иметь запись пароля и на бумаге. Однако помните, только вы несете ответственность за сохранность вашего пароля. Его невозможно восстановить. А если он попадет в другие руки, ваши деньги будут украдены. Отнеситесь к этому вопросу так серьезно, как если бы цена токенов на вашем кошельке когда-то станет равна миллиарду долларов.\\nЧтобы инвестировать, перейдите в этом месседжере на вкладку Кошелек и нажмите кнопку Инвестировать в ICO, или откройте в браузере веб-страницу Adamant.im/ico/. В форме для инвестирования укажите ваш адрес АДАМАНТа — на него будут перечислены токены ADM. При переходе из мессенджера он будет вставлен автоматически, в другом случае вернитесь в мессенджер и кликните на блок Ваш адрес, он будет скопирован в буфер обмена. Укажите криптовалюту, в которой вы хотите инвестировать, и какую сумму. Вы увидите сколько ADM-токенов вы получите, с учетом скидки за объем: 20–30 ETH: +20%, 30–50 ETH: +30%, 50–90 ETH: +40%, 90+ ETH: +50%. Нажмите кнопку Купить токены АДАМАНТ. Вы получите уникальный адрес, на который необходимо выполнить перевод. Как только на него поступит ожидаемая сумма и транзакция будет подтверждена, вы получите токены ADM. Транзакцию можно выполнить с любого кошелька, включая биржи. Необязятельно переводить точную сумму с учетом комиссии, платеж все равно будет засчитан. Остались вопросы? Спрашивайте.\\nПосле того, как вы инвестируете и получите токены ADM, мы рекомендуем вам хранить их в кошельке как можно дольше. Ежемесячно все нераспроданные на ICO токены будут распределяться по кошелькам пользователей, увеличивая балансы на 5%. Подробную информацию можно получить на сайте Adamant.im и в Белой книге Проекта."; + +/* Known contacts: Adamant pre ICO message */ +"Chats.PreIcoMessage" = "Сегодня последний день, когда мы принимаем инвестиции по минимальной цене 0.001 ETH за токен ADM до начала публичного сейла ICO — 30.01. Это самые выгодные условия для инвесторов. Минимальная инвестиция — эквивалент 2 ETH (на этапе публичного сейла ограничений по минимальной сумме нет, но цена токена начинается с 0.002 ETH). Подробная информация о проекте АДАМАНТ на сайте Adamant.im и в Белой книге. Для участия достаточно ответить на это сообщение, и мы вам поможем."; + +/* Known contacts: Adamant welcome message */ +"Chats.WelcomeMessage" = "Добро пожаловать в самый анонимный и безопасный мессенджер АДАМАНТ. Вам начислены приветственные токены, которые вы можете использовать для ознакомления с мессенджером.\\nПомните, что безопасность и анонимность зависит и от вас самих. Не переходите по ссылкам, которые вы получаете в чатах, иначе ваш IP-адрес может быть определен. Не доверяйте расширениям браузера. Лучше всего передавать ваш ADM-адрес собеседникам лично, а не через другие мессенджеры. Храните вашу секретную фразу (пароль) от аккаунта в тайне. Установите на ваше устройство пароль или закрываете вкладку браузера после завершения диалогов.\\nБолее полную информацию о безопасности и анонимности читайте на странице https://adamant.im/ru-staysecured/\\n\\nНе отвечайте на это сообщение, этот адрес служебный."; + +/* Login: Notify user, that he disabled camera in settings, and need to authorize application. */ +"LoginScene.Error.AuthorizeCamera" = "Для чтения QR кодов необходимо разрешить доступ к камере"; + +/* Login: No network error. */ +"LoginScene.Error.NoInternet" = "Нет соединения с сетью"; + +/* Login: notify user that he is trying to login without a passphrase */ +"LoginScene.Error.NoPassphrase" = "Введите пароль"; + +/* Login: Notify user that device not supported by QR reader */ +"LoginScene.Error.QrNotSupported" = "На этом устройстве не поддерживается чтение QR кодов"; + +/* Login: Notify user that scanned QR doesn't contains a passphrase. */ +"LoginScene.Error.WrongQr" = "QR код не содержит пароля"; + +/* Login: notify user that we are trying to log in */ +"LoginScene.LoggingInProgress" = "Входим…"; + +/* Login: Login into previous account with biometry or pincode */ +"LoginScene.LoginIntoAdamant" = "Вход в Адамант"; + +/* Login: generate new passphrase button */ +"LoginScene.Row.Generate" = "Создать новый пароль"; + +/* Login: Login button */ +"LoginScene.Row.Login" = "Вход"; + +/* Login: Passphrase placeholder */ +"LoginScene.Row.Passphrase.Placeholder" = "Пароль"; + +/* Login: Login with pincode button */ +"LoginScene.Row.Pincode" = "Войти с PIN-кодом"; + +/* Login: Login with QR button. */ +"LoginScene.Row.Qr" = "Войти с QR-кодом"; + +/* Login: security alert, notify user that he must save his new passphrase */ +"LoginScene.Row.SavePassphraseAlert" = "Это пароль для нового Кошелька и Мессенджера. Сохраните его! Для входа в Кошелек не нужно логина, только этот пароль. Восстановление пароля невозможно."; + +/* Login: a small hint for a user, that he can tap on passphrase to save it */ +"LoginScene.Row.TapToSave" = "Нажмите чтобы сохранить"; + +/* Login: login with existing passphrase section */ +"LoginScene.Section.Login" = "Вход"; + +/* Login: Create new account section */ +"LoginScene.Section.NewAccount" = "Новый аккаунт"; + +/* New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank. */ +"NewChatScene.Address.Placeholder" = ""; + +/* New chat: Notify user that specified address (%@) not found. Using %@ for address */ +"NewChatScene.Error.AddressNotFoundFormat" = "Адрес не найден: %@"; + +/* New chat: Notify user that he did enter invalid address */ +"NewChatScene.Error.InvalidAddress" = "Неверный адрес"; + +/* New chat: Notify user that he can't start chat with himself */ +"NewChatScene.Error.OwnAddress" = "Вам не нужен анонимный чат, чтобы говорить с самим собой"; + +/* New chat: Remote server returned an error. Using %@ for error description */ +"NewChatScene.Error.RemoteServerFormat" = "Remote server error: %@. Report a bug"; + +/* New Chat: Notify user that scanned QR doesn't contains an address */ +"NewChatScene.Error.WrongQr" = "QR код не содержит адреса"; + +/* New chat: Scan QR with address button */ +"NewChatScene.ScanQr" = "Сканировать QR-код"; + +/* New chat: scene title */ +"NewChatScene.Title" = "Новый Чат"; + +/* Notifications: New message notification title */ +"NotificationsService.NewMessage.Title" = "Новое Сообщение"; + +/* Notifications: New transfer transaction title */ +"NotificationsService.NewTransfer.Title" = "Новый перевод"; + +/* Notifications: User has disabled notifications. Head him into settings */ +"NotificationsService.NotificationsDisabled" = "Уведомления отключены. Вы можете включить их в Настройках"; + +/* Pinpad: Ask user to create new pin */ +"Pinpad.EnterNewPin" = "Введите новый PIN-код"; + +/* Pinpad: Ask user to repeat new pin */ +"Pinpad.ReenterPin" = "Введите PIN-код ещё раз"; + +/* QRGenerator: user typed in wrong invalid */ +"QrGeneratorScene.Error.InvalidPassphrase" = "Введите корректный пароль"; + +/* QRGenerator: Bad Internal generator error message format. Using %@ for error description */ +"QrGeneratorScene.Error.InternalErrorFormat" = "Internal error: %@. Report a bug"; + +/* QRGenerator: Passphrase textview placeholder */ +"QrGeneratorScene.Passphrase.Placeholder" = "Пароль"; + +/* QRGenerator: small 'Tap to save' tooltip under generated QR */ +"QrGeneratorScene.TapToSave" = "Нажмите для сохранения"; + +/* QRGenerator: scene title */ +"QrGeneratorScene.Title" = "QR Генератор"; + +/* Config: turn off 'Stay Logged In' confirmation */ +"SettingsPage.DoNotStayLoggedIn" = "Выходить из системы при выходе из приложения"; + +/* Config: Authorization reason for turning biometry off */ +"SettingsPage.DoNotUseBiometry" = "Отключить вход с биометрией"; + +/* Config: Generate QR with passphrase row */ +"SettingsPage.Row.GenerateQr" = "Создать QR-код с паролем"; + +/* Config: Show notifications */ +"SettingsPage.Row.Notifications" = "Уведомления"; + +/* Config: Stay logged option */ +"SettingsPage.Row.StayLoggedIn" = "Оставаться в системе"; + +/* Config: Version row */ +"SettingsPage.Row.Version" = "Версия"; + +/* Config: Application Info section */ +"SettingsPage.Section.ApplicationInfo" = "Приложение"; + +/* Config: Settings section */ +"SettingsPage.Section.Settings" = "Безопасность"; + +/* Config: Utilities section */ +"SettingsPage.Section.Utilities" = "Утилиты"; + +/* Config: scene title */ +"SettingsPage.Title" = "Настройки"; + +/* Config: Authorization reason for turning biometry on */ +"SettingsPage.UseBiometry" = "Использовать биометрию для входа в систему"; + +/* Shared alert 'Cancel' button. Used anywhere */ +"Shared.Cancel" = "Отмена"; + +/* Shared alert notification: message about item copied to pasteboard. */ +"Shared.CopiedToPasteboard" = "Скопировано!"; + +/* Shared alert 'Copy' button. Used anywhere. Used for copy-paste info. */ +"Shared.CopyToPasteboard" = "Копировать"; + +/* Shared alert Done message. Used anywhere */ +"Shared.Done" = "Готово"; + +/* Shared alert 'Error' title. Used anywhere */ +"Shared.Error" = "Ошибка"; + +/* Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere. */ +"Shared.GenerateQRCode" = "Создать QR-код"; + +/* Shared alert 'Ok' button. Used anywhere */ +"Shared.Ok" = "Ок"; + +/* Shared alert 'Save' button. Used anywhere */ +"Shared.Save" = "Сохранить"; + +/* Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title. */ +"Shared.Settings" = "Настройки"; + +/* Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu. */ +"Shared.Share" = "Поделиться"; + +/* Main tab bar: Account page */ +"Tabs.Account" = "Аккаунт"; + +/* Main tab bar: Chats page */ +"Tabs.Chats" = "Чаты"; + +/* Main tab bar: Settings page */ +"Tabs.Settings" = "Настройки"; + +/* Transaction details: amount row. */ +"TransactionDetailsScene.Row.Amount" = "Количество"; + +/* Transaction details: Block id row. */ +"TransactionDetailsScene.Row.Block" = "Блок"; + +/* Transaction details: confirmations row. */ +"TransactionDetailsScene.Row.Confirmations" = "Подтверждения"; + +/* Transaction details: date row. */ +"TransactionDetailsScene.Row.Date" = "Дата"; + +/* Transaction details: 'Open transaction in explorer' row. */ +"TransactionDetailsScene.Row.Explorer" = "Открыть в Explorer"; + +/* Transaction details: fee row. */ +"TransactionDetailsScene.Row.Fee" = "Комиссия"; + +/* Transaction details: sender row. */ +"TransactionDetailsScene.Row.From" = "Отправитель"; + +/* Transaction details: Id row. */ +"TransactionDetailsScene.Row.Id" = "Id"; + +/* Transaction details: recipient row. */ +"TransactionDetailsScene.Row.To" = "Получатель"; + +/* Export transaction: 'Share transaction summary' button */ +"TransactionDetailsScene.Share.Summary" = "Сводка"; + +/* Export transaction: 'Share transaction URL' button */ +"TransactionDetailsScene.Share.URL" = "URL"; + +/* Transfer: transfer amount placeholder */ +"TransferScene.Amount.Placeholder" = "для перевода"; + +/* Transfer: Address not found error */ +"TransferScene.Error.AddressNotFound" = "Адрес не найден"; + +/* Transfer: Address validation error */ +"TransferScene.Error.InvalidAddress" = "Введите корректный адрес"; + +/* Transfer: Amount is hiegher that user's total money notification */ +"TransferScene.Error.NotEnoughtMoney" = "У вас нет такого количества токенов"; + +/* Transfer: Amount is zero, or even negative notification */ +"TransferScene.Error.TooLittleMoney" = "Вам следует отправить больше токенов"; + +/* Transfer: recipient address placeholder */ +"TransferScene.Recipient.Placeholder" = "получателя"; + +/* Transfer: amount of adamant to transfer. */ +"TransferScene.Row.Amount" = "Количество"; + +/* Transfer: logged user balance. */ +"TransferScene.Row.Balance" = "Баланс"; + +/* Transfer: maximum amount to transfer: available account money substracting transfer fee. */ +"TransferScene.Row.MaxToTransfer" = "Максимум"; + +/* Transfer: recipient address */ +"TransferScene.Row.Recipient" = "Адрес"; + +/* Transfer: Send button */ +"TransferScene.Row.Send" = "Отправить"; + +/* Transfer: total amount of transaction: money to transfer adding fee */ +"TransferScene.Row.Total" = "Итого"; + +/* Transfer: transfer fee */ +"TransferScene.Row.TransactionFee" = "Комиссия"; + +/* Transfer: 'Transfer info' section */ +"TransferScene.Section.TransferInfo" = "Перевод"; + +/* Transfer: 'Your wallet' section */ +"TransferScene.Section.YourWallet" = "Ваш кошелёк"; + +/* Transfer: Confirm transfer alert: Send tokens button */ +"TransferScene.Send" = "Отправить"; + +/* Transfer: Confirm transfer %1$@ tokens to %2$@ message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'. */ +"TransferScene.SendConfirmFormat" = "Отправить %1$@ получателю %2$@?"; + +/* Transfer: Processing message */ +"TransferScene.SendingFundsProgress" = "Отправляем токены..."; + +/* Transfer: Tokens transfered successfully message */ +"TransferScene.TransferSuccessMessage" = "Готово!"; diff --git a/Adamant/Assets/ru.lproj/Localizable.stringsdict b/Adamant/Assets/l18n/ru.lproj/Localizable.stringsdict similarity index 91% rename from Adamant/Assets/ru.lproj/Localizable.stringsdict rename to Adamant/Assets/l18n/ru.lproj/Localizable.stringsdict index 78a262f35..db18a6a6a 100644 --- a/Adamant/Assets/ru.lproj/Localizable.stringsdict +++ b/Adamant/Assets/l18n/ru.lproj/Localizable.stringsdict @@ -2,7 +2,7 @@ - You have %d new message(s) + NotificationsService.NewMessage.BodyFormat NSStringLocalizedFormatKey У вас %#@messages@ @@ -20,7 +20,7 @@ %d новых сообщения - You have %d new transfer(s) + NotificationsService.NewTransfer.BodyFormat NSStringLocalizedFormatKey У вас %#@transfers@ diff --git a/Adamant/Assets/ru.lproj/InfoPlist.strings b/Adamant/Assets/ru.lproj/InfoPlist.strings deleted file mode 100644 index 2cd714a50..000000000 --- a/Adamant/Assets/ru.lproj/InfoPlist.strings +++ /dev/null @@ -1,15 +0,0 @@ -/* (No Comment) */ -"CFBundleDisplayName" = "Адамант"; - -/* (No Comment) */ -"CFBundleName" = ""; - -/* (No Comment) */ -"NSCameraUsageDescription" = "Необходим доступ к Камере для чтения QR-кодов с адресами и паролями"; - -/* (No Comment) */ -"NSPhotoLibraryAddUsageDescription" = "Необходим доступ к Фотографиям для сохранения созданных QR-кодов"; - -/* (No Comment) */ -"NSPhotoLibraryUsageDescription" = "Необходим доступ к Фотографиям для сканирования QR-кодов с адресами и паролями со сделанных ранее фотографий"; - diff --git a/Adamant/Assets/ru.lproj/Localizable.strings b/Adamant/Assets/ru.lproj/Localizable.strings deleted file mode 100644 index cb7448de4..000000000 --- a/Adamant/Assets/ru.lproj/Localizable.strings +++ /dev/null @@ -1,304 +0,0 @@ -/* New chat: Remote server returned an error. */ -"%@" = "%@"; - -/* Product name */ -"ADAMANT" = "АДАМАНТ"; - -/* Wallet page: Account section title. */ -"Account" = "Аккаунт"; - -/* ApiService: Account not found error, appending account info. */ -"Account not found: %@" = "Аккаунт не найден: %@"; - -/* Wallet page: Actions section title */ -"Actions" = "Действия"; - -/* Transfer: recipient address */ -"Address" = "Адрес"; - -/* New chat: Notify user that specified address (%@) not found */ -"Address %@ not found" = "Адрес %@ не найден"; - -/* Transfer: Address not found error */ -"Address not found" = "Такой адрес не найден"; - -/* Transaction details: amount row. - Transfer: amount of adamant to transfer. */ -"Amount" = "Количество"; - -/* Config: Application Info section */ -"Application info" = "Приложение"; - -/* Transfer: logged user balance. - Wallet page: Balance row title */ -"Balance" = "Баланс"; - -/* Transaction details: Block id row. */ -"Block" = "Блок"; - -/* Shared alert 'Cancel' button. Used anywhere */ -"Cancel" = "Отмена"; - -/* Transaction details: confirmations row. */ -"Confirmations" = "Подтверждений"; - -/* Shared alert notification: message about item copied to pasteboard. */ -"Copied to Pasteboard" = "Скопировано!"; - -/* Shared alert 'Copy' button. Used anywhere. Used for copy-paste info. */ -"Copy to Pasteboard" = "Копировать"; - -/* Transaction details: date row. */ -"Date" = "Дата"; - -/* Config: turn off 'Stay Logged In' confirmation */ -"Do not stay logged in" = "Выходить из системы при выходе из приложения"; - -/* Config: Authorization reason for turning biometry off */ -"Do not use biometry to log in" = "Отключить вход с биометрией"; - -/* Shared alert Done message. Used anywhere */ -"Done" = "Готово"; - -/* Wallet page: Inform user that sending tokens not allowed by Apple until the end of ICO */ -"Due to Apple restrictions, sending tokens is not allowed until the end of the ICO. For now, you can send tokens using WebApp at msg.adamant.im" = "Ввиду ограничений Apple, отправка токенов отключена до конца ICO. В данный момент вы можете отправлять токены с помощью WebApp по адресу msg.adamant.im"; - -/* Login: notify user that he is trying to login without a passphrase */ -"Enter a passphrase!" = "Введите пароль"; - -/* QRGenerator: user typed in wrong invalid */ -"Enter correct passphrase" = "Введите корректный пароль"; - -/* Pinpad: Ask user to create new pin */ -"Enter new pin" = "Введите новый пин"; - -/* Shared alert 'Error' title. Used anywhere */ -"Error" = "Ошибка"; - -/* Chat: input bar: Estimated fee */ -"~%@" = "~%@"; - -/* Transaction details: fee row. */ -"Fee" = "Комиссия"; - -/* Transaction details: sender row. */ -"From" = "Отправитель"; - -/* Transfer: Tokens transfered successfully message */ -"Funds sended!" = "Токены переведены!"; - -/* Shared alert 'Generate QR' button. Used to generate QR codes with addresses and passphrases. Used with sharing and saving, anywhere. */ -"Generate QR Code" = "Создать QR-код"; - -/* Config: Generate QR with passphrase row */ -"Generate QR with passphrase" = "Создать QR-код с паролем"; - -/* Login: generate new passphrase button */ -"Generate new passphrase" = "Создать новый"; - -/* Wallet page: 'Transfer not allowed' alert 'go to WebApp button' */ -"Go to msg.adamant.im" = "Открыть msg.adamant.im"; - -/* Transaction details: Id row. */ -"Id" = "Номер"; - -/* Wallet page: 'Invest in ICO' button */ -"Invest in ICO" = "Инвестировать в ICO"; - -/* Login: notify user that we a logging in */ -"Logging in" = "Входим..."; - -/* Login: Login button - Login: login with existing passphrase section */ -"Login" = "Вход"; - -/* Login: Login into previous account with biometry or pincode */ -"Login into Adamant" = "Вход в Адамант"; - -/* Wallet page: 'Logout' button - Wallet page: Confirm logout alert: Logout (Ok) button */ -"Logout" = "Выход"; - -/* Wallet page: Confirm logout alert */ -"Logout from %@?" = "Выйти из %@?"; - -/* Transfer: maximum amount to transfer: available account money substracting transfer fee. */ -"Max to transfer" = "Доступно для перевода"; - -/* Chat: Notify user that message cannot be empty */ -"Message is empty" = "Сообщение пусто!"; - -/* Chat: Message is too long */ -"Message is too long" = "Сообщение слишком длинное"; - -/* Login: Create new account section */ -"New account" = "Новый аккаунт"; - -/* Chat: message input placeholder - Notifications: New message notification title */ -"New message" = "Новое сообщение"; - -/* Notifications: New transfer transaction title */ -"New transfer" = "Новый перевод"; - -/* ApiService: No connection message. Generally bad network. */ -"No connection" = "Нет соединения с интернетом"; - -/* Login: No network error. */ -"No connection with The Internet" = "Нет соединения с сетью"; - -/* Config: Show notifications */ -"Notifications" = "Уведомления"; - -/* Notifications: User has disabled notifications. Head him into settings */ -"Notifications disabled. You can reenable notifications in Settings" = "Уведомления отключены. Вы можете включить их в Настройках"; - -/* Shared alert 'Ok' button. Used anywhere */ -"Ok" = "Ок"; - -/* Transaction details: 'Open transaction in explorer' row. */ -"Open in Explorer" = "Открыть в Explorer"; - -/* Login: Passphrase placeholder - QRGenerator: Passphrase textview placeholder */ -"Passphrase" = "Пароль"; - -/* Login: Login with pincode button */ -"Login with Pincode" = "Войти с pin-кодом"; - -/* Transfer: Address validation error */ -"Please enter a valid recipient address" = "Введите корректный адрес получателя"; - -/* New chat: Notify user that he did enter invalid address */ -"Please specify valid recipient address" = "Неверный адрес"; - -/* Login: Login with QR button. */ -"Login with QR" = "Войти с QR-кодом"; - -/* New Chat: Notify user that scanned QR doesn't contains an address */ -"QR code does not contains a valid adamant address" = "QR код не содержит адреса"; - -/* Login: Notify user that scanned QR doesn't contains a passphrase. */ -"QR code does not contains a valid passphrase" = "QR код не содержит пароля"; - -/* Login: Notify user that device not supported by QR reader */ -"QR codes reading not supported by the current device" = "На этом устройстве не поддерживается чтение QR кодов"; - -/* Pinpad: Ask user to repeat new pin */ -"Re-enter new pin" = "Введите пин ещё раз"; - -/* Shared alert 'Save' button. Used anywhere */ -"Save" = "Сохранить"; - -/* Login: security alert, notify user that he must save his new passphrase */ -"Save the passphrase for new Wallet and Messenger account. There is no login to enter Wallet, only the passphrase needed. If lost, no way to recover it" = "Это пароль для нового Кошелька и Мессенджера. Сохраните его! Для входа в Кошелек не нужно логина, только этот пароль. Восстановление пароля невозможно."; - -/* New chat: Scan QR with address button */ -"Scan QR" = "Сканировать QR код"; - -/* Chat: Send message button - Transfer: Confirm transfer alert: Send tokens button */ -"Send" = "Отправить"; - -/* Transfer: Confirm transfer X tokens to Y message. Note two variables: at runtime %1$@ will be amount (with ADM suffix), and %2$@ will be recipient address. You can use address before amount with this so called 'position tokens'. */ -"Send %1$@ to %2$@?" = "Отправить %1$@ получателю %2$@?"; - -/* Transfer: Send button */ -"Send Funds" = "Отправить токены"; - -/* Wallet page: 'Send tokens' button */ -"Send Tokens" = "Отправить токены"; - -/* Transfer: Processing message */ -"Sending funds..." = "Отправляем токены..."; - -/* Config: Settings section - Shared alert 'Settings' button. Used to go to system Settings app, on application settings page. Should be same as Settings application title. */ -"Settings" = "Настройки"; - -/* Shared alert 'Share' button. Used anywhere for presenting standart iOS 'Share' menu. */ -"Share" = "Поделиться"; - -/* Wallet page: 'Transfer not allowed' alert title */ -"Sorry!" = "Ой!"; - -/* Config: Stay logged option */ -"Stay Logged in" = "Оставаться в сети"; - -/* Export transaction: 'Share transaction summary' button */ -"Summary" = "Сводка"; - -/* Login: a small hint for a user, that he can tap on passphrase to save it - QRGenerator: small 'Tap to save' tooltip under generated QR */ -"Tap to save" = "Нажмите для сохранения"; - -/* Transaction details: recipient row. */ -"To" = "Получатель"; - -/* Transfer: total amount of transaction: money to transfer adding fee */ -"Total" = "Итого"; - -/* Transfer: transfer fee */ -"Transaction fee" = "Комиссия"; - -/* Transfer: 'Transfer info' section */ -"Transfer Info" = "Перевод"; - -/* Export transaction: 'Share transaction URL' button */ -"URL" = "URL"; - -/* Unknown internal error */ -"Unknown error" = "Неизвестная ошибка"; - -/* Config: Authorization reason for turning biometry on */ -"Use biometry to log in" = "Использовать биометрию для входа в систему"; - -/* ApiService: User not logged error - Login: user not logged error */ -"User not logged" = "Не выполнен вход"; - -/* Config: Utilities section */ -"Utilities" = "Утилиты"; - -/* Config: Version row */ -"Version" = "Версия"; - -/* Wallet page: Wallet section title */ -"Wallet" = "Кошелёк"; - -/* Known contacts: Adamant welcome message */ -"Welcome to ADAMANT, the most secure and anonymous messenger. You are credited with bounty tokens, which you can use to get acquainted with the messenger.\nRemember, your security and anonymity is up to you also. Do not follow links you receive, otherwise your IP can be compromised. Do not trust browser extensions. Better to share your ADM address personally, but not using other messengers. Keep your secret passphrase secure. Set a password on your device or logout before leaving.\nLearn more about security and anonymity at https://adamant.im/staysecured/.\n\nDo not reply to this message, it is a system account." = "Добро пожаловать в самый анонимный и безопасный мессенджер АДАМАНТ. Вам начислены приветственные токены, которые вы можете использовать для ознакомления с мессенджером.\nПомните, что безопасность и анонимность зависит и от вас самих. Не переходите по ссылкам, которые вы получаете в чатах, иначе ваш IP-адрес может быть определен. Не доверяйте расширениям браузера. Лучше всего передавать ваш ADM-адрес собеседникам лично, а не через другие мессенджеры. Храните вашу секретную фразу (пароль) от аккаунта в тайне. Установите на ваше устройство пароль или закрываете вкладку браузера после завершения диалогов.\nБолее полную информацию о безопасности и анонимности читайте на странице https://adamant.im/ru-staysecured/\n\nНе отвечайте на это сообщение, этот адрес служебный."; - -/* Login: user typed in wrong passphrase */ -"Wrong passphrase!" = "Неправильный пароль"; - -/* Chat: Notify user that he doesn't have money to pay a message fee */ -"You don't have enough money to send a message" = "Недостаточно токенов для отправки сообщения"; - -/* Transfer: Amount is hiegher that user's total money notification */ -"You don't have that much money" = "У вас нет столько токенов"; - -/* New chat: Notify user that he can't start chat with himself */ -"You don't need an encrypted anonymous chat to talk to yourself" = "Вам не нужен анонимный чат, чтобы говорить с самим собой"; - -/* Known contacts: Adamant pre ICO message */ -"You have a possibility to invest in ADAMANT, the most secure and anonymous messenger. Now is a Pre-ICO stage — the most profitable for investors. Learn more on Adamant.im website or in the Whitepaper. To participate just reply to this message and we will assist. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "Сегодня последний день, когда мы принимаем инвестиции по минимальной цене 0.001 ETH за токен ADM до начала публичного сейла ICO — 30.01. Это самые выгодные условия для инвесторов. Минимальная инвестиция — эквивалент 2 ETH (на этапе публичного сейла ограничений по минимальной сумме нет, но цена токена начинается с 0.002 ETH). Подробная информация о проекте АДАМАНТ на сайте Adamant.im и в Белой книге. Для участия достаточно ответить на это сообщение, и мы вам поможем."; - -/* Known contacts: Adamant ICO message */ -"You have a possibility to invest in ICO of ADAMANT, the most secure and anonymous messenger. Earlier you participate, better offer you will get. Learn more on Adamant.im website or in the Whitepaper. To invest, go to Wallet→Invest in the ICO, or follow a website page Adamant.im/ico/. If you still have any questions, you can ask them by replying to this message. We are eager to answer quickly, but sometimes delays for a couple of hours are possible.\nAfter you invest and receive ADM tokens, we recommend to keep them as long as possible. All of unsold tokens during ICO will be distributed among users wallets, adding 5% monthly. Additional info is on Adamant.im website and in the Whitepaper." = "У вас есть возможность инвестировать в ICO самого защищенного мессенджера АДАМАНТ. Более раннее участие — более выгодные условия. Подробная информация об условиях на сайте Adamant.im и в Белой книге проекта. Если вы уже ознакомились с нашим сайтом и Белой книгой, но у вас остались вопросы, вы можете задать их, ответив на это сообщение. Мы стараемся реагировать быстро, но иногда возможны задержки до нескольких часов.\nВажно! Пожалуйста, убедитесь, что вы сохранили пароль к этому аккаунту — выйдите из аккаунта и войдите в него снова. Лучше всего иметь запись пароля и на бумаге. Однако помните, только вы несете ответственность за сохранность вашего пароля. Его невозможно восстановить. А если он попадет в другие руки, ваши деньги будут украдены. Отнеситесь к этому вопросу так серьезно, как если бы цена токенов на вашем кошельке когда-то станет равна миллиарду долларов.\nЧтобы инвестировать, перейдите в этом месседжере на вкладку Кошелек и нажмите кнопку Инвестировать в ICO, или откройте в браузере веб-страницу Adamant.im/ico/. В форме для инвестирования укажите ваш адрес АДАМАНТа — на него будут перечислены токены ADM. При переходе из мессенджера он будет вставлен автоматически, в другом случае вернитесь в мессенджер и кликните на блок Ваш адрес, он будет скопирован в буфер обмена. Укажите криптовалюту, в которой вы хотите инвестировать, и какую сумму. Вы увидите сколько ADM-токенов вы получите, с учетом скидки за объем: 20–30 ETH: +20%, 30–50 ETH: +30%, 50–90 ETH: +40%, 90+ ETH: +50%. Нажмите кнопку Купить токены АДАМАНТ. Вы получите уникальный адрес, на который необходимо выполнить перевод. Как только на него поступит ожидаемая сумма и транзакция будет подтверждена, вы получите токены ADM. Транзакцию можно выполнить с любого кошелька, включая биржи. Необязятельно переводить точную сумму с учетом комиссии, платеж все равно будет засчитан. Остались вопросы? Спрашивайте.\nПосле того, как вы инвестируете и получите токены ADM, мы рекомендуем вам хранить их в кошельке как можно дольше. Ежемесячно все нераспроданные на ICO токены будут распределяться по кошелькам пользователей, увеличивая балансы на 5%. Подробную информацию можно получить на сайте Adamant.im и в Белой книге Проекта."; - -/* Login: Notify user, that he disabled camera in settings, and need to authorize application. */ -"You need to authorize Adamant to use device's Camera" = "Для чтения QR кодов необходимо разрешить доступ к камере"; - -/* Transfer: Amount is zero, or even negative notification */ -"You should send more money" = "Нужно отправить больше токенов"; - -/* Transfer: 'Your wallet' section */ -"Your wallet" = "Ваш кошелёк"; - -/* Transfer: recipient address placeholder */ -"of the recipient" = "получателя"; - -/* Transfer: transfer amount placeholder */ -"to send" = "для перевода"; - diff --git a/Adamant/ServiceProtocols/NotificationsService.swift b/Adamant/ServiceProtocols/NotificationsService.swift index 8b7d1e649..82cfb0dd5 100644 --- a/Adamant/ServiceProtocols/NotificationsService.swift +++ b/Adamant/ServiceProtocols/NotificationsService.swift @@ -16,7 +16,7 @@ extension String.adamantLocalized { static let newMessageBody = NSLocalizedString("NotificationsService.NewMessage.BodyFormat", comment: "Notifications: new messages notification body. Using %d for amount") static let newTransferTitle = NSLocalizedString("NotificationsService.NewTransfer.Title", comment: "Notifications: New transfer transaction title") - static let newTransferBody = NSLocalizedString("NotificationsService.NewTransferFormat", comment: "Notifications: New transfer notification body. Using %d for amount") + static let newTransferBody = NSLocalizedString("NotificationsService.NewTransfer.BodyFormat", comment: "Notifications: New transfer notification body. Using %d for amount") private init() {} } diff --git a/Adamant/Stories/Account/AccountViewController.swift b/Adamant/Stories/Account/AccountViewController.swift index 2aa41e770..a5077949e 100644 --- a/Adamant/Stories/Account/AccountViewController.swift +++ b/Adamant/Stories/Account/AccountViewController.swift @@ -13,7 +13,7 @@ import SafariServices // MARK: - Localization extension String.adamantLocalized { struct account { - static let title = NSLocalizedString("AccountTab.title", comment: "Account page: scene title") + static let title = NSLocalizedString("AccountTab.Title", comment: "Account page: scene title") static let rowBalance = NSLocalizedString("AccountTab.Row.Balance", comment: "Account tab: Balance row title") static let rowSendTokens = NSLocalizedString("AccountTab.Row.SendTokens", comment: "Account tab: 'Send tokens' button") @@ -22,7 +22,7 @@ extension String.adamantLocalized { static let sorryAlert = NSLocalizedString("AccountTab.TransferBlocked.Title", comment: "Account tab: 'Transfer not allowed' alert title") static let webApp = NSLocalizedString("AccountTab.TransferBlocked.GoToPWA", comment: "Account tab: 'Transfer not allowed' alert 'go to WebApp button'") - static let transferNotAllowed = NSLocalizedString("AccountTab.Message", comment: "Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO") + static let transferNotAllowed = NSLocalizedString("AccountTab.TransferBlocked.Message", comment: "Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO") static let sectionAccount = NSLocalizedString("AccountTab.Section.Account", comment: "Account tab: Account section title.") static let sectionWallet = NSLocalizedString("AccountTab.Section.Wallet", comment: "Account tab: Wallet section title") diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 0256d29e1..634549457 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -21,7 +21,7 @@ extension String.adamantLocalized { static let notEnoughMoney = NSLocalizedString("ChatScene.Error.NotEnoughMoney", comment: "Chat: Notify user that he doesn't have money to pay a message fee") static let internalErrorFormat = NSLocalizedString("ChatScene.Error.InternalErrorFormat", comment: "Chat: Notify user about bad internal error. Usually this should be reported as a bug. Using %@ for error description") - static let serverErrorFormat = NSLocalizedString("ChatScene.Error.RemoteServerError", comment: "Chat: Notify user about server error. Using %@ for error description") + static let serverErrorFormat = NSLocalizedString("ChatScene.Error.RemoteServerErrorFormat", comment: "Chat: Notify user about server error. Using %@ for error description") private init() { } } diff --git a/Adamant/Stories/Chats/NewChatViewController.swift b/Adamant/Stories/Chats/NewChatViewController.swift index 2ae308c10..1fcefa80c 100644 --- a/Adamant/Stories/Chats/NewChatViewController.swift +++ b/Adamant/Stories/Chats/NewChatViewController.swift @@ -16,7 +16,7 @@ extension String.adamantLocalized { struct newChat { static let title = NSLocalizedString("NewChatScene.Title", comment: "New chat: scene title") - static let addressPlaceholder = NSLocalizedString(NewChatScene.Address.Placeholder, comment: "New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank.") + static let addressPlaceholder = NSLocalizedString("NewChatScene.Address.Placeholder", comment: "New chat: Recipient address placeholder. Note that address text field always shows U letter, so you can left this line blank.") static let scanQrButton = NSLocalizedString("NewChatScene.ScanQr", comment: "New chat: Scan QR with address button") static let specifyValidAddressMessage = NSLocalizedString("NewChatScene.Error.InvalidAddress", comment: "New chat: Notify user that he did enter invalid address") diff --git a/Adamant/Stories/Settings/QRGeneratorViewController.swift b/Adamant/Stories/Settings/QRGeneratorViewController.swift index dfeb5ab5f..88e8d54ba 100644 --- a/Adamant/Stories/Settings/QRGeneratorViewController.swift +++ b/Adamant/Stories/Settings/QRGeneratorViewController.swift @@ -20,7 +20,7 @@ extension String.adamantLocalized { static let passphrasePlaceholder = NSLocalizedString("QrGeneratorScene.Passphrase.Placeholder", comment: "QRGenerator: Passphrase textview placeholder") static let wrongPassphraseError = NSLocalizedString("QrGeneratorScene.Error.InvalidPassphrase", comment: "QRGenerator: user typed in wrong invalid") - static let internalError = NSLocalizedString("QrGeneratorScene.ErrorInternalError", comment: "QRGenerator: Bad Internal generator error message format. Using %@ for error description") + static let internalError = NSLocalizedString("QrGeneratorScene.Error.InternalErrorFormat", comment: "QRGenerator: Bad Internal generator error message format. Using %@ for error description") private init() {} } From 10f6ae346ae6dc1a0fda29e6ffc73bdb978377fd Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 21:58:14 +0300 Subject: [PATCH 05/13] Account page refactored for Eureka --- Adamant.xcodeproj/project.pbxproj | 8 + Adamant/Services/AdamantAccountService.swift | 8 +- Adamant/SharedCells/AccountCell.xib | 55 ++ Adamant/SharedCells/EurekaAccountRow.swift | 26 + .../Account/AccountViewController.swift | 478 +++++++++--------- .../SettingsViewController+StayIn.swift | 6 +- 6 files changed, 344 insertions(+), 237 deletions(-) create mode 100644 Adamant/SharedCells/AccountCell.xib create mode 100644 Adamant/SharedCells/EurekaAccountRow.swift diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 86f0e5c79..8224fd19a 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -56,6 +56,8 @@ E95CB451205D77B200A7218E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E95CB453205D77B200A7218E /* InfoPlist.strings */; }; E95CB456205D77B500A7218E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E95CB458205D77B500A7218E /* Localizable.strings */; }; E95CB45E205D7F9600A7218E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = E95CB460205D7F9600A7218E /* Localizable.stringsdict */; }; + E95CB464205D8BBA00A7218E /* EurekaAccountRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95CB462205D8BBA00A7218E /* EurekaAccountRow.swift */; }; + E95CB465205D8BBA00A7218E /* AccountCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E95CB463205D8BBA00A7218E /* AccountCell.xib */; }; E95F856520067A030070534A /* GlobalConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F856420067A030070534A /* GlobalConstants.swift */; }; E95F85692006AB9D0070534A /* NormalizedTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F85682006AB9D0070534A /* NormalizedTransaction.swift */; }; E95F856B200789450070534A /* JSModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95F856A200789450070534A /* JSModels.swift */; }; @@ -233,6 +235,8 @@ E95CB45A205D77DD00A7218E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = ""; }; E95CB45F205D7F9600A7218E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; E95CB461205D7FD000A7218E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; + E95CB462205D8BBA00A7218E /* EurekaAccountRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EurekaAccountRow.swift; sourceTree = ""; }; + E95CB463205D8BBA00A7218E /* AccountCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountCell.xib; sourceTree = ""; }; E95F856420067A030070534A /* GlobalConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalConstants.swift; sourceTree = ""; }; E95F85682006AB9D0070534A /* NormalizedTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NormalizedTransaction.swift; sourceTree = ""; }; E95F856A200789450070534A /* JSModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSModels.swift; sourceTree = ""; }; @@ -683,6 +687,8 @@ E9E7CDC62003F6D200DFC4DB /* TransactionTableViewCell.xib */, E9942B86203D9E5100C163AF /* EurekaQRRow.swift */, E9942B88203D9ECA00C163AF /* QrCell.xib */, + E95CB462205D8BBA00A7218E /* EurekaAccountRow.swift */, + E95CB463205D8BBA00A7218E /* AccountCell.xib */, ); path = SharedCells; sourceTree = ""; @@ -813,6 +819,7 @@ E913C8F91FFFA51D001A83F7 /* Assets.xcassets in Resources */, E9EC341F200524CA00C0E546 /* Roboto_700_normal.ttf in Resources */, E9942B89203D9ECA00C163AF /* QrCell.xib in Resources */, + E95CB465205D8BBA00A7218E /* AccountCell.xib in Resources */, E9C51EED2011416E00385EB7 /* adamant-core.js in Resources */, E90A4945204C6204009F6A65 /* PassphraseCell.xib in Resources */, E9E7CDC82003F6D200DFC4DB /* TransactionTableViewCell.xib in Resources */, @@ -994,6 +1001,7 @@ E9E7CDCA20040CC200DFC4DB /* Transaction.swift in Sources */, E95F85692006AB9D0070534A /* NormalizedTransaction.swift in Sources */, E913C90D1FFFA99B001A83F7 /* Keypair.swift in Sources */, + E95CB464205D8BBA00A7218E /* EurekaAccountRow.swift in Sources */, E948E03B20235E2300975D6B /* SettingsRoutes.swift in Sources */, E9CAE8D82018ACA700345E76 /* AdamantApi+Transfers.swift in Sources */, E9E7CDCC20040FDC00DFC4DB /* TransactionType.swift in Sources */, diff --git a/Adamant/Services/AdamantAccountService.swift b/Adamant/Services/AdamantAccountService.swift index 1d27ef587..858b1d3c1 100644 --- a/Adamant/Services/AdamantAccountService.swift +++ b/Adamant/Services/AdamantAccountService.swift @@ -145,13 +145,7 @@ extension AdamantAccountService: AccountService { stateSemaphore.wait() switch state { - case .notLogged: - fallthrough - - case .isLoggingIn: - fallthrough - - case .updating: + case .notLogged, .isLoggingIn, .updating: stateSemaphore.signal() return diff --git a/Adamant/SharedCells/AccountCell.xib b/Adamant/SharedCells/AccountCell.xib new file mode 100644 index 000000000..d117f8d00 --- /dev/null +++ b/Adamant/SharedCells/AccountCell.xib @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Adamant/SharedCells/EurekaAccountRow.swift b/Adamant/SharedCells/EurekaAccountRow.swift new file mode 100644 index 000000000..d4f427edc --- /dev/null +++ b/Adamant/SharedCells/EurekaAccountRow.swift @@ -0,0 +1,26 @@ +// +// EurekaAccountRow.swift +// Adamant +// +// Created by Anokhov Pavel on 17.03.2018. +// Copyright © 2018 Adamant. All rights reserved. +// + +import UIKit +import Eureka + +public class AccountCell: Cell, CellType { + @IBOutlet weak var avatarImageView: UIImageView! + @IBOutlet weak var addressLabel: UILabel! + + public override func update() { + addressLabel.text = row.value + } +} + +public final class AccountRow: Row, RowType { + required public init(tag: String?) { + super.init(tag: tag) + cellProvider = CellProvider(nibName: "AccountCell") + } +} diff --git a/Adamant/Stories/Account/AccountViewController.swift b/Adamant/Stories/Account/AccountViewController.swift index a5077949e..92f194926 100644 --- a/Adamant/Stories/Account/AccountViewController.swift +++ b/Adamant/Stories/Account/AccountViewController.swift @@ -8,6 +8,7 @@ import UIKit import SafariServices +import Eureka // MARK: - Localization @@ -15,19 +16,10 @@ extension String.adamantLocalized { struct account { static let title = NSLocalizedString("AccountTab.Title", comment: "Account page: scene title") - static let rowBalance = NSLocalizedString("AccountTab.Row.Balance", comment: "Account tab: Balance row title") - static let rowSendTokens = NSLocalizedString("AccountTab.Row.SendTokens", comment: "Account tab: 'Send tokens' button") - static let rowInvest = NSLocalizedString("AccountTab.Row.JoinIco", comment: "Account tab: 'Invest in ICO' button") - static let rowLogout = NSLocalizedString("AccountTab.Row.Logout", comment: "Account tab: 'Logout' button") - static let sorryAlert = NSLocalizedString("AccountTab.TransferBlocked.Title", comment: "Account tab: 'Transfer not allowed' alert title") static let webApp = NSLocalizedString("AccountTab.TransferBlocked.GoToPWA", comment: "Account tab: 'Transfer not allowed' alert 'go to WebApp button'") static let transferNotAllowed = NSLocalizedString("AccountTab.TransferBlocked.Message", comment: "Account tab: Inform user that sending tokens not allowed by Apple until the end of ICO") - static let sectionAccount = NSLocalizedString("AccountTab.Section.Account", comment: "Account tab: Account section title.") - static let sectionWallet = NSLocalizedString("AccountTab.Section.Wallet", comment: "Account tab: Wallet section title") - static let sectionActions = NSLocalizedString("AccountTab.Section.Actions", comment: "Account tab: Actions section title") - private init() { } } } @@ -39,22 +31,75 @@ fileprivate extension String.adamantLocalized.alert { // MARK: - -class AccountViewController: UIViewController { +class AccountViewController: FormViewController { // MARK: - Constants - private let cellIdentifier = "cell" - private let webAppUrl = URL.init(string: "https://msg.adamant.im") - private enum Sections: Int { - case account = 0, wallet, actions + + // MARK: - Rows & Sections + private enum Sections { + case account + case wallet + case actions - static let total = 3 + var localized: String { + switch self { + case .account: + return NSLocalizedString("AccountTab.Section.Account", comment: "Account tab: Account section title.") + + case .wallet: + return NSLocalizedString("AccountTab.Section.Wallet", comment: "Account tab: Wallet section title") + + case .actions: + return NSLocalizedString("AccountTab.Section.Actions", comment: "Account tab: Actions section title") + } + } } - private enum WalletRows: Int { - case balance, sendTokens, invest + private enum Rows { + case account + case balance + case sendTokens + case invest + case logout + + var tag: String { + switch self { + case .account: + return "acc" + + case .balance: + return "balance" + + case .sendTokens: + return "sendTokens" + + case .invest: + return "invest" + + case .logout: + return "logout" + } + } - static let total = 3 + var localized: String { + switch self { + case .account: + return "" + + case .balance: + return NSLocalizedString("AccountTab.Row.Balance", comment: "Account tab: Balance row title") + + case .sendTokens: + return NSLocalizedString("AccountTab.Row.SendTokens", comment: "Account tab: 'Send tokens' button") + + case .invest: + return NSLocalizedString("AccountTab.Row.JoinIco", comment: "Account tab: 'Invest in ICO' button") + + case .logout: + return NSLocalizedString("AccountTab.Row.Logout", comment: "Account tab: 'Logout' button") + } + } } @@ -64,257 +109,238 @@ class AccountViewController: UIViewController { var router: Router! - // MARK: - IBOutlets - @IBOutlet weak var tableView: UITableView! - - // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() navigationItem.title = String.adamantLocalized.account.title - - tableView.delegate = self - tableView.dataSource = self + navigationOptions = .Disabled - NotificationCenter.default.addObserver(forName: .adamantUserLoggedIn, object: nil, queue: OperationQueue.main) { [weak self] _ in - self?.tableView.reloadData() - } - NotificationCenter.default.addObserver(forName: .adamantUserLoggedOut, object: nil, queue: OperationQueue.main) { [weak self] _ in - self?.tableView.reloadData() - } - NotificationCenter.default.addObserver(forName: .adamantAccountDataUpdated, object: nil, queue: OperationQueue.main) { [weak self] _ in - guard let account = self?.accountService.account, - let cell = self?.tableView.cellForRow(at: IndexPath(row: 0, section: 1)) else { - return - } + // MARK: Account Section + form +++ Section(Sections.account.localized) - cell.detailTextLabel?.text = AdamantUtilities.format(balance: account.balance) - } - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - if let indexPath = tableView.indexPathForSelectedRow { - tableView.deselectRow(at: indexPath, animated: animated) - } - - NotificationCenter.default.addObserver(forName: Notification.Name.adamantAccountDataUpdated, object: nil, queue: OperationQueue.main) { _ in - self.refreshBalanceCell() - } - } - - deinit { - NotificationCenter.default.removeObserver(self) - } -} - - -// MARK: - UITableView -extension AccountViewController: UITableViewDataSource, UITableViewDelegate { - func numberOfSections(in tableView: UITableView) -> Int { - if accountService.account != nil { - return Sections.total - } else { - return 0 - } - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if accountService.account != nil, let sect = Sections(rawValue: section) { - switch sect { - case .account: return 1 - case .wallet: return WalletRows.total - case .actions: return 1 + <<< AccountRow() { [weak self] in + $0.tag = Rows.account.tag + $0.cell.height = {65} } - } else { - return 0 - } - } - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - - if indexPath.section == 0 && indexPath.row == 0 { - return 65 - } - - return 44.5 - } - - func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - return UIView() - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - guard let section = Sections(rawValue: indexPath.section) else { - return - } + .cellUpdate({ [weak self] (cell, row) in + cell.avatarImageView.tintColor = UIColor.adamantChatIcons + if let label = cell.addressLabel { + label.font = UIFont.adamantPrimary(size: 17) + label.textColor = UIColor.adamantPrimary + } + + row.value = self?.accountService.account?.address + }) + .onCellSelection({ [weak self] (_, row) in + guard let address = self?.accountService.account?.address else { + return + } + + let encodedAddress = AdamantUriTools.encode(request: AdamantUri.address(address: address, params: nil)) + + self?.dialogService.presentShareAlertFor(string: encodedAddress, + types: [.copyToPasteboard, .share, .generateQr(sharingTip: address)], + excludedActivityTypes: ShareContentType.address.excludedActivityTypes, + animated: true, + completion: { + guard let indexPath = row.indexPath else { + return + } + self?.tableView.deselectRow(at: indexPath, animated: true) + }) + }) - switch section { - case .account: - tableView.deselectRow(at: indexPath, animated: true) - - guard let address = self.accountService.account?.address else { - return + // MARK: Wallet section + +++ Section(Sections.wallet.localized) + // MARK: Balance + <<< LabelRow() { [weak self] in + $0.tag = Rows.balance.tag + $0.title = Rows.balance.localized + + if let balance = self?.accountService?.account?.balance { + $0.value = AdamantUtilities.format(balance: balance) + } } - - let encodedAddress = AdamantUriTools.encode(request: AdamantUri.address(address: address, params: nil)) - - dialogService.presentShareAlertFor(string: encodedAddress, - types: [.copyToPasteboard, .share, .generateQr(sharingTip: address)], - excludedActivityTypes: ShareContentType.address.excludedActivityTypes, - animated: true, - completion: nil) - - case .wallet: - guard let row = WalletRows(rawValue: indexPath.row) else { - return + .cellSetup({ (cell, _) in + cell.selectionStyle = .gray + }) + .cellUpdate({ (cell, _) in + if let label = cell.textLabel { + label.font = UIFont.adamantPrimary(size: 17) + label.textColor = UIColor.adamantPrimary + } + + cell.accessoryType = .disclosureIndicator + }) + .onCellSelection({ [weak self] (_, _) in + guard let vc = self?.router.get(scene: AdamantScene.Transactions.transactions), let nav = self?.navigationController else { + return + } + nav.pushViewController(vc, animated: true) + }) + + // MARK: Send tokens + <<< LabelRow() { + $0.tag = Rows.sendTokens.tag + $0.title = Rows.sendTokens.localized } - - switch row { - case .balance: - let vc = router.get(scene: AdamantScene.Transactions.transactions) - navigationController?.pushViewController(vc, animated: true) + .cellSetup({ (cell, _) in + cell.selectionStyle = .gray + }) + .cellUpdate({ (cell, _) in + if let label = cell.textLabel { + label.font = UIFont.adamantPrimary(size: 17) + label.textColor = UIColor.adamantPrimary + } - case .sendTokens: - // + cell.accessoryType = .disclosureIndicator + }) + .onCellSelection({ [weak self] (_, row) in let alert = UIAlertController(title: String.adamantLocalized.account.sorryAlert, message: String.adamantLocalized.account.transferNotAllowed, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel, handler: nil)) + let cancel = UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel) { _ in + guard let indexPath = row.indexPath else { + return + } + + self?.tableView.deselectRow(at: indexPath, animated: true) + } + + alert.addAction(cancel) - if let url = self.webAppUrl { - alert.addAction(UIAlertAction(title: String.adamantLocalized.account.webApp, style: .default, handler: { [weak self] _ in + if let url = self?.webAppUrl { + let webApp = UIAlertAction(title: String.adamantLocalized.account.webApp, style: .default) { [weak self] _ in let safari = SFSafariViewController(url: url) safari.preferredControlTintColor = UIColor.adamantPrimary self?.present(safari, animated: true, completion: nil) - })) + } + alert.addAction(webApp) } - present(alert, animated: true, completion: { [weak self] in - self?.tableView.deselectRow(at: indexPath, animated: true) - }) - // + self?.present(alert, animated: true, completion: nil) + }) + + // MARK: ICO + <<< LabelRow() { + $0.tag = Rows.invest.tag + $0.title = Rows.invest.localized + } + .cellSetup({ (cell, _) in + cell.selectionStyle = .gray + }) + .cellUpdate({ (cell, _) in + if let label = cell.textLabel { + label.font = UIFont.adamantPrimary(size: 17) + label.textColor = UIColor.adamantPrimary + } - case .invest: - guard let address = accountService.account?.address, + cell.accessoryType = .disclosureIndicator + }) + .onCellSelection({ [weak self] (_, _) in + guard let address = self?.accountService.account?.address, let url = URL(string: "https://adamant.im/ico/?wallet=\(address)") else { return } let safari = SFSafariViewController(url: url) safari.preferredControlTintColor = UIColor.adamantPrimary - present(safari, animated: true, completion: nil) - return - } - - case .actions: - guard let address = accountService.account?.address else { - return - } + self?.present(safari, animated: true, completion: nil) + }) + + // MARK: Actions section + +++ Section(Sections.actions.localized) - let alert = UIAlertController(title: String.localizedStringWithFormat(String.adamantLocalized.alert.logoutMessageFormat, address), message: nil, preferredStyle: .alert) - let cancel = UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel) { [weak self] _ in - self?.tableView.deselectRow(at: indexPath, animated: true) + <<< LabelRow() { + $0.tag = Rows.logout.tag + $0.title = Rows.logout.localized } - let logout = UIAlertAction(title: String.adamantLocalized.alert.logoutButton, style: .default) { [weak self] _ in - self?.accountService.logout() - if let vc = self?.router.get(scene: AdamantScene.Login.login) { - self?.dialogService.present(vc, animated: true, completion: nil) + .cellSetup({ (cell, _) in + cell.selectionStyle = .gray + }) + .cellUpdate({ (cell, _) in + if let label = cell.textLabel { + label.font = UIFont.adamantPrimary(size: 17) + label.textColor = UIColor.adamantPrimary } - } - - alert.addAction(cancel) - alert.addAction(logout) - present(alert, animated: true, completion: nil) + + cell.accessoryType = .disclosureIndicator + }) + .onCellSelection({ [weak self] (_, row) in + guard let address = self?.accountService.account?.address else { + return + } + + let alert = UIAlertController(title: String.localizedStringWithFormat(String.adamantLocalized.alert.logoutMessageFormat, address), message: nil, preferredStyle: .alert) + let cancel = UIAlertAction(title: String.adamantLocalized.alert.cancel, style: .cancel) { _ in + guard let indexPath = row.indexPath else { + return + } + + self?.tableView.deselectRow(at: indexPath, animated: true) + } + let logout = UIAlertAction(title: String.adamantLocalized.alert.logoutButton, style: .default) { [weak self] _ in + self?.accountService.logout() + if let vc = self?.router.get(scene: AdamantScene.Login.login) { + self?.dialogService.present(vc, animated: true, completion: nil) + } + } + + alert.addAction(cancel) + alert.addAction(logout) + self?.present(alert, animated: true, completion: nil) + }) + + + // MARK: Notifications + NotificationCenter.default.addObserver(forName: .adamantUserLoggedIn, object: nil, queue: OperationQueue.main) { [weak self] _ in + self?.refreshBalanceCell() + } + NotificationCenter.default.addObserver(forName: .adamantUserLoggedOut, object: nil, queue: OperationQueue.main) { [weak self] _ in + self?.refreshBalanceCell() + } + + NotificationCenter.default.addObserver(forName: .adamantAccountDataUpdated, object: nil, queue: OperationQueue.main) { [weak self] _ in + self?.refreshBalanceCell() + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + if let indexPath = tableView.indexPathForSelectedRow { + tableView.deselectRow(at: indexPath, animated: animated) } } + + deinit { + NotificationCenter.default.removeObserver(self) + } } -// MARK: - UITableView Cells +// MARK: - Other extension AccountViewController { - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let account = accountService.account, - let section = Sections(rawValue: indexPath.section) else { - return UITableViewCell(style: .default, reuseIdentifier: nil) - } + private func refreshBalanceCell() { + let address: String? + let balance: String? - let cell: UITableViewCell - if let c = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) { - cell = c + if let account = accountService.account { + address = account.address + balance = AdamantUtilities.format(balance: account.balance) } else { - cell = UITableViewCell(style: .value1, reuseIdentifier: cellIdentifier) - cell.accessoryType = .disclosureIndicator - cell.textLabel?.font = UIFont.adamantPrimary(size: 17) - cell.detailTextLabel?.font = UIFont.adamantPrimary(size: 17) - - cell.textLabel?.textColor = UIColor.adamantPrimary - cell.detailTextLabel?.textColor = UIColor.adamantPrimary - - cell.imageView?.tintColor = UIColor.adamantChatIcons + address = nil + balance = nil } - switch section { - case .account: - cell.textLabel?.text = account.address - cell.detailTextLabel?.text = nil - cell.imageView?.image = #imageLiteral(resourceName: "account") - - case .wallet: - guard let row = WalletRows(rawValue: indexPath.row) else { - break - } - - switch row { - case .balance: - cell.textLabel?.text = String.adamantLocalized.account.rowBalance - cell.detailTextLabel?.text = AdamantUtilities.format(balance: account.balance) - cell.imageView?.image = nil - - case .sendTokens: - cell.textLabel?.text = String.adamantLocalized.account.rowSendTokens - cell.detailTextLabel?.text = nil - cell.imageView?.image = nil - - case .invest: - cell.textLabel?.text = String.adamantLocalized.account.rowInvest - cell.detailTextLabel?.text = nil - cell.imageView?.image = nil - } - - case .actions: - cell.textLabel?.text = String.adamantLocalized.account.rowLogout - cell.detailTextLabel?.text = nil - cell.imageView?.image = nil + if let row: AccountRow = form.rowBy(tag: Rows.account.tag) { + row.value = address + row.reload() } - return cell - } - - func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - guard let sect = Sections(rawValue: section) else { - return nil + if let row: LabelRow = form.rowBy(tag: Rows.balance.tag) { + row.value = balance + row.reload() } - - switch sect { - case .account: - return String.adamantLocalized.account.sectionAccount - - case .wallet: - return String.adamantLocalized.account.sectionWallet - - case .actions: - return String.adamantLocalized.account.sectionActions - } - } - - private func refreshBalanceCell() { - guard let account = accountService.account, - let cell = tableView.cellForRow(at: IndexPath(row: WalletRows.balance.rawValue, section: Sections.wallet.rawValue)) else { - return - } - - cell.detailTextLabel?.text = AdamantUtilities.format(balance: account.balance) } } diff --git a/Adamant/Stories/Settings/SettingsViewController+StayIn.swift b/Adamant/Stories/Settings/SettingsViewController+StayIn.swift index e6113e648..d8dc9b7d6 100644 --- a/Adamant/Stories/Settings/SettingsViewController+StayIn.swift +++ b/Adamant/Stories/Settings/SettingsViewController+StayIn.swift @@ -232,10 +232,8 @@ extension SettingsViewController: PinpadViewControllerDelegate { switch pinpadRequest { // MARK: User canceled turning on StayIn - case PinpadRequest.createPin?: - fallthrough - - case PinpadRequest.reenterPin(pin: _)?: + case PinpadRequest.createPin?, + PinpadRequest.reenterPin(pin: _)?: if let row: SwitchRow = form.rowBy(tag: Rows.stayLoggedIn.tag) { row.value = false row.updateCell() From 3fcfd286bc348f8bf875b75a177e9b3ba1eb675f Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 22:04:23 +0300 Subject: [PATCH 06/13] Fixed new messages count on logout. --- .../Account/AccountViewController.swift | 2 +- .../Chats/ChatListViewController.swift | 33 +++++++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Adamant/Stories/Account/AccountViewController.swift b/Adamant/Stories/Account/AccountViewController.swift index 92f194926..25c9e5670 100644 --- a/Adamant/Stories/Account/AccountViewController.swift +++ b/Adamant/Stories/Account/AccountViewController.swift @@ -119,7 +119,7 @@ class AccountViewController: FormViewController { // MARK: Account Section form +++ Section(Sections.account.localized) - <<< AccountRow() { [weak self] in + <<< AccountRow() { $0.tag = Rows.account.tag $0.cell.height = {65} } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index 4f1ec9b82..09fb323d2 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -65,6 +65,7 @@ class ChatListViewController: UIViewController { self?.tableView.reloadData() } NotificationCenter.default.addObserver(forName: .adamantUserLoggedOut, object: nil, queue: OperationQueue.main) { [weak self] _ in + self?.setBadgeValue(nil) self?.chatsController = nil self?.tableView.reloadData() } @@ -207,18 +208,7 @@ extension ChatListViewController: NSFetchedResultsControllerDelegate { tableView.endUpdates() case let c where c == unreadController: - let item: UITabBarItem - if let i = navigationController?.tabBarItem { - item = i - } else { - item = tabBarItem - } - - if let count = controller.fetchedObjects?.count, count > 0 { - item.badgeValue = String(count) - } else { - item.badgeValue = nil - } + setBadgeValue(controller.fetchedObjects?.count) default: break @@ -318,8 +308,25 @@ extension ChatListViewController: ChatViewControllerDelegate { } -// MARK: - Current chat +// MARK: - Tools extension ChatListViewController { + /// TabBar item badge + func setBadgeValue(_ value: Int?) { + let item: UITabBarItem + if let i = navigationController?.tabBarItem { + item = i + } else { + item = tabBarItem + } + + if let value = value, value > 0 { + item.badgeValue = String(value) + } else { + item.badgeValue = nil + } + } + + /// Current chat func presentedChatroom() -> Chatroom? { // Showing another page guard tabBarController?.selectedViewController == self else { From 020c728ec0309cf1b9b3b084091d051140eb498c Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 22:28:37 +0300 Subject: [PATCH 07/13] SharedCells cleaned. --- Adamant.xcodeproj/project.pbxproj | 26 +++---- .../RoundAvatarTableViewCell.swift | 62 ---------------- .../SharedCells/RoundAvatarTableViewCell.xib | 73 ------------------- .../Chats/ChatListViewController.swift | 12 +-- .../Chats}/ChatTableViewCell.swift | 6 -- .../Chats}/ChatTableViewCell.xib | 0 Adamant/Stories/Chats/ChatsRoutes.swift | 1 - .../TransactionTableViewCell.swift | 6 -- .../TransactionTableViewCell.xib | 0 .../Transactions/TransactionsRoutes.swift | 1 - .../TransactionsViewController.swift | 11 +-- 11 files changed, 21 insertions(+), 177 deletions(-) delete mode 100644 Adamant/SharedCells/RoundAvatarTableViewCell.swift delete mode 100644 Adamant/SharedCells/RoundAvatarTableViewCell.xib rename Adamant/{SharedCells => Stories/Chats}/ChatTableViewCell.swift (89%) rename Adamant/{SharedCells => Stories/Chats}/ChatTableViewCell.xib (100%) rename Adamant/{SharedCells => Stories/Transactions}/TransactionTableViewCell.swift (84%) rename Adamant/{SharedCells => Stories/Transactions}/TransactionTableViewCell.xib (100%) diff --git a/Adamant.xcodeproj/project.pbxproj b/Adamant.xcodeproj/project.pbxproj index 8224fd19a..589dd859c 100644 --- a/Adamant.xcodeproj/project.pbxproj +++ b/Adamant.xcodeproj/project.pbxproj @@ -127,8 +127,6 @@ E9E7CDB32002B9FB00DFC4DB /* LoginRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDB22002B9FB00DFC4DB /* LoginRoutes.swift */; }; E9E7CDB52002BA6900DFC4DB /* SwinjectedRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDB42002BA6900DFC4DB /* SwinjectedRouter.swift */; }; E9E7CDB72003994E00DFC4DB /* AdamantUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDB62003994E00DFC4DB /* AdamantUtilities.swift */; }; - E9E7CDBB2003AAA700DFC4DB /* RoundAvatarTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDB92003AAA700DFC4DB /* RoundAvatarTableViewCell.swift */; }; - E9E7CDBC2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9E7CDBA2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib */; }; E9E7CDBE2003AEFB00DFC4DB /* CellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDBD2003AEFB00DFC4DB /* CellFactory.swift */; }; E9E7CDC02003AF6D00DFC4DB /* AdamantCellFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDBF2003AF6D00DFC4DB /* AdamantCellFactory.swift */; }; E9E7CDC22003F5A400DFC4DB /* TransactionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E7CDC12003F5A400DFC4DB /* TransactionsViewController.swift */; }; @@ -306,8 +304,6 @@ E9E7CDB22002B9FB00DFC4DB /* LoginRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginRoutes.swift; sourceTree = ""; }; E9E7CDB42002BA6900DFC4DB /* SwinjectedRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwinjectedRouter.swift; sourceTree = ""; }; E9E7CDB62003994E00DFC4DB /* AdamantUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdamantUtilities.swift; sourceTree = ""; }; - E9E7CDB92003AAA700DFC4DB /* RoundAvatarTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundAvatarTableViewCell.swift; sourceTree = ""; }; - E9E7CDBA2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RoundAvatarTableViewCell.xib; sourceTree = ""; }; E9E7CDBD2003AEFB00DFC4DB /* CellFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFactory.swift; sourceTree = ""; }; E9E7CDBF2003AF6D00DFC4DB /* AdamantCellFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdamantCellFactory.swift; sourceTree = ""; }; E9E7CDC12003F5A400DFC4DB /* TransactionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsViewController.swift; sourceTree = ""; }; @@ -526,10 +522,12 @@ isa = PBXGroup; children = ( E94E7B05205D48B20042B639 /* TransactionsRoutes.swift */, - E94E7B0B205D5E4A0042B639 /* TransactionsViewController.xib */, E9E7CDC12003F5A400DFC4DB /* TransactionsViewController.swift */, - E94E7B0D205D5EA80042B639 /* TransactionDetailsViewController.xib */, + E94E7B0B205D5E4A0042B639 /* TransactionsViewController.xib */, E9EC34132005178500C0E546 /* TransactionDetailsViewController.swift */, + E94E7B0D205D5EA80042B639 /* TransactionDetailsViewController.xib */, + E9E7CDC52003F6D200DFC4DB /* TransactionTableViewCell.swift */, + E9E7CDC62003F6D200DFC4DB /* TransactionTableViewCell.xib */, ); path = Transactions; sourceTree = ""; @@ -559,10 +557,12 @@ isa = PBXGroup; children = ( E95F857E2008C8D60070534A /* ChatsRoutes.swift */, - E94E7B00205D3F090042B639 /* ChatListViewController.xib */, E95F85842008CB3A0070534A /* ChatListViewController.swift */, + E94E7B00205D3F090042B639 /* ChatListViewController.xib */, E93EFE12200D1156000BB482 /* ChatViewController.swift */, E9C51EF02013F18000385EB7 /* NewChatViewController.swift */, + E95F85C5200A9B070070534A /* ChatTableViewCell.swift */, + E95F85C6200A9B070070534A /* ChatTableViewCell.xib */, ); path = Chats; sourceTree = ""; @@ -669,8 +669,8 @@ isa = PBXGroup; children = ( E9E7CDB02002B97B00DFC4DB /* AccountRoutes.swift */, - E94E7B09205D59F50042B639 /* AccountViewController.xib */, E9E7CDAA2002AFA500DFC4DB /* AccountViewController.swift */, + E94E7B09205D59F50042B639 /* AccountViewController.xib */, E9EC342020052ABB00C0E546 /* TransferViewController.swift */, ); path = Account; @@ -679,12 +679,6 @@ E9E7CDB82003AA8E00DFC4DB /* SharedCells */ = { isa = PBXGroup; children = ( - E95F85C5200A9B070070534A /* ChatTableViewCell.swift */, - E95F85C6200A9B070070534A /* ChatTableViewCell.xib */, - E9E7CDB92003AAA700DFC4DB /* RoundAvatarTableViewCell.swift */, - E9E7CDBA2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib */, - E9E7CDC52003F6D200DFC4DB /* TransactionTableViewCell.swift */, - E9E7CDC62003F6D200DFC4DB /* TransactionTableViewCell.xib */, E9942B86203D9E5100C163AF /* EurekaQRRow.swift */, E9942B88203D9ECA00C163AF /* QrCell.xib */, E95CB462205D8BBA00A7218E /* EurekaAccountRow.swift */, @@ -713,8 +707,8 @@ E9FAE5DB203ECD41008D3A6B /* Shared */ = { isa = PBXGroup; children = ( - E9FAE5E1203ED1AE008D3A6B /* ShareQrViewController.xib */, E9FAE5E0203ED1AE008D3A6B /* ShareQrViewController.swift */, + E9FAE5E1203ED1AE008D3A6B /* ShareQrViewController.xib */, E94E7B07205D4CB80042B639 /* SharedRoutes.swift */, ); path = Shared; @@ -814,7 +808,6 @@ E9256F762039A9A200DE86E9 /* LaunchScreen.storyboard in Resources */, E95CB451205D77B200A7218E /* InfoPlist.strings in Resources */, E9EC341B200524CA00C0E546 /* Roboto_300_normal.ttf in Resources */, - E9E7CDBC2003AAA700DFC4DB /* RoundAvatarTableViewCell.xib in Resources */, E95F85C8200A9B070070534A /* ChatTableViewCell.xib in Resources */, E913C8F91FFFA51D001A83F7 /* Assets.xcassets in Resources */, E9EC341F200524CA00C0E546 /* Roboto_700_normal.ttf in Resources */, @@ -979,7 +972,6 @@ E9393FAA2055D03300EE6F30 /* AdamantMessage.swift in Sources */, E90A494D204DA932009F6A65 /* LocalAuthentication.swift in Sources */, E95F856F2007B61D0070534A /* GetPublicKeyResponse.swift in Sources */, - E9E7CDBB2003AAA700DFC4DB /* RoundAvatarTableViewCell.swift in Sources */, E9E7CDAF2002B8A100DFC4DB /* Router.swift in Sources */, E9E7CDC72003F6D200DFC4DB /* TransactionTableViewCell.swift in Sources */, E9B3D3A9202082450019EB36 /* AdamantTransfersProvider.swift in Sources */, diff --git a/Adamant/SharedCells/RoundAvatarTableViewCell.swift b/Adamant/SharedCells/RoundAvatarTableViewCell.swift deleted file mode 100644 index b094ed53f..000000000 --- a/Adamant/SharedCells/RoundAvatarTableViewCell.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// RoundAvatarTableViewCell.swift -// Adamant -// -// Created by Anokhov Pavel on 08.01.2018. -// Copyright © 2018 Adamant. All rights reserved. -// - -import UIKit - -extension SharedCell { - static let RoundAvatarCell = SharedCell(cellIdentifier: "roundAvatar", - xibName: "RoundAvatarTableViewCell", - rowHeight: 72) -} - -class RoundAvatarTableViewCell: UITableViewCell { - - - // MARK: - IBOutlets - - @IBOutlet weak var avatarImageView: UIImageView! - @IBOutlet weak var mainTextLabel: UILabel! - @IBOutlet weak var detailsTextLabel: UILabel! - - - // MARK: - Properties - - var mainText: String? { - didSet { - if let text = mainText, text.count > 0 { - mainTextLabel.isHidden = false - mainTextLabel.text = text - } else { - mainTextLabel.isHidden = true - } - } - } - - var detailsText: String? { - didSet { - if let text = detailsText, text.count > 0 { - detailsTextLabel.isHidden = false - detailsTextLabel.text = text - } else { - detailsTextLabel.isHidden = true - } - } - } - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - -} diff --git a/Adamant/SharedCells/RoundAvatarTableViewCell.xib b/Adamant/SharedCells/RoundAvatarTableViewCell.xib deleted file mode 100644 index 774f692ca..000000000 --- a/Adamant/SharedCells/RoundAvatarTableViewCell.xib +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - Exo2-Regular - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index 09fb323d2..8dfbdb47d 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -18,10 +18,12 @@ extension String.adamantLocalized { } class ChatListViewController: UIViewController { + let cellIdentifier = "cell" + let cellHeight: CGFloat = 74.0 + // MARK: Dependencies var accountService: AccountService! var chatsProvider: ChatsProvider! - var cellFactory: CellFactory! var router: Router! // MARK: IBOutlet @@ -32,7 +34,6 @@ class ChatListViewController: UIViewController { var chatsController: NSFetchedResultsController? var unreadController: NSFetchedResultsController? - let chatCell = SharedCell.ChatCell.cellIdentifier private var preservedMessagess = [String:String]() @@ -45,7 +46,7 @@ class ChatListViewController: UIViewController { // MARK: TableView tableView.dataSource = self tableView.delegate = self - tableView.register(cellFactory.nib(for: SharedCell.ChatCell), forCellReuseIdentifier: chatCell) + tableView.register(UINib(nibName: "ChatTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier) chatsController = chatsProvider.getChatroomsController() chatsController?.delegate = self @@ -121,7 +122,7 @@ extension ChatListViewController: UITableViewDelegate, UITableViewDataSource { } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return SharedCell.ChatCell.defaultRowHeight + return cellHeight } func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { @@ -145,7 +146,7 @@ extension ChatListViewController: UITableViewDelegate, UITableViewDataSource { // MARK: - UITableView Cells extension ChatListViewController { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: chatCell, for: indexPath) as! ChatTableViewCell + let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! ChatTableViewCell cell.accessoryType = .disclosureIndicator cell.accountLabel.textColor = UIColor.adamantPrimary @@ -202,7 +203,6 @@ extension ChatListViewController: NSFetchedResultsControllerDelegate { } func controllerDidChangeContent(_ controller: NSFetchedResultsController) { - switch controller { case let c where c == chatsController: tableView.endUpdates() diff --git a/Adamant/SharedCells/ChatTableViewCell.swift b/Adamant/Stories/Chats/ChatTableViewCell.swift similarity index 89% rename from Adamant/SharedCells/ChatTableViewCell.swift rename to Adamant/Stories/Chats/ChatTableViewCell.swift index fda2d705a..2d0c3cfd4 100644 --- a/Adamant/SharedCells/ChatTableViewCell.swift +++ b/Adamant/Stories/Chats/ChatTableViewCell.swift @@ -9,12 +9,6 @@ import UIKit import FreakingSimpleRoundImageView -extension SharedCell { - static let ChatCell = SharedCell(cellIdentifier: "chatCell", - xibName: "ChatTableViewCell", - rowHeight: 74) -} - class ChatTableViewCell: UITableViewCell { // MARK: - IBOutlets @IBOutlet weak var avatarImageView: RoundImageView! diff --git a/Adamant/SharedCells/ChatTableViewCell.xib b/Adamant/Stories/Chats/ChatTableViewCell.xib similarity index 100% rename from Adamant/SharedCells/ChatTableViewCell.xib rename to Adamant/Stories/Chats/ChatTableViewCell.xib diff --git a/Adamant/Stories/Chats/ChatsRoutes.swift b/Adamant/Stories/Chats/ChatsRoutes.swift index 8f9c6d253..88b3b2f65 100644 --- a/Adamant/Stories/Chats/ChatsRoutes.swift +++ b/Adamant/Stories/Chats/ChatsRoutes.swift @@ -14,7 +14,6 @@ extension AdamantScene { let c = ChatListViewController(nibName: "ChatListViewController", bundle: nil) c.accountService = r.resolve(AccountService.self) c.chatsProvider = r.resolve(ChatsProvider.self) - c.cellFactory = r.resolve(CellFactory.self) c.router = r.resolve(Router.self) return c }) diff --git a/Adamant/SharedCells/TransactionTableViewCell.swift b/Adamant/Stories/Transactions/TransactionTableViewCell.swift similarity index 84% rename from Adamant/SharedCells/TransactionTableViewCell.swift rename to Adamant/Stories/Transactions/TransactionTableViewCell.swift index b5c3eb0ff..1930e6b33 100644 --- a/Adamant/SharedCells/TransactionTableViewCell.swift +++ b/Adamant/Stories/Transactions/TransactionTableViewCell.swift @@ -8,12 +8,6 @@ import UIKit -extension SharedCell { - static let TransactionCell = SharedCell(cellIdentifier: "transactionCell", - xibName: "TransactionTableViewCell", - rowHeight: 90) -} - class TransactionTableViewCell: UITableViewCell { enum TransactionType { diff --git a/Adamant/SharedCells/TransactionTableViewCell.xib b/Adamant/Stories/Transactions/TransactionTableViewCell.xib similarity index 100% rename from Adamant/SharedCells/TransactionTableViewCell.xib rename to Adamant/Stories/Transactions/TransactionTableViewCell.xib diff --git a/Adamant/Stories/Transactions/TransactionsRoutes.swift b/Adamant/Stories/Transactions/TransactionsRoutes.swift index 62d664a66..816e86d98 100644 --- a/Adamant/Stories/Transactions/TransactionsRoutes.swift +++ b/Adamant/Stories/Transactions/TransactionsRoutes.swift @@ -12,7 +12,6 @@ extension AdamantScene { struct Transactions { static let transactions = AdamantScene(identifier: "TransactionsViewController", factory: { r in let c = TransactionsViewController(nibName: "TransactionsViewController", bundle: nil) - c.cellFactory = r.resolve(CellFactory.self) c.transfersProvider = r.resolve(TransfersProvider.self) c.router = r.resolve(Router.self) return c diff --git a/Adamant/Stories/Transactions/TransactionsViewController.swift b/Adamant/Stories/Transactions/TransactionsViewController.swift index fec6826b0..bfd0555d9 100644 --- a/Adamant/Stories/Transactions/TransactionsViewController.swift +++ b/Adamant/Stories/Transactions/TransactionsViewController.swift @@ -10,8 +10,10 @@ import UIKit import CoreData class TransactionsViewController: UIViewController { + let cellIdentifier = "cell" + let cellHeight: CGFloat = 90.0 + // MARK: - Dependencies - var cellFactory: CellFactory! var transfersProvider: TransfersProvider! var router: Router! @@ -31,8 +33,7 @@ class TransactionsViewController: UIViewController { controller = transfersProvider.transfersController() controller?.delegate = self - - tableView.register(cellFactory.nib(for: .TransactionCell), forCellReuseIdentifier: SharedCell.TransactionCell.cellIdentifier) + tableView.register(UINib.init(nibName: "TransactionTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier) tableView.dataSource = self tableView.delegate = self @@ -93,7 +94,7 @@ extension TransactionsViewController: UITableViewDataSource, UITableViewDelegate } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return SharedCell.TransactionCell.defaultRowHeight + return cellHeight } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -111,7 +112,7 @@ extension TransactionsViewController: UITableViewDataSource, UITableViewDelegate } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = tableView.dequeueReusableCell(withIdentifier: SharedCell.TransactionCell.cellIdentifier, for: indexPath) as? TransactionTableViewCell, + guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? TransactionTableViewCell, let transfer = controller?.object(at: indexPath) else { // TODO: Display & Log error return UITableViewCell(style: .default, reuseIdentifier: "cell") From 8c53f64865717c220d1e763f5e5d4843ac216324 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 22:40:41 +0300 Subject: [PATCH 08/13] Localization comments. --- Adamant/Assets/l18n/en.lproj/InfoPlist.strings | 10 +++++----- Adamant/Assets/l18n/ru.lproj/InfoPlist.strings | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Adamant/Assets/l18n/en.lproj/InfoPlist.strings b/Adamant/Assets/l18n/en.lproj/InfoPlist.strings index 721f889b9..3e17b555a 100644 --- a/Adamant/Assets/l18n/en.lproj/InfoPlist.strings +++ b/Adamant/Assets/l18n/en.lproj/InfoPlist.strings @@ -1,15 +1,15 @@ -/* (No Comment) */ +/* The user-visible name of the bundle; used by Siri and visible on the Home screen in iOS. */ "CFBundleDisplayName" = "Adamant"; -/* (No Comment) */ +/* The short name of the bundle, which may be displayed to users in situations such as the absence of a value for CFBundleDisplayName. This name should be less than 16 characters long. */ "CFBundleName" = "Adamant"; -/* (No Comment) */ +/* Camera authorization reason */ "NSCameraUsageDescription" = "The camera needed to scan QR codes for addresses and passphrases"; -/* (No Comment) */ +/* Readonly access to photolibrary reason */ "NSPhotoLibraryAddUsageDescription" = "Saving generated QR codes with passphrases and addresses"; -/* (No Comment) */ +/* ReadWrite access to photolibrary reason */ "NSPhotoLibraryUsageDescription" = "Reading QR codes with passphrases and addresses"; diff --git a/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings index 6d1e286a6..f2899cd2a 100644 --- a/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings +++ b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings @@ -1,15 +1,15 @@ -/* (No Comment) */ +/* The user-visible name of the bundle; used by Siri and visible on the Home screen in iOS. */ "CFBundleDisplayName" = "Адамант"; -/* (No Comment) */ +/* The short name of the bundle, which may be displayed to users in situations such as the absence of a value for CFBundleDisplayName. This name should be less than 16 characters long. */ "CFBundleName" = "Адамант"; -/* (No Comment) */ +/* Camera authorization reason */ "NSCameraUsageDescription" = "Чтения QR-кодов с адресами и паролями"; -/* (No Comment) */ +/* Readonly access to photolibrary reason */ "NSPhotoLibraryAddUsageDescription" = "Сохранение созданных QR-кодов"; -/* (No Comment) */ +/* ReadWrite access to photolibrary reason */ "NSPhotoLibraryUsageDescription" = "Сканирование QR-кодов с адресами и паролями со сделанных ранее фотографий"; From 38bb95aa68a93c4959183bb18dc64ceb28ed49e4 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sat, 17 Mar 2018 23:48:36 +0300 Subject: [PATCH 09/13] Better fetchedResults controllers handling --- .../DataProviders/ChatsProvider.swift | 6 +-- .../DataProviders/AdamantChatsProvider.swift | 33 +++--------- .../AdamantTransfersProvider.swift | 4 +- .../Chats/ChatListViewController.swift | 50 +++++++++++++------ .../Stories/Chats/ChatViewController.swift | 6 +++ .../Transactions/TransactionsRoutes.swift | 1 + .../TransactionsViewController.swift | 30 +++++++++-- 7 files changed, 80 insertions(+), 50 deletions(-) diff --git a/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift b/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift index 8b7ba8324..f028cf4ca 100644 --- a/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift +++ b/Adamant/ServiceProtocols/DataProviders/ChatsProvider.swift @@ -75,11 +75,11 @@ protocol ChatsProvider: DataProvider { var readedLastHeight: Int64? { get } // MARK: - Getting chats and messages - func getChatroomsController() -> NSFetchedResultsController? - func getChatController(for chatroom: Chatroom) -> NSFetchedResultsController? + func getChatroomsController() -> NSFetchedResultsController + func getChatController(for chatroom: Chatroom) -> NSFetchedResultsController /// Unread messages controller. Sections by chatroom. - func getUnreadMessagesController() -> NSFetchedResultsController? + func getUnreadMessagesController() -> NSFetchedResultsController /// Returns asociated with account chatroom, or create new, in viewContext func chatroomWith(_ account: CoreDataAccount) -> Chatroom diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 53b7acb72..314724352 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -344,24 +344,18 @@ extension AdamantChatsProvider { // MARK: - Getting messages extension AdamantChatsProvider { - func getChatroomsController() -> NSFetchedResultsController? { + func getChatroomsController() -> NSFetchedResultsController { let request: NSFetchRequest = NSFetchRequest(entityName: Chatroom.entityName) request.sortDescriptors = [NSSortDescriptor(key: "updatedAt", ascending: false)] request.predicate = NSPredicate(format: "partner!=nil") let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: stack.container.viewContext, sectionNameKeyPath: nil, cacheName: nil) - do { - try controller.performFetch() - return controller - } catch { - print("Error fetching request: \(error)") - return nil - } + return controller } - func getChatController(for chatroom: Chatroom) -> NSFetchedResultsController? { + func getChatController(for chatroom: Chatroom) -> NSFetchedResultsController { guard let context = chatroom.managedObjectContext else { - return nil + fatalError() } let request: NSFetchRequest = NSFetchRequest(entityName: ChatTransaction.entityName) @@ -369,13 +363,7 @@ extension AdamantChatsProvider { request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil) - do { - try controller.performFetch() - return controller - } catch { - print("Error fetching request: \(error)") - return nil - } + return controller } func chatroomWith(_ account: CoreDataAccount) -> Chatroom { @@ -400,21 +388,14 @@ extension AdamantChatsProvider { return chatroom } - func getUnreadMessagesController() -> NSFetchedResultsController? { + func getUnreadMessagesController() -> NSFetchedResultsController { let request = NSFetchRequest(entityName: ChatTransaction.entityName) request.predicate = NSPredicate(format: "isUnread == true") request.sortDescriptors = [NSSortDescriptor.init(key: "date", ascending: false)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: stack.container.viewContext, sectionNameKeyPath: "chatroom.partner.address", cacheName: nil) - controller.section - do { - try controller.performFetch() - return controller - } catch { - print("Error fetching unread messages: \(error)") - return nil - } + return controller } } diff --git a/Adamant/Services/DataProviders/AdamantTransfersProvider.swift b/Adamant/Services/DataProviders/AdamantTransfersProvider.swift index a5e1efaa6..06c762d77 100644 --- a/Adamant/Services/DataProviders/AdamantTransfersProvider.swift +++ b/Adamant/Services/DataProviders/AdamantTransfersProvider.swift @@ -179,7 +179,7 @@ extension AdamantTransfersProvider { let request = NSFetchRequest(entityName: TransferTransaction.entityName) request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: stack.container.viewContext, sectionNameKeyPath: nil, cacheName: nil) - try! controller.performFetch() + return controller } @@ -188,7 +188,7 @@ extension AdamantTransfersProvider { request.predicate = NSPredicate(format: "isUnread == true") request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)] let controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: stack.container.viewContext, sectionNameKeyPath: nil, cacheName: nil) - try! controller.performFetch() + return controller } diff --git a/Adamant/Stories/Chats/ChatListViewController.swift b/Adamant/Stories/Chats/ChatListViewController.swift index 8dfbdb47d..388af0bc8 100644 --- a/Adamant/Stories/Chats/ChatListViewController.swift +++ b/Adamant/Stories/Chats/ChatListViewController.swift @@ -48,27 +48,16 @@ class ChatListViewController: UIViewController { tableView.delegate = self tableView.register(UINib(nibName: "ChatTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier) - chatsController = chatsProvider.getChatroomsController() - chatsController?.delegate = self - unreadController = chatsProvider.getUnreadMessagesController() - unreadController?.delegate = self - - tableView.reloadData() + if self.accountService.account != nil { + initFetchedRequestControllers(provider: chatsProvider) + } // MARK: Login/Logout NotificationCenter.default.addObserver(forName: .adamantUserLoggedIn, object: nil, queue: OperationQueue.main) { [weak self] _ in - guard let controller = self?.chatsProvider.getChatroomsController() else { - return - } - - controller.delegate = self - self?.chatsController = controller - self?.tableView.reloadData() + self?.initFetchedRequestControllers(provider: self?.chatsProvider) } NotificationCenter.default.addObserver(forName: .adamantUserLoggedOut, object: nil, queue: OperationQueue.main) { [weak self] _ in - self?.setBadgeValue(nil) - self?.chatsController = nil - self?.tableView.reloadData() + self?.initFetchedRequestControllers(provider: nil) } } @@ -108,6 +97,35 @@ class ChatListViewController: UIViewController { vc.chatroom = chatroom vc.delegate = self } + + + /// - Parameter provider: nil to drop controllers and reset table + private func initFetchedRequestControllers(provider: ChatsProvider?) { + guard let provider = provider else { + chatsController = nil + unreadController = nil + tableView.reloadData() + return + } + + chatsController = provider.getChatroomsController() + unreadController = provider.getUnreadMessagesController() + + chatsController?.delegate = self + unreadController?.delegate = self + + do { + try chatsController?.performFetch() + try unreadController?.performFetch() + } catch { + chatsController = nil + unreadController = nil + print("There was an error performing fetch: \(error)") + } + + tableView.reloadData() + setBadgeValue(unreadController?.fetchedObjects?.count) + } } diff --git a/Adamant/Stories/Chats/ChatViewController.swift b/Adamant/Stories/Chats/ChatViewController.swift index 634549457..679f5f90a 100644 --- a/Adamant/Stories/Chats/ChatViewController.swift +++ b/Adamant/Stories/Chats/ChatViewController.swift @@ -89,6 +89,12 @@ class ChatViewController: MessagesViewController { controller.delegate = self self?.chatController = controller + + do { + try controller.performFetch() + } catch { + print("There was an error performing fetch: \(error)") + } if let collection = self?.messagesCollectionView { DispatchQueue.main.async { diff --git a/Adamant/Stories/Transactions/TransactionsRoutes.swift b/Adamant/Stories/Transactions/TransactionsRoutes.swift index 816e86d98..cadb08796 100644 --- a/Adamant/Stories/Transactions/TransactionsRoutes.swift +++ b/Adamant/Stories/Transactions/TransactionsRoutes.swift @@ -12,6 +12,7 @@ extension AdamantScene { struct Transactions { static let transactions = AdamantScene(identifier: "TransactionsViewController", factory: { r in let c = TransactionsViewController(nibName: "TransactionsViewController", bundle: nil) + c.accountService = r.resolve(AccountService.self) c.transfersProvider = r.resolve(TransfersProvider.self) c.router = r.resolve(Router.self) return c diff --git a/Adamant/Stories/Transactions/TransactionsViewController.swift b/Adamant/Stories/Transactions/TransactionsViewController.swift index bfd0555d9..0d5a30adb 100644 --- a/Adamant/Stories/Transactions/TransactionsViewController.swift +++ b/Adamant/Stories/Transactions/TransactionsViewController.swift @@ -14,6 +14,7 @@ class TransactionsViewController: UIViewController { let cellHeight: CGFloat = 90.0 // MARK: - Dependencies + var accountService: AccountService! var transfersProvider: TransfersProvider! var router: Router! @@ -30,14 +31,21 @@ class TransactionsViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - controller = transfersProvider.transfersController() - controller?.delegate = self + if accountService.account != nil { + initFetchedResultController(provider: transfersProvider) + } tableView.register(UINib.init(nibName: "TransactionTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier) tableView.dataSource = self tableView.delegate = self - tableView.reloadData() + NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedIn, object: nil, queue: nil) { [weak self] notification in + self?.initFetchedResultController(provider: self?.transfersProvider) + } + + NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedOut, object: nil, queue: nil) { [weak self] _ in + self?.initFetchedResultController(provider: nil) + } } override func viewWillAppear(_ animated: Bool) { @@ -46,6 +54,22 @@ class TransactionsViewController: UIViewController { tableView.deselectRow(at: indexPath, animated: animated) } } + + + /// - Parameter provider: nil to drop and reset + private func initFetchedResultController(provider: TransfersProvider?) { + controller = transfersProvider.transfersController() + controller?.delegate = self + + do { + try controller?.performFetch() + } catch { + print("There was an error performing fetch: \(error)") + controller = nil + } + + tableView.reloadData() + } } // MARK: - UITableView Cells From 1d006351c1ac372809c77221e52ba86e55ee0a02 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sun, 18 Mar 2018 00:09:47 +0300 Subject: [PATCH 10/13] Fixed saving & loading readedMessageHeight. --- .../DataProviders/AdamantChatsProvider.swift | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 314724352..0ed409030 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -34,13 +34,28 @@ class AdamantChatsProvider: ChatsProvider { // MARK: Lifecycle init() { NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedIn, object: nil, queue: nil) { [weak self] notification in - self?.update() + guard let store = self?.securedStore else { + return + } + + guard let loggedAddress = notification.userInfo?[AdamantUserInfoKey.AccountService.loggedAccountAddress] as? String else { + store.remove(StoreKey.chatProvider.address) + store.remove(StoreKey.chatProvider.receivedLastHeight) + store.remove(StoreKey.chatProvider.readedLastHeight) + return + } - if let address = notification.userInfo?[AdamantUserInfoKey.AccountService.loggedAccountAddress] as? String { - self?.securedStore.set(address, for: StoreKey.chatProvider.address) + if let savedAddress = self?.securedStore.get(StoreKey.chatProvider.address), savedAddress == loggedAddress { + if let raw = store.get(StoreKey.chatProvider.readedLastHeight), let h = Int64(raw) { + self?.readedLastHeight = h + } } else { - print("Can't get logged address.") + store.remove(StoreKey.chatProvider.receivedLastHeight) + store.remove(StoreKey.chatProvider.readedLastHeight) + store.set(loggedAddress, for: StoreKey.chatProvider.address) } + + self?.update() } NotificationCenter.default.addObserver(forName: Notification.Name.adamantUserLoggedOut, object: nil, queue: nil) { [weak self] _ in @@ -100,8 +115,11 @@ extension AdamantChatsProvider { private func reset(notify: Bool) { let prevState = self.state setState(.updating, previous: prevState, notify: false) // Block update calls + receivedLastHeight = nil readedLastHeight = nil + securedStore.remove(StoreKey.chatProvider.receivedLastHeight) + securedStore.remove(StoreKey.chatProvider.readedLastHeight) let chatrooms = NSFetchRequest(entityName: Chatroom.entityName) let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) @@ -172,8 +190,14 @@ extension AdamantChatsProvider { self?.readedLastHeight = self?.receivedLastHeight - if let h = self?.receivedLastHeight, let store = self?.securedStore { - store.set(String(h), for: StoreKey.chatProvider.receivedLastHeight) + if let store = self?.securedStore { + if let h = self?.receivedLastHeight { + store.set(String(h), for: StoreKey.chatProvider.receivedLastHeight) + } + + if let h = self?.readedLastHeight { + store.set(String(h), for: StoreKey.chatProvider.readedLastHeight) + } } } } From 3e8d5584c2a0422f2b4058091b256544a4e3f207 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sun, 18 Mar 2018 00:20:28 +0300 Subject: [PATCH 11/13] All messages as unread for logged account fixed. --- .../DataProviders/AdamantChatsProvider.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Adamant/Services/DataProviders/AdamantChatsProvider.swift b/Adamant/Services/DataProviders/AdamantChatsProvider.swift index 0ed409030..59650bc18 100644 --- a/Adamant/Services/DataProviders/AdamantChatsProvider.swift +++ b/Adamant/Services/DataProviders/AdamantChatsProvider.swift @@ -188,14 +188,18 @@ extension AdamantChatsProvider { userInfo: [AdamantUserInfoKey.ChatProvider.lastMessageHeight:h]) } - self?.readedLastHeight = self?.receivedLastHeight + if let h = self?.receivedLastHeight { + self?.readedLastHeight = h + } else { + self?.readedLastHeight = 0 + } if let store = self?.securedStore { if let h = self?.receivedLastHeight { store.set(String(h), for: StoreKey.chatProvider.receivedLastHeight) } - if let h = self?.readedLastHeight { + if let h = self?.readedLastHeight, h > 0 { store.set(String(h), for: StoreKey.chatProvider.readedLastHeight) } } @@ -638,12 +642,6 @@ extension AdamantChatsProvider { chatroom.hasUnreadMessages = true trs.forEach({$0.isUnread = true}) } - } else { - let msgs = Dictionary(grouping: newChatTransactions, by: ({ (t: ChatTransaction) -> Chatroom in t.chatroom!})) - for (chatroom, trs) in msgs { - chatroom.hasUnreadMessages = true - trs.forEach({$0.isUnread = true}) - } } From 9b53c1d3bc293153b17f26f60a02167bed55ff18 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sun, 18 Mar 2018 00:28:44 +0300 Subject: [PATCH 12/13] typo --- Adamant/Assets/l18n/ru.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings index f2899cd2a..2fc51ea3b 100644 --- a/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings +++ b/Adamant/Assets/l18n/ru.lproj/InfoPlist.strings @@ -5,7 +5,7 @@ "CFBundleName" = "Адамант"; /* Camera authorization reason */ -"NSCameraUsageDescription" = "Чтения QR-кодов с адресами и паролями"; +"NSCameraUsageDescription" = "Чтение QR-кодов с адресами и паролями"; /* Readonly access to photolibrary reason */ "NSPhotoLibraryAddUsageDescription" = "Сохранение созданных QR-кодов"; From 693c17ee01f1afc77deb8b78d804a4bf23584801 Mon Sep 17 00:00:00 2001 From: Pavel Anokhov Date: Sun, 18 Mar 2018 00:34:58 +0300 Subject: [PATCH 13/13] Version --- Adamant/Info.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Adamant/Info.plist b/Adamant/Info.plist index 0d5a1c703..3949de9fc 100644 --- a/Adamant/Info.plist +++ b/Adamant/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.3.1 + 0.3.2 CFBundleVersion - 17 + 18 LSRequiresIPhoneOS NSCameraUsageDescription