diff --git a/assets/images/2.0x/backup.png b/assets/images/2.0x/backup.png index 044e494a9..5cf40bba7 100644 Binary files a/assets/images/2.0x/backup.png and b/assets/images/2.0x/backup.png differ diff --git a/assets/images/2.0x/restore_keys.png b/assets/images/2.0x/restore_keys.png index db52a8a2f..6a90ef2c2 100644 Binary files a/assets/images/2.0x/restore_keys.png and b/assets/images/2.0x/restore_keys.png differ diff --git a/assets/images/2.0x/restore_seed.png b/assets/images/2.0x/restore_seed.png index ae32393cc..2bbea22cf 100644 Binary files a/assets/images/2.0x/restore_seed.png and b/assets/images/2.0x/restore_seed.png differ diff --git a/assets/images/2.0x/restore_wallet_image.png b/assets/images/2.0x/restore_wallet_image.png index 85c913533..3e3aecb91 100644 Binary files a/assets/images/2.0x/restore_wallet_image.png and b/assets/images/2.0x/restore_wallet_image.png differ diff --git a/assets/images/3.0x/backup.png b/assets/images/3.0x/backup.png index 48737c9b2..5971200dc 100644 Binary files a/assets/images/3.0x/backup.png and b/assets/images/3.0x/backup.png differ diff --git a/assets/images/3.0x/restore_keys.png b/assets/images/3.0x/restore_keys.png index 05cf12ed7..1d7301275 100644 Binary files a/assets/images/3.0x/restore_keys.png and b/assets/images/3.0x/restore_keys.png differ diff --git a/assets/images/3.0x/restore_seed.png b/assets/images/3.0x/restore_seed.png index addaf2cd0..de1a10bb7 100644 Binary files a/assets/images/3.0x/restore_seed.png and b/assets/images/3.0x/restore_seed.png differ diff --git a/assets/images/3.0x/restore_wallet_image.png b/assets/images/3.0x/restore_wallet_image.png index e96af8782..6a6fdd775 100644 Binary files a/assets/images/3.0x/restore_wallet_image.png and b/assets/images/3.0x/restore_wallet_image.png differ diff --git a/assets/images/backup.png b/assets/images/backup.png index e7948fba8..665128ac3 100644 Binary files a/assets/images/backup.png and b/assets/images/backup.png differ diff --git a/assets/images/restore_keys.png b/assets/images/restore_keys.png index cc1d80691..bbb7890f1 100644 Binary files a/assets/images/restore_keys.png and b/assets/images/restore_keys.png differ diff --git a/assets/images/restore_seed.png b/assets/images/restore_seed.png index 6a3ca415e..938cac4dd 100644 Binary files a/assets/images/restore_seed.png and b/assets/images/restore_seed.png differ diff --git a/assets/images/restore_wallet_image.png b/assets/images/restore_wallet_image.png index 4bd343eb3..9fee53f1d 100644 Binary files a/assets/images/restore_wallet_image.png and b/assets/images/restore_wallet_image.png differ diff --git a/cw_monero/pubspec.lock b/cw_monero/pubspec.lock index f462e288d..0aa42cd07 100644 --- a/cw_monero/pubspec.lock +++ b/cw_monero/pubspec.lock @@ -7,42 +7,42 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "2.0.11" + version: "2.0.13" args: dependency: transitive description: name: args url: "https://pub.dartlang.org" source: hosted - version: "1.5.2" + version: "1.6.0" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.0" + version: "2.4.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "2.0.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.1.3" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" + version: "1.14.12" convert: dependency: transitive description: @@ -56,7 +56,7 @@ packages: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.4" ffi: dependency: "direct main" description: @@ -80,7 +80,7 @@ packages: name: image url: "https://pub.dartlang.org" source: hosted - version: "2.1.4" + version: "2.1.12" matcher: dependency: transitive description: @@ -109,13 +109,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.4.0" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0+1" petitparser: dependency: transitive description: @@ -136,7 +129,7 @@ packages: name: quiver url: "https://pub.dartlang.org" source: hosted - version: "2.0.5" + version: "2.1.3" sky_engine: dependency: transitive description: flutter @@ -148,7 +141,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.5.5" + version: "1.7.0" stack_trace: dependency: transitive description: @@ -183,7 +176,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.11" + version: "0.2.15" typed_data: dependency: transitive description: @@ -204,7 +197,7 @@ packages: name: xml url: "https://pub.dartlang.org" source: hosted - version: "3.5.0" + version: "3.6.1" sdks: dart: ">=2.6.0 <3.0.0" flutter: ">=0.1.4 <2.0.0" diff --git a/ios/Podfile b/ios/Podfile index 78d39756e..6697f0a53 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -15,59 +15,72 @@ def parse_KV_file(file, separator='=') if !File.exists? file_abs_path return []; end - pods_ary = [] + generated_key_values = {} skip_line_start_symbols = ["#", "/"] - File.foreach(file_abs_path) { |line| - next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } - plugin = line.split(pattern=separator) - if plugin.length == 2 - podname = plugin[0].strip() - path = plugin[1].strip() - podpath = File.expand_path("#{path}", file_abs_path) - pods_ary.push({:name => podname, :path => podpath}); - else - puts "Invalid plugin specification: #{line}" - end - } - return pods_ary + File.foreach(file_abs_path) do |line| + next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } + plugin = line.split(pattern=separator) + if plugin.length == 2 + podname = plugin[0].strip() + path = plugin[1].strip() + podpath = File.expand_path("#{path}", file_abs_path) + generated_key_values[podname] = podpath + else + puts "Invalid plugin specification: #{line}" + end + end + generated_key_values end target 'Runner' do - # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock - # referring to absolute paths on developers' machines. use_frameworks! - system('rm -rf .symlinks') - system('mkdir -p .symlinks/plugins') + use_modular_headers! - # Flutter Pods - generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') - if generated_xcode_build_settings.empty? - puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first." - end - generated_xcode_build_settings.map { |p| - if p[:name] == 'FLUTTER_FRAMEWORK_DIR' - symlink = File.join('.symlinks', 'flutter') - File.symlink(File.dirname(p[:path]), symlink) - pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) + # Flutter Pod + + copied_flutter_dir = File.join(__dir__, 'Flutter') + copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') + copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') + unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) + # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. + # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. + # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. + + generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') + unless File.exist?(generated_xcode_build_settings_path) + raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" end - } + generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) + cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; + + unless File.exist?(copied_framework_path) + FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) + end + unless File.exist?(copied_podspec_path) + FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) + end + end + + # Keep pod path relative so it can be checked into Podfile.lock. + pod 'Flutter', :path => 'Flutter' # Plugin Pods - plugin_pods = parse_KV_file('../.flutter-plugins') - plugin_pods.map { |p| - symlink = File.join('.symlinks', 'plugins', p[:name]) - File.symlink(p[:path], symlink) - pod p[:name], :path => File.join(symlink, 'ios') - } -end -# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system. -install! 'cocoapods', :disable_input_output_paths => true + # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock + # referring to absolute paths on developers' machines. + system('rm -rf .symlinks') + system('mkdir -p .symlinks/plugins') + plugin_pods = parse_KV_file('../.flutter-plugins') + plugin_pods.each do |name, path| + symlink = File.join('.symlinks', 'plugins', name) + File.symlink(path, symlink) + pod name, :path => File.join(symlink, 'ios') + end +end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings['SWIFT_VERSION'] = '4.0' # required by simple_permission config.build_settings['ENABLE_BITCODE'] = 'NO' end end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 64e81a4e8..451d74c1f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -65,7 +65,7 @@ DEPENDENCIES: - cw_monero (from `.symlinks/plugins/cw_monero/ios`) - devicelocale (from `.symlinks/plugins/devicelocale/ios`) - esys_flutter_share (from `.symlinks/plugins/esys_flutter_share/ios`) - - Flutter (from `.symlinks/flutter/ios`) + - Flutter (from `Flutter`) - flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - local_auth (from `.symlinks/plugins/local_auth/ios`) @@ -98,7 +98,7 @@ EXTERNAL SOURCES: esys_flutter_share: :path: ".symlinks/plugins/esys_flutter_share/ios" Flutter: - :path: ".symlinks/flutter/ios" + :path: Flutter flutter_plugin_android_lifecycle: :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" flutter_secure_storage: @@ -157,6 +157,6 @@ SPEC CHECKSUMS: url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c -PODFILE CHECKSUM: f1916a43bb28badbd408be80e8e4b8652a74e93e +PODFILE CHECKSUM: c34e2287a9ccaa606aeceab922830efb9a6ff69a COCOAPODS: 1.9.3 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index cf8308171..822dd4355 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -272,9 +272,40 @@ files = ( ); inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", + "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", + "${BUILT_PRODUCTS_DIR}/barcode_scan/barcode_scan.framework", + "${BUILT_PRODUCTS_DIR}/cw_monero/cw_monero.framework", + "${BUILT_PRODUCTS_DIR}/devicelocale/devicelocale.framework", + "${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework", + "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", + "${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework", + "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework", + "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework", + "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", + "${BUILT_PRODUCTS_DIR}/share/share.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cw_monero.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/devicelocale.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/share.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/lib/di.dart b/lib/di.dart index 1b533d69c..490eb590e 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -58,6 +58,7 @@ import 'package:mobx/mobx.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; +import 'package:cake_wallet/view_model/wallet_restoration_from_keys_vm.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/src/domain/common/wallet_type.dart'; @@ -168,6 +169,16 @@ Future setup( type: type, language: language, seed: mnemonic); }); + getIt + .registerFactoryParam((args, _) { + final type = args.first as WalletType; + final language = args[1] as String; + + return WalletRestorationFromKeysVM( + getIt.get(param1: type), walletInfoSource, + type: type, language: language); + }); + getIt.registerFactory( () => WalletAddressListViewModel(wallet: getIt.get().wallet)); @@ -302,8 +313,8 @@ Future setup( getIt.get(), contactSource)); - getIt.registerFactory( - () => ContactListPage(getIt.get())); + getIt.registerFactoryParam((bool isEditable, _) => + ContactListPage(getIt.get(), isEditable: isEditable)); getIt.registerFactoryParam((Contact contact, _) => ContactPage(getIt.get(param1: contact))); diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 5408734ae..a14182527 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -144,6 +144,9 @@ class S implements WidgetsLocalizations { String get reset => "Reset"; String get restore_active_seed => "Active seed"; String get restore_address => "Address"; + String get restore_bitcoin_description_from_keys => "Restore your wallet from generated WIF string from your private keys"; + String get restore_bitcoin_description_from_seed => "Restore your wallet from 12 word combination code"; + String get restore_bitcoin_title_from_keys => "Restore from WIF"; String get restore_description_from_backup => "You can restore the whole Cake Wallet app from your back-up file"; String get restore_description_from_keys => "Restore your wallet from generated keystrokes saved from your private keys"; String get restore_description_from_seed => "Restore your wallet from either the 25 word or 13 word combination code"; @@ -496,6 +499,8 @@ class $de extends S { @override String get settings_title => "die Einstellungen"; @override + String get restore_bitcoin_description_from_seed => "Stellen Sie Ihre Brieftasche aus dem 12-Wort-Kombinationscode wieder her"; + @override String get address_book_menu => "Adressbuch"; @override String get wallet_restoration_store_incorrect_seed_length => "Falsche Samenlänge"; @@ -630,6 +635,10 @@ class $de extends S { @override String get xmr_available_balance => "XMR verfügbares Guthaben"; @override + String get restore_bitcoin_description_from_keys => "Stellen Sie Ihre Brieftasche aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her"; + @override + String get restore_bitcoin_title_from_keys => "Aus WIF wiederherstellen"; + @override String get scan_qr_code => "Scannen Sie den QR-Code, um die Adresse zu erhalten"; @override String get trade_state_paid => "Bezahlt"; @@ -1128,6 +1137,8 @@ class $hi extends S { @override String get settings_title => "सेटिंग्स"; @override + String get restore_bitcoin_description_from_seed => "12 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें"; + @override String get address_book_menu => "पता पुस्तिका"; @override String get wallet_restoration_store_incorrect_seed_length => "गलत बीज की लंबाई"; @@ -1262,6 +1273,10 @@ class $hi extends S { @override String get xmr_available_balance => "XMR उपलब्ध शेष राशि"; @override + String get restore_bitcoin_description_from_keys => "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें"; + @override + String get restore_bitcoin_title_from_keys => "WIF से पुनर्स्थापित करें"; + @override String get scan_qr_code => "पता प्राप्त करने के लिए QR कोड स्कैन करें"; @override String get trade_state_paid => "भुगतान किया है"; @@ -1760,6 +1775,8 @@ class $ru extends S { @override String get settings_title => "Настройки"; @override + String get restore_bitcoin_description_from_seed => "Вы можете восстановить кошелёк используя 12-ти значную мнемоническую фразу"; + @override String get address_book_menu => "Адресная книга"; @override String get wallet_restoration_store_incorrect_seed_length => "Неверная длина мнемонической фразы"; @@ -1894,6 +1911,10 @@ class $ru extends S { @override String get xmr_available_balance => "Доступный XMR баланс"; @override + String get restore_bitcoin_description_from_keys => "Вы можете восстановить кошелёк с помощью WIF"; + @override + String get restore_bitcoin_title_from_keys => "Восстановить с помощью WIF"; + @override String get scan_qr_code => "Отсканируйте QR-код для получения адреса"; @override String get trade_state_paid => "Оплаченная"; @@ -2392,6 +2413,8 @@ class $ko extends S { @override String get settings_title => "설정"; @override + String get restore_bitcoin_description_from_seed => "12 단어 조합 코드에서 지갑 복원"; + @override String get address_book_menu => "주소록"; @override String get wallet_restoration_store_incorrect_seed_length => "시드 길이가 잘못되었습니다"; @@ -2526,6 +2549,10 @@ class $ko extends S { @override String get xmr_available_balance => "XMR 사용 가능한 잔액"; @override + String get restore_bitcoin_description_from_keys => "개인 키에서 생성 된 WIF 문자열에서 지갑 복원"; + @override + String get restore_bitcoin_title_from_keys => "WIF에서 복원"; + @override String get scan_qr_code => "QR 코드를 스캔하여 주소를 얻습니다."; @override String get trade_state_paid => "유료"; @@ -3024,6 +3051,8 @@ class $pt extends S { @override String get settings_title => "Configurações"; @override + String get restore_bitcoin_description_from_seed => "Restaure sua carteira a partir de um código de combinação de 12 palavras"; + @override String get address_book_menu => "Livro de endereços"; @override String get wallet_restoration_store_incorrect_seed_length => "Comprimento de semente incorreto"; @@ -3158,6 +3187,10 @@ class $pt extends S { @override String get xmr_available_balance => "Saldo XMR disponível"; @override + String get restore_bitcoin_description_from_keys => "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas"; + @override + String get restore_bitcoin_title_from_keys => "Restaurar de WIF"; + @override String get scan_qr_code => "Digitalize o código QR para obter o endereço"; @override String get trade_state_paid => "Paga"; @@ -3656,6 +3689,8 @@ class $uk extends S { @override String get settings_title => "Налаштування"; @override + String get restore_bitcoin_description_from_seed => "Ви можете відновити гаманець використовуючи 12-ти слівну мнемонічну фразу"; + @override String get address_book_menu => "Адресна книга"; @override String get wallet_restoration_store_incorrect_seed_length => "Невірна довжина мнемонічної фрази"; @@ -3790,6 +3825,10 @@ class $uk extends S { @override String get xmr_available_balance => "Доступний XMR баланс"; @override + String get restore_bitcoin_description_from_keys => "Ви можете відновити гаманець за допомогою WIF"; + @override + String get restore_bitcoin_title_from_keys => "Відновити за допомогою WIF"; + @override String get scan_qr_code => "Скануйте QR-код для одержання адреси"; @override String get trade_state_paid => "Оплачена"; @@ -4288,6 +4327,8 @@ class $ja extends S { @override String get settings_title => "設定"; @override + String get restore_bitcoin_description_from_seed => "12ワードの組み合わせコードからウォレットを復元する"; + @override String get address_book_menu => "住所録"; @override String get wallet_restoration_store_incorrect_seed_length => "誤ったシード長s"; @@ -4422,6 +4463,10 @@ class $ja extends S { @override String get xmr_available_balance => "XMR利用可能残高"; @override + String get restore_bitcoin_description_from_keys => "秘密鍵から生成されたWIF文字列からウォレットを復元します"; + @override + String get restore_bitcoin_title_from_keys => "WIFから復元"; + @override String get scan_qr_code => "QRコードをスキャンして住所を取得します"; @override String get trade_state_paid => "有料"; @@ -4924,6 +4969,8 @@ class $pl extends S { @override String get settings_title => "Ustawienia"; @override + String get restore_bitcoin_description_from_seed => "Przywróć swój portfel z kodu złożonego z 12 słów"; + @override String get address_book_menu => "Książka adresowa"; @override String get wallet_restoration_store_incorrect_seed_length => "Nieprawidłowa długość nasion"; @@ -5058,6 +5105,10 @@ class $pl extends S { @override String get xmr_available_balance => "XMR Dostępne saldo"; @override + String get restore_bitcoin_description_from_keys => "Przywróć swój portfel z wygenerowanego ciągu WIF z kluczy prywatnych"; + @override + String get restore_bitcoin_title_from_keys => "Przywróć z WIF"; + @override String get scan_qr_code => "Zeskanuj kod QR, aby uzyskać adres"; @override String get trade_state_paid => "Płatny"; @@ -5556,6 +5607,8 @@ class $es extends S { @override String get settings_title => "Configuraciones"; @override + String get restore_bitcoin_description_from_seed => "Restaure su billetera a partir del código de combinación de 12 palabras"; + @override String get address_book_menu => "Libreta de direcciones"; @override String get wallet_restoration_store_incorrect_seed_length => "Longitud de semilla incorrecta"; @@ -5690,6 +5743,10 @@ class $es extends S { @override String get xmr_available_balance => "XMR Available Balance"; @override + String get restore_bitcoin_description_from_keys => "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas"; + @override + String get restore_bitcoin_title_from_keys => "Restaurar desde WIF"; + @override String get scan_qr_code => "Escanee el código QR para obtener la dirección"; @override String get trade_state_paid => "Pagado"; @@ -6188,6 +6245,8 @@ class $nl extends S { @override String get settings_title => "Instellingen"; @override + String get restore_bitcoin_description_from_seed => "Herstel uw portemonnee met een combinatiecode van 12 woorden"; + @override String get address_book_menu => "Adresboek"; @override String get wallet_restoration_store_incorrect_seed_length => "Onjuiste zaadlengte"; @@ -6322,6 +6381,10 @@ class $nl extends S { @override String get xmr_available_balance => "XMR Beschikbaar saldo"; @override + String get restore_bitcoin_description_from_keys => "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels"; + @override + String get restore_bitcoin_title_from_keys => "Herstel van WIF"; + @override String get scan_qr_code => "Scan de QR-code om het adres te krijgen"; @override String get trade_state_paid => "Betaald"; @@ -6820,6 +6883,8 @@ class $zh extends S { @override String get settings_title => "设定值"; @override + String get restore_bitcoin_description_from_seed => "從12個單詞的組合碼恢復您的錢包"; + @override String get address_book_menu => "地址簿"; @override String get wallet_restoration_store_incorrect_seed_length => "种子长度错误"; @@ -6954,6 +7019,10 @@ class $zh extends S { @override String get xmr_available_balance => "XMR 可用余额 "; @override + String get restore_bitcoin_description_from_keys => "從私鑰中生成的WIF字符串還原您的錢包"; + @override + String get restore_bitcoin_title_from_keys => "從WIF還原"; + @override String get scan_qr_code => "掃描二維碼獲取地址"; @override String get trade_state_paid => "已付费"; diff --git a/lib/router.dart b/lib/router.dart index 68e010293..14f658e0c 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; +import 'package:cake_wallet/view_model/wallet_restoration_from_keys_vm.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -165,6 +166,7 @@ class Router { builder: (_) => NewWalletTypePage( onTypeSelected: (context, type) => Navigator.of(context) .pushNamed(Routes.restoreWalletOptions, arguments: type), + isNewWallet: false, )); case Routes.restoreOptions: @@ -196,7 +198,7 @@ class Router { ? Routes.seedLanguage : Routes.restoreWalletFromKeys; final args = type == WalletType.monero - ? [type, Routes.restoreWalletFromSeed] + ? [type, Routes.restoreWalletFromKeys] : [type]; Navigator.of(context).pushNamed(route, arguments: args); @@ -236,17 +238,12 @@ class Router { ? args[1] as String : 'English'; // FIXME: Unnamed constant; English default and only one language for bitcoin. + final walletRestorationFromKeysVM = + getIt.get(param1: [type, language]); + return CupertinoPageRoute( - builder: (_) => - ProxyProvider( - update: (_, authStore, __) => WalletRestorationStore( - authStore: authStore, - sharedPreferences: sharedPreferences, - walletListService: walletListService), - child: RestoreWalletFromKeysPage( - walletsService: walletListService, - walletService: walletService, - sharedPreferences: sharedPreferences))); + builder: (_) => RestoreWalletFromKeysPage( + walletRestorationFromKeysVM: walletRestorationFromKeysVM)); case Routes.dashboard: return CupertinoPageRoute( @@ -340,11 +337,11 @@ class Router { case Routes.addressBook: return MaterialPageRoute( - builder: (_) => getIt.get()); + builder: (_) => getIt.get(param1: true)); case Routes.pickerAddressBook: return MaterialPageRoute( - builder: (_) => getIt.get()); + builder: (_) => getIt.get(param1: false)); case Routes.addressBookAddContact: return CupertinoPageRoute( @@ -360,24 +357,6 @@ class Router { return CupertinoPageRoute( builder: (_) => getIt.get()); - /*MultiProvider( - providers: [ - ProxyProvider( - update: (_, settingsStore, __) => ExchangeTradeStore( - trade: settings.arguments as Trade, - walletStore: walletStore, - trades: trades), - ), - ProxyProvider( - update: (_, settingsStore, __) => SendStore( - transactionDescriptions: transactionDescriptions, - walletService: walletService, - settingsStore: settingsStore, - priceStore: priceStore)), - ], - child: ExchangeTradePage(), - ));*/ - case Routes.exchangeConfirm: return MaterialPageRoute( builder: (_) => getIt.get()); diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 1eaf95b46..60d780d2d 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; @@ -40,6 +42,7 @@ class _WalletNameFormState extends State { static const aspectRatioImage = 1.22; final walletNameImage = Image.asset('assets/images/wallet_name.png'); + final walletNameLightImage = Image.asset('assets/images/wallet_name_light.png'); final _formKey = GlobalKey(); final _languageSelectorKey = GlobalKey(); ReactionDisposer _stateReaction; @@ -72,6 +75,9 @@ class _WalletNameFormState extends State { @override Widget build(BuildContext context) { + final walletImage = getIt.get().isDarkTheme + ? walletNameImage : walletNameLightImage; + return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( @@ -82,7 +88,7 @@ class _WalletNameFormState extends State { padding: EdgeInsets.only(left: 12, right: 12), child: AspectRatio( aspectRatio: aspectRatioImage, - child: FittedBox(child: walletNameImage, fit: BoxFit.fill)), + child: FittedBox(child: walletImage, fit: BoxFit.fill)), ), Padding( padding: EdgeInsets.only(top: 24), @@ -98,19 +104,26 @@ class _WalletNameFormState extends State { Theme.of(context).primaryTextTheme.title.color), decoration: InputDecoration( hintStyle: TextStyle( - fontSize: 16.0, + fontSize: 18.0, + fontWeight: FontWeight.w500, color: Theme.of(context) - .primaryTextTheme - .caption + .accentTextTheme + .display3 .color), hintText: S.of(context).wallet_name, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).dividerColor, + color: Theme.of(context) + .accentTextTheme + .display3 + .decorationColor, width: 1.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).dividerColor, + color: Theme.of(context) + .accentTextTheme + .display3 + .decorationColor, width: 1.0))), validator: WalletNameValidator())), ), @@ -122,7 +135,7 @@ class _WalletNameFormState extends State { textAlign: TextAlign.center, style: TextStyle( fontSize: 16.0, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color), ), ), @@ -140,7 +153,8 @@ class _WalletNameFormState extends State { builder: (context) { return LoadingPrimaryButton( onPressed: _confirmForm, - text: S.of(context).continue_text, + //text: S.of(context).continue_text, + text: S.of(context).seed_language_next, color: Colors.green, textColor: Colors.white, isLoading: _walletNewVM.state is WalletCreatedSuccessfully, diff --git a/lib/src/screens/new_wallet/new_wallet_type_page.dart b/lib/src/screens/new_wallet/new_wallet_type_page.dart index 9dfcfbf33..673bd9478 100644 --- a/lib/src/screens/new_wallet/new_wallet_type_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_type_page.dart @@ -1,4 +1,6 @@ +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/domain/common/wallet_type.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -6,15 +8,17 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; -import 'package:cake_wallet/routes.dart'; class NewWalletTypePage extends BasePage { - NewWalletTypePage({this.onTypeSelected}); + NewWalletTypePage({this.onTypeSelected, this.isNewWallet = true}); final void Function(BuildContext, WalletType) onTypeSelected; + final bool isNewWallet; @override - String get title => S.current.new_wallet; + String get title => isNewWallet + ? S.current.new_wallet + : S.current.wallet_list_restore_wallet; @override Widget body(BuildContext context) => @@ -38,6 +42,7 @@ class WalletTypeFormState extends State { final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24); final walletTypeImage = Image.asset('assets/images/wallet_type.png'); + final walletTypeLightImage = Image.asset('assets/images/wallet_type_light.png'); WalletType selected; List types; @@ -50,6 +55,9 @@ class WalletTypeFormState extends State { @override Widget build(BuildContext context) { + final walletImage = getIt.get().isDarkTheme + ? walletTypeImage : walletTypeLightImage; + return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( @@ -61,7 +69,7 @@ class WalletTypeFormState extends State { padding: EdgeInsets.only(left: 12, right: 12), child: AspectRatio( aspectRatio: aspectRatioImage, - child: FittedBox(child: walletTypeImage, fit: BoxFit.fill)), + child: FittedBox(child: walletImage, fit: BoxFit.fill)), ), Padding( padding: EdgeInsets.only(top: 48), @@ -70,7 +78,7 @@ class WalletTypeFormState extends State { textAlign: TextAlign.center, style: TextStyle( fontSize: 16, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color), ), ), @@ -79,8 +87,7 @@ class WalletTypeFormState extends State { child: SelectButton( image: _iconFor(type), text: walletTypeToString(type), - color: _backgroundColorFor(selected == type), - textColor: _textColorFor(selected == type), + isSelected: selected == type, onTap: () => setState(() => selected = type)), )) ], @@ -97,16 +104,6 @@ class WalletTypeFormState extends State { ); } - // FIXME: Move color selection inside ui element; add isSelected to buttons. - - Color _backgroundColorFor(bool isSelected) => isSelected - ? Theme.of(context).accentTextTheme.title.decorationColor - : Theme.of(context).accentTextTheme.title.backgroundColor; - - Color _textColorFor(bool isSelected) => isSelected - ? Theme.of(context).primaryTextTheme.title.backgroundColor - : Theme.of(context).primaryTextTheme.title.color; - Image _iconFor(WalletType type) { switch (type) { case WalletType.monero: diff --git a/lib/src/screens/new_wallet/widgets/select_button.dart b/lib/src/screens/new_wallet/widgets/select_button.dart index 7e583ec4e..bd69a8015 100644 --- a/lib/src/screens/new_wallet/widgets/select_button.dart +++ b/lib/src/screens/new_wallet/widgets/select_button.dart @@ -4,21 +4,30 @@ class SelectButton extends StatelessWidget { SelectButton({ @required this.image, @required this.text, - @required this.color, - @required this.textColor, @required this.onTap, + this.isSelected = false, }); final Image image; final String text; - final Color color; - final Color textColor; + final bool isSelected; final VoidCallback onTap; - final selectArrowImage = Image.asset('assets/images/select_arrow.png'); - @override Widget build(BuildContext context) { + final color = isSelected + ? Theme.of(context).accentTextTheme.subtitle.decorationColor + : Theme.of(context).accentTextTheme.caption.color; + final textColor = isSelected + ? Theme.of(context).accentTextTheme.headline.decorationColor + : Theme.of(context).primaryTextTheme.title.color; + final arrowColor = isSelected + ? Theme.of(context).accentTextTheme.headline.decorationColor + : Theme.of(context).accentTextTheme.subhead.color; + + final selectArrowImage = Image.asset('assets/images/select_arrow.png', + color: arrowColor); + return GestureDetector( onTap: onTap, child: Container( @@ -39,9 +48,7 @@ class SelectButton extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ - image != null - ? image - : Offstage(), + image ?? Offstage(), Padding( padding: image != null ? EdgeInsets.only(left: 15) @@ -50,7 +57,7 @@ class SelectButton extends StatelessWidget { text, style: TextStyle( fontSize: 18, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: textColor ), ), diff --git a/lib/src/screens/restore/restore_wallet_from_keys_page.dart b/lib/src/screens/restore/restore_wallet_from_keys_page.dart index 766ef7a0e..6f950f6e4 100644 --- a/lib/src/screens/restore/restore_wallet_from_keys_page.dart +++ b/lib/src/screens/restore/restore_wallet_from_keys_page.dart @@ -1,40 +1,36 @@ -import 'package:mobx/mobx.dart'; -import 'package:provider/provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; +import 'package:cake_wallet/core/validator.dart'; +import 'package:cake_wallet/palette.dart'; import 'package:flutter/services.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/domain/services/wallet_list_service.dart'; -import 'package:cake_wallet/src/domain/services/wallet_service.dart'; -import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_store.dart'; -import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_state.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/view_model/wallet_restoration_from_keys_vm.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class RestoreWalletFromKeysPage extends BasePage { RestoreWalletFromKeysPage( - {@required this.walletsService, - @required this.sharedPreferences, - @required this.walletService}); + {@required this.walletRestorationFromKeysVM}); - final WalletListService walletsService; - final WalletService walletService; - final SharedPreferences sharedPreferences; + final WalletRestorationFromKeysVM walletRestorationFromKeysVM; @override String get title => S.current.restore_title_from_keys; @override - Widget body(BuildContext context) => RestoreFromKeysFrom(); + Widget body(BuildContext context) => RestoreFromKeysFrom(walletRestorationFromKeysVM); } class RestoreFromKeysFrom extends StatefulWidget { + RestoreFromKeysFrom(this.walletRestorationFromKeysVM); + + final WalletRestorationFromKeysVM walletRestorationFromKeysVM; + @override _RestoreFromKeysFromState createState() => _RestoreFromKeysFromState(); } @@ -46,6 +42,23 @@ class _RestoreFromKeysFromState extends State { final _addressController = TextEditingController(); final _viewKeyController = TextEditingController(); final _spendKeyController = TextEditingController(); + final _wifController = TextEditingController(); + + @override + void initState() { + _nameController.addListener(() => + widget.walletRestorationFromKeysVM.name = _nameController.text); + _addressController.addListener(() => + widget.walletRestorationFromKeysVM.address = _addressController.text); + _viewKeyController.addListener(() => + widget.walletRestorationFromKeysVM.viewKey = _viewKeyController.text); + _spendKeyController.addListener(() => + widget.walletRestorationFromKeysVM.spendKey = _spendKeyController.text); + _wifController.addListener(() => + widget.walletRestorationFromKeysVM.wif = _wifController.text); + + super.initState(); + } @override void dispose() { @@ -53,31 +66,14 @@ class _RestoreFromKeysFromState extends State { _addressController.dispose(); _viewKeyController.dispose(); _spendKeyController.dispose(); + _wifController.dispose(); super.dispose(); } - void onHandleControllers(WalletRestorationStore walletRestorationStore) { - if (_nameController.text.isNotEmpty && - _addressController.text.isNotEmpty && - _viewKeyController.text.isNotEmpty && - _spendKeyController.text.isNotEmpty) { - walletRestorationStore.setDisabledState(false); - } else { - walletRestorationStore.setDisabledState(true); - } - } - @override Widget build(BuildContext context) { - final walletRestorationStore = Provider.of(context); - final seedLanguageStore = Provider.of(context); - _nameController.addListener(() {onHandleControllers(walletRestorationStore);}); - _addressController.addListener(() {onHandleControllers(walletRestorationStore);}); - _viewKeyController.addListener(() {onHandleControllers(walletRestorationStore);}); - _spendKeyController.addListener(() {onHandleControllers(walletRestorationStore);}); - - reaction((_) => walletRestorationStore.state, (WalletRestorationState state) { + /*reaction((_) => walletRestorationStore.state, (WalletRestorationState state) { if (state is WalletRestoredSuccessfully) { Navigator.of(context).popUntil((route) => route.isFirst); } @@ -96,7 +92,7 @@ class _RestoreFromKeysFromState extends State { }); }); } - }); + });*/ return Container( padding: EdgeInsets.only(left: 24, right: 24), @@ -110,66 +106,39 @@ class _RestoreFromKeysFromState extends State { Flexible( child: Container( padding: EdgeInsets.only(top: 20.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color - ), + child: BaseTextFormField( controller: _nameController, - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.caption.color, - fontSize: 16 - ), - hintText: S.of(context).restore_wallet_name, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), - validator: (value) { - walletRestorationStore.validateWalletName(value); - return walletRestorationStore.errorMessage; - }, - ), + hintText: S.of(context).restore_wallet_name, + validator: WalletNameValidator(), + ) )) ], ), + if (!widget.walletRestorationFromKeysVM.hasRestorationHeight) + Row( + children: [ + Flexible( + child: Container( + padding: EdgeInsets.only(top: 20.0), + child: BaseTextFormField( + controller: _wifController, + hintText: 'WIF', + ) + )) + ], + ), + if (widget.walletRestorationFromKeysVM.hasRestorationHeight) ... [ Row( children: [ Flexible( child: Container( padding: EdgeInsets.only(top: 20.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color - ), + child: BaseTextFormField( controller: _addressController, keyboardType: TextInputType.multiline, maxLines: null, - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.caption.color, - fontSize: 16 - ), - hintText: S.of(context).restore_address, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), - validator: (value) { - walletRestorationStore.validateAddress(value); - return walletRestorationStore.errorMessage; - }, - ), + hintText: S.of(context).restore_address, + ) )) ], ), @@ -178,31 +147,10 @@ class _RestoreFromKeysFromState extends State { Flexible( child: Container( padding: EdgeInsets.only(top: 20.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color - ), + child: BaseTextFormField( controller: _viewKeyController, - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.caption.color, - fontSize: 16 - ), - hintText: S.of(context).restore_view_key_private, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), - validator: (value) { - walletRestorationStore.validateKeys(value); - return walletRestorationStore.errorMessage; - }, - ), + hintText: S.of(context).restore_view_key_private, + ) )) ], ), @@ -211,35 +159,19 @@ class _RestoreFromKeysFromState extends State { Flexible( child: Container( padding: EdgeInsets.only(top: 20.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color - ), + child: BaseTextFormField( controller: _spendKeyController, - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.caption.color, - fontSize: 16 - ), - hintText: S.of(context).restore_spend_key_private, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), - validator: (value) { - walletRestorationStore.validateKeys(value); - return walletRestorationStore.errorMessage; - }, - ), + hintText: S.of(context).restore_spend_key_private, + ) )) ], ), - BlockchainHeightWidget(key: _blockchainHeightKey), + BlockchainHeightWidget( + key: _blockchainHeightKey, + onHeightChange: (height) { + widget.walletRestorationFromKeysVM.height = height; + print(height); + })], ]), ), bottomSectionPadding: EdgeInsets.only(bottom: 24), @@ -247,19 +179,19 @@ class _RestoreFromKeysFromState extends State { return LoadingPrimaryButton( onPressed: () { if (_formKey.currentState.validate()) { - walletRestorationStore.restoreFromKeys( + /*walletRestorationStore.restoreFromKeys( name: _nameController.text, language: seedLanguageStore.selectedSeedLanguage, address: _addressController.text, viewKey: _viewKeyController.text, spendKey: _spendKeyController.text, - restoreHeight: _blockchainHeightKey.currentState.height); + restoreHeight: _blockchainHeightKey.currentState.height);*/ } }, text: S.of(context).restore_recover, - color: Colors.green, + color: Palette.blueCraiola, textColor: Colors.white, - isDisabled: walletRestorationStore.disabledState, + //isDisabled: walletRestorationStore.disabledState, ); }), ), diff --git a/lib/src/screens/restore/restore_wallet_from_seed_details.dart b/lib/src/screens/restore/restore_wallet_from_seed_details.dart index 5a83a8b3c..3225be9e7 100644 --- a/lib/src/screens/restore/restore_wallet_from_seed_details.dart +++ b/lib/src/screens/restore/restore_wallet_from_seed_details.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/palette.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -9,6 +10,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; class RestoreWalletFromSeedDetailsPage extends BasePage { @@ -91,27 +93,9 @@ class _RestoreFromSeedDetailsFormState Flexible( child: Container( padding: EdgeInsets.only(top: 20.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color), + child: BaseTextFormField( controller: _nameController, - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .caption - .color, - fontSize: 16), - hintText: S.of(context).restore_wallet_name, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), + hintText: S.of(context).restore_wallet_name, validator: WalletNameValidator(), ), )) @@ -137,7 +121,7 @@ class _RestoreFromSeedDetailsFormState isLoading: widget.walletRestorationFromSeedVM.state is WalletCreating, text: S.of(context).restore_recover, - color: Colors.green, + color: Palette.blueCraiola, textColor: Colors.white, isDisabled: _nameController.text.isNotEmpty, ); diff --git a/lib/src/screens/restore/restore_wallet_from_seed_page.dart b/lib/src/screens/restore/restore_wallet_from_seed_page.dart index 5c46b32ef..bc30a48d8 100644 --- a/lib/src/screens/restore/restore_wallet_from_seed_page.dart +++ b/lib/src/screens/restore/restore_wallet_from_seed_page.dart @@ -20,20 +20,40 @@ class RestoreWalletFromSeedPage extends BasePage { String get title => S.current.restore_title_from_seed; @override - Color get backgroundLightColor => Palette.lavender; + Color get titleColor => Colors.white; @override - Color get backgroundDarkColor => PaletteDark.lightNightBlue; + Color get backgroundLightColor => Colors.transparent; + + @override + Color get backgroundDarkColor => Colors.transparent; + + @override + bool get resizeToAvoidBottomPadding => false; @override Widget body(BuildContext context) => - RestoreFromSeedForm(key: formKey, type: type, language: language); + RestoreFromSeedForm(key: formKey, type: type, language: language, + leading: leading(context), middle: middle(context)); + + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding, + body: Container( + color: Theme.of(context).backgroundColor, + child: body(context) + ) + ); + } } class RestoreFromSeedForm extends StatefulWidget { - RestoreFromSeedForm({Key key, this.type, this.language}) : super(key: key); + RestoreFromSeedForm({Key key, this.type, this.language, this.leading, this.middle}) : super(key: key); final WalletType type; final String language; + final Widget leading; + final Widget middle; @override _RestoreFromSeedFormState createState() => _RestoreFromSeedFormState(); @@ -49,18 +69,17 @@ class _RestoreFromSeedFormState extends State { return GestureDetector( onTap: () => SystemChannels.textInput.invokeMethod('TextInput.hide'), - child: Container( - color: Theme.of(context).backgroundColor, - child: SeedWidget( - key: _seedKey, - maxLength: mnemonicLength(widget.type), - onMnemonicChange: (seed) => null, - onFinish: () => Navigator.of(context).pushNamed( - Routes.restoreWalletFromSeedDetails, - arguments: [widget.type, widget.language, mnemonic()]), - validator: - SeedValidator(type: widget.type, language: widget.language), - ), + child: SeedWidget( + key: _seedKey, + maxLength: mnemonicLength(widget.type), + onMnemonicChange: (seed) => null, + onFinish: () => Navigator.of(context).pushNamed( + Routes.restoreWalletFromSeedDetails, + arguments: [widget.type, widget.language, mnemonic()]), + leading: widget.leading, + middle: widget.middle, + validator: + SeedValidator(type: widget.type, language: widget.language), ), ); } diff --git a/lib/src/screens/restore/restore_wallet_options_page.dart b/lib/src/screens/restore/restore_wallet_options_page.dart index bb805e7c0..750a9c7e0 100644 --- a/lib/src/screens/restore/restore_wallet_options_page.dart +++ b/lib/src/screens/restore/restore_wallet_options_page.dart @@ -1,11 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/screens/restore/widgets/restore_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/domain/common/wallet_type.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; class RestoreWalletOptionsPage extends BasePage { RestoreWalletOptionsPage( @@ -18,7 +15,7 @@ class RestoreWalletOptionsPage extends BasePage { final Function(BuildContext context) onRestoreFromKeys; @override - String get title => S.current.restore_seed_keys_restore; + String get title => S.current.restore_restore_wallet; final imageSeed = Image.asset('assets/images/restore_seed.png'); final imageKeys = Image.asset('assets/images/restore_keys.png'); @@ -56,7 +53,7 @@ class RestoreWalletOptionsPage extends BasePage { return S.of(context).restore_description_from_seed; case WalletType.bitcoin: // TODO: Add transaction for bitcoin description. - return 'Restore your wallet from 12 word combination code'; + return S.of(context).restore_bitcoin_description_from_seed; default: return ''; } @@ -68,7 +65,7 @@ class RestoreWalletOptionsPage extends BasePage { return S.of(context).restore_description_from_keys; case WalletType.bitcoin: // TODO: Add transaction for bitcoin description. - return 'Restore your wallet from generated WIF string from your private keys'; + return S.of(context).restore_bitcoin_description_from_keys; default: return ''; } @@ -80,7 +77,7 @@ class RestoreWalletOptionsPage extends BasePage { return S.of(context).restore_title_from_keys; case WalletType.bitcoin: // TODO: Add transaction for bitcoin description. - return 'Restore from WIF'; + return S.of(context).restore_bitcoin_title_from_keys; default: return ''; } diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index ba07d1fe8..8945d51c4 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -19,12 +19,12 @@ class RestoreButton extends StatelessWidget { onTap: onPressed, child: Container( width: double.infinity, - height: 150, + height: 170, padding: EdgeInsets.all(24), alignment: Alignment.topLeft, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).accentTextTheme.title.backgroundColor, + color: Theme.of(context).accentTextTheme.caption.color, ), child: Row( mainAxisSize: MainAxisSize.max, @@ -44,7 +44,7 @@ class RestoreButton extends StatelessWidget { title, style: TextStyle( fontSize: 16, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color ), ), @@ -54,7 +54,8 @@ class RestoreButton extends StatelessWidget { description, style: TextStyle( fontSize: 14, - color: Theme.of(context).primaryTextTheme.caption.color + fontWeight: FontWeight.normal, + color: Theme.of(context).primaryTextTheme.overline.color ), ), ) diff --git a/lib/src/screens/seed_language/seed_language_page.dart b/lib/src/screens/seed_language/seed_language_page.dart index 48b2fd5b6..ccee8aae5 100644 --- a/lib/src/screens/seed_language/seed_language_page.dart +++ b/lib/src/screens/seed_language/seed_language_page.dart @@ -1,5 +1,6 @@ +import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/src/widgets/seed_language_selector.dart'; -import 'package:provider/provider.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -7,8 +8,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; -import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; -import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart'; class SeedLanguage extends BasePage { @@ -16,6 +15,9 @@ class SeedLanguage extends BasePage { final Function(BuildContext, String) onConfirm; + @override + String get title => S.current.wallet_list_restore_wallet; + @override Widget body(BuildContext context) => SeedLanguageForm(onConfirm: onConfirm); } @@ -33,10 +35,14 @@ class SeedLanguageFormState extends State { static const aspectRatioImage = 1.22; final walletNameImage = Image.asset('assets/images/wallet_name.png'); + final walletNameLightImage = Image.asset('assets/images/wallet_name_light.png'); final _languageSelectorKey = GlobalKey(); @override Widget build(BuildContext context) { + final walletImage = getIt.get().isDarkTheme + ? walletNameImage : walletNameLightImage; + return Container( padding: EdgeInsets.only(top: 24), child: ScrollableWithBottomSection( @@ -47,7 +53,7 @@ class SeedLanguageFormState extends State { padding: EdgeInsets.only(left: 12, right: 12), child: AspectRatio( aspectRatio: aspectRatioImage, - child: FittedBox(child: walletNameImage, fit: BoxFit.fill)), + child: FittedBox(child: walletImage, fit: BoxFit.fill)), ), Padding( padding: EdgeInsets.only(top: 40), @@ -56,7 +62,7 @@ class SeedLanguageFormState extends State { textAlign: TextAlign.center, style: TextStyle( fontSize: 16.0, - fontWeight: FontWeight.w600, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color), ), ), diff --git a/lib/src/screens/seed_language/widgets/seed_language_picker.dart b/lib/src/screens/seed_language/widgets/seed_language_picker.dart index cc476b294..47e43c7c7 100644 --- a/lib/src/screens/seed_language/widgets/seed_language_picker.dart +++ b/lib/src/screens/seed_language/widgets/seed_language_picker.dart @@ -1,9 +1,9 @@ import 'dart:ui'; +import 'package:cake_wallet/src/widgets/alert_background.dart'; +import 'package:cake_wallet/src/widgets/alert_close_button.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; -import 'package:provider/provider.dart'; -import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; List flagImages = [ @@ -57,170 +57,111 @@ class SeedLanguagePicker extends StatefulWidget { class SeedLanguagePickerState extends State { SeedLanguagePickerState({this.selected}); + final closeButton = Image.asset('assets/images/close.png'); String selected; @override Widget build(BuildContext context) { - return GestureDetector( - onTap: () => Navigator.of(context).pop(), - child: Container( - color: Colors.transparent, - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0), - child: Container( - decoration: BoxDecoration( - color: PaletteDark.darkNightBlue.withOpacity(0.75)), - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - padding: EdgeInsets.only(left: 24, right: 24), - child: Text( - S.of(context).seed_choose, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - decoration: TextDecoration.none, - color: Colors.white), + return AlertBackground( + child: Stack( + alignment: Alignment.center, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: EdgeInsets.only(left: 24, right: 24), + child: Text( + S.of(context).seed_choose, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + fontFamily: 'Poppins', + decoration: TextDecoration.none, + color: Colors.white ), ), - Padding( - padding: EdgeInsets.only(top: 24), - child: GestureDetector( - onTap: () => null, - child: Container( - height: 300, - width: 300, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(14)), - color: Theme.of(context).dividerColor), - child: GridView.count( - shrinkWrap: true, - crossAxisCount: 3, - childAspectRatio: 1, - physics: const NeverScrollableScrollPhysics(), - crossAxisSpacing: 1, - mainAxisSpacing: 1, - children: List.generate(9, (index) { - if (index == 8) { - return gridTile( - isCurrent: false, - place: Places.bottomRight, - image: null, - text: '', - onTap: null); - } else { - final code = languageCodes[index]; - final flag = flagImages[index]; - final isCurrent = - index == seedLanguages.indexOf(selected); + ), + Padding( + padding: EdgeInsets.only(top: 24), + child: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(14)), + child: Container( + height: 300, + width: 300, + color: Theme.of(context).accentTextTheme.title.backgroundColor, + child: GridView.count( + shrinkWrap: true, + crossAxisCount: 3, + childAspectRatio: 1, + physics: const NeverScrollableScrollPhysics(), + crossAxisSpacing: 1, + mainAxisSpacing: 1, + children: List.generate(9, (index) { - if (index == 0) { - return gridTile( - isCurrent: isCurrent, - place: Places.topLeft, - image: flag, - text: code, - onTap: () { - selected = seedLanguages[index]; - Navigator.of(context).pop(selected); - }); + if (index == 8) { + + return gridTile( + isCurrent: false, + image: null, + text: '', + onTap: null); + + } + + final code = languageCodes[index]; + final flag = flagImages[index]; + final isCurrent = + index == seedLanguages.indexOf(selected); + + return gridTile( + isCurrent: isCurrent, + image: flag, + text: code, + onTap: () { + selected = seedLanguages[index]; + Navigator.of(context).pop(selected); } - - if (index == 2) { - return gridTile( - isCurrent: isCurrent, - place: Places.topRight, - image: flag, - text: code, - onTap: () { - selected = seedLanguages[index]; - Navigator.of(context).pop(selected); - }); - } - - if (index == 6) { - return gridTile( - isCurrent: isCurrent, - place: Places.bottomLeft, - image: flag, - text: code, - onTap: () { - selected = seedLanguages[index]; - Navigator.of(context).pop(selected); - }); - } - - return gridTile( - isCurrent: isCurrent, - place: Places.inside, - image: flag, - text: code, - onTap: () { - selected = seedLanguages[index]; - Navigator.of(context).pop(selected); - }); - } - }), - ), + ); + }), ), ), - ) - ], - ), + ), + ) + ], ), - ), - ), - ), + AlertCloseButton(image: closeButton) + ], + ) ); } - Widget gridTile( - {@required bool isCurrent, - @required Places place, - @required Image image, - @required String text, - @required VoidCallback onTap}) { - BorderRadius borderRadius; - final color = isCurrent - ? Theme.of(context).accentTextTheme.subtitle.decorationColor - : Theme.of(context).primaryTextTheme.display1.color; - final textColor = isCurrent - ? Colors.blue - : Theme.of(context).primaryTextTheme.title.color; + Widget gridTile({ + @required bool isCurrent, + @required Image image, + @required String text, + @required VoidCallback onTap}) { - switch (place) { - case Places.topLeft: - borderRadius = BorderRadius.only(topLeft: Radius.circular(14)); - break; - case Places.topRight: - borderRadius = BorderRadius.only(topRight: Radius.circular(14)); - break; - case Places.bottomLeft: - borderRadius = BorderRadius.only(bottomLeft: Radius.circular(14)); - break; - case Places.bottomRight: - borderRadius = BorderRadius.only(bottomRight: Radius.circular(14)); - break; - case Places.inside: - borderRadius = BorderRadius.all(Radius.circular(0)); - break; - } + final color = isCurrent + ? Theme.of(context).textTheme.body2.color + : Theme.of(context).accentTextTheme.title.color; + final textColor = isCurrent + ? Palette.blueCraiola + : Theme.of(context).primaryTextTheme.title.color; return GestureDetector( onTap: onTap, child: Container( padding: EdgeInsets.all(10), - decoration: BoxDecoration(borderRadius: borderRadius, color: color), + color: color, child: Center( child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - image != null ? image : Offstage(), + image ?? Offstage(), Padding( padding: image != null ? EdgeInsets.only(left: 10) @@ -229,14 +170,17 @@ class SeedLanguagePickerState extends State { text, style: TextStyle( fontSize: 18, - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w600, + fontFamily: 'Poppins', decoration: TextDecoration.none, - color: textColor), + color: textColor + ), ), ) ], ), ), - )); + ) + ); } } diff --git a/lib/src/screens/welcome/welcome_page.dart b/lib/src/screens/welcome/welcome_page.dart index 46a4fb89f..78cd04835 100644 --- a/lib/src/screens/welcome/welcome_page.dart +++ b/lib/src/screens/welcome/welcome_page.dart @@ -1,12 +1,10 @@ +import 'package:cake_wallet/di.dart'; +import 'package:cake_wallet/store/settings_store.dart'; import 'package:flutter/material.dart'; -import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:provider/provider.dart'; -import 'package:cake_wallet/themes.dart'; -import 'package:cake_wallet/theme_changer.dart'; class WelcomePage extends BasePage { static const aspectRatioImage = 1.25; @@ -23,14 +21,13 @@ class WelcomePage extends BasePage { @override Widget body(BuildContext context) { - final _themeChanger = Provider.of(context); - final welcomeImage = _themeChanger.getTheme() == Themes.darkTheme - ? welcomeImageDark : welcomeImageLight; + final welcomeImage = getIt.get().isDarkTheme + ? welcomeImageDark : welcomeImageLight; final newWalletImage = Image.asset('assets/images/new_wallet.png', height: 12, width: 12, - color: Palette.oceanBlue); + color: Theme.of(context).accentTextTheme.headline.decorationColor); final restoreWalletImage = Image.asset('assets/images/restore_wallet.png', height: 12, width: 12, @@ -60,13 +57,14 @@ class WelcomePage extends BasePage { S.of(context).welcome, style: TextStyle( fontSize: 18, - color: Theme.of(context).primaryTextTheme.caption.color, + fontWeight: FontWeight.w500, + color: Theme.of(context).accentTextTheme.display3.color, ), textAlign: TextAlign.center, ), ), Padding( - padding: EdgeInsets.only(top: 10), + padding: EdgeInsets.only(top: 5), child: Text( S.of(context).cake_wallet, style: TextStyle( @@ -78,13 +76,13 @@ class WelcomePage extends BasePage { ), ), Padding( - padding: EdgeInsets.only(top: 14), + padding: EdgeInsets.only(top: 5), child: Text( S.of(context).first_wallet_text, style: TextStyle( fontSize: 16, - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme.caption.color, + fontWeight: FontWeight.w500, + color: Theme.of(context).accentTextTheme.display3.color, ), textAlign: TextAlign.center, ), @@ -97,7 +95,8 @@ class WelcomePage extends BasePage { S.of(context).please_make_selection, style: TextStyle( fontSize: 12, - color: Theme.of(context).primaryTextTheme.caption.color, + fontWeight: FontWeight.normal, + color: Theme.of(context).accentTextTheme.display3.color, ), textAlign: TextAlign.center, ), @@ -107,18 +106,17 @@ class WelcomePage extends BasePage { onPressed: () => Navigator.pushNamed(context, Routes.newWalletFromWelcome), image: newWalletImage, text: S.of(context).create_new, - color: Colors.white, - textColor: Palette.oceanBlue, - borderColor: Palette.oceanBlue, + color: Theme.of(context).accentTextTheme.subtitle.decorationColor, + textColor: Theme.of(context).accentTextTheme.headline.decorationColor, ), ), Padding( padding: EdgeInsets.only(top: 10), child: PrimaryImageButton( - onPressed: () => Navigator.pushNamed(context, Routes.restoreOptions), + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome), image: restoreWalletImage, text: S.of(context).restore_wallet, - color: Theme.of(context).primaryTextTheme.overline.color, + color: Theme.of(context).accentTextTheme.caption.color, textColor: Theme.of(context).primaryTextTheme.title.color), ) ], diff --git a/lib/src/widgets/base_alert_dialog.dart b/lib/src/widgets/base_alert_dialog.dart index 14b5a58a4..d22d01d5a 100644 --- a/lib/src/widgets/base_alert_dialog.dart +++ b/lib/src/widgets/base_alert_dialog.dart @@ -31,6 +31,7 @@ class BaseAlertDialog extends StatelessWidget { textAlign: TextAlign.center, style: TextStyle( fontSize: 16, + fontWeight: FontWeight.normal, fontFamily: 'Poppins', color: Theme.of(context).primaryTextTheme.title.color, decoration: TextDecoration.none, diff --git a/lib/src/widgets/blockchain_height_widget.dart b/lib/src/widgets/blockchain_height_widget.dart index 9e66d4077..2f6105887 100644 --- a/lib/src/widgets/blockchain_height_widget.dart +++ b/lib/src/widgets/blockchain_height_widget.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/domain/monero/get_height_by_date.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; class BlockchainHeightWidget extends StatefulWidget { BlockchainHeightWidget({GlobalKey key, this.onHeightChange}) @@ -46,26 +47,12 @@ class BlockchainHeightState extends State { Flexible( child: Container( padding: EdgeInsets.only(top: 20.0, bottom: 10.0), - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color), + child: BaseTextFormField( controller: restoreHeightController, keyboardType: TextInputType.numberWithOptions( signed: false, decimal: false), - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context).primaryTextTheme.caption.color, - fontSize: 16), - hintText: S.of(context).widgets_restore_from_blockheight, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), - ), + hintText: S.of(context).widgets_restore_from_blockheight, + ) )) ], ), @@ -75,7 +62,7 @@ class BlockchainHeightState extends State { S.of(context).widgets_or, style: TextStyle( fontSize: 16.0, - fontWeight: FontWeight.bold, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color), ), ), @@ -86,31 +73,10 @@ class BlockchainHeightState extends State { child: InkWell( onTap: () => _selectDate(context), child: IgnorePointer( - child: TextFormField( - style: TextStyle( - fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.title.color), - decoration: InputDecoration( - hintStyle: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .caption - .color, - fontSize: 16), - hintText: S.of(context).widgets_restore_from_date, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0)), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Theme.of(context).dividerColor, - width: 1.0))), + child: BaseTextFormField( controller: dateController, - validator: (value) { - return null; - }, - ), + hintText: S.of(context).widgets_restore_from_date, + ) ), ), )) diff --git a/lib/src/widgets/seed_language_selector.dart b/lib/src/widgets/seed_language_selector.dart index f66cadb8e..74420d370 100644 --- a/lib/src/widgets/seed_language_selector.dart +++ b/lib/src/widgets/seed_language_selector.dart @@ -34,14 +34,14 @@ class SeedLanguageSelectorState extends State { return SelectButton( image: null, text: seedLocales[seedLanguages.indexOf(selected)], - color: Theme.of(context).accentTextTheme.title.backgroundColor, - textColor: Theme.of(context).primaryTextTheme.title.color, onTap: () async { final selected = await showDialog( context: context, builder: (BuildContext context) => SeedLanguagePicker(key: _pickerKey, selected: this.selected)); - setState(() => this.selected = selected); + if (selected != null) { + setState(() => this.selected = selected); + } }); } } diff --git a/lib/src/widgets/seed_widget.dart b/lib/src/widgets/seed_widget.dart index c9b918556..5da136c74 100644 --- a/lib/src/widgets/seed_widget.dart +++ b/lib/src/widgets/seed_widget.dart @@ -6,6 +6,7 @@ import 'package:cake_wallet/core/seed_validator.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/domain/common/mnemonic_item.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter/widgets.dart'; class SeedWidget extends StatefulWidget { SeedWidget( @@ -13,6 +14,8 @@ class SeedWidget extends StatefulWidget { this.maxLength, this.onMnemonicChange, this.onFinish, + this.leading, + this.middle, this.validator}) : super(key: key); @@ -20,6 +23,8 @@ class SeedWidget extends StatefulWidget { final Function(List) onMnemonicChange; final Function() onFinish; final SeedValidator validator; + final Widget leading; + final Widget middle; @override SeedWidgetState createState() => SeedWidgetState(maxLength: maxLength); @@ -199,74 +204,91 @@ class SeedWidgetState extends State { child: Column(children: [ Flexible( fit: FlexFit.tight, - flex: 1, + flex: 2, child: Container( width: double.infinity, height: double.infinity, - padding: EdgeInsets.all(24), + padding: EdgeInsets.all(0), decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)), - color: Theme.of(context).accentTextTheme.title.backgroundColor), - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - S.of(context).restore_active_seed, - style: TextStyle( - fontSize: 14, - color: - Theme.of(context).primaryTextTheme.caption.color), - ), - Padding( - padding: EdgeInsets.only(top: 5), - child: Wrap( - children: items.map((item) { - final isValid = widget.validator.isValid(item); - final isSelected = selectedItem == item; - - return InkWell( - onTap: () => onMnemonicTap(item), - child: Container( - decoration: BoxDecoration( - color: isValid - ? Colors.transparent - : Palette.red), - margin: EdgeInsets.only(right: 7, bottom: 8), - child: Text( - item.toString(), - style: TextStyle( - color: isValid - ? Theme.of(context) - .primaryTextTheme - .title - .color - : Theme.of(context) - .primaryTextTheme - .caption - .color, - fontSize: 16, - fontWeight: isSelected - ? FontWeight.w900 - : FontWeight.w400, - decoration: isSelected - ? TextDecoration.underline - : TextDecoration.none), - )), - ); - }).toList(), - )) + gradient: LinearGradient(colors: [ + Theme.of(context).primaryTextTheme.subhead.color, + Theme.of(context).primaryTextTheme.subhead.decorationColor, ], - ), + begin: Alignment.topLeft, + end: Alignment.bottomRight) ), + child: Column( + children: [ + CupertinoNavigationBar( + leading: widget.leading, + middle: widget.middle, + backgroundColor: Colors.transparent, + border: null, + ), + Expanded( + child: Container( + padding: EdgeInsets.all(24), + alignment: Alignment.topLeft, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + S.of(context).restore_active_seed, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: + Theme.of(context).textTheme.overline.backgroundColor), + ), + Padding( + padding: EdgeInsets.only(top: 5), + child: Wrap( + children: items.map((item) { + final isValid = widget.validator.isValid(item); + final isSelected = selectedItem == item; + + return InkWell( + onTap: () => onMnemonicTap(item), + child: Container( + decoration: BoxDecoration( + color: isValid + ? Colors.transparent + : Palette.red), + margin: EdgeInsets.only(right: 7, bottom: 8), + child: Text( + item.toString(), + style: TextStyle( + color: isValid + ? Colors.white + : Colors.grey, + fontSize: 16, + fontWeight: isSelected + ? FontWeight.w900 + : FontWeight.w600, + decoration: isSelected + ? TextDecoration.underline + : TextDecoration.none), + )), + ); + }).toList(), + )) + ], + ), + ), + ) + ) + ], + ) ), ), Flexible( fit: FlexFit.tight, - flex: 2, + flex: 3, child: Padding( padding: EdgeInsets.only(left: 24, top: 48, right: 24, bottom: 24), @@ -277,8 +299,8 @@ class SeedWidgetState extends State { Text( S.of(context).restore_new_seed, style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, + fontSize: 20, + fontWeight: FontWeight.w500, color: Theme.of(context).primaryTextTheme.title.color), ), @@ -291,6 +313,7 @@ class SeedWidgetState extends State { : null, style: TextStyle( fontSize: 16.0, + fontWeight: FontWeight.normal, color: Theme.of(context).primaryTextTheme.title.color), controller: _seedController, @@ -306,10 +329,11 @@ class SeedWidgetState extends State { Text('${items.length}/$maxLength', style: TextStyle( color: Theme.of(context) - .primaryTextTheme - .caption - .color, - fontSize: 14)), + .accentTextTheme + .display2 + .decorationColor, + fontWeight: FontWeight.normal, + fontSize: 16)), SizedBox(width: 10), InkWell( onTap: () async => @@ -322,17 +346,14 @@ class SeedWidgetState extends State { decoration: BoxDecoration( color: Theme.of(context) .accentTextTheme - .title - .backgroundColor, + .caption + .color, borderRadius: BorderRadius.circular(10.0)), child: Text( S.of(context).paste, style: TextStyle( - color: Theme.of(context) - .primaryTextTheme - .title - .color), + color: Palette.blueCraiola), )), ) ], @@ -341,20 +362,21 @@ class SeedWidgetState extends State { ), hintStyle: TextStyle( color: Theme.of(context) - .primaryTextTheme - .caption - .color, + .accentTextTheme + .display2 + .decorationColor, + fontWeight: FontWeight.normal, fontSize: 16), hintText: S.of(context).restore_from_seed_placeholder, errorText: _errorMessage, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).dividerColor, + color: Theme.of(context).accentTextTheme.subtitle.backgroundColor, width: 1.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).dividerColor, + color: Theme.of(context).accentTextTheme.subtitle.backgroundColor, width: 1.0))), enableInteractiveSelection: false, ), @@ -386,7 +408,7 @@ class SeedWidgetState extends State { onPressed: () => widget.onFinish != null ? widget.onFinish() : null, - color: Colors.green, + color: Palette.blueCraiola, textColor: Colors.white) : PrimaryButton( text: selectedItem != null @@ -397,7 +419,7 @@ class SeedWidgetState extends State { : null, onDisabledPressed: () => showErrorIfExist(), isDisabled: !isCurrentMnemonicValid, - color: Colors.green, + color: Palette.blueCraiola, textColor: Colors.white), ), ) diff --git a/lib/themes.dart b/lib/themes.dart index a25a61de1..e2f75b7ff 100644 --- a/lib/themes.dart +++ b/lib/themes.dart @@ -154,6 +154,11 @@ class Themes { ), display2: TextStyle( color: Palette.shadowWhite, // action button color (address text field) + decorationColor: Palette.darkGray // hint text (seed widget) + ), + display3: TextStyle( + color: Palette.darkGray, // hint text (new wallet page) + decorationColor: Palette.periwinkleCraiola // underline (new wallet page) ), ), @@ -320,6 +325,11 @@ class Themes { ), display2: TextStyle( color: PaletteDark.nightBlue, // action button color (address text field) + decorationColor: PaletteDark.darkCyanBlue // hint text (seed widget) + ), + display3: TextStyle( + color: PaletteDark.cyanBlue, // hint text (new wallet page) + decorationColor: PaletteDark.darkGrey // underline (new wallet page) ), ), diff --git a/lib/view_model/wallet_restoration_from_keys_vm.dart b/lib/view_model/wallet_restoration_from_keys_vm.dart new file mode 100644 index 000000000..e0e0114c6 --- /dev/null +++ b/lib/view_model/wallet_restoration_from_keys_vm.dart @@ -0,0 +1,64 @@ +import 'package:flutter/foundation.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/monero/monero_wallet_service.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_wallet_creation_credentials.dart'; +import 'package:cake_wallet/core/generate_wallet_password.dart'; +import 'package:cake_wallet/core/wallet_creation_service.dart'; +import 'package:cake_wallet/core/wallet_credentials.dart'; +import 'package:cake_wallet/src/domain/common/wallet_type.dart'; +import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; +import 'package:cake_wallet/src/domain/common/wallet_info.dart'; + +part 'wallet_restoration_from_keys_vm.g.dart'; + +class WalletRestorationFromKeysVM = WalletRestorationFromKeysVMBase + with _$WalletRestorationFromKeysVM; + +abstract class WalletRestorationFromKeysVMBase extends WalletCreationVM + with Store { + WalletRestorationFromKeysVMBase(this._walletCreationService, Box walletInfoSource, + {@required WalletType type, @required this.language}) + : super(walletInfoSource, type: type, isRecovery: true); + + @observable + int height; + + @observable + String viewKey; + + @observable + String spendKey; + + @observable + String wif; + + @observable + String address; + + bool get hasRestorationHeight => type == WalletType.monero; + + final String language; + final WalletCreationService _walletCreationService; + + @override + WalletCredentials getCredentials(dynamic options) { + final password = generateWalletPassword(type); + + switch (type) { + case WalletType.monero: + return MoneroRestoreWalletFromKeysCredentials( + name: name, password: password, language: language, address: address, + viewKey: viewKey, spendKey: spendKey, height: height); + case WalletType.bitcoin: + return BitcoinRestoreWalletFromWIFCredentials( + name: name, password: password, wif: wif); + default: + return null; + } + } + + @override + Future process(WalletCredentials credentials) async => + _walletCreationService.restoreFromKeys(credentials); +} diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index 68095ca01..219e17320 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Beschreibung zur Wiederherstellung der Brieftasche", "restore_new_seed" : "Neuer Seed", "restore_active_seed" : "Aktives Seed", + "restore_bitcoin_description_from_seed" : "Stellen Sie Ihre Brieftasche aus dem 12-Wort-Kombinationscode wieder her", + "restore_bitcoin_description_from_keys" : "Stellen Sie Ihre Brieftasche aus der generierten WIF-Zeichenfolge aus Ihren privaten Schlüsseln wieder her", + "restore_bitcoin_title_from_keys" : "Aus WIF wiederherstellen", "seed_title" : "Seed", diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 277ce28ba..82afbe400 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Wallet restore description", "restore_new_seed" : "New seed", "restore_active_seed" : "Active seed", + "restore_bitcoin_description_from_seed" : "Restore your wallet from 12 word combination code", + "restore_bitcoin_description_from_keys" : "Restore your wallet from generated WIF string from your private keys", + "restore_bitcoin_title_from_keys" : "Restore from WIF", "seed_title" : "Seed", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index f6cc257f6..f01e9002b 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Restaurar billetera", "restore_new_seed" : "Nueva semilla", "restore_active_seed" : "Semilla activa", + "restore_bitcoin_description_from_seed" : "Restaure su billetera a partir del código de combinación de 12 palabras", + "restore_bitcoin_description_from_keys" : "Restaure su billetera a partir de una cadena WIF generada a partir de sus claves privadas", + "restore_bitcoin_title_from_keys" : "Restaurar desde WIF", "seed_title" : "Semilla", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index 9e0e1a032..7b0d95adf 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "बटुआ विवरण पुनर्स्थापित करें", "restore_new_seed" : "नया बीज", "restore_active_seed" : "सक्रिय बीज", + "restore_bitcoin_description_from_seed" : "12 शब्द संयोजन कोड से अपने वॉलेट को पुनर्स्थापित करें", + "restore_bitcoin_description_from_keys" : "अपने निजी कुंजी से उत्पन्न WIF स्ट्रिंग से अपने वॉलेट को पुनर्स्थापित करें", + "restore_bitcoin_title_from_keys" : "WIF से पुनर्स्थापित करें", "seed_title" : "बीज", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index a1822f806..000475bd8 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "ウォレットの復元", "restore_new_seed" : "新しい種", "restore_active_seed" : "アクティブシード", + "restore_bitcoin_description_from_seed" : "12ワードの組み合わせコードからウォレットを復元する", + "restore_bitcoin_description_from_keys" : "秘密鍵から生成されたWIF文字列からウォレットを復元します", + "restore_bitcoin_title_from_keys" : "WIFから復元", "seed_title" : "シード", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 31d7f6cfd..c33dded12 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "월렛 복원 설명", "restore_new_seed" : "새로운 씨앗", "restore_active_seed" : "활성 종자", + "restore_bitcoin_description_from_seed" : "12 단어 조합 코드에서 지갑 복원", + "restore_bitcoin_description_from_keys" : "개인 키에서 생성 된 WIF 문자열에서 지갑 복원", + "restore_bitcoin_title_from_keys" : "WIF에서 복원", "seed_title" : "씨", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index 542be0271..2fc68aef3 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Portemonnee-herstelbeschrijving", "restore_new_seed" : "Nieuw zaad", "restore_active_seed" : "Actief zaad", + "restore_bitcoin_description_from_seed" : "Herstel uw portemonnee met een combinatiecode van 12 woorden", + "restore_bitcoin_description_from_keys" : "Herstel uw portemonnee van de gegenereerde WIF-string van uw privésleutels", + "restore_bitcoin_title_from_keys" : "Herstel van WIF", "seed_title" : "Zaad", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index da2bd6f2e..5970fadb8 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Opis przywracania portfela", "restore_new_seed" : "Nowe nasienie", "restore_active_seed" : "Aktywne nasiona", + "restore_bitcoin_description_from_seed" : "Przywróć swój portfel z kodu złożonego z 12 słów", + "restore_bitcoin_description_from_keys" : "Przywróć swój portfel z wygenerowanego ciągu WIF z kluczy prywatnych", + "restore_bitcoin_title_from_keys" : "Przywróć z WIF", "seed_title" : "Ziarno", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7f4df2a4a..f085280bf 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Restauração da carteira", "restore_new_seed" : "Nova semente", "restore_active_seed" : "Semente ativa", + "restore_bitcoin_description_from_seed" : "Restaure sua carteira a partir de um código de combinação de 12 palavras", + "restore_bitcoin_description_from_keys" : "Restaure sua carteira a partir da string WIF gerada de suas chaves privadas", + "restore_bitcoin_title_from_keys" : "Restaurar de WIF", "seed_title" : "Semente", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b5f82e379..68c1453b3 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Описание восстановления кошелька", "restore_new_seed" : "Новая мнемоническая фраза", "restore_active_seed" : "Активная мнемоническая фраза", + "restore_bitcoin_description_from_seed" : "Вы можете восстановить кошелёк используя 12-ти значную мнемоническую фразу", + "restore_bitcoin_description_from_keys" : "Вы можете восстановить кошелёк с помощью WIF", + "restore_bitcoin_title_from_keys" : "Восстановить с помощью WIF", "seed_title" : "Мнемоническая фраза", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index bcfc96688..2cf2119b2 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "Опис відновлюваного гаманця", "restore_new_seed" : "Нова мнемонічна фраза", "restore_active_seed" : "Активна мнемонічна фраза", + "restore_bitcoin_description_from_seed" : "Ви можете відновити гаманець використовуючи 12-ти слівну мнемонічну фразу", + "restore_bitcoin_description_from_keys" : "Ви можете відновити гаманець за допомогою WIF", + "restore_bitcoin_title_from_keys" : "Відновити за допомогою WIF", "seed_title" : "Мнемонічна фраза", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 0f5794a10..8fcce5de1 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -165,6 +165,9 @@ "restore_wallet_restore_description" : "钱包还原说明", "restore_new_seed" : "新種子", "restore_active_seed" : "活性種子", + "restore_bitcoin_description_from_seed" : "從12個單詞的組合碼恢復您的錢包", + "restore_bitcoin_description_from_keys" : "從私鑰中生成的WIF字符串還原您的錢包", + "restore_bitcoin_title_from_keys" : "從WIF還原", "seed_title" : "种子",