diff --git a/analysis_options.yaml b/analysis_options.yaml index 4c0b97735..139f2b9bb 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -5,17 +5,14 @@ analyzer: implicit-casts: false implicit-dynamic: false exclude: - - **/*.yaml - - build/** - - **/*.g.dart - - lib/generated/*.dart + - "build/**" + - "**/*.g.dart" + - "lib/generated/*.dart" linter: rules: - always_declare_return_types - - always_specify_types - annotate_overrides - - avoid_as - avoid_empty_else - avoid_init_to_null - avoid_return_types_on_setters @@ -48,17 +45,13 @@ linter: - prefer_final_fields - prefer_final_locals - prefer_is_not_empty - - public_member_api_docs - slash_for_doc_comments - sort_constructors_first - sort_unnamed_constructors_first - - super_goes_last - test_types_in_equals - throw_in_finally - - type_annotate_public_apis - type_init_formals - unawaited_futures - - unnecessary_brace_in_string_interp - unnecessary_getters_setters - unrelated_type_equality_checks - valid_regexps \ No newline at end of file diff --git a/cw_monero/lib/account_list.dart b/cw_monero/lib/account_list.dart index f72c57ae2..bf5618a1b 100644 --- a/cw_monero/lib/account_list.dart +++ b/cw_monero/lib/account_list.dart @@ -26,7 +26,7 @@ final accountSetLabelNative = moneroApi .lookup>('account_set_label_row') .asFunction(); -refreshAccounts() => accountRefreshNative(); +void refreshAccounts() => accountRefreshNative(); List getAllAccount() { final size = accountSizeNative(); @@ -38,24 +38,29 @@ List getAllAccount() { .toList(); } -addAccountSync({String label}) { +void addAccountSync({String label}) { final labelPointer = Utf8.toUtf8(label); accountAddNewNative(labelPointer); free(labelPointer); } -setLabelForAccountSync({int accountIndex, String label}) { +void setLabelForAccountSync({int accountIndex, String label}) { final labelPointer = Utf8.toUtf8(label); accountSetLabelNative(accountIndex, labelPointer); free(labelPointer); } -_addAccount(String label) => addAccountSync(label: label); +void _addAccount(String label) => addAccountSync(label: label); -_setLabelForAccount(Map args) => setLabelForAccountSync( - label: args['label'], accountIndex: args['accountIndex']); +void _setLabelForAccount(Map args) { + final label = args['label'] as String; + final accountIndex = args['accountIndex'] as int; -Future addAccount({String label}) async => compute(_addAccount, label); + setLabelForAccountSync(label: label, accountIndex: accountIndex); +} -Future setLabelForAccount({int accountIndex, String label}) async => compute( - _setLabelForAccount, {'accountIndex': accountIndex, 'label': label}); +Future addAccount({String label}) async => compute(_addAccount, label); + +Future setLabelForAccount({int accountIndex, String label}) async => + compute( + _setLabelForAccount, {'accountIndex': accountIndex, 'label': label}); diff --git a/cw_monero/lib/exceptions/connection_to_node_exception.dart b/cw_monero/lib/exceptions/connection_to_node_exception.dart index 4a3733f52..6ee272b89 100644 --- a/cw_monero/lib/exceptions/connection_to_node_exception.dart +++ b/cw_monero/lib/exceptions/connection_to_node_exception.dart @@ -1,5 +1,5 @@ class ConnectionToNodeException implements Exception { - final String message; - ConnectionToNodeException({this.message}); + + final String message; } \ No newline at end of file diff --git a/cw_monero/lib/exceptions/creation_transaction_exception.dart b/cw_monero/lib/exceptions/creation_transaction_exception.dart index 94bb2a53f..bb477d673 100644 --- a/cw_monero/lib/exceptions/creation_transaction_exception.dart +++ b/cw_monero/lib/exceptions/creation_transaction_exception.dart @@ -1,7 +1,7 @@ class CreationTransactionException implements Exception { - final String message; - CreationTransactionException({this.message}); + + final String message; @override String toString() => message; diff --git a/cw_monero/lib/exceptions/setup_wallet_exception.dart b/cw_monero/lib/exceptions/setup_wallet_exception.dart index 0c044fe67..ce43c0ec6 100644 --- a/cw_monero/lib/exceptions/setup_wallet_exception.dart +++ b/cw_monero/lib/exceptions/setup_wallet_exception.dart @@ -1,5 +1,5 @@ class SetupWalletException implements Exception { - final String message; - SetupWalletException({this.message}); + + final String message; } \ No newline at end of file diff --git a/cw_monero/lib/exceptions/wallet_creation_exception.dart b/cw_monero/lib/exceptions/wallet_creation_exception.dart index cb1984ab6..a35553385 100644 --- a/cw_monero/lib/exceptions/wallet_creation_exception.dart +++ b/cw_monero/lib/exceptions/wallet_creation_exception.dart @@ -1,5 +1,5 @@ class WalletCreationException implements Exception { - final String message; - WalletCreationException({this.message}); + + final String message; } \ No newline at end of file diff --git a/cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart b/cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart index bf16c1cae..5f08437d4 100644 --- a/cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart +++ b/cw_monero/lib/exceptions/wallet_restore_from_keys_exception.dart @@ -1,5 +1,5 @@ class WalletRestoreFromKeysException implements Exception { - final String message; - WalletRestoreFromKeysException({this.message}); + + final String message; } \ No newline at end of file diff --git a/cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart b/cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart index 6d48684ff..fd89e4161 100644 --- a/cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart +++ b/cw_monero/lib/exceptions/wallet_restore_from_seed_exception.dart @@ -1,5 +1,5 @@ class WalletRestoreFromSeedException implements Exception { - final String message; - WalletRestoreFromSeedException({this.message}); + + final String message; } \ No newline at end of file diff --git a/cw_monero/lib/structs/pending_transaction.dart b/cw_monero/lib/structs/pending_transaction.dart index fa88a9faa..b492f28a0 100644 --- a/cw_monero/lib/structs/pending_transaction.dart +++ b/cw_monero/lib/structs/pending_transaction.dart @@ -14,10 +14,10 @@ class PendingTransactionRaw extends Struct { } class PendingTransactionDescription { + PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress}); + final int amount; final int fee; final String hash; final int pointerAddress; - - PendingTransactionDescription({this.amount, this.fee, this.hash, this.pointerAddress}); } \ No newline at end of file diff --git a/cw_monero/lib/subaddress_list.dart b/cw_monero/lib/subaddress_list.dart index ba93af453..e6ad85dd0 100644 --- a/cw_monero/lib/subaddress_list.dart +++ b/cw_monero/lib/subaddress_list.dart @@ -26,7 +26,7 @@ final subaddrressSetLabelNative = moneroApi .lookup>('subaddress_set_label') .asFunction(); -refreshSubaddresses({int accountIndex}) => +void refreshSubaddresses({int accountIndex}) => subaddressRefreshNative(accountIndex); List getAllSubaddresses() { @@ -40,25 +40,35 @@ List getAllSubaddresses() { .toList(); } -addSubaddressSync({int accountIndex, String label}) { +void addSubaddressSync({int accountIndex, String label}) { final labelPointer = Utf8.toUtf8(label); subaddrressAddNewNative(accountIndex, labelPointer); free(labelPointer); } -setLabelForSubaddressSync({int accountIndex, int addressIndex, String label}) { +void setLabelForSubaddressSync( + {int accountIndex, int addressIndex, String label}) { final labelPointer = Utf8.toUtf8(label); + subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer); free(labelPointer); } -_addSubaddress(Map args) => - addSubaddressSync(accountIndex: args['accountIndex'], label: args['label']); +void _addSubaddress(Map args) { + final label = args['label'] as String; + final accountIndex = args['accountIndex'] as int; -_setLabelForSubaddress(Map args) => setLabelForSubaddressSync( - accountIndex: args['accountIndex'], - addressIndex: args['addressIndex'], - label: args['label']); + addSubaddressSync(accountIndex: accountIndex, label: label); +} + +void _setLabelForSubaddress(Map args) { + final label = args['label'] as String; + final accountIndex = args['accountIndex'] as int; + final addressIndex = args['addressIndex'] as int; + + setLabelForSubaddressSync( + accountIndex: accountIndex, addressIndex: addressIndex, label: label); +} Future addSubaddress({int accountIndex, String label}) async => compute(_addSubaddress, {'accountIndex': accountIndex, 'label': label}); @@ -69,4 +79,4 @@ Future setLabelForSubaddress( 'accountIndex': accountIndex, 'addressIndex': addressIndex, 'label': label - }); \ No newline at end of file + }); diff --git a/cw_monero/lib/transaction_history.dart b/cw_monero/lib/transaction_history.dart index 1b3ce9126..2eacbb744 100644 --- a/cw_monero/lib/transaction_history.dart +++ b/cw_monero/lib/transaction_history.dart @@ -29,7 +29,7 @@ final transactionCommitNative = moneroApi .lookup>('transaction_commit') .asFunction(); -refreshTransactions() => transactionsRefreshNative(); +void refreshTransactions() => transactionsRefreshNative(); int countOfTransactions() => transactionsCountNative(); @@ -84,10 +84,10 @@ PendingTransactionDescription createTransactionSync( pointerAddress: pendingTransactionRawPointer.address); } -commitTransactionFromPointerAddress({int address}) => commitTransaction( +void commitTransactionFromPointerAddress({int address}) => commitTransaction( transactionPointer: Pointer.fromAddress(address)); -commitTransaction({Pointer transactionPointer}) { +void commitTransaction({Pointer transactionPointer}) { final errorMessagePointer = allocate(); final isCommited = transactionCommitNative(transactionPointer, errorMessagePointer) != 0; @@ -99,13 +99,20 @@ commitTransaction({Pointer transactionPointer}) { } } -PendingTransactionDescription _createTransactionSync(Map args) => - createTransactionSync( - address: args['address'], - paymentId: args['paymentId'], - amount: args['amount'], - priorityRaw: args['priorityRaw'], - accountIndex: args['accountIndex']); +PendingTransactionDescription _createTransactionSync(Map args) { + final address = args['address'] as String; + final paymentId = args['paymentId'] as String; + final amount = args['amount'] as String; + final priorityRaw = args['priorityRaw'] as int; + final accountIndex = args['accountIndex'] as int; + + return createTransactionSync( + address: address, + paymentId: paymentId, + amount: amount, + priorityRaw: priorityRaw, + accountIndex: accountIndex); +} Future createTransaction( {String address, diff --git a/cw_monero/lib/wallet.dart b/cw_monero/lib/wallet.dart index 560d6a79c..cdb23d07d 100644 --- a/cw_monero/lib/wallet.dart +++ b/cw_monero/lib/wallet.dart @@ -179,23 +179,23 @@ bool setupNodeSync( return isSetupNode; } -startRefreshSync() => startRefreshNative(); +void startRefreshSync() => startRefreshNative(); Future connectToNode() async => connecToNodeNative() != 0; -setRefreshFromBlockHeight({int height}) => +void setRefreshFromBlockHeight({int height}) => setRefreshFromBlockHeightNative(height); -setRecoveringFromSeed({bool isRecovery}) => +void setRecoveringFromSeed({bool isRecovery}) => setRecoveringFromSeedNative(_boolToInt(isRecovery)); -storeSync() { +void storeSync() { final pathPointer = Utf8.toUtf8(''); storeNative(pathPointer); free(pathPointer); } -closeCurrentWallet() => closeCurrentWalletNative(); +void closeCurrentWallet() => closeCurrentWalletNative(); String getSecretViewKey() => convertUTF8ToString(pointer: getSecretViewKeyNative()); @@ -213,8 +213,8 @@ Timer _updateSyncInfoTimer; int _lastKnownBlockHeight = 0; -setListeners(Future Function(int) onNewBlock, Future Function() onNeedToRefresh, - Future Function() onNewTransaction) { +void setListeners(Future Function(int) onNewBlock, + Future Function() onNeedToRefresh, Future Function() onNewTransaction) { if (_updateSyncInfoTimer != null) { _updateSyncInfoTimer.cancel(); } @@ -240,25 +240,36 @@ setListeners(Future Function(int) onNewBlock, Future Function() onNeedToRefresh, setListenerNative(); } -closeListeners() { +void closeListeners() { if (_updateSyncInfoTimer != null) { _updateSyncInfoTimer.cancel(); } } -onStartup() => onStartupNative(); +void onStartup() => onStartupNative(); -_storeSync(_) => storeSync(); -bool _setupNodeSync(Map args) => setupNodeSync( - address: args['address'], - login: args['login'] ?? '', - password: args['password'] ?? '', - useSSL: args['useSSL'], - isLightWallet: args['isLightWallet']); -bool _isConnected(_) => isConnectedSync(); -int _getNodeHeight(_) => getNodeHeightSync(); +void _storeSync(Object _) => storeSync(); -startRefresh() => startRefreshSync(); +bool _setupNodeSync(Map args) { + final address = args['address'] as String; + final login = (args['login'] ?? '') as String; + final password = (args['password'] ?? '') as String; + final useSSL = args['useSSL'] as bool; + final isLightWallet = args['isLightWallet'] as bool; + + return setupNodeSync( + address: address, + login: login, + password: password, + useSSL: useSSL, + isLightWallet: isLightWallet); +} + +bool _isConnected(Object _) => isConnectedSync(); + +int _getNodeHeight(Object _) => getNodeHeightSync(); + +void startRefresh() => startRefreshSync(); Future setupNode( {String address, @@ -280,4 +291,4 @@ Future isConnected() => compute(_isConnected, 0); Future getNodeHeight() => compute(_getNodeHeight, 0); -rescanBlockchainAsync() => rescanBlockchainAsyncNative(); \ No newline at end of file +void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); diff --git a/cw_monero/lib/wallet_manager.dart b/cw_monero/lib/wallet_manager.dart index 4c6e2ef54..8d37941ef 100644 --- a/cw_monero/lib/wallet_manager.dart +++ b/cw_monero/lib/wallet_manager.dart @@ -31,7 +31,7 @@ final loadWalletNative = moneroApi .lookup>('load_wallet') .asFunction(); -createWalletSync( +void createWalletSync( {String path, String password, String language = 'English', @@ -63,7 +63,7 @@ bool isWalletExistSync({String path}) { return isExist; } -restoreWalletFromSeedSync( +void restoreWalletFromSeedSync( {String path, String password, String seed, @@ -92,7 +92,7 @@ restoreWalletFromSeedSync( } } -restoreWalletFromKeysSync( +void restoreWalletFromKeysSync( {String path, String password, String language = 'English', @@ -133,7 +133,7 @@ restoreWalletFromKeysSync( } } -loadWallet({String path, String password, int nettype = 0}) { +void loadWallet({String path, String password, int nettype = 0}) { final pathPointer = Utf8.toUtf8(path); final passwordPointer = Utf8.toUtf8(password); @@ -142,34 +142,52 @@ loadWallet({String path, String password, int nettype = 0}) { free(passwordPointer); } -_createWallet(args) => - createWalletSync(path: args['path'], password: args['password']); +void _createWallet(Map args) { + final path = args['path'] as String; + final password = args['password'] as String; -_restoreFromSeed(args) => restoreWalletFromSeedSync( - path: args['path'], - password: args['password'], - seed: args['seed'], - restoreHeight: args['restoreHeight']); + createWalletSync(path: path, password: password); +} -_restoreFromKeys(args) => restoreWalletFromKeysSync( - path: args['path'], - password: args['password'], - restoreHeight: args['restoreHeight'], - address: args['address'], - viewKey: args['viewKey'], - spendKey: args['spendKey']); +void _restoreFromSeed(Map args) { + final path = args['path'] as String; + final password = args['password'] as String; + final seed = args['seed'] as String; + final restoreHeight = args['restoreHeight'] as int; -_openWallet(Map args) async => + restoreWalletFromSeedSync( + path: path, password: password, seed: seed, restoreHeight: restoreHeight); +} + +void _restoreFromKeys(Map args) { + final path = args['path'] as String; + final password = args['password'] as String; + final restoreHeight = args['restoreHeight'] as int; + final address = args['address'] as String; + final viewKey = args['viewKey'] as String; + final spendKey = args['spendKey'] as String; + + restoreWalletFromKeysSync( + path: path, + password: password, + restoreHeight: restoreHeight, + address: address, + viewKey: viewKey, + spendKey: spendKey); +} + +Future _openWallet(Map args) async => loadWallet(path: args['path'], password: args['password']); bool _isWalletExist(String path) => isWalletExistSync(path: path); -openWallet({String path, String password, int nettype = 0}) async => +void openWallet({String path, String password, int nettype = 0}) async => loadWallet(path: path, password: password); -Future openWalletAsync(Map args) async => compute(_openWallet, args); +Future openWalletAsync(Map args) async => + compute(_openWallet, args); -Future createWallet( +Future createWallet( {String path, String password, String language = 'English', @@ -215,4 +233,4 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); -Future isWalletExist({String path}) => compute(_isWalletExist, path); \ No newline at end of file +Future isWalletExist({String path}) => compute(_isWalletExist, path); diff --git a/lib/main.dart b/lib/main.dart index 16ffa4c0e..c97b83b20 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; -import 'package:cw_monero/wallet.dart' as moneroWallet; +import 'package:cw_monero/wallet.dart' as monero_wallet; import 'package:cake_wallet/router.dart'; import 'theme_changer.dart'; import 'themes.dart'; @@ -39,7 +39,7 @@ import 'package:cake_wallet/src/domain/common/language.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - var appDir = await getApplicationDocumentsDirectory(); + final appDir = await getApplicationDocumentsDirectory(); Hive.init(appDir.path); Hive.registerAdapter(ContactAdapter(), 0); Hive.registerAdapter(NodeAdapter(), 1); @@ -50,18 +50,20 @@ void main() async { final secureStorage = FlutterSecureStorage(); final transactionDescriptionsBoxKey = await getEncryptionKey( - secureStorage: secureStorage, forKey: 'transactionDescriptionsBoxKey'); // FIXME: Unnamed constant + secureStorage: secureStorage, + forKey: 'transactionDescriptionsBoxKey'); // FIXME: Unnamed constant final tradesBoxKey = await getEncryptionKey( - secureStorage: secureStorage, forKey: 'tradesBoxKey'); // FIXME: Unnamed constant + secureStorage: secureStorage, + forKey: 'tradesBoxKey'); // FIXME: Unnamed constant - var contacts = await Hive.openBox(Contact.boxName); - var nodes = await Hive.openBox(Node.boxName); - var transactionDescriptions = await Hive.openBox( + final contacts = await Hive.openBox(Contact.boxName); + final nodes = await Hive.openBox(Node.boxName); + final transactionDescriptions = await Hive.openBox( TransactionDescription.boxName, encryptionKey: transactionDescriptionsBoxKey); - var trades = + final trades = await Hive.openBox(Trade.boxName, encryptionKey: tradesBoxKey); - var walletInfoSource = await Hive.openBox(WalletInfo.boxName); + final walletInfoSource = await Hive.openBox(WalletInfo.boxName); final sharedPreferences = await SharedPreferences.getInstance(); final walletService = WalletService(); @@ -124,7 +126,7 @@ void main() async { ], child: CakeWalletApp())); } -initialSetup( +Future initialSetup( {WalletListService walletListService, SharedPreferences sharedPreferences, Box nodes, @@ -137,7 +139,7 @@ initialSetup( sharedPreferences: sharedPreferences, nodes: nodes); await authStore.started(); - moneroWallet.onStartup(); + monero_wallet.onStartup(); } class CakeWalletApp extends StatelessWidget { diff --git a/lib/router.dart b/lib/router.dart index c7bdc5753..c10ebea12 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -19,6 +19,10 @@ import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.da import 'package:cake_wallet/src/domain/common/node.dart'; import 'package:cake_wallet/src/domain/monero/transaction_description.dart'; import 'package:cake_wallet/src/domain/exchange/trade.dart'; +import 'package:cake_wallet/src/domain/monero/account.dart'; +import 'package:cake_wallet/src/domain/common/mnemotic_item.dart'; +import 'package:cake_wallet/src/domain/common/transaction_info.dart'; +import 'package:cake_wallet/src/domain/monero/subaddress.dart'; // MARK: Import stores @@ -101,10 +105,10 @@ class Router { Box trades}) { switch (settings.name) { case Routes.welcome: - return MaterialPageRoute(builder: (_) => createWelcomePage()); + return MaterialPageRoute(builder: (_) => createWelcomePage()); case Routes.newWalletFromWelcome: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => Provider( create: (_) => UserStore( accountService: UserService( @@ -115,7 +119,7 @@ class Router { Navigator.pushNamed(context, Routes.newWallet)))); case Routes.newWallet: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => ProxyProvider( @@ -132,10 +136,10 @@ class Router { Function(BuildContext, String) callback; if (settings.arguments is Function(BuildContext, String)) { - callback = settings.arguments; + callback = settings.arguments as Function(BuildContext, String); } - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => Provider( create: (_) => UserStore( accountService: UserService( @@ -147,13 +151,14 @@ class Router { fullscreenDialog: true); case Routes.restoreOptions: - return CupertinoPageRoute(builder: (_) => RestoreOptionsPage()); + return CupertinoPageRoute(builder: (_) => RestoreOptionsPage()); case Routes.restoreWalletOptions: - return CupertinoPageRoute(builder: (_) => RestoreWalletOptionsPage()); + return CupertinoPageRoute( + builder: (_) => RestoreWalletOptionsPage()); case Routes.restoreWalletOptionsFromWelcome: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => Provider( create: (_) => UserStore( accountService: UserService( @@ -164,14 +169,14 @@ class Router { context, Routes.restoreWalletOptions)))); case Routes.seed: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => createSeedPage( settingsStore: settingsStore, walletService: walletService, - callback: settings.arguments)); + callback: settings.arguments as void Function())); case Routes.restoreWalletFromSeed: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => ProxyProvider( update: (_, authStore, __) => WalletRestorationStore( @@ -184,7 +189,7 @@ class Router { sharedPreferences: sharedPreferences))); case Routes.restoreWalletFromKeys: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => ProxyProvider( update: (_, authStore, __) => WalletRestorationStore( @@ -197,7 +202,7 @@ class Router { sharedPreferences: sharedPreferences))); case Routes.dashboard: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => createDashboardPage( walletService: walletService, priceStore: priceStore, @@ -207,7 +212,7 @@ class Router { walletStore: walletStore)); case Routes.send: - return CupertinoPageRoute( + return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => MultiProvider(providers: [ ProxyProvider( @@ -227,7 +232,7 @@ class Router { ], child: SendPage())); case Routes.receive: - return CupertinoPageRoute( + return CupertinoPageRoute( fullscreenDialog: true, builder: (_) => MultiProvider(providers: [ Provider( @@ -236,30 +241,30 @@ class Router { ], child: ReceivePage())); case Routes.transactionDetails: - return CupertinoPageRoute( + return CupertinoPageRoute( fullscreenDialog: true, - builder: (_) => - TransactionDetailsPage(transactionInfo: settings.arguments)); + builder: (_) => TransactionDetailsPage( + transactionInfo: settings.arguments as TransactionInfo)); case Routes.newSubaddress: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => Provider( create: (_) => SubadrressCreationStore(walletService: walletService), child: NewSubaddressPage())); case Routes.disclaimer: - return CupertinoPageRoute(builder: (_) => DisclaimerPage()); + return CupertinoPageRoute(builder: (_) => DisclaimerPage()); case Routes.readDisclaimer: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => DisclaimerPage(isReadOnly: true)); case Routes.seedAlert: - return CupertinoPageRoute(builder: (_) => SeedAlert()); + return CupertinoPageRoute(builder: (_) => SeedAlert()); case Routes.walletList: - return MaterialPageRoute( + return MaterialPageRoute( fullscreenDialog: true, builder: (_) => Provider( create: (_) => WalletListStore( @@ -268,40 +273,43 @@ class Router { child: WalletListPage())); case Routes.auth: - return MaterialPageRoute( + return MaterialPageRoute( fullscreenDialog: true, builder: (_) => Provider( create: (_) => AuthStore( sharedPreferences: sharedPreferences, userService: userService, walletService: walletService), - child: AuthPage(onAuthenticationFinished: settings.arguments), + child: AuthPage( + onAuthenticationFinished: + settings.arguments as OnAuthenticationFinished), )); case Routes.unlock: - return MaterialPageRoute( + return MaterialPageRoute( fullscreenDialog: true, builder: (_) => createUnlockPage( sharedPreferences: sharedPreferences, userService: userService, walletService: walletService, - onAuthenticationFinished: settings.arguments)); + onAuthenticationFinished: + settings.arguments as OnAuthenticationFinished)); case Routes.nodeList: - return CupertinoPageRoute(builder: (context) { + return CupertinoPageRoute(builder: (context) { return Provider( create: (_) => NodeListStore(nodesSource: nodes), child: NodeListPage()); }); case Routes.newNode: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => Provider( create: (_) => NodeListStore(nodesSource: nodes), child: NewNodePage())); case Routes.login: - return CupertinoPageRoute(builder: (context) { + return CupertinoPageRoute(builder: (context) { final authenticationStore = Provider.of(context); return createLoginPage( @@ -313,7 +321,7 @@ class Router { }); case Routes.accountList: - return MaterialPageRoute( + return MaterialPageRoute( builder: (context) { return MultiProvider(providers: [ Provider( @@ -324,14 +332,14 @@ class Router { fullscreenDialog: true); case Routes.accountCreation: - return CupertinoPageRoute(builder: (context) { + return CupertinoPageRoute(builder: (context) { return Provider( create: (_) => AccountListStore(walletService: walletService), - child: AccountPage(account: settings.arguments)); + child: AccountPage(account: settings.arguments as Account)); }); case Routes.addressBook: - return MaterialPageRoute(builder: (context) { + return MaterialPageRoute(builder: (context) { return MultiProvider( providers: [ Provider( @@ -344,7 +352,7 @@ class Router { }); case Routes.pickerAddressBook: - return MaterialPageRoute(builder: (context) { + return MaterialPageRoute(builder: (context) { return MultiProvider( providers: [ Provider( @@ -357,7 +365,7 @@ class Router { }); case Routes.addressBookAddContact: - return CupertinoPageRoute(builder: (context) { + return CupertinoPageRoute(builder: (context) { return MultiProvider( providers: [ Provider( @@ -365,12 +373,12 @@ class Router { AccountListStore(walletService: walletService)), Provider(create: (_) => AddressBookStore(contacts: contacts)) ], - child: ContactPage(contact: settings.arguments), + child: ContactPage(contact: settings.arguments as Contact), ); }); case Routes.showKeys: - return MaterialPageRoute( + return MaterialPageRoute( builder: (context) { return Provider( create: (_) => WalletKeysStore(walletService: walletService), @@ -380,12 +388,13 @@ class Router { fullscreenDialog: true); case Routes.exchangeTrade: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => MultiProvider( providers: [ ProxyProvider( update: (_, settingsStore, __) => ExchangeTradeStore( - trade: settings.arguments, walletStore: walletStore), + trade: settings.arguments as Trade, + walletStore: walletStore), ), ProxyProvider( update: (_, settingsStore, __) => SendStore( @@ -398,21 +407,22 @@ class Router { )); case Routes.exchangeConfirm: - return MaterialPageRoute( - builder: (_) => ExchangeConfirmPage(trade: settings.arguments)); + return MaterialPageRoute( + builder: (_) => + ExchangeConfirmPage(trade: settings.arguments as Trade)); case Routes.tradeDetails: - return MaterialPageRoute(builder: (context) { + return MaterialPageRoute(builder: (context) { return MultiProvider(providers: [ ProxyProvider( update: (_, settingsStore, __) => ExchangeTradeStore( - trade: settings.arguments, walletStore: walletStore), + trade: settings.arguments as Trade, walletStore: walletStore), ) ], child: TradeDetailsPage()); }); case Routes.subaddressList: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => MultiProvider(providers: [ Provider( create: (_) => @@ -420,17 +430,18 @@ class Router { ], child: SubaddressListPage())); case Routes.restoreWalletFromSeedDetails: - return CupertinoPageRoute( + return CupertinoPageRoute( builder: (_) => ProxyProvider( update: (_, authStore, __) => WalletRestorationStore( authStore: authStore, sharedPreferences: sharedPreferences, walletListService: walletListService, - seed: settings.arguments), + seed: settings.arguments as List), child: RestoreWalletFromSeedDetailsPage())); + case Routes.exchange: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => MultiProvider(providers: [ Provider(create: (_) { final xmrtoprovider = XMRTOExchangeProvider(); @@ -449,25 +460,25 @@ class Router { ], child: ExchangePage())); case Routes.settings: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => Provider( create: (_) => NodeListStore(nodesSource: nodes), child: SettingsPage())); case Routes.rescan: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => Provider( create: (_) => RescanWalletStore(walletService: walletService), child: RescanPage())); case Routes.faq: - return MaterialPageRoute(builder: (_) => FaqPage()); + return MaterialPageRoute(builder: (_) => FaqPage()); case Routes.changeLanguage: - return MaterialPageRoute(builder: (_) => ChangeLanguage()); + return MaterialPageRoute(builder: (_) => ChangeLanguage()); default: - return MaterialPageRoute( + return MaterialPageRoute( builder: (_) => Scaffold( body: Center( child: Text(S.current.router_no_route(settings.name))), diff --git a/lib/src/domain/common/balance_display_mode.dart b/lib/src/domain/common/balance_display_mode.dart index 590daf5f3..42dc09924 100644 --- a/lib/src/domain/common/balance_display_mode.dart +++ b/lib/src/domain/common/balance_display_mode.dart @@ -3,6 +3,9 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/domain/common/enumerable_item.dart'; class BalanceDisplayMode extends EnumerableItem with Serializable { + const BalanceDisplayMode({@required String title, @required int raw}) + : super(title: title, raw: raw); + static const all = [ BalanceDisplayMode.fullBalance, BalanceDisplayMode.availableBalance, @@ -27,9 +30,6 @@ class BalanceDisplayMode extends EnumerableItem with Serializable { } } - const BalanceDisplayMode({@required String title, @required int raw}) - : super(title: title, raw: raw); - @override String toString() { switch (this) { diff --git a/lib/src/domain/common/contact.dart b/lib/src/domain/common/contact.dart index 11f851253..1fc9507fd 100644 --- a/lib/src/domain/common/contact.dart +++ b/lib/src/domain/common/contact.dart @@ -6,6 +6,9 @@ part 'contact.g.dart'; @HiveType() class Contact extends HiveObject { + Contact({@required this.name, @required this.address, CryptoCurrency type}) + : raw = type?.raw; + static const boxName = 'Contacts'; @HiveField(0) @@ -19,12 +22,6 @@ class Contact extends HiveObject { CryptoCurrency get type => CryptoCurrency.deserialize(raw: raw); - Contact( - {@required this.name, - @required this.address, - CryptoCurrency type}) - : raw = type?.raw; - - updateCryptoCurrency({@required CryptoCurrency currency}) => + void updateCryptoCurrency({@required CryptoCurrency currency}) => raw = currency.raw; } diff --git a/lib/src/domain/common/crypto_currency.dart b/lib/src/domain/common/crypto_currency.dart index aa8220d4e..2c04262fc 100644 --- a/lib/src/domain/common/crypto_currency.dart +++ b/lib/src/domain/common/crypto_currency.dart @@ -5,6 +5,9 @@ part 'crypto_currency.g.dart'; @HiveType() class CryptoCurrency extends EnumerableItem with Serializable { + const CryptoCurrency({final String title, final int raw}) + : super(title: title, raw: raw); + static const all = [ CryptoCurrency.xmr, CryptoCurrency.btc, @@ -58,9 +61,6 @@ class CryptoCurrency extends EnumerableItem with Serializable { } } - const CryptoCurrency({final String title, final int raw}) - : super(title: title, raw: raw); - @override String toString() => title; } diff --git a/lib/src/domain/common/default_settings_migration.dart b/lib/src/domain/common/default_settings_migration.dart index 64ff94898..7a5e138a0 100644 --- a/lib/src/domain/common/default_settings_migration.dart +++ b/lib/src/domain/common/default_settings_migration.dart @@ -11,7 +11,7 @@ Future defaultSettingsMigration( {@required int version, @required SharedPreferences sharedPreferences, @required Box nodes}) async { - int currentVersion = + final currentVersion = sharedPreferences.getInt('current_default_settings_migration_version') ?? 0; @@ -22,17 +22,17 @@ Future defaultSettingsMigration( try { switch (version) { case 1: - sharedPreferences.setString( + await sharedPreferences.setString( 'current_fiat_currency', FiatCurrency.usd.toString()); - sharedPreferences.setInt( + await sharedPreferences.setInt( 'current_fee_priority', TransactionPriority.standart.raw); - sharedPreferences.setInt('current_balance_display_mode', + await sharedPreferences.setInt('current_balance_display_mode', BalanceDisplayMode.availableBalance.raw); - sharedPreferences.setInt( + await sharedPreferences.setInt( 'current_default_settings_migration_version', 1); - sharedPreferences.setBool('save_recipient_address', false); + await sharedPreferences.setBool('save_recipient_address', false); await resetToDefault(nodes); - sharedPreferences.setInt('current_node_id', 0); + await sharedPreferences.setInt('current_node_id', 0); break; default: break; @@ -41,6 +41,6 @@ Future defaultSettingsMigration( print('Migration error: ${e.toString()}'); } - sharedPreferences.setInt( + await sharedPreferences.setInt( 'current_default_settings_migration_version', version); } diff --git a/lib/src/domain/common/digest_request.dart b/lib/src/domain/common/digest_request.dart index a32bde983..4f4be1c95 100644 --- a/lib/src/domain/common/digest_request.dart +++ b/lib/src/domain/common/digest_request.dart @@ -1,5 +1,5 @@ import 'dart:convert'; -import 'package:dio/dio.dart' as Dio; +import 'package:dio/dio.dart' as __dio; import 'package:crypto/crypto.dart' as crypto; import 'dart:math' as math; @@ -8,13 +8,13 @@ class DigestRequest { String generateCnonce() { final rnd = math.Random.secure(); - var values = List.generate(32, (i) => rnd.nextInt(256)); + final values = List.generate(32, (i) => rnd.nextInt(256)); return base64Url.encode(values).substring(0, 8); } String generateHA1({String realm, String username, String password}) { final ha1CredentialsData = - Utf8Encoder().convert('$username:$realm:$password'); + Utf8Encoder().convert('$username:$realm:$password'); final ha1 = md5.convert(ha1CredentialsData).toString(); return ha1; @@ -29,13 +29,13 @@ class DigestRequest { String generateResponseString( {String ha1, - String ha2, - String nonce, - String nonceCount, - String cnonce, - String qop}) { + String ha2, + String nonce, + String nonceCount, + String cnonce, + String qop}) { final responseData = - Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2'); + Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2'); final response = md5.convert(responseData).toString(); return response; @@ -43,8 +43,8 @@ class DigestRequest { Map parsetAuthorizationHeader({String source}) { final authHeaderParts = - source.substring(7).split(',').map((item) => item.trim()); - var authenticate = Map(); + source.substring(7).split(',').map((item) => item.trim()); + final authenticate = Map(); for (final part in authHeaderParts) { final kv = part.split('='); @@ -55,30 +55,25 @@ class DigestRequest { return authenticate; } - Future request( + Future<__dio.Response> request( {String uri, String login, String password}) async { - final path = '/json_rpc'; - final method = 'POST'; + const path = '/json_rpc'; + const method = 'POST'; final url = Uri.http(uri, path); - final dio = Dio.Dio(); - - Map headers = {'Content-type': 'application/json'}; - String body = - json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"}); - - var credentialsResponse = await dio.post(url.toString(), - options: Dio.Options(headers: headers, validateStatus: (_) => true)); - var resHeaeders = credentialsResponse.headers; - final authenticate = - parsetAuthorizationHeader(source: resHeaeders['www-authenticate'].first); + final dio = __dio.Dio(); + final headers = {'Content-type': 'application/json'}; + final body = + json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"}); + final credentialsResponse = await dio.post(url.toString(), + options: __dio.Options(headers: headers, validateStatus: (_) => true)); + final authenticate = parsetAuthorizationHeader( + source: credentialsResponse.headers['www-authenticate'].first); final qop = authenticate['qop']; final algorithm = 'MD5'; final realm = 'monero-rpc'; final nonce = authenticate['nonce']; final cnonce = generateCnonce(); - - var nonceCount = '00000001'; - + final nonceCount = '00000001'; final ha1 = generateHA1(realm: realm, username: login, password: password); final ha2 = generateHA2(method: method, uri: path); final response = generateResponseString( @@ -92,11 +87,10 @@ class DigestRequest { final authorizationHeaders = { 'Content-type': 'application/json', 'Authorization': - 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"' + 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"' }; - final res = await dio.post(url.toString(), - options: Dio.Options(headers: authorizationHeaders), data: body); - return res; + return await dio.post(url.toString(), + options: __dio.Options(headers: authorizationHeaders), data: body); } -} \ No newline at end of file +} diff --git a/lib/src/domain/common/enumerable_item.dart b/lib/src/domain/common/enumerable_item.dart index 01d912a13..e9deb3056 100644 --- a/lib/src/domain/common/enumerable_item.dart +++ b/lib/src/domain/common/enumerable_item.dart @@ -1,11 +1,11 @@ import 'package:flutter/foundation.dart'; abstract class EnumerableItem { + const EnumerableItem({@required this.title, @required this.raw}); + final T raw; final String title; - const EnumerableItem({@required this.title, @required this.raw}); - @override String toString() => title; } diff --git a/lib/src/domain/common/fetch_price.dart b/lib/src/domain/common/fetch_price.dart index 7c92fefb9..34957aa70 100644 --- a/lib/src/domain/common/fetch_price.dart +++ b/lib/src/domain/common/fetch_price.dart @@ -20,12 +20,12 @@ Future fetchPriceFor({CryptoCurrency crypto, FiatCurrency fiat}) async { return 0.0; } - final responseJSON = json.decode(response.body); - final data = responseJSON['data']; + final responseJSON = json.decode(response.body) as Map; + final data = responseJSON['data'] as List>; for (final item in data) { if (item['symbol'] == cryptoToString(crypto)) { - price = item['quote'][fiatStringified]['price']; + price = item['quote'][fiatStringified]['price'] as double; break; } } diff --git a/lib/src/domain/common/fiat_currency.dart b/lib/src/domain/common/fiat_currency.dart index 4b28e73d1..7c86ad610 100644 --- a/lib/src/domain/common/fiat_currency.dart +++ b/lib/src/domain/common/fiat_currency.dart @@ -1,6 +1,11 @@ import 'package:cake_wallet/src/domain/common/enumerable_item.dart'; class FiatCurrency extends EnumerableItem with Serializable { + const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol); + + @override + bool operator ==(Object other) => other is FiatCurrency && other.raw == raw; + static const all = [ FiatCurrency.aud, FiatCurrency.bgn, @@ -71,10 +76,6 @@ class FiatCurrency extends EnumerableItem with Serializable { static const zar = FiatCurrency(symbol: 'ZAR'); static const vef = FiatCurrency(symbol: 'VEF'); - const FiatCurrency({String symbol}) : super(title: symbol, raw: symbol); - - operator ==(o) => o is FiatCurrency && o.raw == raw; - @override int get hashCode => raw.hashCode ^ title.hashCode; } diff --git a/lib/src/domain/common/language.dart b/lib/src/domain/common/language.dart index 8af3c571d..70f7b5899 100644 --- a/lib/src/domain/common/language.dart +++ b/lib/src/domain/common/language.dart @@ -1,16 +1,14 @@ import 'package:flutter/material.dart'; class Language with ChangeNotifier { + Language(this._currentLanguage); String _currentLanguage; - Language(this._currentLanguage); + String getCurrentLanguage() => _currentLanguage; - getCurrentLanguage() => _currentLanguage; - - setCurrentLanguage(String language){ + void setCurrentLanguage(String language) { _currentLanguage = language; notifyListeners(); } - } \ No newline at end of file diff --git a/lib/src/domain/common/mnemotic_item.dart b/lib/src/domain/common/mnemotic_item.dart index 01521c28a..6f7690b4c 100644 --- a/lib/src/domain/common/mnemotic_item.dart +++ b/lib/src/domain/common/mnemotic_item.dart @@ -1,13 +1,11 @@ class MnemoticItem { + MnemoticItem({String text, this.dic}) : _text = text; + String get text => _text; final List dic; String _text; - MnemoticItem({String text, this.dic}) { - _text = text; - } - bool isCorrect() => dic.contains(text); void changeText(String text) { @@ -16,4 +14,4 @@ class MnemoticItem { @override String toString() => text; -} \ No newline at end of file +} diff --git a/lib/src/domain/common/node.dart b/lib/src/domain/common/node.dart index 7855cfe89..8bce8d113 100644 --- a/lib/src/domain/common/node.dart +++ b/lib/src/domain/common/node.dart @@ -8,6 +8,13 @@ part 'node.g.dart'; @HiveType() class Node extends HiveObject { + Node({@required this.uri, this.login, this.password}); + + Node.fromMap(Map map) + : uri = (map['uri'] ?? '') as String, + login = map['login'] as String, + password = map['password'] as String; + static const boxName = 'Nodes'; @HiveField(0) @@ -19,31 +26,24 @@ class Node extends HiveObject { @HiveField(2) String password; - Node({@required this.uri, this.login, this.password}); - - Node.fromMap(Map map) - : uri = map['uri'] ?? '', - login = map['login'], - password = map['password']; - Future requestNode(String uri, {String login, String password}) async { - var resBody; + Map resBody; if (login != null && password != null) { final digestRequest = DigestRequest(); - var response = await digestRequest.request( + final response = await digestRequest.request( uri: uri, login: login, password: password); - resBody = response.data; + resBody = response.data as Map; } else { final url = Uri.http(uri, '/json_rpc'); - Map headers = {'Content-type': 'application/json'}; - String body = + final headers = {'Content-type': 'application/json'}; + final body = json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"}); - var response = + final response = await http.post(url.toString(), headers: headers, body: body); - resBody = json.decode(response.body); + resBody = json.decode(response.body) as Map; } - return !resBody["result"]["offline"]; + return !(resBody["result"]["offline"] as bool); } } diff --git a/lib/src/domain/common/node_list.dart b/lib/src/domain/common/node_list.dart index 6d19a8916..1ee860663 100644 --- a/lib/src/domain/common/node_list.dart +++ b/lib/src/domain/common/node_list.dart @@ -4,20 +4,21 @@ import "package:yaml/yaml.dart"; import 'package:cake_wallet/src/domain/common/node.dart'; Future> loadDefaultNodes() async { - String nodesRaw = await rootBundle.loadString('assets/node_list.yml'); - List nodes = loadYaml(nodesRaw); + final nodesRaw = await rootBundle.loadString('assets/node_list.yml'); + final nodes = loadYaml(nodesRaw) as List>; + return nodes.map((raw) => Node.fromMap(raw)).toList(); } Future resetToDefault(Box nodeSource) async { final nodes = await loadDefaultNodes(); - await nodeSource.clear(); + final enteties = Map(); - Map enteties = {}; + await nodeSource.clear(); for (var i = 0; i < nodes.length; i++) { enteties[i] = nodes[i]; } await nodeSource.putAll(enteties); -} \ No newline at end of file +} diff --git a/lib/src/domain/common/pending_transaction.dart b/lib/src/domain/common/pending_transaction.dart index bbf069f30..9168b3195 100644 --- a/lib/src/domain/common/pending_transaction.dart +++ b/lib/src/domain/common/pending_transaction.dart @@ -1,15 +1,9 @@ import 'package:flutter/foundation.dart'; -import 'package:cw_monero/transaction_history.dart' as transactionHistory; +import 'package:cw_monero/transaction_history.dart' as transaction_history; import 'package:cw_monero/structs/pending_transaction.dart'; import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; class PendingTransaction { - final String amount; - final String fee; - final String hash; - - int _pointerAddress; - PendingTransaction( {@required this.amount, @required this.fee, @required this.hash}); @@ -20,6 +14,12 @@ class PendingTransaction { hash = transactionDescription.hash, _pointerAddress = transactionDescription.pointerAddress; - Future commit() async => transactionHistory + final String amount; + final String fee; + final String hash; + + int _pointerAddress; + + Future commit() async => transaction_history .commitTransactionFromPointerAddress(address: _pointerAddress); } diff --git a/lib/src/domain/common/qr_scanner.dart b/lib/src/domain/common/qr_scanner.dart index b3e8eee84..4a26bdde5 100644 --- a/lib/src/domain/common/qr_scanner.dart +++ b/lib/src/domain/common/qr_scanner.dart @@ -10,6 +10,6 @@ Future presentQRScanner() async { return result; } catch (e) { isQrScannerShown = false; - throw e; + rethrow; } } diff --git a/lib/src/domain/common/sync_status.dart b/lib/src/domain/common/sync_status.dart index beef7b782..e83ce6f9d 100644 --- a/lib/src/domain/common/sync_status.dart +++ b/lib/src/domain/common/sync_status.dart @@ -9,18 +9,20 @@ abstract class SyncStatus { } class SyncingSyncStatus extends SyncStatus { + SyncingSyncStatus(this.height, this.blockchainHeight, this.refreshHeight); + final int height; final int blockchainHeight; final int refreshHeight; - SyncingSyncStatus(this.height, this.blockchainHeight, this.refreshHeight); - + @override double progress() { final line = blockchainHeight - refreshHeight; final diff = line - (blockchainHeight - height); return diff <= 0 ? 0.0 : diff / line; } + @override String title() => S.current.sync_status_syncronizing; @override @@ -28,39 +30,51 @@ class SyncingSyncStatus extends SyncStatus { } class SyncedSyncStatus extends SyncStatus { + @override double progress() => 1.0; + @override String title() => S.current.sync_status_syncronized; } class NotConnectedSyncStatus extends SyncStatus { const NotConnectedSyncStatus(); + @override double progress() => 0.0; + @override String title() => S.current.sync_status_not_connected; } class StartingSyncStatus extends SyncStatus { + @override double progress() => 0.0; + @override String title() => S.current.sync_status_starting_sync; } class FailedSyncStatus extends SyncStatus { + @override double progress() => 1.0; + @override String title() => S.current.sync_status_failed_connect; } class ConnectingSyncStatus extends SyncStatus { + @override double progress() => 0.0; + @override String title() => S.current.sync_status_connecting; } class ConnectedSyncStatus extends SyncStatus { + @override double progress() => 0.0; + @override String title() => S.current.sync_status_connected; -} \ No newline at end of file +} diff --git a/lib/src/domain/common/transaction_info.dart b/lib/src/domain/common/transaction_info.dart index 2ad5c58a0..08fcd2372 100644 --- a/lib/src/domain/common/transaction_info.dart +++ b/lib/src/domain/common/transaction_info.dart @@ -4,26 +4,20 @@ import 'package:cake_wallet/src/domain/common/parseBoolFromString.dart'; import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; class TransactionInfo { - final String id; - final int height; - final TransactionDirection direction; - final DateTime date; - final int accountIndex; - final bool isPending; - final int amount; - String recipientAddress; - String _fiatAmount; + TransactionInfo(this.id, this.height, this.direction, this.date, + this.isPending, this.amount, this.accountIndex); TransactionInfo.fromMap(Map map) - : id = map['hash'] ?? '', - height = map['height'] ?? '', - direction = parseTransactionDirectionFromNumber(map['direction']) ?? - TransactionDirection.incoming, + : id = (map['hash'] ?? '') as String, + height = (map['height'] ?? 0) as int, + direction = + parseTransactionDirectionFromNumber(map['direction'] as String) ?? + TransactionDirection.incoming, date = DateTime.fromMillisecondsSinceEpoch( - (int.parse(map['timestamp']) ?? 0) * 1000), - isPending = parseBoolFromString(map['isPending']), - amount = map['amount'], - accountIndex = int.parse(map['accountIndex']); + (int.parse(map['timestamp'] as String) ?? 0) * 1000), + isPending = parseBoolFromString(map['isPending'] as String), + amount = map['amount'] as int, + accountIndex = int.parse(map['accountIndex'] as String); TransactionInfo.fromRow(TransactionInfoRow row) : id = row.getHash(), @@ -35,12 +29,20 @@ class TransactionInfo { amount = row.getAmount(), accountIndex = row.subaddrAccount; - TransactionInfo(this.id, this.height, this.direction, this.date, - this.isPending, this.amount, this.accountIndex); + final String id; + final int height; + final TransactionDirection direction; + final DateTime date; + final int accountIndex; + final bool isPending; + final int amount; + String recipientAddress; + + String _fiatAmount; String amountFormatted() => '${moneroAmountToString(amount: amount)} XMR'; String fiatAmount() => _fiatAmount ?? ''; - changeFiatAmount(String amount) => _fiatAmount = amount; + void changeFiatAmount(String amount) => _fiatAmount = amount; } diff --git a/lib/src/domain/common/transaction_priority.dart b/lib/src/domain/common/transaction_priority.dart index f00058b7e..f611313e0 100644 --- a/lib/src/domain/common/transaction_priority.dart +++ b/lib/src/domain/common/transaction_priority.dart @@ -2,6 +2,9 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/domain/common/enumerable_item.dart'; class TransactionPriority extends EnumerableItem with Serializable { + const TransactionPriority({String title, int raw}) + : super(title: title, raw: raw); + static const all = [ TransactionPriority.slow, TransactionPriority.regular, @@ -33,9 +36,6 @@ class TransactionPriority extends EnumerableItem with Serializable { } } - const TransactionPriority({String title, int raw}) - : super(title: title, raw: raw); - @override String toString() { switch (this) { diff --git a/lib/src/domain/common/wallet_description.dart b/lib/src/domain/common/wallet_description.dart index d62f37970..f56616cb1 100644 --- a/lib/src/domain/common/wallet_description.dart +++ b/lib/src/domain/common/wallet_description.dart @@ -1,8 +1,8 @@ import 'package:cake_wallet/src/domain/common/wallet_type.dart'; class WalletDescription { + WalletDescription({this.name, this.type}); + final String name; final WalletType type; - - WalletDescription({this.name, this.type}); } \ No newline at end of file diff --git a/lib/src/domain/common/wallet_info.dart b/lib/src/domain/common/wallet_info.dart index 4bf382d11..ce676ea64 100644 --- a/lib/src/domain/common/wallet_info.dart +++ b/lib/src/domain/common/wallet_info.dart @@ -5,8 +5,11 @@ part 'wallet_info.g.dart'; @HiveType() class WalletInfo extends HiveObject { + WalletInfo( + {this.id, this.name, this.type, this.isRecovery, this.restoreHeight}); + static const boxName = 'WalletInfo'; - + @HiveField(0) String id; @@ -21,7 +24,4 @@ class WalletInfo extends HiveObject { @HiveField(4) int restoreHeight; - - WalletInfo( - {this.id, this.name, this.type, this.isRecovery, this.restoreHeight}); } diff --git a/lib/src/domain/exchange/changenow/changenow_exchange_provider.dart b/lib/src/domain/exchange/changenow/changenow_exchange_provider.dart index e2c5dcc28..7fc3f5d63 100644 --- a/lib/src/domain/exchange/changenow/changenow_exchange_provider.dart +++ b/lib/src/domain/exchange/changenow/changenow_exchange_provider.dart @@ -15,45 +15,50 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da import 'package:cake_wallet/src/domain/exchange/trade_not_created_exeption.dart'; class ChangeNowExchangeProvider extends ExchangeProvider { + ChangeNowExchangeProvider() + : super( + pairList: CryptoCurrency.all + .map((i) { + return CryptoCurrency.all.map((k) { + if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) { + return ExchangePair(from: i, to: k, reverse: false); + } + + if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) { + return null; + } + + return ExchangePair(from: i, to: k, reverse: true); + }).where((c) => c != null); + }) + .expand((i) => i) + .toList()); + static const apiUri = 'https://changenow.io/api/v1'; static const apiKey = secrets.change_now_api_key; static const _exchangeAmountUriSufix = '/exchange-amount/'; static const _transactionsUriSufix = '/transactions/'; static const _minAmountUriSufix = '/min-amount/'; + @override String get title => 'ChangeNOW'; + + @override ExchangeProviderDescription get description => ExchangeProviderDescription.changeNow; - ChangeNowExchangeProvider() { - pairList = CryptoCurrency.all - .map((i) { - return CryptoCurrency.all.map((k) { - if (i == CryptoCurrency.btc && k == CryptoCurrency.xmr) { - return ExchangePair(from: i, to: k, reverse: false); - } - - if (i == CryptoCurrency.xmr && k == CryptoCurrency.btc) { - return null; - } - - return ExchangePair(from: i, to: k, reverse: true); - }).where((c) => c != null); - }) - .expand((i) => i) - .toList(); - } - + @override Future fetchLimits({CryptoCurrency from, CryptoCurrency to}) async { final symbol = from.toString() + '_' + to.toString(); final url = apiUri + _minAmountUriSufix + symbol; final response = await get(url); - final responseJSON = json.decode(response.body); - final double min = responseJSON['minAmount']; + final responseJSON = json.decode(response.body) as Map; + final min = responseJSON['minAmount'] as double; return Limits(min: min, max: null); } + @override Future createTrade({TradeRequest request}) async { const url = apiUri + _transactionsUriSufix + apiKey; final _request = request as ChangeNowRequest; @@ -70,37 +75,44 @@ class ChangeNowExchangeProvider extends ExchangeProvider { if (response.statusCode != 200) { if (response.statusCode == 400) { - final responseJSON = json.decode(response.body); - final error = responseJSON['message']; + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + throw TradeNotCreatedException(description, description: error); } throw TradeNotCreatedException(description); } - final responseJSON = json.decode(response.body); + final responseJSON = json.decode(response.body) as Map; + final id = responseJSON['id'] as String; + final inputAddress = responseJSON['payinAddress'] as String; + final refundAddress = responseJSON['refundAddress'] as String; + final extraId = responseJSON['payinExtraId'] as String; return Trade( - id: responseJSON['id'], + id: id, from: _request.from, to: _request.to, provider: description, - inputAddress: responseJSON['payinAddress'], - refundAddress: responseJSON['refundAddress'], - extraId: responseJSON["payinExtraId"], + inputAddress: inputAddress, + refundAddress: refundAddress, + extraId: extraId, createdAt: DateTime.now(), amount: _request.amount, state: TradeState.created); } + @override Future findTradeById({@required String id}) async { final url = apiUri + _transactionsUriSufix + id + '/' + apiKey; final response = await get(url); if (response.statusCode != 200) { if (response.statusCode == 400) { - final responseJSON = json.decode(response.body); - final error = responseJSON['message']; + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['message'] as String; + throw TradeNotFoundException(id, provider: description, description: error); } @@ -108,20 +120,31 @@ class ChangeNowExchangeProvider extends ExchangeProvider { throw TradeNotFoundException(id, provider: description); } - final responseJSON = json.decode(response.body); - + final responseJSON = json.decode(response.body) as Map; + final fromCurrency = responseJSON['fromCurrency'] as String; + final from = CryptoCurrency.fromString(fromCurrency); + final toCurrency = responseJSON['toCurrency'] as String; + final to = CryptoCurrency.fromString(toCurrency); + final inputAddress = responseJSON['payinAddress'] as String; + final expectedSendAmount = responseJSON['expectedSendAmount'].toString(); + final status = responseJSON['status'] as String; + final state = TradeState.deserialize(raw: status); + final extraId = responseJSON['payinExtraId'] as String; + final outputTransaction = responseJSON['payoutHash'] as String; + return Trade( id: id, - from: CryptoCurrency.fromString(responseJSON['fromCurrency']), - to: CryptoCurrency.fromString(responseJSON['toCurrency']), + from: from, + to: to, provider: description, - inputAddress: responseJSON['payinAddress'], - amount: responseJSON['expectedSendAmount'].toString(), - state: TradeState.deserialize(raw: responseJSON['status']), - extraId: responseJSON['payinExtraId'], - outputTransaction: responseJSON['payoutHash']); + inputAddress: inputAddress, + amount: expectedSendAmount, + state: state, + extraId: extraId, + outputTransaction: outputTransaction); } + @override Future calculateAmount( {CryptoCurrency from, CryptoCurrency to, double amount}) async { final url = apiUri + @@ -132,8 +155,9 @@ class ChangeNowExchangeProvider extends ExchangeProvider { '_' + to.toString(); final response = await get(url); - final responseJSON = json.decode(response.body); + final responseJSON = json.decode(response.body) as Map; + final estimatedAmount = responseJSON['estimatedAmount'] as double; - return responseJSON['estimatedAmount']; + return estimatedAmount; } } diff --git a/lib/src/domain/exchange/changenow/changenow_request.dart b/lib/src/domain/exchange/changenow/changenow_request.dart index 827074ad6..0201cb3c6 100644 --- a/lib/src/domain/exchange/changenow/changenow_request.dart +++ b/lib/src/domain/exchange/changenow/changenow_request.dart @@ -3,16 +3,16 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/trade_request.dart'; class ChangeNowRequest extends TradeRequest { - CryptoCurrency from; - CryptoCurrency to; - String address; - String amount; - String refundAddress; - ChangeNowRequest( {@required this.from, @required this.to, @required this.address, @required this.amount, @required this.refundAddress}); + + CryptoCurrency from; + CryptoCurrency to; + String address; + String amount; + String refundAddress; } diff --git a/lib/src/domain/exchange/exchange_pair.dart b/lib/src/domain/exchange/exchange_pair.dart index 1b200a2a2..42e2b5db0 100644 --- a/lib/src/domain/exchange/exchange_pair.dart +++ b/lib/src/domain/exchange/exchange_pair.dart @@ -1,9 +1,9 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; class ExchangePair { + ExchangePair({this.from, this.to, this.reverse = true}); + final CryptoCurrency from; final CryptoCurrency to; final bool reverse; - - ExchangePair({this.from, this.to, this.reverse = true}); -} \ No newline at end of file +} diff --git a/lib/src/domain/exchange/exchange_provider.dart b/lib/src/domain/exchange/exchange_provider.dart index 5051de18d..9079d367d 100644 --- a/lib/src/domain/exchange/exchange_provider.dart +++ b/lib/src/domain/exchange/exchange_provider.dart @@ -7,6 +7,8 @@ import 'package:cake_wallet/src/domain/exchange/trade.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; abstract class ExchangeProvider { + ExchangeProvider({this.pairList}); + String get title; List pairList; ExchangeProviderDescription description; diff --git a/lib/src/domain/exchange/exchange_provider_description.dart b/lib/src/domain/exchange/exchange_provider_description.dart index eaed56a97..0ae388848 100644 --- a/lib/src/domain/exchange/exchange_provider_description.dart +++ b/lib/src/domain/exchange/exchange_provider_description.dart @@ -2,6 +2,9 @@ import 'package:cake_wallet/src/domain/common/enumerable_item.dart'; class ExchangeProviderDescription extends EnumerableItem with Serializable { + const ExchangeProviderDescription({String title, int raw}) + : super(title: title, raw: raw); + static const xmrto = ExchangeProviderDescription(title: 'XMR.TO', raw: 0); static const changeNow = ExchangeProviderDescription(title: 'ChangeNOW', raw: 1); @@ -16,9 +19,4 @@ class ExchangeProviderDescription extends EnumerableItem return null; } } - - final String title; - - const ExchangeProviderDescription({this.title, int raw}) - : super(title: title, raw: raw); } diff --git a/lib/src/domain/exchange/limits.dart b/lib/src/domain/exchange/limits.dart index a005282ca..980557055 100644 --- a/lib/src/domain/exchange/limits.dart +++ b/lib/src/domain/exchange/limits.dart @@ -1,6 +1,6 @@ class Limits { + const Limits({this.min, this.max}); + final double min; final double max; - - const Limits({this.min, this.max}); } \ No newline at end of file diff --git a/lib/src/domain/exchange/trade.dart b/lib/src/domain/exchange/trade.dart index 177deb3ce..3554d340a 100644 --- a/lib/src/domain/exchange/trade.dart +++ b/lib/src/domain/exchange/trade.dart @@ -7,6 +7,25 @@ part 'trade.g.dart'; @HiveType() class Trade extends HiveObject { + Trade( + {this.id, + ExchangeProviderDescription provider, + CryptoCurrency from, + CryptoCurrency to, + TradeState state, + this.createdAt, + this.expiredAt, + this.amount, + this.inputAddress, + this.extraId, + this.outputTransaction, + this.refundAddress, + this.walletId}) + : providerRaw = provider?.raw, + fromRaw = from?.raw, + toRaw = to?.raw, + stateRaw = state?.raw; + static const boxName = 'Trades'; @HiveField(0) @@ -59,38 +78,20 @@ class Trade extends HiveObject { static Trade fromMap(Map map) { return Trade( - id: map['id'], - provider: ExchangeProviderDescription.deserialize(raw: map['provider']), - from: CryptoCurrency.deserialize(raw: map['input']), - to: CryptoCurrency.deserialize(raw: map['output']), + id: map['id'] as String, + provider: ExchangeProviderDescription.deserialize( + raw: map['provider'] as int), + from: CryptoCurrency.deserialize(raw: map['input'] as int), + to: CryptoCurrency.deserialize(raw: map['output'] as int), createdAt: map['date'] != null - ? DateTime.fromMillisecondsSinceEpoch(map['date']) + ? DateTime.fromMillisecondsSinceEpoch(map['date'] as int) : null, - amount: map['amount'], - walletId: map['wallet_id']); + amount: map['amount'] as String, + walletId: map['wallet_id'] as String); } - Trade( - {this.id, - ExchangeProviderDescription provider, - CryptoCurrency from, - CryptoCurrency to, - TradeState state, - this.createdAt, - this.expiredAt, - this.amount, - this.inputAddress, - this.extraId, - this.outputTransaction, - this.refundAddress, - this.walletId}) - : providerRaw = provider?.raw, - fromRaw = from?.raw, - toRaw = to?.raw, - stateRaw = state?.raw; - Map toMap() { - return { + return { 'id': id, 'provider': provider.serialize(), 'input': from.serialize(), diff --git a/lib/src/domain/exchange/trade_not_created_exeption.dart b/lib/src/domain/exchange/trade_not_created_exeption.dart index ea0dcda7e..2fc037a06 100644 --- a/lib/src/domain/exchange/trade_not_created_exeption.dart +++ b/lib/src/domain/exchange/trade_not_created_exeption.dart @@ -2,11 +2,11 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da import 'package:cake_wallet/generated/i18n.dart'; class TradeNotCreatedException implements Exception { + TradeNotCreatedException(this.provider, {this.description = ''}); + ExchangeProviderDescription provider; String description; - TradeNotCreatedException(this.provider, {this.description = ''}); - @override String toString() { var text = provider != null diff --git a/lib/src/domain/exchange/trade_not_found_exeption.dart b/lib/src/domain/exchange/trade_not_found_exeption.dart index b00d75657..ad789a215 100644 --- a/lib/src/domain/exchange/trade_not_found_exeption.dart +++ b/lib/src/domain/exchange/trade_not_found_exeption.dart @@ -2,12 +2,12 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da import 'package:cake_wallet/generated/i18n.dart'; class TradeNotFoundException implements Exception { + TradeNotFoundException(this.tradeId, {this.provider, this.description = ''}); + String tradeId; ExchangeProviderDescription provider; String description; - TradeNotFoundException(this.tradeId, {this.provider, this.description = ''}); - @override String toString() { var text = tradeId != null && provider != null diff --git a/lib/src/domain/exchange/trade_state.dart b/lib/src/domain/exchange/trade_state.dart index 6121bfb45..2487ae89c 100644 --- a/lib/src/domain/exchange/trade_state.dart +++ b/lib/src/domain/exchange/trade_state.dart @@ -2,6 +2,12 @@ import 'package:flutter/foundation.dart'; import 'package:cake_wallet/src/domain/common/enumerable_item.dart'; class TradeState extends EnumerableItem with Serializable { + const TradeState({@required String raw, @required String title}) + : super(raw: raw, title: title); + + @override + bool operator ==(Object other) => other is TradeState && other.raw == raw; + static const pending = TradeState(raw: 'pending', title: 'Pending'); static const confirming = TradeState(raw: 'confirming', title: 'Confirming'); static const trading = TradeState(raw: 'trading', title: 'Trading'); @@ -58,11 +64,6 @@ class TradeState extends EnumerableItem with Serializable { } } - const TradeState({@required String raw, @required String title}) - : super(raw: raw, title: title); - - operator ==(o) => o is TradeState && o.raw == raw; - @override int get hashCode => raw.hashCode ^ title.hashCode; } diff --git a/lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart b/lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart index 9cf75983a..df9cf828f 100644 --- a/lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart +++ b/lib/src/domain/exchange/xmrto/xmrto_exchange_provider.dart @@ -14,6 +14,12 @@ import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.da import 'package:cake_wallet/src/domain/exchange/trade_not_found_exeption.dart'; class XMRTOExchangeProvider extends ExchangeProvider { + XMRTOExchangeProvider() + : super(pairList: [ + ExchangePair( + from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false) + ]); + static const userAgent = 'CakeWallet/XMR iOS'; static const originalApiUri = 'https://xmr.to/api/v2/xmr2btc'; static const proxyApiUri = 'https://xmrproxy.net/api/v2/xmr2btc'; @@ -35,18 +41,16 @@ class XMRTOExchangeProvider extends ExchangeProvider { return _apiUri; } + @override String get title => 'XMR.TO'; + @override ExchangeProviderDescription get description => ExchangeProviderDescription.xmrto; - List pairList = [ - ExchangePair( - from: CryptoCurrency.xmr, to: CryptoCurrency.btc, reverse: false) - ]; - double _rate = 0; + @override Future fetchLimits({CryptoCurrency from, CryptoCurrency to}) async { final url = await getApiUri() + _orderParameterUriSufix; final response = await get(url); @@ -55,13 +59,14 @@ class XMRTOExchangeProvider extends ExchangeProvider { return Limits(min: 0, max: 0); } - final responseJSON = json.decode(response.body); - final double min = responseJSON['lower_limit']; - final double max = responseJSON['upper_limit']; + final responseJSON = json.decode(response.body) as Map; + final min = responseJSON['lower_limit'] as double; + final max = responseJSON['upper_limit'] as double; return Limits(min: min, max: max); } + @override Future createTrade({TradeRequest request}) async { final _request = request as XMRTOTradeRequest; final url = await getApiUri() + _orderCreateUriSufix; @@ -74,16 +79,17 @@ class XMRTOExchangeProvider extends ExchangeProvider { if (response.statusCode != 201) { if (response.statusCode == 400) { - final responseJSON = json.decode(response.body); - throw TradeNotCreatedException(description, - description: responseJSON['error_msg']); + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['error_msg'] as String; + + throw TradeNotCreatedException(description, description: error); } throw TradeNotCreatedException(description); } - final responseJSON = json.decode(response.body); - final uuid = responseJSON["uuid"]; + final responseJSON = json.decode(response.body) as Map; + final uuid = responseJSON["uuid"] as String; return Trade( id: uuid, @@ -95,6 +101,7 @@ class XMRTOExchangeProvider extends ExchangeProvider { createdAt: DateTime.now()); } + @override Future findTradeById({@required String id}) async { const headers = { 'Content-Type': 'application/json', @@ -106,8 +113,9 @@ class XMRTOExchangeProvider extends ExchangeProvider { if (response.statusCode != 200) { if (response.statusCode == 400) { - final responseJSON = json.decode(response.body); - final error = responseJSON['error_msg']; + final responseJSON = json.decode(response.body) as Map; + final error = responseJSON['error_msg'] as String; + throw TradeNotFoundException(id, provider: description, description: error); } @@ -115,14 +123,14 @@ class XMRTOExchangeProvider extends ExchangeProvider { throw TradeNotFoundException(id, provider: description); } - final responseJSON = json.decode(response.body); - final address = responseJSON['xmr_receiving_integrated_address']; - final paymentId = responseJSON['xmr_required_payment_id_short']; + final responseJSON = json.decode(response.body) as Map; + final address = responseJSON['xmr_receiving_integrated_address'] as String; + final paymentId = responseJSON['xmr_required_payment_id_short'] as String; final amount = responseJSON['xmr_amount_total'].toString(); - final stateRaw = responseJSON['state']; - final expiredAtRaw = responseJSON['expires_at']; + final stateRaw = responseJSON['state'] as String; + final expiredAtRaw = responseJSON['expires_at'] as String; final expiredAt = DateTime.parse(expiredAtRaw).toLocal(); - final outputTransaction = responseJSON['btc_transaction_id']; + final outputTransaction = responseJSON['btc_transaction_id'] as String; final state = TradeState.deserialize(raw: stateRaw); return Trade( @@ -138,6 +146,7 @@ class XMRTOExchangeProvider extends ExchangeProvider { outputTransaction: outputTransaction); } + @override Future calculateAmount( {CryptoCurrency from, CryptoCurrency to, double amount}) async { if (from != CryptoCurrency.xmr && to != CryptoCurrency.btc) { @@ -158,9 +167,10 @@ class XMRTOExchangeProvider extends ExchangeProvider { final url = await getApiUri() + _orderParameterUriSufix; final response = await get(url, headers: {'Content-Type': 'application/json'}); - final responseJSON = json.decode(response.body); - double btcprice = responseJSON['price']; - double price = 1 / btcprice; + final responseJSON = json.decode(response.body) as Map; + final btcprice = responseJSON['price'] as double; + final price = 1 / btcprice; + return price; } catch (e) { print(e.toString()); diff --git a/lib/src/domain/exchange/xmrto/xmrto_trade_request.dart b/lib/src/domain/exchange/xmrto/xmrto_trade_request.dart index 426a78d46..204798698 100644 --- a/lib/src/domain/exchange/xmrto/xmrto_trade_request.dart +++ b/lib/src/domain/exchange/xmrto/xmrto_trade_request.dart @@ -3,16 +3,16 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/trade_request.dart'; class XMRTOTradeRequest extends TradeRequest { - final CryptoCurrency from; - final CryptoCurrency to; - final String amount; - final String address; - final String refundAddress; - XMRTOTradeRequest( {@required this.from, @required this.to, @required this.amount, @required this.address, @required this.refundAddress}); + + final CryptoCurrency from; + final CryptoCurrency to; + final String amount; + final String address; + final String refundAddress; } diff --git a/lib/src/domain/monero/account.dart b/lib/src/domain/monero/account.dart index 3e7c5204b..d54d70e90 100644 --- a/lib/src/domain/monero/account.dart +++ b/lib/src/domain/monero/account.dart @@ -1,16 +1,16 @@ import 'package:cw_monero/structs/account_row.dart'; class Account { - final int id; - final String label; - Account({this.id, this.label}); Account.fromMap(Map map) - : this.id = map['id'] == null ? 0 : int.parse(map['id']), - this.label = map['label'] ?? ''; + : this.id = map['id'] == null ? 0 : int.parse(map['id'] as String), + this.label = (map['label'] ?? '') as String; Account.fromRow(AccountRow row) : this.id = row.getId(), this.label = row.getLabel(); + + final int id; + final String label; } diff --git a/lib/src/domain/monero/account_list.dart b/lib/src/domain/monero/account_list.dart index 52ce739ff..dfec3d384 100644 --- a/lib/src/domain/monero/account_list.dart +++ b/lib/src/domain/monero/account_list.dart @@ -1,20 +1,20 @@ import 'package:rxdart/rxdart.dart'; -import 'package:cw_monero/account_list.dart' as accountListAPI; +import 'package:cw_monero/account_list.dart' as account_list; import 'package:cake_wallet/src/domain/monero/account.dart'; class AccountList { - get accounts => _accounts.stream; - BehaviorSubject> _accounts; - - bool _isRefreshing; - bool _isUpdating; - AccountList() { _isRefreshing = false; _isUpdating = false; _accounts = BehaviorSubject>(); } + Observable> get accounts => _accounts.stream; + + BehaviorSubject> _accounts; + bool _isRefreshing; + bool _isUpdating; + Future update() async { if (_isUpdating) { return; @@ -22,46 +22,47 @@ class AccountList { try { _isUpdating = true; - await refresh(); + refresh(); final accounts = getAll(); _accounts.add(accounts); _isUpdating = false; } catch (e) { _isUpdating = false; - throw e; + rethrow; } } List getAll() { - return accountListAPI + return account_list .getAllAccount() .map((accountRow) => Account.fromRow(accountRow)) .toList(); } Future addAccount({String label}) async { - await accountListAPI.addAccount(label: label); + await account_list.addAccount(label: label); await update(); } Future setLabelSubaddress({int accountIndex, String label}) async { - await accountListAPI.setLabelForAccount(accountIndex: accountIndex, label: label); + await account_list.setLabelForAccount( + accountIndex: accountIndex, label: label); await update(); } - refresh() { + void refresh() { if (_isRefreshing) { return; } try { _isRefreshing = true; - accountListAPI.refreshAccounts(); + account_list.refreshAccounts(); _isRefreshing = false; } catch (e) { _isRefreshing = false; print(e); - throw e; + rethrow; } } } diff --git a/lib/src/domain/monero/get_height_by_date.dart b/lib/src/domain/monero/get_height_by_date.dart index 41406c794..1e12312ab 100644 --- a/lib/src/domain/monero/get_height_by_date.dart +++ b/lib/src/domain/monero/get_height_by_date.dart @@ -77,7 +77,8 @@ int getHeigthByDate({DateTime date}) { if (endHeight <= 0) { endHeight = dates.values.toList()[dates.length - 1]; - final preLastDate = dateFormat.parse(dates.keys.elementAt(dates.keys.length - 2)); + final preLastDate = + dateFormat.parse(dates.keys.elementAt(dates.keys.length - 2)); preLastYear = preLastDate.year; preLastMonth = preLastDate.month; } else { @@ -90,12 +91,12 @@ int getHeigthByDate({DateTime date}) { preLastYear -= 1; } - var startRaw = '$preLastYear' + '-' + '$preLastMonth'; - var startHeight = dates[startRaw]; - var diff = endHeight - startHeight; - var heightPerDay = diff / 30; - var daysHeight = date.day * heightPerDay.round(); - var height = endHeight + daysHeight; + final startRaw = '$preLastYear' + '-' + '$preLastMonth'; + final startHeight = dates[startRaw]; + final diff = endHeight - startHeight; + final heightPerDay = diff / 30; + final daysHeight = date.day * heightPerDay.round(); + final height = endHeight + daysHeight; return height; } diff --git a/lib/src/domain/monero/monero_balance.dart b/lib/src/domain/monero/monero_balance.dart index c49ea8cb9..aee87fe4e 100644 --- a/lib/src/domain/monero/monero_balance.dart +++ b/lib/src/domain/monero/monero_balance.dart @@ -2,8 +2,8 @@ import 'package:flutter/foundation.dart'; import 'package:cake_wallet/src/domain/common/balance.dart'; class MoneroBalance extends Balance { + MoneroBalance({@required this.fullBalance, @required this.unlockedBalance}); + final String fullBalance; final String unlockedBalance; - - MoneroBalance({@required this.fullBalance, @required this.unlockedBalance}); } diff --git a/lib/src/domain/monero/monero_transaction_creation_credentials.dart b/lib/src/domain/monero/monero_transaction_creation_credentials.dart index c35b7705f..9df8a105d 100644 --- a/lib/src/domain/monero/monero_transaction_creation_credentials.dart +++ b/lib/src/domain/monero/monero_transaction_creation_credentials.dart @@ -3,11 +3,11 @@ import 'package:cake_wallet/src/domain/common/transaction_priority.dart'; class MoneroTransactionCreationCredentials extends TransactionCreationCredentials { + MoneroTransactionCreationCredentials( + {this.address, this.paymentId, this.priority, this.amount}); + final String address; final String paymentId; final String amount; final TransactionPriority priority; - - MoneroTransactionCreationCredentials( - {this.address, this.paymentId, this.priority, this.amount}); -} \ No newline at end of file +} diff --git a/lib/src/domain/monero/monero_transaction_history.dart b/lib/src/domain/monero/monero_transaction_history.dart index a6c7f1eaa..fb65e631f 100644 --- a/lib/src/domain/monero/monero_transaction_history.dart +++ b/lib/src/domain/monero/monero_transaction_history.dart @@ -1,26 +1,29 @@ import 'dart:core'; import 'package:flutter/services.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:cw_monero/transaction_history.dart' as moneroTransactionHistory; +import 'package:cw_monero/transaction_history.dart' + as monero_transaction_history; import 'package:cake_wallet/src/domain/common/transaction_history.dart'; import 'package:cake_wallet/src/domain/common/transaction_info.dart'; -List _getAllTransactions(_) => moneroTransactionHistory +List _getAllTransactions(dynamic _) => monero_transaction_history .getAllTransations() .map((row) => TransactionInfo.fromRow(row)) .toList(); class MoneroTransactionHistory extends TransactionHistory { - get transactions => _transactions.stream; - BehaviorSubject> _transactions; + MoneroTransactionHistory() + : _transactions = BehaviorSubject>.seeded([]); + @override + Observable> get transactions => _transactions.stream; + + final BehaviorSubject> _transactions; bool _isUpdating = false; bool _isRefreshing = false; bool _needToCheckForRefresh = false; - MoneroTransactionHistory() - : _transactions = BehaviorSubject>.seeded([]); - + @override Future update() async { if (_isUpdating) { return; @@ -38,15 +41,18 @@ class MoneroTransactionHistory extends TransactionHistory { } catch (e) { _isUpdating = false; print(e); - throw e; + rethrow; } } + @override Future> getAll({bool force = false}) async => _getAllTransactions(null); - Future count() async => moneroTransactionHistory.countOfTransactions(); + @override + Future count() async => monero_transaction_history.countOfTransactions(); + @override Future refresh() async { if (_isRefreshing) { return; @@ -54,12 +60,12 @@ class MoneroTransactionHistory extends TransactionHistory { try { _isRefreshing = true; - moneroTransactionHistory.refreshTransactions(); + monero_transaction_history.refreshTransactions(); _isRefreshing = false; } on PlatformException catch (e) { _isRefreshing = false; print(e); - throw e; + rethrow; } } } diff --git a/lib/src/domain/monero/monero_wallet.dart b/lib/src/domain/monero/monero_wallet.dart index fab161580..19c48525d 100644 --- a/lib/src/domain/monero/monero_wallet.dart +++ b/lib/src/domain/monero/monero_wallet.dart @@ -3,8 +3,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:cw_monero/wallet.dart' as moneroWallet; -import 'package:cw_monero/transaction_history.dart' as transactionHistory; +import 'package:cw_monero/wallet.dart' as monero_wallet; +import 'package:cw_monero/transaction_history.dart' as transaction_history; import 'package:cake_wallet/src/domain/common/wallet_info.dart'; import 'package:cake_wallet/src/domain/common/wallet.dart'; import 'package:cake_wallet/src/domain/common/sync_status.dart'; @@ -23,9 +23,25 @@ import 'package:cake_wallet/src/domain/monero/subaddress.dart'; import 'package:cake_wallet/src/domain/common/balance.dart'; import 'package:cake_wallet/src/domain/monero/monero_balance.dart'; -const monero_block_size = 1000; +const moneroBlockSize = 1000; class MoneroWallet extends Wallet { + MoneroWallet({this.walletInfoSource, this.walletInfo}) { + _cachedBlockchainHeight = 0; + _isSaving = false; + _lastSaveTime = 0; + _lastRefreshTime = 0; + _refreshHeight = 0; + _lastSyncHeight = 0; + _name = BehaviorSubject(); + _address = BehaviorSubject(); + _syncStatus = BehaviorSubject(); + _onBalanceChange = BehaviorSubject(); + _account = BehaviorSubject()..add(Account(id: 0)); + _subaddress = BehaviorSubject(); + setListeners(); + } + static Future createdWallet( {Box walletInfoSource, String name, @@ -48,8 +64,8 @@ class MoneroWallet extends Wallet { static Future load( Box walletInfoSource, String name, WalletType type) async { final id = walletTypeToString(type).toLowerCase() + '_' + name; - final walletInfo = - walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null); + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == id, orElse: () => null); return await configured( walletInfoSource: walletInfoSource, walletInfo: walletInfo); } @@ -61,29 +77,44 @@ class MoneroWallet extends Wallet { walletInfoSource: walletInfoSource, walletInfo: walletInfo); if (walletInfo.isRecovery) { - await wallet.setRecoveringFromSeed(); + wallet.setRecoveringFromSeed(); if (walletInfo.restoreHeight != null) { - await wallet.setRefreshFromBlockHeight( - height: walletInfo.restoreHeight); + wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight); } } return wallet; } + @override + String get address => _address.value; + + @override + String get name => _name.value; + + @override WalletType getType() => WalletType.monero; - bool get isRecovery => walletInfo.isRecovery; + + @override Observable get syncStatus => _syncStatus.stream; + + @override Observable get onBalanceChange => _onBalanceChange.stream; - Observable get onAccountChange => _account.stream; + + @override Observable get onNameChange => _name.stream; + + @override Observable get onAddressChange => _address.stream; + + Observable get onAccountChange => _account.stream; + Observable get subaddress => _subaddress.stream; + bool get isRecovery => walletInfo.isRecovery; + Account get account => _account.value; - String get address => _address.value; - String get name => _name.value; Box walletInfoSource; WalletInfo walletInfo; @@ -105,27 +136,11 @@ class MoneroWallet extends Wallet { SubaddressList _cachedSubaddressList; AccountList _cachedAccountList; - MoneroWallet( - {this.walletInfoSource, this.walletInfo}) { - _cachedBlockchainHeight = 0; - _isSaving = false; - _lastSaveTime = 0; - _lastRefreshTime = 0; - _refreshHeight = 0; - _lastSyncHeight = 0; - _name = BehaviorSubject(); - _address = BehaviorSubject(); - _syncStatus = BehaviorSubject(); - _onBalanceChange = BehaviorSubject(); - _account = BehaviorSubject()..add(Account(id: 0)); - _subaddress = BehaviorSubject(); - setListeners(); - } - + @override Future updateInfo() async { _name.value = await getName(); final acccountList = getAccountList(); - await acccountList.refresh(); + acccountList.refresh(); _account.value = acccountList.getAll().first; final subaddressList = getSubaddress(); await subaddressList.refresh( @@ -135,67 +150,48 @@ class MoneroWallet extends Wallet { _address.value = await getAddress(); } - Future getFilename() async => moneroWallet.getFilename(); + @override + Future getFilename() async => monero_wallet.getFilename(); + @override Future getName() async => getFilename() .then((filename) => filename.split('/')) .then((splitted) => splitted.last); - Future getAddress() async => moneroWallet.getAddress( + @override + Future getAddress() async => monero_wallet.getAddress( accountIndex: _account.value.id, addressIndex: _subaddress.value.id); - Future getSeed() async => moneroWallet.getSeed(); + @override + Future getSeed() async => monero_wallet.getSeed(); + @override Future getFullBalance() async => moneroAmountToString( - amount: moneroWallet.getFullBalance(accountIndex: _account.value.id)); + amount: monero_wallet.getFullBalance(accountIndex: _account.value.id)); + @override Future getUnlockedBalance() async => moneroAmountToString( - amount: moneroWallet.getUnlockedBalance(accountIndex: _account.value.id)); + amount: + monero_wallet.getUnlockedBalance(accountIndex: _account.value.id)); - Future getCurrentHeight() async => moneroWallet.getCurrentHeight(); + @override + Future getCurrentHeight() async => monero_wallet.getCurrentHeight(); - Future getNodeHeight() async => moneroWallet.getNodeHeight(); + @override + Future getNodeHeight() async => monero_wallet.getNodeHeight(); + @override + Future isConnected() async => monero_wallet.isConnected(); + + @override Future> getKeys() async => { - 'publicViewKey': moneroWallet.getPublicViewKey(), - 'privateViewKey': moneroWallet.getSecretViewKey(), - 'publicSpendKey': moneroWallet.getPublicSpendKey(), - 'privateSpendKey': moneroWallet.getSecretSpendKey() + 'publicViewKey': monero_wallet.getPublicViewKey(), + 'privateViewKey': monero_wallet.getSecretViewKey(), + 'publicSpendKey': monero_wallet.getPublicSpendKey(), + 'privateSpendKey': monero_wallet.getSecretSpendKey() }; - Future close() async { - moneroWallet.closeListeners(); - moneroWallet.closeCurrentWallet(); - } - - Future connectToNode( - {Node node, bool useSSL = false, bool isLightWallet = false}) async { - try { - _syncStatus.value = ConnectingSyncStatus(); - await moneroWallet.setupNode( - address: node.uri, - login: node.login, - password: node.password, - useSSL: useSSL, - isLightWallet: isLightWallet); - _syncStatus.value = ConnectedSyncStatus(); - } catch (e) { - _syncStatus.value = FailedSyncStatus(); - print(e); - } - } - - Future startSync() async { - try { - _syncStatus.value = StartingSyncStatus(); - moneroWallet.startRefresh(); - } on PlatformException catch (e) { - _syncStatus.value = FailedSyncStatus(); - print(e); - throw e; - } - } - + @override TransactionHistory getHistory() { if (_cachedTransactionHistory == null) { _cachedTransactionHistory = MoneroTransactionHistory(); @@ -220,6 +216,45 @@ class MoneroWallet extends Wallet { return _cachedAccountList; } + @override + Future close() async { + monero_wallet.closeListeners(); + monero_wallet.closeCurrentWallet(); + await _name.close(); + await _address.close(); + await _subaddress.close(); + } + + @override + Future connectToNode( + {Node node, bool useSSL = false, bool isLightWallet = false}) async { + try { + _syncStatus.value = ConnectingSyncStatus(); + await monero_wallet.setupNode( + address: node.uri, + login: node.login, + password: node.password, + useSSL: useSSL, + isLightWallet: isLightWallet); + _syncStatus.value = ConnectedSyncStatus(); + } catch (e) { + _syncStatus.value = FailedSyncStatus(); + print(e); + } + } + + @override + Future startSync() async { + try { + _syncStatus.value = StartingSyncStatus(); + monero_wallet.startRefresh(); + } on PlatformException catch (e) { + _syncStatus.value = FailedSyncStatus(); + print(e); + rethrow; + } + } + Future askForSave() async { final diff = DateTime.now().millisecondsSinceEpoch - _lastSaveTime; @@ -238,12 +273,11 @@ class MoneroWallet extends Wallet { return _cachedBlockchainHeight; } + @override Future createTransaction( TransactionCreationCredentials credentials) async { - MoneroTransactionCreationCredentials _credentials = - credentials as MoneroTransactionCreationCredentials; - - final transactionDescription = await transactionHistory.createTransaction( + final _credentials = credentials as MoneroTransactionCreationCredentials; + final transactionDescription = await transaction_history.createTransaction( address: _credentials.address, paymentId: _credentials.paymentId, amount: _credentials.amount, @@ -254,13 +288,19 @@ class MoneroWallet extends Wallet { transactionDescription); } - setRecoveringFromSeed() => - moneroWallet.setRecoveringFromSeed(isRecovery: true); + @override + Future rescan({int restoreHeight = 0}) async { + _syncStatus.value = StartingSyncStatus(); + setRefreshFromBlockHeight(height: restoreHeight); + monero_wallet.rescanBlockchainAsync(); + _syncStatus.value = StartingSyncStatus(); + } - setRefreshFromBlockHeight({int height}) => - moneroWallet.setRefreshFromBlockHeight(height: height); + void setRecoveringFromSeed() => + monero_wallet.setRecoveringFromSeed(isRecovery: true); - Future isConnected() async => moneroWallet.isConnected(); + void setRefreshFromBlockHeight({int height}) => + monero_wallet.setRefreshFromBlockHeight(height: height); Future setAsRecovered() async { walletInfo.isRecovery = false; @@ -285,22 +325,15 @@ class MoneroWallet extends Wallet { Future askForUpdateTransactionHistory() async => await getHistory().update(); - Future rescan({int restoreHeight = 0}) async { - _syncStatus.value = StartingSyncStatus(); - setRefreshFromBlockHeight(height: restoreHeight); - moneroWallet.rescanBlockchainAsync(); - _syncStatus.value = StartingSyncStatus(); - } - - changeCurrentSubaddress(Subaddress subaddress) => + void changeCurrentSubaddress(Subaddress subaddress) => _subaddress.value = subaddress; - changeAccount(Account account) { + void changeAccount(Account account) { _account.add(account); getSubaddress() .refresh(accountIndex: account.id) - .then((_) => getSubaddress().getAll()) + .then((dynamic _) => getSubaddress().getAll()) .then((subaddresses) => _subaddress.value = subaddresses[0]); } @@ -311,16 +344,16 @@ class MoneroWallet extends Wallet { try { _isSaving = true; - moneroWallet.store(); + await monero_wallet.store(); _isSaving = false; } on PlatformException catch (e) { print(e); _isSaving = false; - throw e; + rethrow; } } - setListeners() => moneroWallet.setListeners( + void setListeners() => monero_wallet.setListeners( _onNewBlock, _onNeedToRefresh, _onNewTransaction); Future _onNewBlock(int height) async { @@ -333,13 +366,13 @@ class MoneroWallet extends Wallet { if (isRecovery && (_lastSyncHeight == 0 || - (height - _lastSyncHeight) > monero_block_size)) { + (height - _lastSyncHeight) > moneroBlockSize)) { _lastSyncHeight = height; - askForUpdateBalance(); - askForUpdateTransactionHistory(); + await askForUpdateBalance(); + await askForUpdateTransactionHistory(); } - if (height > 0 && ((nodeHeight - height) < monero_block_size)) { + if (height > 0 && ((nodeHeight - height) < moneroBlockSize)) { _syncStatus.add(SyncedSyncStatus()); } else { _syncStatus.add(SyncingSyncStatus(height, nodeHeight, _refreshHeight)); @@ -363,15 +396,15 @@ class MoneroWallet extends Wallet { return; } - askForUpdateBalance(); + await askForUpdateBalance(); _syncStatus.add(SyncedSyncStatus()); if (isRecovery) { - askForUpdateTransactionHistory(); + await askForUpdateTransactionHistory(); } - if (isRecovery && (nodeHeight - currentHeight < monero_block_size)) { + if (isRecovery && (nodeHeight - currentHeight < moneroBlockSize)) { await setAsRecovered(); } diff --git a/lib/src/domain/monero/monero_wallets_manager.dart b/lib/src/domain/monero/monero_wallets_manager.dart index 81a034ac7..7510eb842 100644 --- a/lib/src/domain/monero/monero_wallets_manager.dart +++ b/lib/src/domain/monero/monero_wallets_manager.dart @@ -3,7 +3,7 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:cw_monero/wallet_manager.dart' as moneroWalletManager; +import 'package:cw_monero/wallet_manager.dart' as monero_wallet_manager; import 'package:cake_wallet/src/domain/common/wallet_info.dart'; import 'package:cake_wallet/src/domain/common/wallet_type.dart'; import 'package:cake_wallet/src/domain/common/wallets_manager.dart'; @@ -24,54 +24,61 @@ Future pathForWallet({String name}) async { } class MoneroWalletsManager extends WalletsManager { + MoneroWalletsManager({@required this.walletInfoSource}); + static const type = WalletType.monero; Box walletInfoSource; - MoneroWalletsManager({@required this.walletInfoSource}); - + @override Future create(String name, String password) async { try { const isRecovery = false; final path = await pathForWallet(name: name); - await moneroWalletManager.createWallet(path: path, password: password); + await monero_wallet_manager.createWallet(path: path, password: password); final wallet = await MoneroWallet.createdWallet( - walletInfoSource: walletInfoSource, name: name, isRecovery: isRecovery) - ..updateInfo(); + walletInfoSource: walletInfoSource, + name: name, + isRecovery: isRecovery); + await wallet.updateInfo(); return wallet; } catch (e) { print('MoneroWalletsManager Error: $e'); - throw e; + rethrow; } } + @override Future restoreFromSeed( String name, String password, String seed, int restoreHeight) async { try { const isRecovery = true; final path = await pathForWallet(name: name); - await moneroWalletManager.restoreFromSeed( + await monero_wallet_manager.restoreFromSeed( path: path, password: password, seed: seed, restoreHeight: restoreHeight); - return await MoneroWallet.createdWallet( + final wallet = await MoneroWallet.createdWallet( walletInfoSource: walletInfoSource, name: name, isRecovery: isRecovery, - restoreHeight: restoreHeight) - ..updateInfo(); + restoreHeight: restoreHeight); + await wallet.updateInfo(); + + return wallet; } catch (e) { print('MoneroWalletsManager Error: $e'); - throw e; + rethrow; } } + @override Future restoreFromKeys( String name, String password, @@ -83,7 +90,7 @@ class MoneroWalletsManager extends WalletsManager { const isRecovery = true; final path = await pathForWallet(name: name); - await moneroWalletManager.restoreFromKeys( + await monero_wallet_manager.restoreFromKeys( path: path, password: password, restoreHeight: restoreHeight, @@ -95,40 +102,43 @@ class MoneroWalletsManager extends WalletsManager { walletInfoSource: walletInfoSource, name: name, isRecovery: isRecovery, - restoreHeight: restoreHeight) - ..updateInfo(); + restoreHeight: restoreHeight); + await wallet.updateInfo(); return wallet; } catch (e) { print('MoneroWalletsManager Error: $e'); - throw e; + rethrow; } } + @override Future openWallet(String name, String password) async { try { final path = await pathForWallet(name: name); - await moneroWalletManager.openWallet(path: path, password: password); - final wallet = await MoneroWallet.load(walletInfoSource, name, type) - ..updateInfo(); + monero_wallet_manager.openWallet(path: path, password: password); + final wallet = await MoneroWallet.load(walletInfoSource, name, type); + await wallet.updateInfo(); return wallet; } catch (e) { print('MoneroWalletsManager Error: $e'); - throw e; + rethrow; } } + @override Future isWalletExit(String name) async { try { final path = await pathForWallet(name: name); - return moneroWalletManager.isWalletExist(path: path); + return monero_wallet_manager.isWalletExist(path: path); } catch (e) { print('MoneroWalletsManager Error: $e'); - throw e; + rethrow; } } + @override Future remove(WalletDescription wallet) async { final dir = await getApplicationDocumentsDirectory(); final root = dir.path.replaceAll('app_flutter', 'files'); @@ -153,8 +163,9 @@ class MoneroWalletsManager extends WalletsManager { final id = walletTypeToString(wallet.type).toLowerCase() + '_' + wallet.name; - final info = walletInfoSource.values.firstWhere((info) => info.id == id, orElse: () => null); - + final info = walletInfoSource.values + .firstWhere((info) => info.id == id, orElse: () => null); + await info?.delete(); } } diff --git a/lib/src/domain/monero/subaddress.dart b/lib/src/domain/monero/subaddress.dart index 9294c2ab6..fce417fa9 100644 --- a/lib/src/domain/monero/subaddress.dart +++ b/lib/src/domain/monero/subaddress.dart @@ -1,19 +1,19 @@ import 'package:cw_monero/structs/subaddress_row.dart'; class Subaddress { - final int id; - final String address; - final String label; - Subaddress({this.id, this.address, this.label}); Subaddress.fromMap(Map map) - : this.id = map['id'] == null ? 0 : int.parse(map['id']), - this.address = map['address'] ?? '', - this.label = map['label'] ?? ''; + : this.id = map['id'] == null ? 0 : int.parse(map['id'] as String), + this.address = (map['address'] ?? '') as String, + this.label = (map['label'] ?? '') as String; Subaddress.fromRow(SubaddressRow row) : this.id = row.getId(), this.address = row.getAddress(), this.label = row.getLabel(); + + final int id; + final String address; + final String label; } diff --git a/lib/src/domain/monero/subaddress_list.dart b/lib/src/domain/monero/subaddress_list.dart index e2d123752..88af93740 100644 --- a/lib/src/domain/monero/subaddress_list.dart +++ b/lib/src/domain/monero/subaddress_list.dart @@ -1,21 +1,21 @@ import 'package:flutter/services.dart'; import 'package:rxdart/rxdart.dart'; -import 'package:cw_monero/subaddress_list.dart' as subaddressListAPI; +import 'package:cw_monero/subaddress_list.dart' as subaddress_list; import 'package:cake_wallet/src/domain/monero/subaddress.dart'; class SubaddressList { - get subaddresses => _subaddress.stream; - BehaviorSubject> _subaddress; - - bool _isRefreshing; - bool _isUpdating; - SubaddressList() { _isRefreshing = false; _isUpdating = false; _subaddress = BehaviorSubject>(); } + Observable> get subaddresses => _subaddress.stream; + + BehaviorSubject> _subaddress; + bool _isRefreshing; + bool _isUpdating; + Future update({int accountIndex}) async { if (_isUpdating) { return; @@ -29,25 +29,26 @@ class SubaddressList { _isUpdating = false; } catch (e) { _isUpdating = false; - throw e; + rethrow; } } List getAll() { - return subaddressListAPI + return subaddress_list .getAllSubaddresses() .map((subaddressRow) => Subaddress.fromRow(subaddressRow)) .toList(); } Future addSubaddress({int accountIndex, String label}) async { - await subaddressListAPI.addSubaddress(accountIndex: accountIndex, label: label); + await subaddress_list.addSubaddress( + accountIndex: accountIndex, label: label); await update(accountIndex: accountIndex); } Future setLabelSubaddress( {int accountIndex, int addressIndex, String label}) async { - await subaddressListAPI.setLabelForSubaddress( + await subaddress_list.setLabelForSubaddress( accountIndex: accountIndex, addressIndex: addressIndex, label: label); await update(); } @@ -59,12 +60,12 @@ class SubaddressList { try { _isRefreshing = true; - subaddressListAPI.refreshSubaddresses(accountIndex: accountIndex); + subaddress_list.refreshSubaddresses(accountIndex: accountIndex); _isRefreshing = false; } on PlatformException catch (e) { _isRefreshing = false; print(e); - throw e; + rethrow; } } } diff --git a/lib/src/domain/monero/transaction_description.dart b/lib/src/domain/monero/transaction_description.dart index a0becfd55..d40773180 100644 --- a/lib/src/domain/monero/transaction_description.dart +++ b/lib/src/domain/monero/transaction_description.dart @@ -4,6 +4,8 @@ part 'transaction_description.g.dart'; @HiveType() class TransactionDescription extends HiveObject { + TransactionDescription({this.id, this.recipientAddress}); + static const boxName = 'TransactionDescriptions'; @HiveField(0) @@ -11,6 +13,4 @@ class TransactionDescription extends HiveObject { @HiveField(1) String recipientAddress; - - TransactionDescription({this.id, this.recipientAddress}); -} \ No newline at end of file +} diff --git a/lib/src/domain/services/user_service.dart b/lib/src/domain/services/user_service.dart index 8560eac00..95429e528 100644 --- a/lib/src/domain/services/user_service.dart +++ b/lib/src/domain/services/user_service.dart @@ -4,11 +4,11 @@ import 'package:cake_wallet/src/domain/common/secret_store_key.dart'; import 'package:cake_wallet/src/domain/common/encrypt.dart'; class UserService { + UserService({this.sharedPreferences, this.secureStorage}); + final FlutterSecureStorage secureStorage; final SharedPreferences sharedPreferences; - UserService({this.sharedPreferences, this.secureStorage}); - Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); diff --git a/lib/src/domain/services/wallet_list_service.dart b/lib/src/domain/services/wallet_list_service.dart index 7fe4e1a26..feb3fe185 100644 --- a/lib/src/domain/services/wallet_list_service.dart +++ b/lib/src/domain/services/wallet_list_service.dart @@ -15,21 +15,15 @@ import 'package:cake_wallet/src/domain/monero/monero_wallets_manager.dart'; import 'package:cake_wallet/src/domain/services/wallet_service.dart'; class WalletIsExistException implements Exception { - String name; - WalletIsExistException(this.name); + String name; + @override String toString() => "Wallet with name $name is already exist!"; } class WalletListService { - final FlutterSecureStorage secureStorage; - final WalletService walletService; - final Box walletInfoSource; - final SharedPreferences sharedPreferences; - WalletsManager walletsManager; - WalletListService( {this.secureStorage, this.walletInfoSource, @@ -37,6 +31,12 @@ class WalletListService { @required this.walletService, @required this.sharedPreferences}); + final FlutterSecureStorage secureStorage; + final WalletService walletService; + final Box walletInfoSource; + final SharedPreferences sharedPreferences; + WalletsManager walletsManager; + Future> getAll() async => walletInfoSource.values .map((info) => WalletDescription(name: info.name, type: info.type)) .toList(); @@ -52,7 +52,7 @@ class WalletListService { final password = Uuid().v4(); await saveWalletPassword(password: password, walletName: name); - + final wallet = await walletsManager.create(name, password); await onWalletChange(wallet); @@ -131,7 +131,7 @@ class WalletListService { final key = generateStoreKeyFor( key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = await secureStorage.read(key: key); - + return decodeWalletPassword(password: encodedPassword); } diff --git a/lib/src/domain/services/wallet_service.dart b/lib/src/domain/services/wallet_service.dart index b805dbb58..c72807c8e 100644 --- a/lib/src/domain/services/wallet_service.dart +++ b/lib/src/domain/services/wallet_service.dart @@ -10,17 +10,40 @@ import 'package:cake_wallet/src/domain/common/pending_transaction.dart'; import 'package:cake_wallet/src/domain/common/node.dart'; class WalletService extends Wallet { - Observable get onWalletChange => _onWalletChanged.stream; + WalletService() { + _currentWallet = null; + walletType = WalletType.none; + _syncStatus = BehaviorSubject(); + _onBalanceChange = BehaviorSubject(); + _onWalletChanged = BehaviorSubject(); + } + + @override Observable get onBalanceChange => _onBalanceChange.stream; + + @override Observable get syncStatus => _syncStatus.stream; + + @override Observable get onAddressChange => _currentWallet.onAddressChange; + + @override Observable get onNameChange => _currentWallet.onNameChange; + + @override String get address => _currentWallet.address; + + @override String get name => _currentWallet.name; - SyncStatus get syncStatusValue => _syncStatus.value; + + @override WalletType get walletType => _currentWallet.walletType; - get currentWallet => _currentWallet; + Observable get onWalletChange => _onWalletChanged.stream; + + SyncStatus get syncStatusValue => _syncStatus.value; + + Wallet get currentWallet => _currentWallet; set currentWallet(Wallet wallet) { _currentWallet = wallet; @@ -44,55 +67,65 @@ class WalletService extends Wallet { BehaviorSubject _syncStatus; Wallet _currentWallet; - WalletService() { - _currentWallet = null; - walletType = WalletType.none; - _syncStatus = BehaviorSubject(); - _onBalanceChange = BehaviorSubject(); - _onWalletChanged = BehaviorSubject(); - } - WalletDescription description; + @override WalletType getType() => WalletType.monero; + @override Future getFilename() => _currentWallet.getFilename(); + @override Future getName() => _currentWallet.getName(); + @override Future getAddress() => _currentWallet.getAddress(); + @override Future getSeed() => _currentWallet.getSeed(); + @override Future> getKeys() => _currentWallet.getKeys(); + @override Future getFullBalance() => _currentWallet.getFullBalance(); + @override Future getUnlockedBalance() => _currentWallet.getUnlockedBalance(); + @override Future getCurrentHeight() => _currentWallet.getCurrentHeight(); + @override Future getNodeHeight() => _currentWallet.getNodeHeight(); + @override Future isConnected() => _currentWallet.isConnected(); + @override Future close() => _currentWallet.close(); - Future connectToNode({Node node, bool useSSL = false, bool isLightWallet = false}) => + @override + Future connectToNode( + {Node node, bool useSSL = false, bool isLightWallet = false}) => _currentWallet.connectToNode( - node: node, - useSSL: useSSL, - isLightWallet: isLightWallet); + node: node, useSSL: useSSL, isLightWallet: isLightWallet); + @override Future startSync() => _currentWallet.startSync(); + @override TransactionHistory getHistory() => _currentWallet.getHistory(); + @override Future createTransaction( TransactionCreationCredentials credentials) => _currentWallet.createTransaction(credentials); + @override Future updateInfo() async => _currentWallet.updateInfo(); - Future rescan({int restoreHeight = 0}) async => _currentWallet.rescan(restoreHeight: restoreHeight); + @override + Future rescan({int restoreHeight = 0}) async => + _currentWallet.rescan(restoreHeight: restoreHeight); } diff --git a/lib/src/reactions/set_reactions.dart b/lib/src/reactions/set_reactions.dart index 001157524..2351bd0b5 100644 --- a/lib/src/reactions/set_reactions.dart +++ b/lib/src/reactions/set_reactions.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/src/domain/common/node.dart'; import 'package:cake_wallet/src/domain/common/sync_status.dart'; import 'package:cake_wallet/src/domain/services/wallet_service.dart'; import 'package:cake_wallet/src/start_updating_price.dart'; @@ -11,7 +12,12 @@ import 'package:cake_wallet/src/stores/price/price_store.dart'; import 'package:cake_wallet/src/stores/authentication/authentication_store.dart'; import 'package:cake_wallet/src/stores/login/login_store.dart'; -setReactions( +Timer _reconnectionTimer; +ReactionDisposer _connectToNodeDisposer; +ReactionDisposer _onSyncStatusChangeDisposer; +ReactionDisposer _onCurrentWalletChangeDisposer; + +void setReactions( {@required SettingsStore settingsStore, @required PriceStore priceStore, @required SyncStore syncStore, @@ -36,29 +42,44 @@ setReactions( }); } -connectToNode({SettingsStore settingsStore, WalletStore walletStore}) => - reaction((_) => settingsStore.node, - (node) async => await walletStore.connectToNode(node: node)); +void connectToNode({SettingsStore settingsStore, WalletStore walletStore}) { + _connectToNodeDisposer?.call(); -onSyncStatusChange( - {SyncStore syncStore, - WalletStore walletStore, - SettingsStore settingsStore}) => - reaction((_) => syncStore.status, (status) async { - if (status is ConnectedSyncStatus) { - await walletStore.startSync(); - } + _connectToNodeDisposer = reaction((_) => settingsStore.node, + (Node node) async => await walletStore.connectToNode(node: node)); +} - // Reconnect to the node if the app is not started sync after 30 seconds - if (status is StartingSyncStatus) { - await startReconnectionObserver( - syncStore: syncStore, walletStore: walletStore); - } - }); +void onCurrentWalletChange( + {WalletStore walletStore, + SettingsStore settingsStore, + PriceStore priceStore}) { + _onCurrentWalletChangeDisposer?.call(); -Timer _reconnectionTimer; + reaction((_) => walletStore.name, (String _) { + walletStore.connectToNode(node: settingsStore.node); + startUpdatingPrice(settingsStore: settingsStore, priceStore: priceStore); + }); +} -startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) { +void onSyncStatusChange( + {SyncStore syncStore, + WalletStore walletStore, + SettingsStore settingsStore}) { + _onSyncStatusChangeDisposer?.call(); + + reaction((_) => syncStore.status, (SyncStatus status) async { + if (status is ConnectedSyncStatus) { + await walletStore.startSync(); + } + + // Reconnect to the node if the app is not started sync after 30 seconds + if (status is StartingSyncStatus) { + startReconnectionObserver(syncStore: syncStore, walletStore: walletStore); + } + }); +} + +void startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) { if (_reconnectionTimer != null) { _reconnectionTimer.cancel(); } @@ -75,12 +96,3 @@ startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) { } }); } - -onCurrentWalletChange( - {WalletStore walletStore, - SettingsStore settingsStore, - PriceStore priceStore}) => - reaction((_) => walletStore.name, (_) { - walletStore.connectToNode(node: settingsStore.node); - startUpdatingPrice(settingsStore: settingsStore, priceStore: priceStore); - }); diff --git a/lib/src/screens/accounts/account_list_page.dart b/lib/src/screens/accounts/account_list_page.dart index 2f54a7718..00be33fe5 100644 --- a/lib/src/screens/accounts/account_list_page.dart +++ b/lib/src/screens/accounts/account_list_page.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class AccountListPage extends BasePage { + @override String get title => S.current.accounts; @override @@ -21,8 +22,7 @@ class AccountListPage extends BasePage { width: 28.0, height: 28.0, decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).selectedRowColor), + shape: BoxShape.circle, color: Theme.of(context).selectedRowColor), child: Stack( alignment: Alignment.center, children: [ @@ -35,7 +35,7 @@ class AccountListPage extends BasePage { onPressed: () async { await Navigator.of(context) .pushNamed(Routes.accountCreation); - await accountListStore.updateAccountList(); + accountListStore.updateAccountList(); }, child: Offstage()), ) @@ -53,13 +53,10 @@ class AccountListPage extends BasePage { return Container( padding: EdgeInsets.only(top: 10, bottom: 20), - child: Observer( - builder: (_) { - final accounts = accountListStore.accounts; - return ListView.builder( - itemCount: accounts == null - ? 0 - : accounts.length, + child: Observer(builder: (_) { + final accounts = accountListStore.accounts; + return ListView.builder( + itemCount: accounts == null ? 0 : accounts.length, itemBuilder: (BuildContext context, int index) { final account = accounts[index]; @@ -78,7 +75,10 @@ class AccountListPage extends BasePage { account.label, style: TextStyle( fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.headline.color), + color: Theme.of(context) + .primaryTextTheme + .headline + .color), ), onTap: () { if (isCurrent) { @@ -102,8 +102,9 @@ class AccountListPage extends BasePage { color: Colors.blue, icon: Icons.edit, onTap: () async { - await Navigator.of(context) - .pushNamed(Routes.accountCreation, arguments: account); + await Navigator.of(context).pushNamed( + Routes.accountCreation, + arguments: account); // await accountListStore.updateAccountList().then((_) { // if (isCurrent) walletStore.setAccount(accountListStore.accounts[index]); // }); @@ -113,8 +114,7 @@ class AccountListPage extends BasePage { ); }); }); - } - ), + }), ); } } diff --git a/lib/src/screens/accounts/account_page.dart b/lib/src/screens/accounts/account_page.dart index 76677939e..d02bfb479 100644 --- a/lib/src/screens/accounts/account_page.dart +++ b/lib/src/screens/accounts/account_page.dart @@ -10,22 +10,24 @@ import 'package:cake_wallet/src/domain/monero/account.dart'; import 'package:cake_wallet/palette.dart'; class AccountPage extends BasePage { - String get title => 'Account'; + AccountPage({this.account}); + final Account account; - AccountPage({this.account}); + @override + String get title => 'Account'; @override Widget body(BuildContext context) => AccountForm(account); } class AccountForm extends StatefulWidget { - final Account account; - AccountForm(this.account); + final Account account; + @override - createState() => AccountFormState(); + AccountFormState createState() => AccountFormState(); } class AccountFormState extends State { @@ -61,8 +63,8 @@ class AccountFormState extends State { hintStyle: TextStyle(color: Theme.of(context).hintColor), hintText: S.of(context).account, focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Palette.cakeGreen, width: 2.0)), + borderSide: + BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, width: 1.0))), @@ -88,7 +90,7 @@ class AccountFormState extends State { await accountListStore.addAccount( label: _textController.text); } - Navigator.pop(context, _textController.text); + Navigator.of(context).pop(_textController.text); }, text: widget.account != null ? 'Rename' : S.of(context).add, diff --git a/lib/src/screens/address_book/address_book_page.dart b/lib/src/screens/address_book/address_book_page.dart index 20d849dc6..002c4d939 100644 --- a/lib/src/screens/address_book/address_book_page.dart +++ b/lib/src/screens/address_book/address_book_page.dart @@ -12,13 +12,18 @@ import 'package:cake_wallet/src/stores/address_book/address_book_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class AddressBookPage extends BasePage { - bool get isModalBackButton => true; - String get title => S.current.address_book; - AppBarStyle get appBarStyle => AppBarStyle.withShadow; + AddressBookPage({this.isEditable = true}); final bool isEditable; - AddressBookPage({this.isEditable = true}); + @override + bool get isModalBackButton => true; + + @override + String get title => S.current.address_book; + + @override + AppBarStyle get appBarStyle => AppBarStyle.withShadow; @override Widget trailing(BuildContext context) { @@ -32,8 +37,7 @@ class AddressBookPage extends BasePage { width: 28.0, height: 28.0, decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).selectedRowColor), + shape: BoxShape.circle, color: Theme.of(context).selectedRowColor), child: Stack( alignment: Alignment.center, children: [ @@ -79,16 +83,17 @@ class AddressBookPage extends BasePage { return; } - bool isCopied = await showNameAndAddressDialog(context, contact.name, contact.address); + final isCopied = await showNameAndAddressDialog( + context, contact.name, contact.address); + if (isCopied) { - Clipboard.setData(ClipboardData(text: contact.address)); + await Clipboard.setData( + ClipboardData(text: contact.address)); Scaffold.of(context).showSnackBar( SnackBar( - content: - Text('Copied to Clipboard'), + content: Text('Copied to Clipboard'), backgroundColor: Colors.green, - duration: - Duration(milliseconds: 1500), + duration: Duration(milliseconds: 1500), ), ); } @@ -117,48 +122,51 @@ class AddressBookPage extends BasePage { ), ); - return !isEditable ? content - : Slidable( - key: Key('1'),// Key(contact.id.toString()), - actionPane: SlidableDrawerActionPane(), - child: content, - secondaryActions: [ - IconSlideAction( - caption: 'Edit', - color: Colors.blue, - icon: Icons.edit, - onTap: () async { - await Navigator.of(context) - .pushNamed(Routes.addressBookAddContact, arguments: contact); - await addressBookStore.updateContactList(); - }, - ), - IconSlideAction( - caption: 'Delete', - color: Colors.red, - icon: CupertinoIcons.delete, - onTap: () async { - await showAlertDialog(context).then((isDelete) async{ - if (isDelete != null && isDelete) { - await addressBookStore.delete(contact: contact); + return !isEditable + ? content + : Slidable( + key: Key('${contact.key}'), + actionPane: SlidableDrawerActionPane(), + child: content, + secondaryActions: [ + IconSlideAction( + caption: 'Edit', + color: Colors.blue, + icon: Icons.edit, + onTap: () async { + await Navigator.of(context).pushNamed( + Routes.addressBookAddContact, + arguments: contact); await addressBookStore.updateContactList(); - } - }); - }, - ), - ], - dismissal: SlidableDismissal( - child: SlidableDrawerDismissal(), - onDismissed: (actionType) async { - await addressBookStore.delete(contact: contact); - await addressBookStore.updateContactList(); - }, - onWillDismiss: (actionType) async { - return await showAlertDialog(context); - }, - ), - - ); + }, + ), + IconSlideAction( + caption: 'Delete', + color: Colors.red, + icon: CupertinoIcons.delete, + onTap: () async { + await showAlertDialog(context) + .then((isDelete) async { + if (isDelete != null && isDelete) { + await addressBookStore.delete( + contact: contact); + await addressBookStore.updateContactList(); + } + }); + }, + ), + ], + dismissal: SlidableDismissal( + child: SlidableDrawerDismissal(), + onDismissed: (actionType) async { + await addressBookStore.delete(contact: contact); + await addressBookStore.updateContactList(); + }, + onWillDismiss: (actionType) async { + return await showAlertDialog(context); + }, + ), + ); }), )); } @@ -220,42 +228,40 @@ class AddressBookPage extends BasePage { ), actions: [ FlatButton( - onPressed: () => - Navigator.pop(context, false), + onPressed: () => Navigator.of(context).pop( false), child: const Text('Cancel')), FlatButton( - onPressed: () => - Navigator.pop(context, true), + onPressed: () => Navigator.of(context).pop(true), child: const Text('Remove')), ], ); }); } - showNameAndAddressDialog(BuildContext context, String name, String address) async { + Future showNameAndAddressDialog( + BuildContext context, String name, String address) async { return await showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: Text( - name, - textAlign: TextAlign.center, - style: TextStyle(fontWeight: FontWeight.bold), - ), - content: Text( - address, - textAlign: TextAlign.center, - ), - actions: [ - FlatButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text('Cancel')), - FlatButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text('Copy')) - ], - ); - } - ); + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text( + name, + textAlign: TextAlign.center, + style: TextStyle(fontWeight: FontWeight.bold), + ), + content: Text( + address, + textAlign: TextAlign.center, + ), + actions: [ + FlatButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text('Cancel')), + FlatButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text('Copy')) + ], + ); + }); } } diff --git a/lib/src/screens/address_book/contact_page.dart b/lib/src/screens/address_book/contact_page.dart index a42497c8c..cfd2ad419 100644 --- a/lib/src/screens/address_book/contact_page.dart +++ b/lib/src/screens/address_book/contact_page.dart @@ -12,22 +12,24 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/palette.dart'; class ContactPage extends BasePage { - String get title => S.current.contact; + ContactPage({this.contact}); + final Contact contact; - ContactPage({this.contact}); + @override + String get title => S.current.contact; @override Widget body(BuildContext context) => ContactForm(contact); } class ContactForm extends StatefulWidget { - final Contact contact; - ContactForm(this.contact); + final Contact contact; + @override - createState() => ContactFormState(); + State createState() => ContactFormState(); } class ContactFormState extends State { @@ -59,10 +61,11 @@ class ContactFormState extends State { super.dispose(); } - _setCurrencyType(BuildContext context) async { - String currencyType = CryptoCurrency.all[0].toString(); - CryptoCurrency selectedCurrency = CryptoCurrency.all[0]; - await showDialog( + Future _setCurrencyType(BuildContext context) async { + var currencyType = CryptoCurrency.all[0].toString(); + var selectedCurrency = CryptoCurrency.all[0]; + + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -127,8 +130,8 @@ class ContactFormState extends State { hintStyle: TextStyle(color: Theme.of(context).hintColor), hintText: S.of(context).contact_name, focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Palette.cakeGreen, width: 2.0)), + borderSide: + BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, width: 1.0))), @@ -153,8 +156,7 @@ class ContactFormState extends State { decoration: InputDecoration( focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, @@ -215,13 +217,15 @@ class ContactFormState extends State { } else { widget.contact.name = _contactNameController.text; widget.contact.address = _addressController.text; - widget.contact.updateCryptoCurrency(currency: _selectectCrypto); + widget.contact + .updateCryptoCurrency(currency: _selectectCrypto); - await addressBookStore.update(contact: widget.contact); + await addressBookStore.update( + contact: widget.contact); } Navigator.pop(context); } catch (e) { - await showDialog( + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/auth/auth_page.dart b/lib/src/screens/auth/auth_page.dart index 085defe2b..5711b8b5e 100644 --- a/lib/src/screens/auth/auth_page.dart +++ b/lib/src/screens/auth/auth_page.dart @@ -7,13 +7,14 @@ import 'package:cake_wallet/src/stores/auth/auth_state.dart'; import 'package:cake_wallet/src/stores/auth/auth_store.dart'; import 'package:cake_wallet/src/screens/pin_code/pin_code.dart'; +typedef OnAuthenticationFinished = void Function(bool, AuthPageState); class AuthPage extends StatefulWidget { - final Function(bool, AuthPageState) onAuthenticationFinished; - final bool closable; - AuthPage({this.onAuthenticationFinished, this.closable = true}); + final OnAuthenticationFinished onAuthenticationFinished; + final bool closable; + @override AuthPageState createState() => AuthPageState(); } @@ -33,7 +34,7 @@ class AuthPageState extends State { Widget build(BuildContext context) { final authStore = Provider.of(context); - reaction((_) => authStore.state, (state) { + reaction((_) => authStore.state, (AuthState state) { if (state is AuthenticatedSuccessfully) { WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.onAuthenticationFinished != null) { @@ -60,7 +61,24 @@ class AuthPageState extends State { }); } - if (state is AuthenticationFailure || state is AuthenticationBanned) { + if (state is AuthenticationFailure) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _pinCodeKey.currentState.clear(); + _key.currentState.hideCurrentSnackBar(); + _key.currentState.showSnackBar( + SnackBar( + content: Text(S.of(context).failed_authentication(state.error)), + backgroundColor: Colors.red, + ), + ); + + if (widget.onAuthenticationFinished != null) { + widget.onAuthenticationFinished(false, this); + } + }); + } + + if (state is AuthenticationBanned) { WidgetsBinding.instance.addPostFrameCallback((_) { _pinCodeKey.currentState.clear(); _key.currentState.hideCurrentSnackBar(); diff --git a/lib/src/screens/base_page.dart b/lib/src/screens/base_page.dart index 4b5ef8b01..309f0fe50 100644 --- a/lib/src/screens/base_page.dart +++ b/lib/src/screens/base_page.dart @@ -28,7 +28,7 @@ abstract class BasePage extends StatelessWidget { return null; } - ThemeChanger _themeChanger = Provider.of(context); + final _themeChanger = Provider.of(context); Image _closeButton, _backButton; if (_themeChanger.getTheme() == Themes.darkTheme) { @@ -70,7 +70,7 @@ abstract class BasePage extends StatelessWidget { Widget floatingActionButton(BuildContext context) => null; - Widget appBar(BuildContext context) { + ObstructingPreferredSizeWidget appBar(BuildContext context) { final _themeChanger = Provider.of(context); final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 2097193c4..5d2e80361 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -1,6 +1,6 @@ import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; -import 'package:date_range_picker/date_range_picker.dart' as DateRagePicker; +import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -86,24 +86,19 @@ class DashboardPage extends BasePage { child: Image.asset('assets/images/exchange_icon.png', color: Colors.white, height: 26, width: 22), backgroundColor: Palette.floatingActionButton, - onPressed: () async { - final actionListStore = Provider.of(context); - - await Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.exchange); - actionListStore.updateTradeList(); - }); + onPressed: () async => await Navigator.of(context, rootNavigator: true) + .pushNamed(Routes.exchange)); void _presentWalletMenu(BuildContext bodyContext) { final walletMenu = WalletMenu(bodyContext); - showDialog( + showDialog( builder: (_) => Picker( items: walletMenu.items, selectedAtIndex: -1, title: S.of(bodyContext).wallet_menu, pickerHeight: 510, - onItemSelected: (item) => + onItemSelected: (String item) => walletMenu.action(walletMenu.items.indexOf(item))), context: bodyContext); } @@ -136,8 +131,9 @@ class DashboardPageBodyState extends State { return Observer( key: _listObserverKey, builder: (_) { - final items = - actionListStore.items == null ? [] : actionListStore.items; + final items = actionListStore.items == null + ? [] + : actionListStore.items; final itemsCount = items.length + 2; return ListView.builder( @@ -225,19 +221,17 @@ class DashboardPageBodyState extends State { builder: (_) { final savedDisplayMode = settingsStore.balanceDisplayMode; - final displayMode = - balanceStore.isReversing - ? (savedDisplayMode == - BalanceDisplayMode - .availableBalance - ? BalanceDisplayMode - .fullBalance - : BalanceDisplayMode - .availableBalance) - : savedDisplayMode; - var title = displayMode.toString(); + final displayMode = balanceStore + .isReversing + ? (savedDisplayMode == + BalanceDisplayMode + .availableBalance + ? BalanceDisplayMode.fullBalance + : BalanceDisplayMode + .availableBalance) + : savedDisplayMode; - return Text(title, + return Text(displayMode.toString(), style: TextStyle( color: Palette.violet, fontSize: 16)); @@ -248,16 +242,15 @@ class DashboardPageBodyState extends State { final savedDisplayMode = settingsStore.balanceDisplayMode; var balance = '---'; - final displayMode = - balanceStore.isReversing - ? (savedDisplayMode == - BalanceDisplayMode - .availableBalance - ? BalanceDisplayMode - .fullBalance - : BalanceDisplayMode - .availableBalance) - : savedDisplayMode; + final displayMode = balanceStore + .isReversing + ? (savedDisplayMode == + BalanceDisplayMode + .availableBalance + ? BalanceDisplayMode.fullBalance + : BalanceDisplayMode + .availableBalance) + : savedDisplayMode; if (displayMode == BalanceDisplayMode.availableBalance) { @@ -499,7 +492,7 @@ class DashboardPageBodyState extends State { onSelected: (item) async { if (item == 2) { final List picked = - await DateRagePicker.showDatePicker( + await date_rage_picker.showDatePicker( context: context, initialFirstDate: DateTime.now() .subtract(Duration(days: 1)), diff --git a/lib/src/screens/dashboard/date_section_raw.dart b/lib/src/screens/dashboard/date_section_raw.dart index dea6310f4..155bbc22b 100644 --- a/lib/src/screens/dashboard/date_section_raw.dart +++ b/lib/src/screens/dashboard/date_section_raw.dart @@ -4,19 +4,21 @@ import 'package:intl/intl.dart'; import 'package:cake_wallet/generated/i18n.dart'; class DateSectionRaw extends StatelessWidget { + DateSectionRaw({this.date}); + static final dateSectionDateFormat = DateFormat("d MMM"); static final nowDate = DateTime.now(); final DateTime date; - DateSectionRaw({this.date}); - @override Widget build(BuildContext context) { final diffDays = date.difference(nowDate).inDays; - final isToday = nowDate.day == date.day && nowDate.month == date.month && nowDate.year == date.year; + final isToday = nowDate.day == date.day && + nowDate.month == date.month && + nowDate.year == date.year; var title = ""; - + if (isToday) { title = S.of(context).today; } else if (diffDays == 0) { diff --git a/lib/src/screens/dashboard/trade_row.dart b/lib/src/screens/dashboard/trade_row.dart index 668dc05a0..c3e88c8e2 100644 --- a/lib/src/screens/dashboard/trade_row.dart +++ b/lib/src/screens/dashboard/trade_row.dart @@ -4,13 +4,6 @@ import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; class TradeRow extends StatelessWidget { - final VoidCallback onTap; - final ExchangeProviderDescription provider; - final CryptoCurrency from; - final CryptoCurrency to; - final String createdAtFormattedDate; - final String formattedAmount; - TradeRow( {this.provider, this.from, @@ -19,6 +12,13 @@ class TradeRow extends StatelessWidget { this.formattedAmount, @required this.onTap}); + final VoidCallback onTap; + final ExchangeProviderDescription provider; + final CryptoCurrency from; + final CryptoCurrency to; + final String createdAtFormattedDate; + final String formattedAmount; + @override Widget build(BuildContext context) { final amountCrypto = provider == ExchangeProviderDescription.xmrto @@ -48,7 +48,10 @@ class TradeRow extends StatelessWidget { Text('${from.toString()} → ${to.toString()}', style: TextStyle( fontSize: 16, - color: Theme.of(context).primaryTextTheme.subhead.color)), + color: Theme.of(context) + .primaryTextTheme + .subhead + .color)), formattedAmount != null ? Text(formattedAmount + ' ' + amountCrypto, style: const TextStyle( diff --git a/lib/src/screens/dashboard/transaction_raw.dart b/lib/src/screens/dashboard/transaction_raw.dart index 0f7dc5ef5..383db5218 100644 --- a/lib/src/screens/dashboard/transaction_raw.dart +++ b/lib/src/screens/dashboard/transaction_raw.dart @@ -4,13 +4,6 @@ import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; import 'package:cake_wallet/generated/i18n.dart'; class TransactionRow extends StatelessWidget { - final VoidCallback onTap; - final TransactionDirection direction; - final String formattedDate; - final String formattedAmount; - final String formattedFiatAmount; - final bool isPending; - TransactionRow( {this.direction, this.formattedDate, @@ -19,6 +12,13 @@ class TransactionRow extends StatelessWidget { this.isPending, @required this.onTap}); + final VoidCallback onTap; + final TransactionDirection direction; + final String formattedDate; + final String formattedAmount; + final String formattedFiatAmount; + final bool isPending; + @override Widget build(BuildContext context) { return InkWell( @@ -53,7 +53,10 @@ class TransactionRow extends StatelessWidget { (isPending ? S.of(context).pending : ''), style: TextStyle( fontSize: 16, - color: Theme.of(context).primaryTextTheme.subhead.color)), + color: Theme.of(context) + .primaryTextTheme + .subhead + .color)), Text(formattedAmount, style: const TextStyle( fontSize: 16, color: Palette.purpleBlue)) diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index c4899bbe2..1e48ee325 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:provider/provider.dart'; -import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; class WalletMenu { + WalletMenu(this.context); + final List items = [ S.current.reconnect, S.current.rescan, @@ -14,9 +17,8 @@ class WalletMenu { S.current.accounts, S.current.address_book_menu ]; - final BuildContext context; - WalletMenu(this.context); + final BuildContext context; void action(int index) { switch (index) { @@ -32,7 +34,7 @@ class WalletMenu { break; case 3: Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) => + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) => isAuthenticatedSuccessfully ? Navigator.of(auth.context).popAndPushNamed(Routes.seed) : null); @@ -40,7 +42,7 @@ class WalletMenu { break; case 4: Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) => + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) => isAuthenticatedSuccessfully ? Navigator.of(auth.context) .popAndPushNamed(Routes.showKeys) @@ -57,10 +59,10 @@ class WalletMenu { } } - Future _presentReconnectAlert(BuildContext context) async { + Future _presentReconnectAlert(BuildContext context) async { final walletStore = Provider.of(context); - await showDialog( + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/disclaimer/disclaimer_page.dart b/lib/src/screens/disclaimer/disclaimer_page.dart index 7f48c6264..6e916df6f 100644 --- a/lib/src/screens/disclaimer/disclaimer_page.dart +++ b/lib/src/screens/disclaimer/disclaimer_page.dart @@ -8,10 +8,10 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart'; class DisclaimerPage extends BasePage { - final bool isReadOnly; - DisclaimerPage({this.isReadOnly = false}); + final bool isReadOnly; + @override bool get isModalBackButton => false; @@ -23,25 +23,25 @@ class DisclaimerPage extends BasePage { } class DisclaimerPageBody extends StatefulWidget { - final bool isReadOnly; - DisclaimerPageBody({this.isReadOnly = true}); + final bool isReadOnly; + @override - createState() => DisclaimerBodyState(false); + DisclaimerBodyState createState() => DisclaimerBodyState(false); } class DisclaimerBodyState extends State { - static const xmrto_url = 'https://xmr.to/app_static/html/tos.html'; - static const changenow_url = 'https://changenow.io/terms-of-use'; + DisclaimerBodyState(this._isAccepted); - bool _isAccepted; + static const xmrtoUrl = 'https://xmr.to/app_static/html/tos.html'; + static const changenowUrl = 'https://changenow.io/terms-of-use'; + + final bool _isAccepted; bool _checked = false; String _fileText = ''; - DisclaimerBodyState(this._isAccepted); - - launchUrl(String url) async { + Future launchUrl(String url) async { if (await canLaunch(url)) await launch(url); } @@ -50,8 +50,8 @@ class DisclaimerBodyState extends State { setState(() {}); } - _showAlertDialog(BuildContext context) async { - await showDialog( + Future _showAlertDialog(BuildContext context) async { + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -66,7 +66,7 @@ class DisclaimerBodyState extends State { actions: [ FlatButton( onPressed: () { - Navigator.pop(context); + Navigator.of(context).pop(); }, child: Text('OK')), ], @@ -74,9 +74,7 @@ class DisclaimerBodyState extends State { }); } - _afterLayout(_) { - _showAlertDialog(context); - } + void _afterLayout(Duration _) => _showAlertDialog(context); @override void initState() { @@ -87,7 +85,6 @@ class DisclaimerBodyState extends State { @override Widget build(BuildContext context) { - return Column( children: [ SizedBox(height: 10.0), @@ -166,9 +163,9 @@ class DisclaimerBodyState extends State { children: [ Expanded( child: GestureDetector( - onTap: () => launchUrl(xmrto_url), + onTap: () => launchUrl(xmrtoUrl), child: Text( - xmrto_url, + xmrtoUrl, textAlign: TextAlign.left, style: TextStyle( color: Colors.blue, @@ -187,17 +184,17 @@ class DisclaimerBodyState extends State { children: [ Expanded( child: GestureDetector( - onTap: () => launchUrl(changenow_url), - child: Text( - changenow_url, - textAlign: TextAlign.left, - style: TextStyle( - color: Colors.blue, - fontSize: 14.0, - fontWeight: FontWeight.normal, - decoration: TextDecoration.underline), - ), - )) + onTap: () => launchUrl(changenowUrl), + child: Text( + changenowUrl, + textAlign: TextAlign.left, + style: TextStyle( + color: Colors.blue, + fontSize: 14.0, + fontWeight: FontWeight.normal, + decoration: TextDecoration.underline), + ), + )) ], ), SizedBox( @@ -288,8 +285,14 @@ class DisclaimerBodyState extends State { child: PrimaryButton( onPressed: _checked ? () {} : null, text: 'Accept', - color: Theme.of(context).primaryTextTheme.button.backgroundColor, - borderColor: Theme.of(context).primaryTextTheme.button.decorationColor, + color: Theme.of(context) + .primaryTextTheme + .button + .backgroundColor, + borderColor: Theme.of(context) + .primaryTextTheme + .button + .decorationColor, ), ) : Offstage(), diff --git a/lib/src/screens/exchange/exchange_page.dart b/lib/src/screens/exchange/exchange_page.dart index 82d6604cf..a5cb2b55c 100644 --- a/lib/src/screens/exchange/exchange_page.dart +++ b/lib/src/screens/exchange/exchange_page.dart @@ -6,8 +6,9 @@ import 'package:provider/provider.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/domain/exchange/xmrto/xmrto_exchange_provider.dart'; import 'package:cake_wallet/src/stores/exchange/exchange_trade_state.dart'; import 'package:cake_wallet/src/stores/exchange/limits_state.dart'; @@ -20,15 +21,14 @@ import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class ExchangePage extends BasePage { + @override String get title => S.current.exchange; @override bool get isModalBackButton => true; - final Image arrowBottomPurple = Image.asset( - 'assets/images/arrow_bottom_purple_icon.png', - height: 8, - ); + final Image arrowBottomPurple = + Image.asset('assets/images/arrow_bottom_purple_icon.png', height: 8); @override Widget middle(BuildContext context) { @@ -93,12 +93,12 @@ class ExchangePage extends BasePage { final items = exchangeStore.providersForCurrentPair(); final selectedItem = items.indexOf(exchangeStore.provider); - showDialog( + showDialog( builder: (_) => Picker( items: items, selectedAtIndex: selectedItem, title: S.of(context).change_exchange_provider, - onItemSelected: (provider) => + onItemSelected: (ExchangeProvider provider) => exchangeStore.changeProvider(provider: provider)), context: context); } @@ -253,8 +253,9 @@ class ExchangeFormState extends State { builder: (_) => LoadingPrimaryButton( text: S.of(context).exchange, onPressed: () { - if (_formKey.currentState.validate()) + if (_formKey.currentState.validate()) { exchangeStore.createTrade(); + } }, color: Theme.of(context) .primaryTextTheme @@ -327,34 +328,38 @@ class ExchangeFormState extends State { reaction( (_) => walletStore.name, - (_) => _onWalletNameChange( + (String _) => _onWalletNameChange( walletStore, store.receiveCurrency, receiveKey)); reaction( (_) => walletStore.name, - (_) => _onWalletNameChange( + (String _) => _onWalletNameChange( walletStore, store.depositCurrency, depositKey)); - reaction((_) => store.receiveCurrency, - (currency) => _onCurrencyChange(currency, walletStore, receiveKey)); + reaction( + (_) => store.receiveCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, walletStore, receiveKey)); - reaction((_) => store.depositCurrency, - (currency) => _onCurrencyChange(currency, walletStore, depositKey)); + reaction( + (_) => store.depositCurrency, + (CryptoCurrency currency) => + _onCurrencyChange(currency, walletStore, depositKey)); - reaction((_) => store.depositAmount, (amount) { + reaction((_) => store.depositAmount, (String amount) { if (depositKey.currentState.amountController.text != amount) { depositKey.currentState.amountController.text = amount; } }); - reaction((_) => store.receiveAmount, (amount) { + reaction((_) => store.receiveAmount, (String amount) { if (receiveKey.currentState.amountController.text != store.receiveAmount) { receiveKey.currentState.amountController.text = amount; } }); - reaction((_) => store.provider, (provider) { + reaction((_) => store.provider, (ExchangeProvider provider) { final isReversed = provider is XMRTOExchangeProvider; if (isReversed) { @@ -373,10 +378,10 @@ class ExchangeFormState extends State { receiveKey.currentState.changeIsAmountEstimated(!isReversed); }); - reaction((_) => store.tradeState, (state) { + reaction((_) => store.tradeState, (ExchangeTradeState state) { if (state is TradeIsCreatedFailure) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -397,7 +402,7 @@ class ExchangeFormState extends State { } }); - reaction((_) => store.limitsState, (state) { + reaction((_) => store.limitsState, (LimitsState state) { final isXMRTO = store.provider is XMRTOExchangeProvider; String min; String max; @@ -444,7 +449,7 @@ class ExchangeFormState extends State { } }); - reaction((_) => walletStore.address, (address) { + reaction((_) => walletStore.address, (String address) { if (store.depositCurrency == CryptoCurrency.xmr) { depositKey.currentState.changeAddress(address: address); } diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index acef42a3e..51a16588d 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -7,18 +7,6 @@ import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/address_text_field.dart'; class ExchangeCard extends StatefulWidget { - final List currencies; - final Function(CryptoCurrency) onCurrencySelected; - final CryptoCurrency initialCurrency; - final String initialWalletName; - final String initialAddress; - final bool initialIsAmountEditable; - final bool initialIsAddressEditable; - final bool isAmountEstimated; - final Image imageArrow; - final FormFieldValidator currencyValueValidator; - final FormFieldValidator addressTextFieldValidator; - ExchangeCard( {Key key, this.initialCurrency, @@ -34,8 +22,20 @@ class ExchangeCard extends StatefulWidget { this.addressTextFieldValidator}) : super(key: key); + final List currencies; + final Function(CryptoCurrency) onCurrencySelected; + final CryptoCurrency initialCurrency; + final String initialWalletName; + final String initialAddress; + final bool initialIsAmountEditable; + final bool initialIsAddressEditable; + final bool isAmountEstimated; + final Image imageArrow; + final FormFieldValidator currencyValueValidator; + final FormFieldValidator addressTextFieldValidator; + @override - createState() => ExchangeCardState(); + ExchangeCardState createState() => ExchangeCardState(); } class ExchangeCardState extends State { @@ -102,7 +102,6 @@ class ExchangeCardState extends State { @override Widget build(BuildContext context) { - return Container( padding: EdgeInsets.fromLTRB(22, 15, 22, 30), width: double.infinity, @@ -150,7 +149,10 @@ class ExchangeCardState extends State { style: TextStyle( fontWeight: FontWeight.bold, fontSize: 24, - color: Theme.of(context).primaryTextTheme.title.color)), + color: Theme.of(context) + .primaryTextTheme + .title + .color)), widget.imageArrow ]), _walletName != null @@ -173,7 +175,10 @@ class ExchangeCardState extends State { textAlign: TextAlign.right, keyboardType: TextInputType.numberWithOptions( signed: false, decimal: false), - inputFormatters: [BlacklistingTextInputFormatter(new RegExp('[\\-|\\ |\\,]'))], + inputFormatters: [ + BlacklistingTextInputFormatter( + RegExp('[\\-|\\ |\\,]')) + ], decoration: InputDecoration( hintStyle: TextStyle( color: Theme.of(context).cardTheme.color, @@ -182,15 +187,14 @@ class ExchangeCardState extends State { hintText: '0.00000000', focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: _isAmountEditable ? Palette.deepPurple : Theme.of(context).focusColor, width: 1.0))), - validator: widget.currencyValueValidator), + validator: widget.currencyValueValidator), SizedBox(height: 5), SizedBox( height: 15, @@ -201,21 +205,29 @@ class ExchangeCardState extends State { children: [ _min != null ? Text( - S.of(context).min_value(_min, _selectedCurrency.toString()), + S.of(context).min_value( + _min, _selectedCurrency.toString()), style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context).primaryTextTheme.subtitle.color), + color: Theme.of(context) + .primaryTextTheme + .subtitle + .color), ) : SizedBox(), _min != null ? SizedBox(width: 10) : SizedBox(), _max != null ? Text( - S.of(context).max_value(_max, _selectedCurrency.toString()), + S.of(context).max_value( + _max, _selectedCurrency.toString()), style: TextStyle( fontSize: 10, height: 1.2, - color: Theme.of(context).primaryTextTheme.subtitle.color)) + color: Theme.of(context) + .primaryTextTheme + .subtitle + .color)) : SizedBox(), ]), ), @@ -248,14 +260,15 @@ class ExchangeCardState extends State { } void _presentPicker(BuildContext context) { - showDialog( + showDialog( builder: (_) => Picker( items: widget.currencies, selectedAtIndex: widget.currencies.indexOf(_selectedCurrency), title: S.of(context).change_currency, - onItemSelected: (item) => widget.onCurrencySelected != null - ? widget.onCurrencySelected(item) - : null), + onItemSelected: (CryptoCurrency item) => + widget.onCurrencySelected != null + ? widget.onCurrencySelected(item) + : null), context: context); } } diff --git a/lib/src/screens/exchange_trade/exchange_confirm_page.dart b/lib/src/screens/exchange_trade/exchange_confirm_page.dart index 10762293d..e892e092d 100644 --- a/lib/src/screens/exchange_trade/exchange_confirm_page.dart +++ b/lib/src/screens/exchange_trade/exchange_confirm_page.dart @@ -8,11 +8,12 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/domain/exchange/trade.dart'; class ExchangeConfirmPage extends BasePage { - String get title => S.current.copy_id; + ExchangeConfirmPage({@required this.trade}); final Trade trade; - ExchangeConfirmPage({@required this.trade}); + @override + String get title => S.current.copy_id; @override Widget body(BuildContext context) { diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 887d58917..807bbbf51 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -20,6 +20,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; class ExchangeTradePage extends BasePage { + @override String get title => S.current.exchange; @override @@ -28,7 +29,7 @@ class ExchangeTradePage extends BasePage { class ExchangeTradeForm extends StatefulWidget { @override - createState() => ExchangeTradeState(); + ExchangeTradeState createState() => ExchangeTradeState(); } class ExchangeTradeState extends State { @@ -330,10 +331,10 @@ class ExchangeTradeState extends State { final sendStore = Provider.of(context); - reaction((_) => sendStore.state, (state) { + reaction((_) => sendStore.state, (SendingState state) { if (state is SendingFailed) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -351,7 +352,7 @@ class ExchangeTradeState extends State { if (state is TransactionCreatedSuccessfully) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/exchange_trade/widgets/copy_button.dart b/lib/src/screens/exchange_trade/widgets/copy_button.dart index b152157ef..79d399c0b 100644 --- a/lib/src/screens/exchange_trade/widgets/copy_button.dart +++ b/lib/src/screens/exchange_trade/widgets/copy_button.dart @@ -2,29 +2,29 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class CopyButton extends StatelessWidget { + const CopyButton( + {@required this.onPressed, + @required this.text, + @required this.color, + @required this.borderColor}); final VoidCallback onPressed; final Color color; final Color borderColor; final String text; - const CopyButton({ - @required this.onPressed, - @required this.text, - @required this.color, - @required this.borderColor}); - @override Widget build(BuildContext context) { return ButtonTheme( - minWidth: double.infinity, - height: 44.0, - child: FlatButton( - onPressed: onPressed, - color: color, - shape: RoundedRectangleBorder(side: BorderSide(color: borderColor), borderRadius: BorderRadius.circular(10.0)), - child: Text(text, style: TextStyle(fontSize: 14.0)), - ) - ); + minWidth: double.infinity, + height: 44.0, + child: FlatButton( + onPressed: onPressed, + color: color, + shape: RoundedRectangleBorder( + side: BorderSide(color: borderColor), + borderRadius: BorderRadius.circular(10.0)), + child: Text(text, style: TextStyle(fontSize: 14.0)), + )); } -} \ No newline at end of file +} diff --git a/lib/src/screens/exchange_trade/widgets/timer_widget.dart b/lib/src/screens/exchange_trade/widgets/timer_widget.dart index d3154aaa1..713148fed 100644 --- a/lib/src/screens/exchange_trade/widgets/timer_widget.dart +++ b/lib/src/screens/exchange_trade/widgets/timer_widget.dart @@ -3,24 +3,24 @@ import 'dart:async'; import 'package:cake_wallet/generated/i18n.dart'; class TimerWidget extends StatefulWidget { + TimerWidget(this.expiratedAt, {this.color = Colors.black}); + final DateTime expiratedAt; final Color color; - TimerWidget(this.expiratedAt, {this.color = Colors.black}); - @override - createState() => TimerWidgetState(); + TimerWidgetState createState() => TimerWidgetState(); } class TimerWidgetState extends State { + TimerWidgetState(); + int _leftSeconds; int _minutes; int _seconds; bool _isExpired; Timer _timer; - TimerWidgetState(); - @override void initState() { super.initState(); @@ -52,7 +52,8 @@ class TimerWidgetState extends State { @override Widget build(BuildContext context) { return _isExpired - ? Text(S.of(context).expired, style: TextStyle(fontSize: 14.0, color: Colors.red)) + ? Text(S.of(context).expired, + style: TextStyle(fontSize: 14.0, color: Colors.red)) : Text( S.of(context).time(_minutes.toString(), _seconds.toString()), style: TextStyle(fontSize: 14.0, color: widget.color), diff --git a/lib/src/screens/faq/faq_page.dart b/lib/src/screens/faq/faq_page.dart index 121865809..78a5ba62a 100644 --- a/lib/src/screens/faq/faq_page.dart +++ b/lib/src/screens/faq/faq_page.dart @@ -7,14 +7,16 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class FaqPage extends BasePage { + @override String get title => S.current.faq; @override Widget body(BuildContext context) { - return FutureBuilder( builder: (context, snapshot) { - var faqItems = json.decode(snapshot.data.toString()); + final faqItems = (json.decode(snapshot.data.toString()) + as List>) ?? + >[]; return ListView.separated( itemBuilder: (BuildContext context, int index) { @@ -22,34 +24,24 @@ class FaqPage extends BasePage { final itemChild = faqItems[index]["answer"]; return ExpansionTile( - title: Text( - itemTitle - ), + title: Text(itemTitle), children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Expanded( child: Container( - padding: EdgeInsets.only( - left: 15.0, - right: 15.0 - ), - child: Text( - itemChild, - ), - ) - ) + padding: EdgeInsets.only(left: 15.0, right: 15.0), + child: Text(itemChild), + )) ], ) ], ); }, - separatorBuilder: (_, __) => Divider( - color: Theme.of(context).dividerTheme.color, - height: 1.0, - ), - itemCount: faqItems == null ? 0 : faqItems.length, + separatorBuilder: (_, __) => + Divider(color: Theme.of(context).dividerTheme.color, height: 1.0), + itemCount: faqItems.length, ); }, future: rootBundle.loadString(getFaqPath(context)), @@ -86,5 +78,4 @@ class FaqPage extends BasePage { return 'assets/faq/faq_en.json'; } } - -} \ No newline at end of file +} diff --git a/lib/src/screens/new_wallet/new_wallet_page.dart b/lib/src/screens/new_wallet/new_wallet_page.dart index 9b713e5bf..845d924fa 100644 --- a/lib/src/screens/new_wallet/new_wallet_page.dart +++ b/lib/src/screens/new_wallet/new_wallet_page.dart @@ -15,24 +15,25 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/palette.dart'; class NewWalletPage extends BasePage { - final WalletListService walletsService; - final WalletService walletService; - final SharedPreferences sharedPreferences; - - String get title => S.current.new_wallet; - NewWalletPage( {@required this.walletsService, @required this.walletService, @required this.sharedPreferences}); + final WalletListService walletsService; + final WalletService walletService; + final SharedPreferences sharedPreferences; + + @override + String get title => S.current.new_wallet; + @override Widget body(BuildContext context) => WalletNameForm(); } class WalletNameForm extends StatefulWidget { @override - createState() => _WalletNameFormState(); + _WalletNameFormState createState() => _WalletNameFormState(); } class _WalletNameFormState extends State { @@ -43,14 +44,14 @@ class _WalletNameFormState extends State { Widget build(BuildContext context) { final walletCreationStore = Provider.of(context); - reaction((_) => walletCreationStore.state, (state) { + reaction((_) => walletCreationStore.state, (WalletCreationState state) { if (state is WalletCreatedSuccessfully) { Navigator.of(context).popUntil((route) => route.isFirst); } if (state is WalletCreationFailure) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -88,8 +89,8 @@ class _WalletNameFormState extends State { fontSize: 24.0, color: Theme.of(context).hintColor), hintText: S.of(context).wallet_name, focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Palette.cakeGreen, width: 2.0)), + borderSide: + BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, diff --git a/lib/src/screens/nodes/new_node_page.dart b/lib/src/screens/nodes/new_node_page.dart index 96a83926d..f3f5d39d7 100644 --- a/lib/src/screens/nodes/new_node_page.dart +++ b/lib/src/screens/nodes/new_node_page.dart @@ -17,7 +17,7 @@ class NewNodePage extends BasePage { class NewNodePageForm extends StatefulWidget { @override - createState() => NewNodeFormState(); + NewNodeFormState createState() => NewNodeFormState(); } class NewNodeFormState extends State { diff --git a/lib/src/screens/nodes/node_indicator.dart b/lib/src/screens/nodes/node_indicator.dart index b08139c84..8d46e03a5 100644 --- a/lib/src/screens/nodes/node_indicator.dart +++ b/lib/src/screens/nodes/node_indicator.dart @@ -2,18 +2,16 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; class NodeIndicator extends StatelessWidget { - final color; - NodeIndicator({this.color = Palette.red}); + final Color color; + @override Widget build(BuildContext context) { return Container( width: 10.0, height: 10.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color), + decoration: BoxDecoration(shape: BoxShape.circle, color: color), ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart index 5ddee1f5f..e5ab3c33f 100644 --- a/lib/src/screens/nodes/nodes_list_page.dart +++ b/lib/src/screens/nodes/nodes_list_page.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/src/screens/base_page.dart'; class NodeListPage extends BasePage { NodeListPage(); + @override String get title => S.current.nodes; @override @@ -26,7 +27,7 @@ class NodeListPage extends BasePage { minWidth: double.minPositive, child: FlatButton( onPressed: () async { - await showDialog( + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -76,10 +77,8 @@ class NodeListPage extends BasePage { height: 28.0, child: FlatButton( shape: CircleBorder(), - onPressed: () async { - await Navigator.of(context).pushNamed(Routes.newNode); - nodeList.update(); - }, + onPressed: () async => + await Navigator.of(context).pushNamed(Routes.newNode), child: Offstage()), ) ], @@ -94,7 +93,7 @@ class NodeListPage extends BasePage { class NodeListPageBody extends StatefulWidget { @override - createState() => NodeListPageBodyState(); + NodeListPageBodyState createState() => NodeListPageBodyState(); } class NodeListPageBodyState extends State { @@ -141,7 +140,7 @@ class NodeListPageBodyState extends State { switch (snapshot.connectionState) { case ConnectionState.done: return NodeIndicator( - color: snapshot.data + color: snapshot.data as bool ? Palette.green : Palette.red); default: @@ -150,7 +149,7 @@ class NodeListPageBodyState extends State { }), onTap: () async { if (!isCurrent) { - await showDialog( + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/pin_code/pin_code.dart b/lib/src/screens/pin_code/pin_code.dart index 7bc7634b1..63c86f80f 100644 --- a/lib/src/screens/pin_code/pin_code.dart +++ b/lib/src/screens/pin_code/pin_code.dart @@ -6,19 +6,20 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; abstract class PinCodeWidget extends StatefulWidget { - final Function(List pin, PinCodeState state) onPinCodeEntered; - final bool hasLengthSwitcher; - PinCodeWidget({Key key, this.onPinCodeEntered, this.hasLengthSwitcher}) : super(key: key); + + final Function(List pin, PinCodeState state) onPinCodeEntered; + final bool hasLengthSwitcher; } class PinCode extends PinCodeWidget { - final Function(List pin, PinCodeState state) onPinCodeEntered; - final bool hasLengthSwitcher; - - PinCode(this.onPinCodeEntered, this.hasLengthSwitcher, Key key) - : super(key: key); + PinCode(Function(List pin, PinCodeState state) onPinCodeEntered, + bool hasLengthSwitcher, Key key) + : super( + key: key, + onPinCodeEntered: onPinCodeEntered, + hasLengthSwitcher: hasLengthSwitcher); @override PinCodeState createState() => PinCodeState(); @@ -30,27 +31,22 @@ class PinCodeState extends State { static const fourPinLength = 4; static final deleteIconImage = Image.asset('assets/images/delete_icon.png'); static final backArrowImage = Image.asset('assets/images/back_arrow.png'); - GlobalKey _gridViewKey = GlobalKey(); + final _gridViewKey = GlobalKey(); int pinLength = defaultPinLength; List pin = List.filled(defaultPinLength, null); String title = S.current.enter_your_pin; double _aspectRatio = 0; - void setTitle(String title) { - setState(() => this.title = title); - } + void setTitle(String title) => setState(() => this.title = title); - void clear() { - setState(() => pin = List.filled(pinLength, null)); - } + void clear() => setState(() => pin = List.filled(pinLength, null)); - void onPinCodeEntered(PinCodeState state) { - widget.onPinCodeEntered(state.pin, this); - } + void onPinCodeEntered(PinCodeState state) => + widget.onPinCodeEntered(state.pin, this); void changePinLength(int length) { - List newPin = List.filled(length, null); + final newPin = List.filled(length, null); setState(() { pinLength = length; @@ -58,19 +54,23 @@ class PinCodeState extends State { }); } - setDefaultPinLength() { + void setDefaultPinLength() { final settingsStore = Provider.of(context); pinLength = settingsStore.defaultPinLength; changePinLength(pinLength); } - getCurrentAspectRatio() { - final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject(); + void calculateAspectRatio() { + final renderBox = + _gridViewKey.currentContext.findRenderObject() as RenderBox; + final cellWidth = renderBox.size.width / 3; + final cellHeight = renderBox.size.height / 4; + + if (cellWidth > 0 && cellHeight > 0) { + _aspectRatio = cellWidth / cellHeight; + } - double cellWidth = renderBox.size.width / 3; - double cellHeight = renderBox.size.height / 4; - if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth / cellHeight; setState(() {}); } @@ -80,15 +80,13 @@ class PinCodeState extends State { WidgetsBinding.instance.addPostFrameCallback(afterLayout); } - afterLayout(_) { + void afterLayout(dynamic _) { setDefaultPinLength(); - getCurrentAspectRatio(); + calculateAspectRatio(); } @override - Widget build(BuildContext context) { - return Scaffold(body: body(context)); - } + Widget build(BuildContext context) => Scaffold(body: body(context)); Widget body(BuildContext context) { return SafeArea( @@ -196,7 +194,7 @@ class PinCodeState extends State { } void _push(int num) { - if (_pinLength() >= pinLength) { + if (currentPinLength() >= pinLength) { return; } @@ -207,13 +205,15 @@ class PinCodeState extends State { } } - if (_pinLength() == pinLength) { + final _currentPinLength = currentPinLength(); + + if (_currentPinLength == pinLength) { onPinCodeEntered(this); } } void _pop() { - if (_pinLength() == 0) { + if (currentPinLength() == 0) { return; } @@ -225,7 +225,7 @@ class PinCodeState extends State { } } - int _pinLength() { + int currentPinLength() { return pin.fold(0, (v, e) { if (e != null) { return v + 1; diff --git a/lib/src/screens/receive/qr_image.dart b/lib/src/screens/receive/qr_image.dart index 45e2793ac..7beb689d2 100644 --- a/lib/src/screens/receive/qr_image.dart +++ b/lib/src/screens/receive/qr_image.dart @@ -10,7 +10,7 @@ class QrImage extends StatelessWidget { Color foregroundColor = Colors.black, int version = 7, int errorCorrectionLevel = QrErrorCorrectLevel.L, - }) : _painter = new QrPainter(data, foregroundColor, version, errorCorrectionLevel); + }) : _painter = QrPainter(data, foregroundColor, version, errorCorrectionLevel); final QrPainter _painter; final Color backgroundColor; @@ -18,7 +18,7 @@ class QrImage extends StatelessWidget { @override Widget build(BuildContext context) { - return new Container( + return Container( width: size, height: size, color: backgroundColor, diff --git a/lib/src/screens/receive/qr_painter.dart b/lib/src/screens/receive/qr_painter.dart index c7f229f46..3ced10895 100644 --- a/lib/src/screens/receive/qr_painter.dart +++ b/lib/src/screens/receive/qr_painter.dart @@ -3,31 +3,32 @@ import 'package:qr/qr.dart'; class QrPainter extends CustomPainter { QrPainter( - String data, - this.color, - this.version, - this.errorCorrectionLevel, - ) : this._qr = new QrCode(version, errorCorrectionLevel) { + String data, + this.color, + this.version, + this.errorCorrectionLevel, + ) : this._qr = QrCode(version, errorCorrectionLevel) { _p.color = this.color; _qr.addData(data); _qr.make(); } - final QrCode _qr; - final _p = new Paint()..style = PaintingStyle.fill; - final int version; final int errorCorrectionLevel; final Color color; + final QrCode _qr; + final _p = Paint()..style = PaintingStyle.fill; + @override void paint(Canvas canvas, Size size) { final squareSize = size.shortestSide / _qr.moduleCount; for (int x = 0; x < _qr.moduleCount; x++) { for (int y = 0; y < _qr.moduleCount; y++) { if (_qr.isDark(y, x)) { - final squareRect = new Rect.fromLTWH(x * squareSize, y * squareSize, squareSize, squareSize); + final squareRect = Rect.fromLTWH( + x * squareSize, y * squareSize, squareSize, squareSize); canvas.drawRect(squareRect, _p); } } @@ -37,9 +38,11 @@ class QrPainter extends CustomPainter { @override bool shouldRepaint(CustomPainter oldDelegate) { if (oldDelegate is QrPainter) { - return this.color != oldDelegate.color || this.errorCorrectionLevel != oldDelegate.errorCorrectionLevel || + return this.color != oldDelegate.color || + this.errorCorrectionLevel != oldDelegate.errorCorrectionLevel || this.version != oldDelegate.version; } + return false; } -} \ No newline at end of file +} diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index 217bf0ae0..718f2bb1c 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -13,7 +13,10 @@ import 'package:cake_wallet/src/screens/receive/qr_image.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class ReceivePage extends BasePage { + @override bool get isModalBackButton => true; + + @override String get title => S.current.receive; @override @@ -31,7 +34,10 @@ class ReceivePage extends BasePage { padding: EdgeInsets.all(0), onPressed: () => Share.text( 'Share address', walletStore.subaddress.address, 'text/plain'), - child: Icon(Icons.share, size: 30.0,)), + child: Icon( + Icons.share, + size: 30.0, + )), ), ); } @@ -43,7 +49,7 @@ class ReceivePage extends BasePage { class ReceiveBody extends StatefulWidget { @override - createState() => ReceiveBodyState(); + ReceiveBodyState createState() => ReceiveBodyState(); } class ReceiveBodyState extends State { @@ -67,8 +73,9 @@ class ReceiveBodyState extends State { amountController.addListener(() { if (_formKey.currentState.validate()) { walletStore.onChangedAmountValue(amountController.text); - } else + } else { walletStore.onChangedAmountValue(''); + } }); return SafeArea( @@ -152,7 +159,7 @@ class ReceiveBodyState extends State { TextInputType.numberWithOptions(decimal: true), inputFormatters: [ BlacklistingTextInputFormatter( - new RegExp('[\\-|\\ |\\,]')) + RegExp('[\\-|\\ |\\,]')) ], style: TextStyle( fontSize: 14.0, @@ -163,8 +170,7 @@ class ReceiveBodyState extends State { hintText: S.of(context).amount, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index b2460ba95..8827ed47e 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -9,7 +9,10 @@ import 'package:cake_wallet/generated/i18n.dart'; class RestoreOptionsPage extends BasePage { static const _aspectRatioImage = 2.086; + @override String get title => S.current.restore_restore_wallet; + + @override Color get backgroundColor => Palette.creamyGrey; final _imageSeedKeys = Image.asset('assets/images/seedKeys.png'); @@ -26,7 +29,8 @@ class RestoreOptionsPage extends BasePage { Flexible( child: RestoreButton( onPressed: () { - Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome); + Navigator.pushNamed( + context, Routes.restoreWalletOptionsFromWelcome); }, image: _imageSeedKeys, aspectRatioImage: _aspectRatioImage, 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 ce5c7913c..526196753 100644 --- a/lib/src/screens/restore/restore_wallet_from_keys_page.dart +++ b/lib/src/screens/restore/restore_wallet_from_keys_page.dart @@ -17,24 +17,25 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/palette.dart'; class RestoreWalletFromKeysPage extends BasePage { - final WalletListService walletsService; - final WalletService walletService; - final SharedPreferences sharedPreferences; - - String get title => S.current.restore_title_from_keys; - RestoreWalletFromKeysPage( {@required this.walletsService, @required this.sharedPreferences, @required this.walletService}); + final WalletListService walletsService; + final WalletService walletService; + final SharedPreferences sharedPreferences; + + @override + String get title => S.current.restore_title_from_keys; + @override Widget body(BuildContext context) => RestoreFromKeysFrom(); } class RestoreFromKeysFrom extends StatefulWidget { @override - createState() => _RestoreFromKeysFromState(); + _RestoreFromKeysFromState createState() => _RestoreFromKeysFromState(); } class _RestoreFromKeysFromState extends State { @@ -49,14 +50,14 @@ class _RestoreFromKeysFromState extends State { Widget build(BuildContext context) { final walletRestorationStore = Provider.of(context); - reaction((_) => walletRestorationStore.state, (state) { + reaction((_) => walletRestorationStore.state, (WalletRestorationState state) { if (state is WalletRestoredSuccessfully) { Navigator.of(context).popUntil((route) => route.isFirst); } if (state is WalletRestorationFailure) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -97,8 +98,7 @@ class _RestoreFromKeysFromState extends State { hintText: S.of(context).restore_wallet_name, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, @@ -127,8 +127,7 @@ class _RestoreFromKeysFromState extends State { hintText: S.of(context).restore_address, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, @@ -155,8 +154,7 @@ class _RestoreFromKeysFromState extends State { hintText: S.of(context).restore_view_key_private, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, @@ -183,8 +181,7 @@ class _RestoreFromKeysFromState extends State { hintText: S.of(context).restore_spend_key_private, focusedBorder: UnderlineInputBorder( borderSide: BorderSide( - color: Palette.cakeGreen, - width: 2.0)), + color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, 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 a1061f3d7..635cad300 100644 --- a/lib/src/screens/restore/restore_wallet_from_seed_details.dart +++ b/lib/src/screens/restore/restore_wallet_from_seed_details.dart @@ -13,6 +13,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/palette.dart'; class RestoreWalletFromSeedDetailsPage extends BasePage { + @override String get title => S.current.restore_wallet_restore_description; @override @@ -21,7 +22,8 @@ class RestoreWalletFromSeedDetailsPage extends BasePage { class RestoreFromSeedDetailsForm extends StatefulWidget { @override - createState() => _RestoreFromSeedDetailsFormState(); + _RestoreFromSeedDetailsFormState createState() => + _RestoreFromSeedDetailsFormState(); } class _RestoreFromSeedDetailsFormState @@ -34,14 +36,14 @@ class _RestoreFromSeedDetailsFormState Widget build(BuildContext context) { final walletRestorationStore = Provider.of(context); - reaction((_) => walletRestorationStore.state, (state) { + reaction((_) => walletRestorationStore.state, (WalletRestorationState state) { if (state is WalletRestoredSuccessfully) { Navigator.of(context).popUntil((route) => route.isFirst); } if (state is WalletRestorationFailure) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( 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 3b7e625af..44ec2f890 100644 --- a/lib/src/screens/restore/restore_wallet_from_seed_page.dart +++ b/lib/src/screens/restore/restore_wallet_from_seed_page.dart @@ -14,24 +14,25 @@ import 'package:cake_wallet/src/stores/wallet_restoration/wallet_restoration_sto import 'package:cake_wallet/src/widgets/seed_widget.dart'; class RestoreWalletFromSeedPage extends BasePage { - final WalletListService walletsService; - final WalletService walletService; - final SharedPreferences sharedPreferences; - - String get title => S.current.restore_title_from_seed; - RestoreWalletFromSeedPage( {@required this.walletsService, @required this.walletService, @required this.sharedPreferences}); + final WalletListService walletsService; + final WalletService walletService; + final SharedPreferences sharedPreferences; + + @override + String get title => S.current.restore_title_from_seed; + @override Widget body(BuildContext context) => RestoreFromSeedForm(); } class RestoreFromSeedForm extends StatefulWidget { @override - createState() => _RestoreFromSeedFormState(); + _RestoreFromSeedFormState createState() => _RestoreFromSeedFormState(); } class _RestoreFromSeedFormState extends State { @@ -46,9 +47,8 @@ class _RestoreFromSeedFormState extends State { (_) => _setReactions(context, walletRestorationStore)); return GestureDetector( - onTap: () { - SystemChannels.textInput.invokeMethod('TextInput.hide'); - }, + onTap: () => + SystemChannels.textInput.invokeMethod('TextInput.hide'), child: Container( padding: EdgeInsets.only(left: 20.0, right: 20.0, bottom: 20.0), child: Column( @@ -90,7 +90,7 @@ class _RestoreFromSeedFormState extends State { return; } - reaction((_) => store.errorMessage, (errorMessage) { + reaction((_) => store.errorMessage, (String errorMessage) { if (errorMessage == null || errorMessage.isEmpty) { _seedKey.currentState.validated(); } else { diff --git a/lib/src/screens/restore/restore_wallet_options_page.dart b/lib/src/screens/restore/restore_wallet_options_page.dart index 296755fb8..1aeb3c509 100644 --- a/lib/src/screens/restore/restore_wallet_options_page.dart +++ b/lib/src/screens/restore/restore_wallet_options_page.dart @@ -9,7 +9,10 @@ import 'package:cake_wallet/generated/i18n.dart'; class RestoreWalletOptionsPage extends BasePage { static const _aspectRatioImage = 2.086; + @override String get title => S.current.restore_seed_keys_restore; + + @override Color get backgroundColor => Palette.creamyGrey; final _imageSeed = Image.asset('assets/images/seedIco.png'); @@ -29,8 +32,8 @@ class RestoreWalletOptionsPage extends BasePage { Navigator.pushNamed(context, Routes.restoreWalletFromSeed), image: _imageSeed, aspectRatioImage: _aspectRatioImage, - titleColor: Palette.lightViolet, - color: Palette.lightViolet, + titleColor: Palette.lightViolet, + color: Palette.lightViolet, title: S.of(context).restore_title_from_seed, description: S.of(context).restore_description_from_seed, textButton: S.of(context).restore_next, @@ -41,8 +44,8 @@ class RestoreWalletOptionsPage extends BasePage { Navigator.pushNamed(context, Routes.restoreWalletFromKeys), image: _imageKeys, aspectRatioImage: _aspectRatioImage, - titleColor: Palette.cakeGreen, - color: Palette.cakeGreen, + titleColor: Palette.cakeGreen, + color: Palette.cakeGreen, title: S.of(context).restore_title_from_keys, description: S.of(context).restore_description_from_keys, textButton: S.of(context).restore_next, diff --git a/lib/src/screens/restore/widgets/restore_button.dart b/lib/src/screens/restore/widgets/restore_button.dart index 41f580cc6..74773e1c3 100644 --- a/lib/src/screens/restore/widgets/restore_button.dart +++ b/lib/src/screens/restore/widgets/restore_button.dart @@ -2,15 +2,6 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; class RestoreButton extends StatelessWidget { - final VoidCallback onPressed; - final Image image; - final double aspectRatioImage; - final Color color; - final Color titleColor; - final String title; - final String description; - final String textButton; - const RestoreButton( {@required this.onPressed, @required this.image, @@ -21,9 +12,17 @@ class RestoreButton extends StatelessWidget { this.description = '', this.textButton = ''}); + final VoidCallback onPressed; + final Image image; + final double aspectRatioImage; + final Color color; + final Color titleColor; + final String title; + final String description; + final String textButton; + @override Widget build(BuildContext context) { - return Container( margin: EdgeInsets.only(top: 20.0, bottom: 20.0), decoration: BoxDecoration( @@ -71,11 +70,11 @@ class RestoreButton extends StatelessWidget { child: Text( description, textAlign: TextAlign.center, - style: - TextStyle( - color: Theme.of(context).accentTextTheme.subhead.color, - fontSize: 14.0, - height: 1.4), + style: TextStyle( + color: + Theme.of(context).accentTextTheme.subhead.color, + fontSize: 14.0, + height: 1.4), ), ) ], @@ -88,7 +87,10 @@ class RestoreButton extends StatelessWidget { decoration: BoxDecoration( border: Border( top: BorderSide( - color: Theme.of(context).accentTextTheme.headline.decorationColor, + color: Theme.of(context) + .accentTextTheme + .headline + .decorationColor, width: 1.15)), color: Colors.transparent, ), diff --git a/lib/src/screens/root/root.dart b/lib/src/screens/root/root.dart index 9482ea861..917ff347b 100644 --- a/lib/src/screens/root/root.dart +++ b/lib/src/screens/root/root.dart @@ -1,11 +1,9 @@ -import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:hive/hive.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/router.dart'; import 'package:cake_wallet/src/stores/authentication/authentication_store.dart'; import 'package:cake_wallet/src/stores/price/price_store.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart'; @@ -19,6 +17,8 @@ import 'package:cake_wallet/src/domain/monero/transaction_description.dart'; import 'package:cake_wallet/src/screens/auth/create_login_page.dart'; import 'package:cake_wallet/src/screens/seed/create_seed_page.dart'; import 'package:cake_wallet/src/screens/dashboard/create_dashboard_page.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; +import 'package:cake_wallet/src/screens/welcome/create_welcome_page.dart'; class Root extends StatefulWidget { Root({Key key}) : super(key: key); @@ -81,7 +81,7 @@ class RootState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.of(context).pushNamed(Routes.unlock, - arguments: (isAuthenticatedSuccessfully, auth) { + arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) { if (!isAuthenticatedSuccessfully) { return; } diff --git a/lib/src/screens/seed/seed_page.dart b/lib/src/screens/seed/seed_page.dart index 13611587a..dcb415735 100644 --- a/lib/src/screens/seed/seed_page.dart +++ b/lib/src/screens/seed/seed_page.dart @@ -11,14 +11,19 @@ import 'package:cake_wallet/src/stores/wallet_seed/wallet_seed_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class SeedPage extends BasePage { + SeedPage({this.onCloseCallback}); + static final image = Image.asset('assets/images/seed_image.png'); + + @override bool get isModalBackButton => true; + + @override String get title => S.current.seed_title; final VoidCallback onCloseCallback; - SeedPage({this.onCloseCallback}); - + @override void onClose(BuildContext context) => onCloseCallback != null ? onCloseCallback() : Navigator.of(context).pop(); diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 274f60795..50b8d675c 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -23,8 +24,13 @@ import 'package:cake_wallet/src/domain/common/sync_status.dart'; import 'package:cake_wallet/src/stores/sync/sync_store.dart'; class SendPage extends BasePage { + @override String get title => S.current.send_title; + + @override bool get isModalBackButton => true; + + @override bool get resizeToAvoidBottomPadding => false; @override @@ -212,7 +218,7 @@ class SendFormState extends State { signed: false, decimal: false), inputFormatters: [ BlacklistingTextInputFormatter( - new RegExp('[\\-|\\ |\\,]')) + RegExp('[\\-|\\ |\\,]')) ], decoration: InputDecoration( prefixIcon: Padding( @@ -272,7 +278,7 @@ class SendFormState extends State { signed: false, decimal: false), inputFormatters: [ BlacklistingTextInputFormatter( - new RegExp('[\\-|\\ |\\,]')) + RegExp('[\\-|\\ |\\,]')) ], decoration: InputDecoration( prefixIcon: Padding( @@ -353,7 +359,7 @@ class SendFormState extends State { FocusScope.of(context).requestFocus(FocusNode()); if (_formKey.currentState.validate()) { - await showDialog( + await showDialog( context: context, builder: (dialogContext) { return AlertDialog( @@ -364,12 +370,11 @@ class SendFormState extends State { FlatButton( child: Text(S.of(context).send), onPressed: () async { - Navigator.of(dialogContext) - .popAndPushNamed( - Routes.auth, - arguments: - (isAuthenticatedSuccessfully, - auth) { + await Navigator.of(dialogContext) + .popAndPushNamed(Routes.auth, + arguments: (bool + isAuthenticatedSuccessfully, + AuthPageState auth) { if (!isAuthenticatedSuccessfully) { return; } @@ -408,13 +413,13 @@ class SendFormState extends State { final sendStore = Provider.of(context); - reaction((_) => sendStore.fiatAmount, (amount) { + reaction((_) => sendStore.fiatAmount, (String amount) { if (amount != _fiatAmountController.text) { _fiatAmountController.text = amount; } }); - reaction((_) => sendStore.cryptoAmount, (amount) { + reaction((_) => sendStore.cryptoAmount, (String amount) { if (amount != _cryptoAmountController.text) { _cryptoAmountController.text = amount; } @@ -436,10 +441,10 @@ class SendFormState extends State { } }); - reaction((_) => sendStore.state, (state) { + reaction((_) => sendStore.state, (SendingState state) { if (state is SendingFailed) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -457,7 +462,7 @@ class SendFormState extends State { if (state is TransactionCreatedSuccessfully) { WidgetsBinding.instance.addPostFrameCallback((_) { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/settings/change_language.dart b/lib/src/screens/settings/change_language.dart index 8a055f2f6..cdadeb585 100644 --- a/lib/src/screens/settings/change_language.dart +++ b/lib/src/screens/settings/change_language.dart @@ -21,7 +21,8 @@ const Map _languages = { }; class ChangeLanguage extends BasePage { - get title => S.current.settings_change_language; + @override + String get title => S.current.settings_change_language; @override Widget body(BuildContext context) { @@ -50,7 +51,7 @@ class ChangeLanguage extends BasePage { ), onTap: () async { if (!isCurrent) { - await showDialog( + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/settings/enter_pin_code.dart b/lib/src/screens/settings/enter_pin_code.dart index 07c727f8c..c18e782c5 100644 --- a/lib/src/screens/settings/enter_pin_code.dart +++ b/lib/src/screens/settings/enter_pin_code.dart @@ -7,39 +7,41 @@ import 'package:cake_wallet/theme_changer.dart'; import 'package:cake_wallet/themes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -class EnterPinCode extends StatefulWidget{ +class EnterPinCode extends StatefulWidget { + const EnterPinCode(this.currentPinLength, this.currentPin); final int currentPinLength; final List currentPin; - const EnterPinCode(this.currentPinLength, this.currentPin); - @override - createState() => EnterPinCodeState(currentPinLength, currentPin); - + EnterPinCodeState createState() => + EnterPinCodeState(currentPinLength, currentPin); } -class EnterPinCodeState extends State{ - GlobalKey _gridViewKey = GlobalKey(); +class EnterPinCodeState extends State { + EnterPinCodeState(this.pinLength, this.currentPin); + final _gridViewKey = GlobalKey(); final _closeButtonImage = Image.asset('assets/images/close_button.png'); - final _closeButtonImageDarkTheme = Image.asset('assets/images/close_button_dark_theme.png'); + final _closeButtonImageDarkTheme = + Image.asset('assets/images/close_button_dark_theme.png'); static final deleteIconImage = Image.asset('assets/images/delete_icon.png'); final int pinLength; final List currentPin; List pin; double _aspectRatio = 0; - EnterPinCodeState(this.pinLength, this.currentPin); + void _calcualteCurrentAspectRatio() { + final renderBox = + _gridViewKey.currentContext.findRenderObject() as RenderBox; + final cellWidth = renderBox.size.width / 3; + final cellHeight = renderBox.size.height / 4; - _getCurrentAspectRatio(){ - final RenderBox renderBox = _gridViewKey.currentContext.findRenderObject(); + if (cellWidth > 0 && cellHeight > 0) { + _aspectRatio = cellWidth / cellHeight; + } - double cellWidth = renderBox.size.width/3; - double cellHeight = renderBox.size.height/4; - if (cellWidth > 0 && cellHeight > 0) _aspectRatio = cellWidth/cellHeight; - setState(() { - }); + setState(() {}); } @override @@ -49,130 +51,125 @@ class EnterPinCodeState extends State{ WidgetsBinding.instance.addPostFrameCallback(_afterLayout); } - _afterLayout(_) { - _getCurrentAspectRatio(); - } + void _afterLayout(dynamic _) => _calcualteCurrentAspectRatio(); @override Widget build(BuildContext context) { - - ThemeChanger _themeChanger = Provider.of(context); - bool _isDarkTheme; - - if (_themeChanger.getTheme() == Themes.darkTheme) _isDarkTheme = true; - else _isDarkTheme = false; + final _themeChanger = Provider.of(context); + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme; return Scaffold( backgroundColor: Theme.of(context).backgroundColor, appBar: CupertinoNavigationBar( - leading: ButtonTheme( - minWidth: double.minPositive, - child: FlatButton( - onPressed: (){ Navigator.pop(context, false); }, - child: _isDarkTheme ? _closeButtonImageDarkTheme : _closeButtonImage + leading: ButtonTheme( + minWidth: double.minPositive, + child: FlatButton( + onPressed: () { + Navigator.pop(context, false); + }, + child: _isDarkTheme + ? _closeButtonImageDarkTheme + : _closeButtonImage), ), - ), - backgroundColor: Theme.of(context).backgroundColor, - border: null, - ), + backgroundColor: Theme.of(context).backgroundColor, + border: null), body: SafeArea( - child: Container( - padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0), - child: Column( - children: [ - Spacer(flex: 2), - Text(S.of(context).enter_your_pin, - style: TextStyle( - fontSize: 24, - color: Palette.wildDarkBlue - ) + child: Container( + padding: EdgeInsets.only(left: 40.0, right: 40.0, bottom: 40.0), + child: Column( + children: [ + Spacer(flex: 2), + Text(S.of(context).enter_your_pin, + style: TextStyle(fontSize: 24, color: Palette.wildDarkBlue)), + Spacer(flex: 3), + Container( + width: 180, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: List.generate(pinLength, (index) { + const size = 10.0; + final isFilled = pin[index] != null; + + return Container( + width: size, + height: size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: + isFilled ? Palette.deepPurple : Colors.transparent, + border: Border.all(color: Palette.wildDarkBlue), + )); + }), ), - Spacer(flex: 3), - Container( - width: 180, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: List.generate(pinLength, (index) { - const size = 10.0; - final isFilled = pin[index] != null; + ), + Spacer(flex: 3), + Flexible( + flex: 24, + child: Container( + key: _gridViewKey, + child: _aspectRatio > 0 + ? GridView.count( + crossAxisCount: 3, + childAspectRatio: _aspectRatio, + physics: const NeverScrollableScrollPhysics(), + children: List.generate(12, (index) { + if (index == 9) { + return Container( + margin: EdgeInsets.all(5.0), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: _isDarkTheme + ? PaletteDark.darkThemePinButton + : Palette.darkGrey, + ), + ); + } else if (index == 10) { + index = 0; + } else if (index == 11) { + return Container( + margin: EdgeInsets.all(5.0), + child: FlatButton( + onPressed: () { + _pop(); + }, + color: _isDarkTheme + ? PaletteDark.darkThemePinButton + : Palette.darkGrey, + shape: CircleBorder(), + child: deleteIconImage, + ), + ); + } else { + index++; + } - return Container( - width: size, - height: size, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: isFilled ? Palette.deepPurple : Colors.transparent, - border: Border.all(color: Palette.wildDarkBlue), - )); - }), - ), - ), - Spacer(flex: 3), - Flexible( - flex: 24, - child: Container( - key: _gridViewKey, - child: _aspectRatio > 0 ? GridView.count( - crossAxisCount: 3, - childAspectRatio: _aspectRatio, - physics: const NeverScrollableScrollPhysics(), - children: List.generate(12, (index) { - - if (index == 9) { - return Container( - margin: EdgeInsets.all(5.0), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: _isDarkTheme ? PaletteDark.darkThemePinButton - : Palette.darkGrey, - ), - ); - } else if (index == 10) { - index = 0; - } else if (index == 11) { - return Container( - margin: EdgeInsets.all(5.0), - child: FlatButton( - onPressed: () { _pop(); }, - color: _isDarkTheme ? PaletteDark.darkThemePinButton - : Palette.darkGrey, - shape: CircleBorder(), - child: deleteIconImage, - ), - ); - } else { - index++; - } - - return Container( - margin: EdgeInsets.all(5.0), - child: FlatButton( - onPressed: () { _push(index); }, - color: _isDarkTheme ? PaletteDark.darkThemePinDigitButton - : Palette.creamyGrey, - shape: CircleBorder(), - child: Text( - '$index', - style: TextStyle( - fontSize: 23.0, - color: Palette.blueGrey - ) - ), - ), - ); - }), - ) : null - ) - ) - ], - ), - ) - ), + return Container( + margin: EdgeInsets.all(5.0), + child: FlatButton( + onPressed: () { + _push(index); + }, + color: _isDarkTheme + ? PaletteDark.darkThemePinDigitButton + : Palette.creamyGrey, + shape: CircleBorder(), + child: Text('$index', + style: TextStyle( + fontSize: 23.0, + color: Palette.blueGrey)), + ), + ); + }), + ) + : null)) + ], + ), + )), ); } - _showIncorrectPinDialog(BuildContext context) async { - await showDialog( + void _showIncorrectPinDialog(BuildContext context) async { + await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( @@ -186,8 +183,7 @@ class EnterPinCodeState extends State{ ), ], ); - } - ); + }); } void _push(int num) { @@ -202,20 +198,16 @@ class EnterPinCodeState extends State{ } } - if (_pinLength() == pinLength) { - - if (listEquals(pin, currentPin)){ + final currentPinLength = _pinLength(); + if (currentPinLength == pinLength) { + if (listEquals(pin, currentPin)) { Navigator.pop(context, true); - } else { - Navigator.pop(context, false); _showIncorrectPinDialog(context); - } - } } @@ -226,7 +218,7 @@ class EnterPinCodeState extends State{ for (var i = pin.length - 1; i >= 0; i--) { if (pin[i] != null) { - setState(() => pin[i] = null); + setState(() => pin[i] = null); break; } } @@ -241,5 +233,4 @@ class EnterPinCodeState extends State{ return v; }); } - -} \ No newline at end of file +} diff --git a/lib/src/screens/settings/items/settings_item.dart b/lib/src/screens/settings/items/settings_item.dart index 68ae7b04d..8f8798b2c 100644 --- a/lib/src/screens/settings/items/settings_item.dart +++ b/lib/src/screens/settings/items/settings_item.dart @@ -2,6 +2,15 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/screens/settings/attributes.dart'; class SettingsItem { + SettingsItem( + {this.onTaped, + this.title, + this.link, + this.image, + this.widget, + this.attribute, + this.widgetBuilder}); + final VoidCallback onTaped; final String title; final String link; @@ -9,12 +18,4 @@ class SettingsItem { final Widget widget; final Attributes attribute; final WidgetBuilder widgetBuilder; - - SettingsItem({this.onTaped, - this.title, - this.link, - this.image, - this.widget, - this.attribute, - this.widgetBuilder}); -} \ No newline at end of file +} diff --git a/lib/src/screens/settings/settings.dart b/lib/src/screens/settings/settings.dart index ca6ccfaa2..7a3eb9fe9 100644 --- a/lib/src/screens/settings/settings.dart +++ b/lib/src/screens/settings/settings.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:cake_wallet/palette.dart'; @@ -25,8 +26,13 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_text_list_row. import 'package:cake_wallet/src/screens/settings/widgets/settings_raw_widget_list_row.dart'; class SettingsPage extends BasePage { + @override String get title => S.current.settings_title; + + @override bool get isModalBackButton => true; + + @override Color get backgroundColor => Palette.lightGrey2; @override @@ -37,7 +43,7 @@ class SettingsPage extends BasePage { class SettingsForm extends StatefulWidget { @override - createState() => SettingsFormState(); + SettingsFormState createState() => SettingsFormState(); } class SettingsFormState extends State { @@ -52,13 +58,13 @@ class SettingsFormState extends State { final _changeNowUrl = 'mailto:support@changenow.io'; final _xmrToUrl = 'mailto:support@xmr.to'; - List _items = List(); + final _items = List(); - _launchUrl(String url) async { + void _launchUrl(String url) async { if (await canLaunch(url)) await launch(url); } - _setSettingsList() { + void _setSettingsList() { final settingsStore = Provider.of(context); settingsStore.setItemHeaders(); @@ -121,11 +127,13 @@ class SettingsFormState extends State { SettingsItem( onTaped: () { Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) => + arguments: (bool isAuthenticatedSuccessfully, + AuthPageState auth) => isAuthenticatedSuccessfully ? Navigator.of(context).popAndPushNamed(Routes.setupPin, - arguments: (setupPinContext, _) => - Navigator.of(context).pop()) + arguments: + (BuildContext setupPinContext, String _) => + Navigator.of(context).pop()) : null); }, title: ItemHeaders.changePIN, @@ -263,7 +271,7 @@ class SettingsFormState extends State { onTaped: () { Navigator.push( context, - CupertinoPageRoute( + CupertinoPageRoute( builder: (BuildContext context) => DisclaimerPage())); }, title: ItemHeaders.termsAndConditions, @@ -276,7 +284,7 @@ class SettingsFormState extends State { setState(() {}); } - _afterLayout(_) => _setSettingsList(); + void _afterLayout(dynamic _) => _setSettingsList(); @override void initState() { @@ -335,11 +343,12 @@ class SettingsFormState extends State { final item = _items[index]; bool _isDrawDivider = true; - if (item.attribute == Attributes.header) + if (item.attribute == Attributes.header) { _isDrawDivider = false; - else if (index < _items.length - 1) { - if (_items[index + 1].attribute == Attributes.header) + } else if (index < _items.length - 1) { + if (_items[index + 1].attribute == Attributes.header) { _isDrawDivider = false; + } } return Column( @@ -413,33 +422,34 @@ class SettingsFormState extends State { }); } - void _setBalance(BuildContext context) async { + Future _setBalance(BuildContext context) async { final settingsStore = Provider.of(context); final selectedDisplayMode = await _presentPicker(context, BalanceDisplayMode.all); if (selectedDisplayMode != null) { - settingsStore.setCurrentBalanceDisplayMode( + await settingsStore.setCurrentBalanceDisplayMode( balanceDisplayMode: selectedDisplayMode); } } - void _setCurrency(BuildContext context) async { + Future _setCurrency(BuildContext context) async { final settingsStore = Provider.of(context); final selectedCurrency = await _presentPicker(context, FiatCurrency.all); if (selectedCurrency != null) { - settingsStore.setCurrentFiatCurrency(currency: selectedCurrency); + await settingsStore.setCurrentFiatCurrency(currency: selectedCurrency); } } - void _setTransactionPriority(BuildContext context) async { + Future _setTransactionPriority(BuildContext context) async { final settingsStore = Provider.of(context); final selectedPriority = await _presentPicker(context, TransactionPriority.all); if (selectedPriority != null) { - settingsStore.setCurrentTransactionPriority(priority: selectedPriority); + await settingsStore.setCurrentTransactionPriority( + priority: selectedPriority); } } } diff --git a/lib/src/screens/settings/widgets/settings_arrow_list_row.dart b/lib/src/screens/settings/widgets/settings_arrow_list_row.dart index 8532d3bc6..5abbf3ce7 100644 --- a/lib/src/screens/settings/widgets/settings_arrow_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_arrow_list_row.dart @@ -4,12 +4,12 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart'; class SettingsArrowListRow extends StatelessWidget { + SettingsArrowListRow({@required this.onTaped, this.title}); + final VoidCallback onTaped; final String title; final _cakeArrowImage = Image.asset('assets/images/cake_arrow.png'); - SettingsArrowListRow({@required this.onTaped, this.title}); - @override Widget build(BuildContext context) { final settingsStore = Provider.of(context); diff --git a/lib/src/screens/settings/widgets/settings_header_list_row.dart b/lib/src/screens/settings/widgets/settings_header_list_row.dart index e64775f8d..a068b262b 100644 --- a/lib/src/screens/settings/widgets/settings_header_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_header_list_row.dart @@ -5,10 +5,10 @@ import 'package:cake_wallet/palette.dart'; import 'package:provider/provider.dart'; class SettingsHeaderListRow extends StatelessWidget { - final String title; - SettingsHeaderListRow({this.title}); + final String title; + @override Widget build(BuildContext context) { final settingsStore = Provider.of(context); @@ -25,10 +25,10 @@ class SettingsHeaderListRow extends StatelessWidget { children: [ Observer( builder: (_) => Text( - settingsStore.itemHeaders[title], - style: TextStyle( - fontSize: 15.0, color: Palette.wildDarkBlue), - )) + settingsStore.itemHeaders[title], + style: TextStyle( + fontSize: 15.0, color: Palette.wildDarkBlue), + )) ], ), ), @@ -38,5 +38,4 @@ class SettingsHeaderListRow extends StatelessWidget { ], ); } - -} \ No newline at end of file +} diff --git a/lib/src/screens/settings/widgets/settings_link_list_row.dart b/lib/src/screens/settings/widgets/settings_link_list_row.dart index d72b01f40..0b41ef9b8 100644 --- a/lib/src/screens/settings/widgets/settings_link_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_link_list_row.dart @@ -2,16 +2,16 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; class SettingsLinktListRow extends StatelessWidget { + SettingsLinktListRow( + {@required this.onTaped, this.title, this.link, this.image}); + final VoidCallback onTaped; final String title; final String link; final Image image; - SettingsLinktListRow({@required this.onTaped, this.title, this.link, this.image}); - @override Widget build(BuildContext context) { - return Container( color: Theme.of(context).accentTextTheme.headline.backgroundColor, child: ListTile( @@ -28,20 +28,17 @@ class SettingsLinktListRow extends StatelessWidget { style: TextStyle( fontSize: 15.0, fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.title.color - ), + color: Theme.of(context).primaryTextTheme.title.color), ), ) ], ), trailing: Text( link, - style: - TextStyle(fontSize: 14.0, color: Palette.cakeGreen), + style: TextStyle(fontSize: 14.0, color: Palette.cakeGreen), ), onTap: onTaped, ), ); } - -} \ No newline at end of file +} diff --git a/lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart b/lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart index e60120123..8dd71a57d 100644 --- a/lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_raw_widget_list_row.dart @@ -1,13 +1,12 @@ import 'package:flutter/material.dart'; class SettingRawWidgetListRow extends StatelessWidget { - final WidgetBuilder widgetBuilder; - SettingRawWidgetListRow({@required this.widgetBuilder}); + final WidgetBuilder widgetBuilder; + @override Widget build(BuildContext context) { - return Container( color: Theme.of(context).accentTextTheme.headline.backgroundColor, child: widgetBuilder(context) ?? Container(), diff --git a/lib/src/screens/settings/widgets/settings_switch_list_row.dart b/lib/src/screens/settings/widgets/settings_switch_list_row.dart index df658bccc..16b2e2a29 100644 --- a/lib/src/screens/settings/widgets/settings_switch_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_switch_list_row.dart @@ -8,13 +8,13 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/src/widgets/standart_switch.dart'; class SettingsSwitchListRow extends StatelessWidget { - final String title; - SettingsSwitchListRow({@required this.title}); + final String title; + Widget _getSwitch(BuildContext context) { final settingsStore = Provider.of(context); - ThemeChanger _themeChanger = Provider.of(context); + final _themeChanger = Provider.of(context); if (settingsStore.itemHeaders[title] == S.of(context).settings_save_recipient_address) { @@ -22,7 +22,7 @@ class SettingsSwitchListRow extends StatelessWidget { builder: (_) => StandartSwitch( value: settingsStore.shouldSaveRecipientAddress, onTaped: () { - bool _currentValue = !settingsStore.shouldSaveRecipientAddress; + final _currentValue = !settingsStore.shouldSaveRecipientAddress; settingsStore.setSaveRecipientAddress( shouldSaveRecipientAddress: _currentValue); })); @@ -34,7 +34,7 @@ class SettingsSwitchListRow extends StatelessWidget { builder: (_) => StandartSwitch( value: settingsStore.allowBiometricalAuthentication, onTaped: () { - bool _currentValue = + final _currentValue = !settingsStore.allowBiometricalAuthentication; settingsStore.setAllowBiometricalAuthentication( allowBiometricalAuthentication: _currentValue); @@ -46,7 +46,7 @@ class SettingsSwitchListRow extends StatelessWidget { builder: (_) => StandartSwitch( value: settingsStore.isDarkTheme, onTaped: () { - bool _currentValue = !settingsStore.isDarkTheme; + final _currentValue = !settingsStore.isDarkTheme; settingsStore.saveDarkTheme(isDarkTheme: _currentValue); _themeChanger.setTheme( _currentValue ? Themes.darkTheme : Themes.lightTheme); diff --git a/lib/src/screens/settings/widgets/settings_text_list_row.dart b/lib/src/screens/settings/widgets/settings_text_list_row.dart index ccda97a4b..ad68471db 100644 --- a/lib/src/screens/settings/widgets/settings_text_list_row.dart +++ b/lib/src/screens/settings/widgets/settings_text_list_row.dart @@ -4,12 +4,12 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart'; class SettingsTextListRow extends StatelessWidget { + SettingsTextListRow({@required this.onTaped, this.title, this.widget}); + final VoidCallback onTaped; final String title; final Widget widget; - SettingsTextListRow({@required this.onTaped, this.title, this.widget}); - @override Widget build(BuildContext context) { final settingsStore = Provider.of(context); diff --git a/lib/src/screens/setup_pin_code/setup_pin_code.dart b/lib/src/screens/setup_pin_code/setup_pin_code.dart index 330a8ee8f..3a6308318 100644 --- a/lib/src/screens/setup_pin_code/setup_pin_code.dart +++ b/lib/src/screens/setup_pin_code/setup_pin_code.dart @@ -9,24 +9,24 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; class SetupPinCodePage extends BasePage { + SetupPinCodePage({this.onPinCodeSetup}); + final Function(BuildContext, String) onPinCodeSetup; @override String get title => S.current.setup_pin; - SetupPinCodePage({this.onPinCodeSetup}); - @override Widget body(BuildContext context) => SetupPinCodeForm(onPinCodeSetup: onPinCodeSetup, hasLengthSwitcher: true); } class SetupPinCodeForm extends PinCodeWidget { - final Function(BuildContext, String) onPinCodeSetup; - final bool hasLengthSwitcher; - SetupPinCodeForm( - {@required this.onPinCodeSetup, @required this.hasLengthSwitcher}); + {@required this.onPinCodeSetup, @required bool hasLengthSwitcher}) + : super(hasLengthSwitcher: hasLengthSwitcher); + + final Function(BuildContext, String) onPinCodeSetup; @override _SetupPinCodeFormState createState() => _SetupPinCodeFormState(); @@ -34,17 +34,16 @@ class SetupPinCodeForm extends PinCodeWidget { class _SetupPinCodeFormState extends PinCodeState { + _SetupPinCodeFormState() { + title = S.current.enter_your_pin; + } - bool isEnteredOriginalPin() => !(_originalPin.length == 0); + bool isEnteredOriginalPin() => _originalPin.isNotEmpty; Function(BuildContext) onPinCodeSetup; List _originalPin = []; UserStore _userStore; SettingsStore _settingsStore; - _SetupPinCodeFormState() { - title = S.current.enter_your_pin; - } - @override void onPinCodeEntered(PinCodeState state) { if (!isEnteredOriginalPin()) { @@ -57,7 +56,7 @@ class _SetupPinCodeFormState _userStore.set(password: pin); _settingsStore.setDefaultPinLength(pinLength: state.pinLength); - showDialog( + showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { @@ -76,7 +75,7 @@ class _SetupPinCodeFormState ); }); } else { - showDialog( + showDialog( context: context, builder: (BuildContext context) { return AlertDialog( diff --git a/lib/src/screens/show_keys/show_keys_page.dart b/lib/src/screens/show_keys/show_keys_page.dart index 4d5a1dd1c..445873e49 100644 --- a/lib/src/screens/show_keys/show_keys_page.dart +++ b/lib/src/screens/show_keys/show_keys_page.dart @@ -9,7 +9,10 @@ import 'package:cake_wallet/src/stores/wallet/wallet_keys_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class ShowKeysPage extends BasePage { + @override bool get isModalBackButton => true; + + @override String get title => S.current.wallet_keys; @override @@ -20,7 +23,7 @@ class ShowKeysPage extends BasePage { padding: EdgeInsets.only(top: 20.0, bottom: 20.0, left: 20, right: 20), child: Observer( builder: (_) { - Map keysMap = { + final keysMap = { S.of(context).view_key_public: walletKeysStore.publicViewKey, S.of(context).view_key_private: walletKeysStore.privateViewKey, S.of(context).spend_key_public: walletKeysStore.publicSpendKey, diff --git a/lib/src/screens/subaddress/new_subaddress_page.dart b/lib/src/screens/subaddress/new_subaddress_page.dart index 06c29a932..421ec767c 100644 --- a/lib/src/screens/subaddress/new_subaddress_page.dart +++ b/lib/src/screens/subaddress/new_subaddress_page.dart @@ -11,6 +11,7 @@ import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/palette.dart'; class NewSubaddressPage extends BasePage { + @override String get title => S.current.new_subaddress_title; @override @@ -21,7 +22,7 @@ class NewSubaddressPage extends BasePage { final subaddressCreationStore = Provider.of(context); - reaction((_) => subaddressCreationStore.state, (state) { + reaction((_) => subaddressCreationStore.state, (SubaddressCreationState state) { if (state is SubaddressCreatedSuccessfully) { WidgetsBinding.instance .addPostFrameCallback((_) => Navigator.of(context).pop()); @@ -58,8 +59,8 @@ class NewSubaddressFormState extends State { hintStyle: TextStyle(color: Theme.of(context).hintColor), hintText: S.of(context).new_subaddress_label_name, focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Palette.cakeGreen, width: 2.0)), + borderSide: + BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: Theme.of(context).focusColor, diff --git a/lib/src/screens/subaddress/subaddress_list_page.dart b/lib/src/screens/subaddress/subaddress_list_page.dart index 28f3b3f58..3a34867d7 100644 --- a/lib/src/screens/subaddress/subaddress_list_page.dart +++ b/lib/src/screens/subaddress/subaddress_list_page.dart @@ -8,12 +8,17 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; class SubaddressListPage extends BasePage { - bool get isModalBackButton => true; - String get title => S.current.subaddress_title; - AppBarStyle get appBarStyle => AppBarStyle.withShadow; - SubaddressListPage(); + @override + bool get isModalBackButton => true; + + @override + String get title => S.current.subaddress_title; + + @override + AppBarStyle get appBarStyle => AppBarStyle.withShadow; + @override Widget body(BuildContext context) { final walletStore = Provider.of(context); diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index 68c19a285..f60aae071 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -10,7 +10,10 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.dart'; class TradeDetailsPage extends BasePage { + @override String get title => S.current.trade_details_title; + + @override bool get isModalBackButton => true; @override @@ -54,7 +57,8 @@ class TradeDetailsPage extends BasePage { color: Theme.of(context).dividerTheme.color, height: 1.0, ), - padding: EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15), + padding: + EdgeInsets.only(left: 25, top: 10, right: 25, bottom: 15), itemCount: items.length, itemBuilder: (BuildContext context, int index) { final item = items[index]; diff --git a/lib/src/screens/transaction_details/standart_list_item.dart b/lib/src/screens/transaction_details/standart_list_item.dart index eb36c3706..9cf23eeb5 100644 --- a/lib/src/screens/transaction_details/standart_list_item.dart +++ b/lib/src/screens/transaction_details/standart_list_item.dart @@ -1,6 +1,6 @@ class StandartListItem { + StandartListItem({this.title, this.value}); + final String title; final String value; - - StandartListItem({this.title, this.value}); -} \ No newline at end of file +} diff --git a/lib/src/screens/transaction_details/standart_list_row.dart b/lib/src/screens/transaction_details/standart_list_row.dart index 5d9f0cd6b..40f140dbe 100644 --- a/lib/src/screens/transaction_details/standart_list_row.dart +++ b/lib/src/screens/transaction_details/standart_list_row.dart @@ -2,14 +2,13 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; class StandartListRow extends StatelessWidget { + StandartListRow({this.title, this.value}); + final String title; final String value; - StandartListRow({this.title, this.value}); - @override Widget build(BuildContext context) { - return Padding( padding: const EdgeInsets.only(top: 10, bottom: 10), child: Column( @@ -23,9 +22,7 @@ class StandartListRow extends StatelessWidget { Padding( padding: const EdgeInsets.only(top: 5), child: Text(value, - style: TextStyle( - fontSize: 14, - color: Palette.wildDarkBlue)), + style: TextStyle(fontSize: 14, color: Palette.wildDarkBlue)), ) ]), ); diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 74a70ab0c..670e6de6f 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -11,12 +11,15 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_row.da import 'package:cake_wallet/src/screens/base_page.dart'; class TransactionDetailsPage extends BasePage { - bool get isModalBackButton => true; - String get title => S.current.transaction_details_title; + TransactionDetailsPage({this.transactionInfo}); final TransactionInfo transactionInfo; - TransactionDetailsPage({this.transactionInfo}); + @override + bool get isModalBackButton => true; + + @override + String get title => S.current.transaction_details_title; @override Widget body(BuildContext context) { @@ -28,23 +31,23 @@ class TransactionDetailsPage extends BasePage { } class TransactionDetailsForm extends StatefulWidget { - final TransactionInfo transactionInfo; - final SettingsStore settingsStore; - TransactionDetailsForm( {@required this.transactionInfo, @required this.settingsStore}); + final TransactionInfo transactionInfo; + final SettingsStore settingsStore; + @override - createState() => TransactionDetailsFormState(); + TransactionDetailsFormState createState() => TransactionDetailsFormState(); } class TransactionDetailsFormState extends State { final DateFormat _dateFormat = DateFormat('dd.MM.yyyy, HH:mm'); - List _items = List(); + final _items = List(); @override void initState() { - List items = [ + final items = [ StandartListItem( title: S.current.transaction_details_transaction_id, value: widget.transactionInfo.id), @@ -59,10 +62,11 @@ class TransactionDetailsFormState extends State { value: widget.transactionInfo.amountFormatted()) ]; - if (widget.settingsStore.shouldSaveRecipientAddress && widget.transactionInfo.recipientAddress != null) { + if (widget.settingsStore.shouldSaveRecipientAddress && + widget.transactionInfo.recipientAddress != null) { items.add(StandartListItem( - title: S.current.transaction_details_recipient_address, - value: widget.transactionInfo.recipientAddress)); + title: S.current.transaction_details_recipient_address, + value: widget.transactionInfo.recipientAddress)); } _items.addAll(items); diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 7bbadfa46..6ec66c566 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -14,8 +14,13 @@ import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart'; import 'package:cake_wallet/src/widgets/picker.dart'; class WalletListPage extends BasePage { + @override bool get isModalBackButton => true; + + @override String get title => S.current.wallet_list_title; + + @override AppBarStyle get appBarStyle => AppBarStyle.withShadow; @override @@ -23,6 +28,7 @@ class WalletListPage extends BasePage { } class WalletListBody extends StatefulWidget { + @override WalletListBodyState createState() => WalletListBodyState(); } @@ -32,15 +38,15 @@ class WalletListBodyState extends State { void presetMenuForWallet(WalletDescription wallet, bool isCurrentWallet, BuildContext bodyContext) { final walletMenu = WalletMenu(bodyContext); - List items = walletMenu.generateItemsForWalletMenu(isCurrentWallet); + final items = walletMenu.generateItemsForWalletMenu(isCurrentWallet); - showDialog( + showDialog( context: bodyContext, builder: (_) => Picker( items: items, selectedAtIndex: -1, title: S.of(context).wallet_menu, - onItemSelected: (item) => walletMenu.action( + onItemSelected: (String item) => walletMenu.action( walletMenu.listItems.indexOf(item), wallet, isCurrentWallet)), ); } diff --git a/lib/src/screens/wallet_list/wallet_menu.dart b/lib/src/screens/wallet_list/wallet_menu.dart index cd1842ed6..0cb278047 100644 --- a/lib/src/screens/wallet_list/wallet_menu.dart +++ b/lib/src/screens/wallet_list/wallet_menu.dart @@ -1,13 +1,16 @@ -import 'package:cake_wallet/src/domain/common/wallet_description.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:provider/provider.dart'; -import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/src/stores/wallet_list/wallet_list_store.dart'; +import 'package:cake_wallet/src/domain/common/wallet_description.dart'; +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; class WalletMenu { + WalletMenu(this.context); final BuildContext context; + final List listItems = [ S.current.wallet_list_load_wallet, S.current.show_seed, @@ -15,10 +18,8 @@ class WalletMenu { S.current.rescan ]; - WalletMenu(this.context); - - ListgenerateItemsForWalletMenu(bool isCurrentWallet) { - List items = new List(); + List generateItemsForWalletMenu(bool isCurrentWallet) { + final items = List(); if (!isCurrentWallet) items.add(listItems[0]); if (isCurrentWallet) items.add(listItems[1]); @@ -29,52 +30,56 @@ class WalletMenu { } void action(int index, WalletDescription wallet, bool isCurrentWallet) { - WalletListStore _walletListStore = Provider.of(context); + final _walletListStore = Provider.of(context); switch (index) { case 0: - Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } + Navigator.of(context).pushNamed(Routes.auth, arguments: + (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + return; + } - try { - auth.changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name)); - await _walletListStore.loadWallet(wallet); - auth.close(); - Navigator.of(context).pop(); - } catch (e) { - auth.changeProcessText( - S.of(context).wallet_list_failed_to_load(wallet.name, e.toString())); - } + try { + auth.changeProcessText( + S.of(context).wallet_list_loading_wallet(wallet.name)); + await _walletListStore.loadWallet(wallet); + auth.close(); + Navigator.of(context).pop(); + } catch (e) { + auth.changeProcessText(S + .of(context) + .wallet_list_failed_to_load(wallet.name, e.toString())); + } }); break; case 1: - Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } - auth.close(); - Navigator.of(context).pushNamed(Routes.seed); + Navigator.of(context).pushNamed(Routes.auth, arguments: + (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + return; + } + auth.close(); + await Navigator.of(context).pushNamed(Routes.seed); }); break; case 2: - Navigator.of(context).pushNamed(Routes.auth, - arguments: (isAuthenticatedSuccessfully, auth) async { - if (!isAuthenticatedSuccessfully) { - return; - } + Navigator.of(context).pushNamed(Routes.auth, arguments: + (bool isAuthenticatedSuccessfully, AuthPageState auth) async { + if (!isAuthenticatedSuccessfully) { + return; + } - try { - auth.changeProcessText(S.of(context).wallet_list_removing_wallet(wallet.name)); - await _walletListStore.remove(wallet); - auth.close(); - } catch (e) { - auth.changeProcessText( - S.of(context).wallet_list_failed_to_remove(wallet.name, e.toString())); - } + try { + auth.changeProcessText( + S.of(context).wallet_list_removing_wallet(wallet.name)); + await _walletListStore.remove(wallet); + auth.close(); + } catch (e) { + auth.changeProcessText(S + .of(context) + .wallet_list_failed_to_remove(wallet.name, e.toString())); + } }); break; case 3: @@ -84,5 +89,4 @@ class WalletMenu { break; } } - -} \ No newline at end of file +} diff --git a/lib/src/screens/welcome/welcome_page.dart b/lib/src/screens/welcome/welcome_page.dart index 30f35afa1..1f559458c 100644 --- a/lib/src/screens/welcome/welcome_page.dart +++ b/lib/src/screens/welcome/welcome_page.dart @@ -1,11 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.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/theme_changer.dart'; -import 'package:cake_wallet/themes.dart'; import 'package:cake_wallet/generated/i18n.dart'; class WelcomePage extends BasePage { @@ -16,15 +13,10 @@ class WelcomePage extends BasePage { @override Widget build(BuildContext context) { - ThemeChanger _themeChanger = Provider.of(context); - bool _isDarkTheme = (_themeChanger.getTheme() == Themes.darkTheme); - return Scaffold( - backgroundColor: - _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor, - resizeToAvoidBottomPadding: false, - body: SafeArea(child: body(context)), - ); + backgroundColor: Theme.of(context).backgroundColor, + resizeToAvoidBottomPadding: false, + body: SafeArea(child: body(context))); } @override diff --git a/lib/src/start_updating_price.dart b/lib/src/start_updating_price.dart index 1f441f084..82a6771b1 100644 --- a/lib/src/start_updating_price.dart +++ b/lib/src/start_updating_price.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:cake_wallet/src/domain/common/fiat_currency.dart'; import 'package:flutter/foundation.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/common/fetch_price.dart'; @@ -7,12 +8,14 @@ import 'package:cake_wallet/src/stores/settings/settings_store.dart'; bool _startedUpdatingPrice = false; -_updatePrice(Map args) async => - await fetchPriceFor(fiat: args['fiat'], crypto: args['crypto']); +Future _updatePrice(Map args) async => await fetchPriceFor( + fiat: args['fiat'] as FiatCurrency, + crypto: args['crypto'] as CryptoCurrency); -updatePrice(Map args) async => compute(_updatePrice, args); +Future updatePrice(Map args) async => compute(_updatePrice, args); -startUpdatingPrice({SettingsStore settingsStore, PriceStore priceStore}) async { +Future startUpdatingPrice( + {SettingsStore settingsStore, PriceStore priceStore}) async { if (_startedUpdatingPrice) { return; } @@ -21,13 +24,13 @@ startUpdatingPrice({SettingsStore settingsStore, PriceStore priceStore}) async { _startedUpdatingPrice = true; final price = await updatePrice( - {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto}); + {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto}); priceStore.changePriceForPair( fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price); Timer.periodic(Duration(seconds: 30), (_) async { final price = await updatePrice( - {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto}); + {'fiat': settingsStore.fiatCurrency, 'crypto': currentCrypto}); priceStore.changePriceForPair( fiat: settingsStore.fiatCurrency, crypto: currentCrypto, price: price); }); diff --git a/lib/src/stores/account_list/account_list_store.dart b/lib/src/stores/account_list/account_list_store.dart index e8ea07d5c..e6361d5a7 100644 --- a/lib/src/stores/account_list/account_list_store.dart +++ b/lib/src/stores/account_list/account_list_store.dart @@ -13,6 +13,18 @@ part 'account_list_store.g.dart'; class AccountListStore = AcountListStoreBase with _$AccountListStore; abstract class AcountListStoreBase with Store { + AcountListStoreBase({@required WalletService walletService}) { + accounts = []; + isAccountCreating = false; + + if (walletService.currentWallet != null) { + _onWalletChanged(walletService.currentWallet); + } + + _onWalletChangeSubscription = + walletService.onWalletChange.listen(_onWalletChanged); + } + @observable List accounts; @@ -29,18 +41,6 @@ abstract class AcountListStoreBase with Store { StreamSubscription _onWalletChangeSubscription; StreamSubscription> _onAccountsChangeSubscription; - AcountListStoreBase({@required WalletService walletService}) { - accounts = []; - isAccountCreating = false; - - if (walletService.currentWallet != null) { - _onWalletChanged(walletService.currentWallet); - } - - _onWalletChangeSubscription = - walletService.onWalletChange.listen(_onWalletChanged); - } - @override void dispose() { _onWalletChangeSubscription.cancel(); @@ -52,8 +52,8 @@ abstract class AcountListStoreBase with Store { super.dispose(); } - Future updateAccountList() async { - await _accountList.refresh(); + void updateAccountList() { + _accountList.refresh(); accounts = _accountList.getAll(); } @@ -61,7 +61,7 @@ abstract class AcountListStoreBase with Store { try { isAccountCreating = true; await _accountList.addAccount(label: label); - await updateAccountList(); + updateAccountList(); isAccountCreating = false; } catch (e) { isAccountCreating = false; @@ -70,19 +70,19 @@ abstract class AcountListStoreBase with Store { Future renameAccount({int index, String label}) async { await _accountList.setLabelSubaddress(accountIndex: index, label: label); - await updateAccountList(); + updateAccountList(); } Future _onWalletChanged(Wallet wallet) async { if (_onAccountsChangeSubscription != null) { - _onAccountsChangeSubscription.cancel(); + await _onAccountsChangeSubscription.cancel(); } if (wallet is MoneroWallet) { _accountList = wallet.getAccountList(); _onAccountsChangeSubscription = _accountList.accounts.listen((accounts) => this.accounts = accounts); - await updateAccountList(); + updateAccountList(); return; } @@ -91,8 +91,8 @@ abstract class AcountListStoreBase with Store { } void validateAccountName(String value) { - String p = '^[a-zA-Z0-9_]{1,15}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[a-zA-Z0-9_]{1,15}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_account_name; } diff --git a/lib/src/stores/action_list/action_list_display_mode.dart b/lib/src/stores/action_list/action_list_display_mode.dart index a4ce36cad..1a0708a1d 100644 --- a/lib/src/stores/action_list/action_list_display_mode.dart +++ b/lib/src/stores/action_list/action_list_display_mode.dart @@ -18,7 +18,7 @@ int serializeActionlistDisplayModes(List modes) { } List deserializeActionlistDisplayModes(int raw) { - List modes = []; + final modes = List(); if (raw == 1 || raw - 10 == 1) { modes.add(ActionListDisplayMode.trades); diff --git a/lib/src/stores/action_list/action_list_store.dart b/lib/src/stores/action_list/action_list_store.dart index 0dd1e30f9..b38b697b7 100644 --- a/lib/src/stores/action_list/action_list_store.dart +++ b/lib/src/stores/action_list/action_list_store.dart @@ -28,8 +28,36 @@ part 'action_list_store.g.dart'; class ActionListStore = ActionListBase with _$ActionListStore; abstract class ActionListBase with Store { + ActionListBase( + {@required WalletService walletService, + @required SettingsStore settingsStore, + @required PriceStore priceStore, + @required this.transactionFilterStore, + @required this.tradeFilterStore, + @required this.transactionDescriptions, + @required this.tradesSource}) { + trades = List(); + _transactions = List(); + _walletService = walletService; + _settingsStore = settingsStore; + _priceStore = priceStore; + + if (walletService.currentWallet != null) { + _onWalletChanged(walletService.currentWallet); + } + + _onWalletChangeSubscription = + walletService.onWalletChange.listen(_onWalletChanged); + + _onTransactionDescriptions = transactionDescriptions + .watch() + .listen((_) async => await _updateTransactionsList()); + + updateTradeList(); + } + static List formattedItemsList(List items) { - var formattedList = List(); + final formattedList = List(); DateTime lastDate; items.sort((a, b) => b.date.compareTo(a.date)); @@ -84,7 +112,7 @@ abstract class ActionListBase with Store { @computed List get items { - var _items = List(); + final _items = List(); if (_settingsStore.actionlistDisplayMode .contains(ActionListDisplayMode.transactions)) { @@ -118,34 +146,6 @@ abstract class ActionListBase with Store { StreamSubscription _onAccountChangeSubscription; StreamSubscription _onTransactionDescriptions; - ActionListBase( - {@required WalletService walletService, - @required SettingsStore settingsStore, - @required PriceStore priceStore, - @required this.transactionFilterStore, - @required this.tradeFilterStore, - @required this.transactionDescriptions, - @required this.tradesSource}) { - trades = List(); - _transactions = List(); - _walletService = walletService; - _settingsStore = settingsStore; - _priceStore = priceStore; - - if (walletService.currentWallet != null) { - _onWalletChanged(walletService.currentWallet); - } - - _onWalletChangeSubscription = - walletService.onWalletChange.listen(_onWalletChanged); - - _onTransactionDescriptions = transactionDescriptions - .watch() - .listen((_) async => await _updateTransactionsList()); - - updateTradeList(); - } - @override void dispose() { if (_onTransactionsChangeSubscription != null) { @@ -174,11 +174,11 @@ abstract class ActionListBase with Store { Future _onWalletChanged(Wallet wallet) async { if (_onTransactionsChangeSubscription != null) { - _onTransactionsChangeSubscription.cancel(); + await _onTransactionsChangeSubscription.cancel(); } if (_onAccountChangeSubscription != null) { - _onAccountChangeSubscription.cancel(); + await _onAccountChangeSubscription.cancel(); } _history = wallet.getHistory(); @@ -199,7 +199,7 @@ abstract class ActionListBase with Store { Future _setTransactions(List transactions) async { final wallet = _walletService.currentWallet; List sortedTransactions = transactions.map((transaction) { - if (transactionDescriptions.values.length > 0) { + if (transactionDescriptions.values.isNotEmpty) { final description = transactionDescriptions.values.firstWhere( (desc) => desc.id == transaction.id, orElse: () => null); diff --git a/lib/src/stores/action_list/date_section_item.dart b/lib/src/stores/action_list/date_section_item.dart index 911887907..5a4b217ad 100644 --- a/lib/src/stores/action_list/date_section_item.dart +++ b/lib/src/stores/action_list/date_section_item.dart @@ -1,7 +1,8 @@ import 'package:cake_wallet/src/stores/action_list/action_list_item.dart'; class DateSectionItem extends ActionListItem { - final DateTime date; - DateSectionItem(this.date); + + @override + final DateTime date; } \ No newline at end of file diff --git a/lib/src/stores/action_list/trade_filter_store.dart b/lib/src/stores/action_list/trade_filter_store.dart index addaf9015..3576e459f 100644 --- a/lib/src/stores/action_list/trade_filter_store.dart +++ b/lib/src/stores/action_list/trade_filter_store.dart @@ -8,6 +8,11 @@ part 'trade_filter_store.g.dart'; class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore; abstract class TradeFilterStoreBase with Store { + TradeFilterStoreBase( + {this.displayXMRTO = true, + this.displayChangeNow = true, + this.walletStore}); + @observable bool displayXMRTO; @@ -16,11 +21,6 @@ abstract class TradeFilterStoreBase with Store { WalletStore walletStore; - TradeFilterStoreBase( - {this.displayXMRTO = true, - this.displayChangeNow = true, - this.walletStore}); - @action void toggleDisplayExchange(ExchangeProviderDescription provider) { switch (provider) { @@ -34,9 +34,8 @@ abstract class TradeFilterStoreBase with Store { } List filtered({List trades}) { - List _trades = + final _trades = trades.where((item) => item.trade.walletId == walletStore.id).toList(); - final needToFilter = !displayChangeNow || !displayXMRTO; return needToFilter diff --git a/lib/src/stores/action_list/trade_list_item.dart b/lib/src/stores/action_list/trade_list_item.dart index 0cb9b3e9d..1c13a1bc1 100644 --- a/lib/src/stores/action_list/trade_list_item.dart +++ b/lib/src/stores/action_list/trade_list_item.dart @@ -2,9 +2,10 @@ import 'package:cake_wallet/src/domain/exchange/trade.dart'; import 'package:cake_wallet/src/stores/action_list/action_list_item.dart'; class TradeListItem extends ActionListItem { + TradeListItem({this.trade}); + final Trade trade; + @override DateTime get date => trade.createdAt; - - TradeListItem({this.trade}); -} \ No newline at end of file +} diff --git a/lib/src/stores/action_list/transaction_filter_store.dart b/lib/src/stores/action_list/transaction_filter_store.dart index 9997930bd..7da1ad74c 100644 --- a/lib/src/stores/action_list/transaction_filter_store.dart +++ b/lib/src/stores/action_list/transaction_filter_store.dart @@ -8,6 +8,9 @@ class TransactionFilterStore = TransactionFilterStoreBase with _$TransactionFilterStore; abstract class TransactionFilterStoreBase with Store { + TransactionFilterStoreBase( + {this.displayIncoming = true, this.displayOutgoing = true}); + @observable bool displayIncoming; @@ -20,9 +23,6 @@ abstract class TransactionFilterStoreBase with Store { @observable DateTime endDate; - TransactionFilterStoreBase( - {this.displayIncoming = true, this.displayOutgoing = true}); - @action void toggleIncoming() => displayIncoming = !displayIncoming; diff --git a/lib/src/stores/action_list/transaction_list_item.dart b/lib/src/stores/action_list/transaction_list_item.dart index c04a57179..ba4ce19d6 100644 --- a/lib/src/stores/action_list/transaction_list_item.dart +++ b/lib/src/stores/action_list/transaction_list_item.dart @@ -2,9 +2,10 @@ import 'package:cake_wallet/src/domain/common/transaction_info.dart'; import 'package:cake_wallet/src/stores/action_list/action_list_item.dart'; class TransactionListItem extends ActionListItem { + TransactionListItem({this.transaction}); + final TransactionInfo transaction; + @override DateTime get date => transaction.date; - - TransactionListItem({this.transaction}); } \ No newline at end of file diff --git a/lib/src/stores/address_book/address_book_store.dart b/lib/src/stores/address_book/address_book_store.dart index 4cf33d9a4..324b60a2c 100644 --- a/lib/src/stores/address_book/address_book_store.dart +++ b/lib/src/stores/address_book/address_book_store.dart @@ -10,6 +10,10 @@ part 'address_book_store.g.dart'; class AddressBookStore = AddressBookStoreBase with _$AddressBookStore; abstract class AddressBookStoreBase with Store { + AddressBookStoreBase({@required this.contacts}) { + updateContactList(); + } + @observable List contactList; @@ -21,10 +25,6 @@ abstract class AddressBookStoreBase with Store { Box contacts; - AddressBookStoreBase({@required this.contacts}) { - updateContactList(); - } - @action Future add({Contact contact}) async => contacts.add(contact); @@ -38,17 +38,18 @@ abstract class AddressBookStoreBase with Store { Future delete({Contact contact}) async => await contact.delete(); void validateContactName(String value) { - String p = '''^[^`,'"]{1,32}\$'''; - RegExp regExp = new RegExp(p); + const pattern = '''^[^`,'"]{1,32}\$'''; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_contact_name; } void validateAddress(String value, {CryptoCurrency cryptoCurrency}) { // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34) - String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); + if (isValid && cryptoCurrency != null) { switch (cryptoCurrency.toString()) { case 'XMR': @@ -70,6 +71,7 @@ abstract class AddressBookStoreBase with Store { isValid = (value.length == 34); } } + errorMessage = isValid ? null : S.current.error_text_address; } } diff --git a/lib/src/stores/auth/auth_state.dart b/lib/src/stores/auth/auth_state.dart index 1361fc75e..01e4c2576 100644 --- a/lib/src/stores/auth/auth_state.dart +++ b/lib/src/stores/auth/auth_state.dart @@ -7,14 +7,14 @@ class AuthenticationInProgress extends AuthState {} class AuthenticatedSuccessfully extends AuthState {} class AuthenticationFailure extends AuthState { - final String error; - AuthenticationFailure({this.error}); + + final String error; } class AuthenticationBanned extends AuthState { - final String error; - AuthenticationBanned({this.error}); + + final String error; } diff --git a/lib/src/stores/auth/auth_store.dart b/lib/src/stores/auth/auth_store.dart index 1a8ba95be..966ccc0b1 100644 --- a/lib/src/stores/auth/auth_store.dart +++ b/lib/src/stores/auth/auth_store.dart @@ -12,6 +12,14 @@ part 'auth_store.g.dart'; class AuthStore = AuthStoreBase with _$AuthStore; abstract class AuthStoreBase with Store { + AuthStoreBase( + {@required this.userService, + @required this.walletService, + @required this.sharedPreferences}) { + state = AuthenticationStateInitial(); + _failureCounter = 0; + } + static const maxFailedLogins = 3; static const banTimeout = 180; // 3 mins final banTimeoutKey = S.current.auth_store_ban_timeout; @@ -27,14 +35,6 @@ abstract class AuthStoreBase with Store { @observable int _failureCounter; - AuthStoreBase( - {@required this.userService, - @required this.walletService, - @required this.sharedPreferences}) { - state = AuthenticationStateInitial(); - _failureCounter = 0; - } - @action Future auth({String password}) async { state = AuthenticationStateInitial(); diff --git a/lib/src/stores/authentication/authentication_store.dart b/lib/src/stores/authentication/authentication_store.dart index fe822cc8f..f9e69f864 100644 --- a/lib/src/stores/authentication/authentication_store.dart +++ b/lib/src/stores/authentication/authentication_store.dart @@ -21,6 +21,10 @@ enum AuthenticationState { } abstract class AuthenticationStoreBase with Store { + AuthenticationStoreBase({@required this.userService}) { + state = AuthenticationState.uninitialized; + } + final UserService userService; @observable @@ -29,10 +33,6 @@ abstract class AuthenticationStoreBase with Store { @observable String errorMessage; - AuthenticationStoreBase({@required this.userService}) { - state = AuthenticationState.uninitialized; - } - Future started() async { final canAuth = await userService.canAuthenticate(); state = canAuth ? AuthenticationState.allowed : AuthenticationState.denied; diff --git a/lib/src/stores/balance/balance_store.dart b/lib/src/stores/balance/balance_store.dart index da7a4b4e3..e279caf97 100644 --- a/lib/src/stores/balance/balance_store.dart +++ b/lib/src/stores/balance/balance_store.dart @@ -15,6 +15,27 @@ part 'balance_store.g.dart'; class BalanceStore = BalanceStoreBase with _$BalanceStore; abstract class BalanceStoreBase with Store { + BalanceStoreBase( + {String fullBalance = '0.0', + String unlockedBalance = '0.0', + @required WalletService walletService, + @required SettingsStore settingsStore, + @required PriceStore priceStore}) { + fullBalance = fullBalance; + unlockedBalance = unlockedBalance; + isReversing = false; + _walletService = walletService; + _settingsStore = settingsStore; + _priceStore = priceStore; + + if (_walletService.currentWallet != null) { + _onWalletChanged(_walletService.currentWallet); + } + + _onWalletChangeSubscription = _walletService.onWalletChange + .listen((wallet) => _onWalletChanged(wallet)); + } + @observable String fullBalance; @@ -54,27 +75,6 @@ abstract class BalanceStoreBase with Store { SettingsStore _settingsStore; PriceStore _priceStore; - BalanceStoreBase( - {String fullBalance = '0.0', - String unlockedBalance = '0.0', - @required WalletService walletService, - @required SettingsStore settingsStore, - @required PriceStore priceStore}) { - fullBalance = fullBalance; - unlockedBalance = unlockedBalance; - isReversing = false; - _walletService = walletService; - _settingsStore = settingsStore; - _priceStore = priceStore; - - if (_walletService.currentWallet != null) { - _onWalletChanged(_walletService.currentWallet); - } - - _onWalletChangeSubscription = _walletService.onWalletChange - .listen((wallet) => _onWalletChanged(wallet)); - } - @override void dispose() { _onWalletChangeSubscription.cancel(); @@ -100,7 +100,7 @@ abstract class BalanceStoreBase with Store { Future _onWalletChanged(Wallet wallet) async { if (_onBalanceChangeSubscription != null) { - _onBalanceChangeSubscription.cancel(); + await _onBalanceChangeSubscription.cancel(); } _onBalanceChangeSubscription = _walletService.onBalanceChange diff --git a/lib/src/stores/exchange/exchange_store.dart b/lib/src/stores/exchange/exchange_store.dart index ead674423..dad09bcd6 100644 --- a/lib/src/stores/exchange/exchange_store.dart +++ b/lib/src/stores/exchange/exchange_store.dart @@ -19,6 +19,21 @@ part 'exchange_store.g.dart'; class ExchangeStore = ExchangeStoreBase with _$ExchangeStore; abstract class ExchangeStoreBase with Store { + ExchangeStoreBase( + {@required ExchangeProvider initialProvider, + @required CryptoCurrency initialDepositCurrency, + @required CryptoCurrency initialReceiveCurrency, + @required this.providerList, + @required this.trades, + @required this.walletStore}) { + provider = initialProvider; + depositCurrency = initialDepositCurrency; + receiveCurrency = initialReceiveCurrency; + limitsState = LimitsInitialState(); + tradeState = ExchangeTradeStateInitial(); + loadLimits(); + } + @observable ExchangeProvider provider; @@ -57,21 +72,6 @@ abstract class ExchangeStoreBase with Store { WalletStore walletStore; - ExchangeStoreBase( - {@required ExchangeProvider initialProvider, - @required CryptoCurrency initialDepositCurrency, - @required CryptoCurrency initialReceiveCurrency, - @required this.providerList, - @required this.trades, - @required this.walletStore}) { - provider = initialProvider; - depositCurrency = initialDepositCurrency; - receiveCurrency = initialReceiveCurrency; - limitsState = LimitsInitialState(); - tradeState = ExchangeTradeStateInitial(); - loadLimits(); - } - @action void changeProvider({ExchangeProvider provider}) { this.provider = provider; @@ -190,12 +190,10 @@ abstract class ExchangeStoreBase with Store { List _providersForPair( {CryptoCurrency from, CryptoCurrency to}) { final providers = providerList - .where((provider) => - provider.pairList - .where((pair) => - pair.from == depositCurrency && pair.to == receiveCurrency) - .length > - 0) + .where((provider) => provider.pairList + .where((pair) => + pair.from == depositCurrency && pair.to == receiveCurrency) + .isNotEmpty) .toList(); return providers; @@ -203,10 +201,9 @@ abstract class ExchangeStoreBase with Store { void _onPairChange() { final isPairExist = provider.pairList - .where((pair) => - pair.from == depositCurrency && pair.to == receiveCurrency) - .length > - 0; + .where((pair) => + pair.from == depositCurrency && pair.to == receiveCurrency) + .isNotEmpty; if (!isPairExist) { final provider = @@ -225,14 +222,15 @@ abstract class ExchangeStoreBase with Store { ExchangeProvider _providerForPair({CryptoCurrency from, CryptoCurrency to}) { final providers = _providersForPair(from: from, to: to); - return providers.length > 0 ? providers[0] : null; + return providers.isNotEmpty ? providers[0] : null; } void validateAddress(String value, {CryptoCurrency cryptoCurrency}) { // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34) - String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); + if (isValid && cryptoCurrency != null) { switch (cryptoCurrency.toString()) { case 'XMR': @@ -254,12 +252,13 @@ abstract class ExchangeStoreBase with Store { isValid = (value.length == 34); } } + errorMessage = isValid ? null : S.current.error_text_address; } void validateCryptoCurrency(String value) { - String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$'; - RegExp regExp = new RegExp(p); + const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_crypto_currency; } diff --git a/lib/src/stores/exchange/exchange_trade_state.dart b/lib/src/stores/exchange/exchange_trade_state.dart index eb171ca28..1f9eecad1 100644 --- a/lib/src/stores/exchange/exchange_trade_state.dart +++ b/lib/src/stores/exchange/exchange_trade_state.dart @@ -8,13 +8,13 @@ class ExchangeTradeStateInitial extends ExchangeTradeState {} class TradeIsCreating extends ExchangeTradeState {} class TradeIsCreatedSuccessfully extends ExchangeTradeState { - final Trade trade; - TradeIsCreatedSuccessfully({@required this.trade}); + + final Trade trade; } class TradeIsCreatedFailure extends ExchangeTradeState { - final String error; - TradeIsCreatedFailure({@required this.error}); + + final String error; } \ No newline at end of file diff --git a/lib/src/stores/exchange/limits_state.dart b/lib/src/stores/exchange/limits_state.dart index 3ca340c1b..ccc5934d8 100644 --- a/lib/src/stores/exchange/limits_state.dart +++ b/lib/src/stores/exchange/limits_state.dart @@ -8,13 +8,13 @@ class LimitsInitialState extends LimitsState {} class LimitsIsLoading extends LimitsState {} class LimitsLoadedSuccessfully extends LimitsState { - final Limits limits; - LimitsLoadedSuccessfully({@required this.limits}); + + final Limits limits; } class LimitsLoadedFailure extends LimitsState { - final String error; - LimitsLoadedFailure({@required this.error}); + + final String error; } diff --git a/lib/src/stores/exchange_trade/exchange_trade_store.dart b/lib/src/stores/exchange_trade/exchange_trade_store.dart index 5876acd7b..6e6cb2536 100644 --- a/lib/src/stores/exchange_trade/exchange_trade_store.dart +++ b/lib/src/stores/exchange_trade/exchange_trade_store.dart @@ -13,6 +13,24 @@ part 'exchange_trade_store.g.dart'; class ExchangeTradeStore = ExchangeTradeStoreBase with _$ExchangeTradeStore; abstract class ExchangeTradeStoreBase with Store { + ExchangeTradeStoreBase( + {@required this.trade, @required WalletStore walletStore}) { + isSendable = trade.from == walletStore.type || + trade.provider == ExchangeProviderDescription.xmrto; + + switch (trade.provider) { + case ExchangeProviderDescription.xmrto: + _provider = XMRTOExchangeProvider(); + break; + case ExchangeProviderDescription.changeNow: + _provider = ChangeNowExchangeProvider(); + break; + } + + _updateTrade(); + _timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); + } + @observable Trade trade; @@ -23,36 +41,20 @@ abstract class ExchangeTradeStoreBase with Store { Timer _timer; - ExchangeTradeStoreBase({@required this.trade, @required WalletStore walletStore}) { - isSendable = trade.from == walletStore.type || trade.provider == ExchangeProviderDescription.xmrto; - - switch (trade.provider) { - case ExchangeProviderDescription.xmrto: - _provider = XMRTOExchangeProvider(); - break; - case ExchangeProviderDescription.changeNow: - _provider = ChangeNowExchangeProvider(); - break; - } - - _updateTrade(); - _timer = Timer.periodic(Duration(seconds: 20), (_) async => _updateTrade()); - } - @override void dispose() { super.dispose(); - + if (_timer != null) { _timer.cancel(); } } @action - Future _updateTrade() async { + Future _updateTrade() async { try { final updatedTrade = await _provider.findTradeById(id: trade.id); - + if (updatedTrade.createdAt == null && trade.createdAt != null) { updatedTrade.createdAt = trade.createdAt; } diff --git a/lib/src/stores/login/login_store.dart b/lib/src/stores/login/login_store.dart index 20e26b815..cd1756ccf 100644 --- a/lib/src/stores/login/login_store.dart +++ b/lib/src/stores/login/login_store.dart @@ -14,25 +14,25 @@ class LoadingCurrentWallet extends LoginState {} class LoadedCurrentWalletSuccessfully extends LoginState {} class LoadedCurrentWalletFailure extends LoginState { - final String errorMessage; - LoadedCurrentWalletFailure({this.errorMessage}); + + final String errorMessage; } class LoginStore = LoginStoreBase with _$LoginStore; abstract class LoginStoreBase with Store { + LoginStoreBase( + {@required this.sharedPreferences, @required this.walletsService}) { + state = InitialLoginState(); + } + final SharedPreferences sharedPreferences; final WalletListService walletsService; @observable LoginState state; - LoginStoreBase( - {@required this.sharedPreferences, @required this.walletsService}) { - state = InitialLoginState(); - } - @action Future loadCurrentWallet() async { state = InitialLoginState(); diff --git a/lib/src/stores/node_list/node_list_store.dart b/lib/src/stores/node_list/node_list_store.dart index 45b4546ef..4565c394d 100644 --- a/lib/src/stores/node_list/node_list_store.dart +++ b/lib/src/stores/node_list/node_list_store.dart @@ -10,6 +10,12 @@ part 'node_list_store.g.dart'; class NodeListStore = NodeListBase with _$NodeListStore; abstract class NodeListBase with Store { + NodeListBase({this.nodesSource}) { + nodes = ObservableList(); + _onNodesChangeSubscription = nodesSource.watch().listen((e) => update()); + update(); + } + @observable ObservableList nodes; @@ -23,12 +29,6 @@ abstract class NodeListBase with Store { StreamSubscription _onNodesChangeSubscription; - NodeListBase({this.nodesSource}) { - nodes = ObservableList(); - _onNodesChangeSubscription = nodesSource.watch().listen((e) => update()); - update(); - } - @override void dispose() { super.dispose(); @@ -39,7 +39,7 @@ abstract class NodeListBase with Store { } @action - update() async => + void update() => nodes.replaceRange(0, nodes.length, nodesSource.values.toList()); @action @@ -71,25 +71,28 @@ abstract class NodeListBase with Store { } void validateNodeAddress(String value) { - String p = + const pattern = '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\$'; - RegExp regExp = new RegExp(p); + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_node_address; } void validateNodePort(String value) { - String p = '^[0-9]{1,5}'; - RegExp regExp = new RegExp(p); + const pattern = '^[0-9]{1,5}'; + final regExp = RegExp(pattern); + if (regExp.hasMatch(value)) { try { - int intValue = int.parse(value); + final intValue = int.parse(value); isValid = (intValue >= 0 && intValue <= 65535); } catch (e) { isValid = false; } - } else + } else { isValid = false; + } + errorMessage = isValid ? null : S.current.error_text_node_port; } } diff --git a/lib/src/stores/price/price_store.dart b/lib/src/stores/price/price_store.dart index 631eca42b..f1db0771a 100644 --- a/lib/src/stores/price/price_store.dart +++ b/lib/src/stores/price/price_store.dart @@ -8,6 +8,8 @@ part 'price_store.g.dart'; class PriceStore = PriceStoreBase with _$PriceStore; abstract class PriceStoreBase with Store { + PriceStoreBase() : prices = ObservableMap(); + static String generateSymbolForPair( {FiatCurrency fiat, CryptoCurrency crypto}) => crypto.toString().toUpperCase() + fiat.toString().toUpperCase(); @@ -15,8 +17,6 @@ abstract class PriceStoreBase with Store { @observable ObservableMap prices; - PriceStoreBase() : prices = ObservableMap(); - @action Future updatePrice({FiatCurrency fiat, CryptoCurrency crypto}) async { final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto); @@ -25,7 +25,8 @@ abstract class PriceStoreBase with Store { } @action - changePriceForPair({FiatCurrency fiat, CryptoCurrency crypto, double price}) { + void changePriceForPair( + {FiatCurrency fiat, CryptoCurrency crypto, double price}) { final symbol = generateSymbolForPair(fiat: fiat, crypto: crypto); prices[symbol] = price; } diff --git a/lib/src/stores/rescan/rescan_wallet_store.dart b/lib/src/stores/rescan/rescan_wallet_store.dart index a2c440405..0231fa300 100644 --- a/lib/src/stores/rescan/rescan_wallet_store.dart +++ b/lib/src/stores/rescan/rescan_wallet_store.dart @@ -6,21 +6,19 @@ part 'rescan_wallet_store.g.dart'; class RescanWalletStore = RescanWalletStoreBase with _$RescanWalletStore; -enum RescanWalletState { - rescaning, none -} +enum RescanWalletState { rescaning, none } abstract class RescanWalletStoreBase with Store { - @observable - RescanWalletState state; - - WalletService _walletService; - RescanWalletStoreBase({@required WalletService walletService}) { _walletService = walletService; state = RescanWalletState.none; } + @observable + RescanWalletState state; + + WalletService _walletService; + @action Future rescanCurrentWallet({int restoreHeight}) async { state = RescanWalletState.rescaning; diff --git a/lib/src/stores/send/send_store.dart b/lib/src/stores/send/send_store.dart index bb45af0d8..130efa8c4 100644 --- a/lib/src/stores/send/send_store.dart +++ b/lib/src/stores/send/send_store.dart @@ -17,6 +17,23 @@ part 'send_store.g.dart'; class SendStore = SendStoreBase with _$SendStore; abstract class SendStoreBase with Store { + SendStoreBase( + {@required this.walletService, + this.settingsStore, + this.transactionDescriptions, + this.priceStore}) { + state = SendingStateInitial(); + _pendingTransaction = null; + _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12; + _fiatNumberFormat = NumberFormat()..maximumFractionDigits = 2; + + reaction((_) => this.state, (SendingState state) async { + if (state is TransactionCreatedSuccessfully) { + await commitTransaction(); + } + }); + } + WalletService walletService; SettingsStore settingsStore; PriceStore priceStore; @@ -43,23 +60,6 @@ abstract class SendStoreBase with Store { NumberFormat _fiatNumberFormat; String _lastRecipientAddress; - SendStoreBase( - {@required this.walletService, - this.settingsStore, - this.transactionDescriptions, - this.priceStore}) { - state = SendingStateInitial(); - _pendingTransaction = null; - _cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12; - _fiatNumberFormat = NumberFormat()..maximumFractionDigits = 2; - - reaction((_) => this.state, (state) async { - if (state is TransactionCreatedSuccessfully) { - commitTransaction(); - } - }); - } - @action Future createTransaction( {String address, String paymentId, String amount}) async { @@ -160,9 +160,10 @@ abstract class SendStoreBase with Store { void validateAddress(String value, {CryptoCurrency cryptoCurrency}) { // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34) - String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; + final regExp = RegExp(pattern); isValid = value == null ? false : regExp.hasMatch(value); + if (isValid && cryptoCurrency != null) { switch (cryptoCurrency.toString()) { case 'XMR': @@ -184,6 +185,7 @@ abstract class SendStoreBase with Store { isValid = (value.length == 34); } } + errorMessage = isValid ? null : S.current.error_text_address; } @@ -191,52 +193,60 @@ abstract class SendStoreBase with Store { if (value.isEmpty) { isValid = true; } else { - String p = '^[A-Fa-f0-9]{16,64}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[A-Fa-f0-9]{16,64}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); } + errorMessage = isValid ? null : S.current.error_text_payment_id; } void validateXMR(String value, String availableBalance) { const double maxValue = 18446744.073709551616; - String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$|ALL'; - RegExp regExp = new RegExp(p); + const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$|ALL'; + final regExp = RegExp(pattern); + if (regExp.hasMatch(value)) { - if (value == 'ALL') + if (value == 'ALL') { isValid = true; - else { + } else { try { - double dValue = double.parse(value); - double maxAvailable = double.parse(availableBalance); + final dValue = double.parse(value); + final maxAvailable = double.parse(availableBalance); isValid = (dValue <= maxAvailable && dValue <= maxValue && dValue > 0); } catch (e) { isValid = false; } } - } else + } else { isValid = false; + } + errorMessage = isValid ? null : S.current.error_text_xmr; } void validateFiat(String value, {double maxValue}) { const double minValue = 0.01; - if (value.isEmpty && cryptoAmount == 'ALL') + + if (value.isEmpty && cryptoAmount == 'ALL') { isValid = true; - else { - String p = '^([0-9]+([.][0-9]{0,2})?|[.][0-9]{1,2})\$'; - RegExp regExp = new RegExp(p); + } else { + const pattern = '^([0-9]+([.][0-9]{0,2})?|[.][0-9]{1,2})\$'; + final regExp = RegExp(pattern); + if (regExp.hasMatch(value)) { try { - double dValue = double.parse(value); + final dValue = double.parse(value); isValid = (dValue >= minValue && dValue <= maxValue); } catch (e) { isValid = false; } - } else + } else { isValid = false; + } } + errorMessage = isValid ? null : "Value of amount can't exceed available balance.\n" diff --git a/lib/src/stores/send/sending_state.dart b/lib/src/stores/send/sending_state.dart index f9d121e7e..c584049c4 100644 --- a/lib/src/stores/send/sending_state.dart +++ b/lib/src/stores/send/sending_state.dart @@ -13,7 +13,7 @@ class TransactionCommiting extends SendingState {} class TransactionCommitted extends SendingState {} class SendingFailed extends SendingState { - String error; - SendingFailed({@required this.error}); + + String error; } diff --git a/lib/src/stores/settings/settings_store.dart b/lib/src/stores/settings/settings_store.dart index 06b961e0a..4ade305bb 100644 --- a/lib/src/stores/settings/settings_store.dart +++ b/lib/src/stores/settings/settings_store.dart @@ -17,6 +17,36 @@ part 'settings_store.g.dart'; class SettingsStore = SettingsStoreBase with _$SettingsStore; abstract class SettingsStoreBase with Store { + SettingsStoreBase( + {@required SharedPreferences sharedPreferences, + @required Box nodes, + @required FiatCurrency initialFiatCurrency, + @required TransactionPriority initialTransactionPriority, + @required BalanceDisplayMode initialBalanceDisplayMode, + @required bool initialSaveRecipientAddress, + @required bool initialAllowBiometricalAuthentication, + @required bool initialDarkTheme, + this.actionlistDisplayMode, + @required int initialPinLength, + @required String initialLanguageCode}) { + fiatCurrency = initialFiatCurrency; + transactionPriority = initialTransactionPriority; + balanceDisplayMode = initialBalanceDisplayMode; + shouldSaveRecipientAddress = initialSaveRecipientAddress; + _sharedPreferences = sharedPreferences; + _nodes = nodes; + allowBiometricalAuthentication = initialAllowBiometricalAuthentication; + isDarkTheme = initialDarkTheme; + defaultPinLength = initialPinLength; + languageCode = initialLanguageCode; + itemHeaders = Map(); + + actionlistDisplayMode.observe( + (dynamic _) => _sharedPreferences.setInt(displayActionListModeKey, + serializeActionlistDisplayModes(actionlistDisplayMode)), + fireImmediately: false); + } + static const currentNodeIdKey = 'current_node_id'; static const currentFiatCurrencyKey = 'current_fiat_currency'; static const currentTransactionPriorityKey = 'current_fee_priority'; @@ -113,36 +143,6 @@ abstract class SettingsStoreBase with Store { SharedPreferences _sharedPreferences; Box _nodes; - SettingsStoreBase( - {@required SharedPreferences sharedPreferences, - @required Box nodes, - @required FiatCurrency initialFiatCurrency, - @required TransactionPriority initialTransactionPriority, - @required BalanceDisplayMode initialBalanceDisplayMode, - @required bool initialSaveRecipientAddress, - @required bool initialAllowBiometricalAuthentication, - @required bool initialDarkTheme, - this.actionlistDisplayMode, - @required int initialPinLength, - @required String initialLanguageCode}) { - fiatCurrency = initialFiatCurrency; - transactionPriority = initialTransactionPriority; - balanceDisplayMode = initialBalanceDisplayMode; - shouldSaveRecipientAddress = initialSaveRecipientAddress; - _sharedPreferences = sharedPreferences; - _nodes = nodes; - allowBiometricalAuthentication = initialAllowBiometricalAuthentication; - isDarkTheme = initialDarkTheme; - defaultPinLength = initialPinLength; - languageCode = initialLanguageCode; - itemHeaders = Map(); - - actionlistDisplayMode.observe( - (dynamic _) => _sharedPreferences.setInt(displayActionListModeKey, - serializeActionlistDisplayModes(actionlistDisplayMode)), - fireImmediately: false); - } - @action Future setAllowBiometricalAuthentication( {@required bool allowBiometricalAuthentication}) async { @@ -168,7 +168,7 @@ abstract class SettingsStoreBase with Store { @action Future setCurrentNode({@required Node node}) async { this.node = node; - await _sharedPreferences.setInt(currentNodeIdKey, node.key); + await _sharedPreferences.setInt(currentNodeIdKey, node.key as int); } @action @@ -203,7 +203,7 @@ abstract class SettingsStoreBase with Store { } Future loadSettings() async => node = await _fetchCurrentNode(); - + @action void toggleTransactionsDisplay() => actionlistDisplayMode.contains(ActionListDisplayMode.transactions) @@ -239,7 +239,7 @@ abstract class SettingsStoreBase with Store { Future _fetchCurrentNode() async { final id = _sharedPreferences.getInt(currentNodeIdKey); - + return _nodes.get(id); } diff --git a/lib/src/stores/subaddress_creation/subaddress_creation_state.dart b/lib/src/stores/subaddress_creation/subaddress_creation_state.dart index b0ba84327..0d8adaae2 100644 --- a/lib/src/stores/subaddress_creation/subaddress_creation_state.dart +++ b/lib/src/stores/subaddress_creation/subaddress_creation_state.dart @@ -7,7 +7,7 @@ class SubaddressIsCreating extends SubaddressCreationState {} class SubaddressCreatedSuccessfully extends SubaddressCreationState {} class SubaddressCreationFailure extends SubaddressCreationState { - String error; - SubaddressCreationFailure({this.error}); + + String error; } \ No newline at end of file diff --git a/lib/src/stores/subaddress_creation/subaddress_creation_store.dart b/lib/src/stores/subaddress_creation/subaddress_creation_store.dart index 3edc71de7..0314e9ac9 100644 --- a/lib/src/stores/subaddress_creation/subaddress_creation_store.dart +++ b/lib/src/stores/subaddress_creation/subaddress_creation_store.dart @@ -15,6 +15,17 @@ class SubadrressCreationStore = SubadrressCreationStoreBase with _$SubadrressCreationStore; abstract class SubadrressCreationStoreBase with Store { + SubadrressCreationStoreBase({@required WalletService walletService}) { + state = SubaddressCreationStateInitial(); + + if (walletService.currentWallet != null) { + _onWalletChanged(walletService.currentWallet); + } + + _onWalletChangeSubscription = + walletService.onWalletChange.listen(_onWalletChanged); + } + SubaddressCreationState state; @observable @@ -28,17 +39,6 @@ abstract class SubadrressCreationStoreBase with Store { StreamSubscription _onAccountChangeSubscription; Account _account; - SubadrressCreationStoreBase({@required WalletService walletService}) { - state = SubaddressCreationStateInitial(); - - if (walletService.currentWallet != null) { - _onWalletChanged(walletService.currentWallet); - } - - _onWalletChangeSubscription = - walletService.onWalletChange.listen(_onWalletChanged); - } - @override void dispose() { _onWalletChangeSubscription.cancel(); @@ -50,7 +50,7 @@ abstract class SubadrressCreationStoreBase with Store { super.dispose(); } - Future add({String label}) async { + Future add({String label}) async { try { state = SubaddressIsCreating(); await _subaddressList.addSubaddress( @@ -61,14 +61,15 @@ abstract class SubadrressCreationStoreBase with Store { } } - Future _onWalletChanged(Wallet wallet) async { + Future _onWalletChanged(Wallet wallet) async { if (wallet is MoneroWallet) { _account = wallet.account; _subaddressList = wallet.getSubaddress(); - _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async { + _onAccountChangeSubscription = + wallet.onAccountChange.listen((account) async { _account = account; - _subaddressList.update(accountIndex: account.id); + await _subaddressList.update(accountIndex: account.id); }); return; } @@ -77,8 +78,8 @@ abstract class SubadrressCreationStoreBase with Store { } void validateSubaddressName(String value) { - String p = '''^[^`,'"]{1,20}\$'''; - RegExp regExp = new RegExp(p); + const pattern = '''^[^`,'"]{1,20}\$'''; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_subaddress_name; } diff --git a/lib/src/stores/subaddress_list/subaddress_list_store.dart b/lib/src/stores/subaddress_list/subaddress_list_store.dart index 9a4154226..b9e6dbe59 100644 --- a/lib/src/stores/subaddress_list/subaddress_list_store.dart +++ b/lib/src/stores/subaddress_list/subaddress_list_store.dart @@ -13,15 +13,6 @@ part 'subaddress_list_store.g.dart'; class SubaddressListStore = SubaddressListStoreBase with _$SubaddressListStore; abstract class SubaddressListStoreBase with Store { - @observable - ObservableList subaddresses; - - SubaddressList _subaddressList; - StreamSubscription _onWalletChangeSubscription; - StreamSubscription> _onSubaddressesChangeSubscription; - StreamSubscription _onAccountChangeSubscription; - Account _account; - SubaddressListStoreBase({@required WalletService walletService}) { subaddresses = ObservableList(); @@ -33,6 +24,15 @@ abstract class SubaddressListStoreBase with Store { walletService.onWalletChange.listen(_onWalletChanged); } + @observable + ObservableList subaddresses; + + SubaddressList _subaddressList; + StreamSubscription _onWalletChangeSubscription; + StreamSubscription> _onSubaddressesChangeSubscription; + StreamSubscription _onAccountChangeSubscription; + Account _account; + @override void dispose() { if (_onSubaddressesChangeSubscription != null) { @@ -47,14 +47,14 @@ abstract class SubaddressListStoreBase with Store { super.dispose(); } - Future _updateSubaddressList({int accountIndex}) async { + Future _updateSubaddressList({int accountIndex}) async { await _subaddressList.refresh(accountIndex: accountIndex); subaddresses = ObservableList.of(_subaddressList.getAll()); } - Future _onWalletChanged(Wallet wallet) async { + Future _onWalletChanged(Wallet wallet) async { if (_onSubaddressesChangeSubscription != null) { - _onSubaddressesChangeSubscription.cancel(); + await _onSubaddressesChangeSubscription.cancel(); } if (wallet is MoneroWallet) { @@ -64,7 +64,8 @@ abstract class SubaddressListStoreBase with Store { .listen((subaddress) => subaddresses = ObservableList.of(subaddress)); await _updateSubaddressList(accountIndex: _account.id); - _onAccountChangeSubscription = wallet.onAccountChange.listen((account) async { + _onAccountChangeSubscription = + wallet.onAccountChange.listen((account) async { _account = account; await _updateSubaddressList(accountIndex: account.id); }); diff --git a/lib/src/stores/sync/sync_store.dart b/lib/src/stores/sync/sync_store.dart index 6c19b4247..bf2bdbbf3 100644 --- a/lib/src/stores/sync/sync_store.dart +++ b/lib/src/stores/sync/sync_store.dart @@ -10,12 +10,6 @@ part 'sync_store.g.dart'; class SyncStore = SyncStoreBase with _$SyncStore; abstract class SyncStoreBase with Store { - @observable - SyncStatus status; - - StreamSubscription _onWalletChangeSubscription; - StreamSubscription _onSyncStatusChangeSubscription; - SyncStoreBase( {SyncStatus syncStatus = const NotConnectedSyncStatus(), @required WalletService walletService}) { @@ -29,6 +23,12 @@ abstract class SyncStoreBase with Store { walletService.onWalletChange.listen(_onWalletChanged); } + @observable + SyncStatus status; + + StreamSubscription _onWalletChangeSubscription; + StreamSubscription _onSyncStatusChangeSubscription; + @override void dispose() { if (_onSyncStatusChangeSubscription != null) { diff --git a/lib/src/stores/user/user_store.dart b/lib/src/stores/user/user_store.dart index 42f62e4b0..2b9369d59 100644 --- a/lib/src/stores/user/user_store.dart +++ b/lib/src/stores/user/user_store.dart @@ -8,6 +8,8 @@ part 'user_store.g.dart'; class UserStore = UserStoreBase with _$UserStore; abstract class UserStoreBase with Store { + UserStoreBase({@required this.accountService}); + UserService accountService; @observable @@ -16,17 +18,15 @@ abstract class UserStoreBase with Store { @observable String errorMessage; - UserStoreBase({@required this.accountService}); - @action Future set({String password}) async { state = UserStoreStateInitial(); try { - await accountService.setPassword(password); - state = PinCodeSetSuccesfully(); - } catch(e) { - state = PinCodeSetFailed(error: e.toString()); - } + await accountService.setPassword(password); + state = PinCodeSetSuccesfully(); + } catch (e) { + state = PinCodeSetFailed(error: e.toString()); + } } } diff --git a/lib/src/stores/user/user_store_state.dart b/lib/src/stores/user/user_store_state.dart index 663c0fd60..1b82200c4 100644 --- a/lib/src/stores/user/user_store_state.dart +++ b/lib/src/stores/user/user_store_state.dart @@ -7,7 +7,7 @@ class UserStoreStateInitial extends UserStoreState {} class PinCodeSetSuccesfully extends UserStoreState {} class PinCodeSetFailed extends UserStoreState { - String error; - PinCodeSetFailed({@required this.error}); + + String error; } diff --git a/lib/src/stores/wallet/wallet_keys_store.dart b/lib/src/stores/wallet/wallet_keys_store.dart index 4d76dc638..be380e29b 100644 --- a/lib/src/stores/wallet/wallet_keys_store.dart +++ b/lib/src/stores/wallet/wallet_keys_store.dart @@ -7,18 +7,6 @@ part 'wallet_keys_store.g.dart'; class WalletKeysStore = WalletKeysStoreBase with _$WalletKeysStore; abstract class WalletKeysStoreBase with Store { - @observable - String publicViewKey; - - @observable - String privateViewKey; - - @observable - String publicSpendKey; - - @observable - String privateSpendKey; - WalletKeysStoreBase({@required WalletService walletService}) { publicViewKey = ''; privateViewKey = ''; @@ -34,4 +22,16 @@ abstract class WalletKeysStoreBase with Store { }); } } + + @observable + String publicViewKey; + + @observable + String privateViewKey; + + @observable + String publicSpendKey; + + @observable + String privateSpendKey; } diff --git a/lib/src/stores/wallet/wallet_store.dart b/lib/src/stores/wallet/wallet_store.dart index 054e1545b..9e2f4e88d 100644 --- a/lib/src/stores/wallet/wallet_store.dart +++ b/lib/src/stores/wallet/wallet_store.dart @@ -15,6 +15,21 @@ part 'wallet_store.g.dart'; class WalletStore = WalletStoreBase with _$WalletStore; abstract class WalletStoreBase with Store { + WalletStoreBase({WalletService walletService, SettingsStore settingsStore}) { + _walletService = walletService; + _settingsStore = settingsStore; + name = ''; + type = CryptoCurrency.xmr; + amountValue = ''; + + if (_walletService.currentWallet != null) { + _onWalletChanged(_walletService.currentWallet); + } + + _onWalletChangeSubscription = _walletService.onWalletChange + .listen((wallet) async => await _onWalletChanged(wallet)); + } + @observable String address; @@ -47,22 +62,6 @@ abstract class WalletStoreBase with Store { StreamSubscription _onAccountChangeSubscription; StreamSubscription _onSubaddressChangeSubscription; - - WalletStoreBase({WalletService walletService, SettingsStore settingsStore}) { - _walletService = walletService; - _settingsStore = settingsStore; - name = ''; - type = CryptoCurrency.xmr; - amountValue = ''; - - if (_walletService.currentWallet != null) { - _onWalletChanged(_walletService.currentWallet); - } - - _onWalletChangeSubscription = _walletService.onWalletChange - .listen((wallet) async => await _onWalletChanged(wallet)); - } - @override void dispose() { if (_onWalletChangeSubscription != null) { @@ -112,7 +111,8 @@ abstract class WalletStoreBase with Store { Future startSync() async => await _walletService.startSync(); @action - Future connectToNode({Node node}) async => await _walletService.connectToNode(node: node); + Future connectToNode({Node node}) async => + await _walletService.connectToNode(node: node); Future _onWalletChanged(Wallet wallet) async { if (this == null) { @@ -123,15 +123,16 @@ abstract class WalletStoreBase with Store { wallet.onAddressChange.listen((address) => this.address = address); if (wallet is MoneroWallet) { - _onAccountChangeSubscription = wallet.onAccountChange.listen((account) => this.account = account); - _onSubaddressChangeSubscription = wallet.subaddress.listen((subaddress) => this.subaddress = subaddress); + _onAccountChangeSubscription = + wallet.onAccountChange.listen((account) => this.account = account); + _onSubaddressChangeSubscription = wallet.subaddress + .listen((subaddress) => this.subaddress = subaddress); } } @action - onChangedAmountValue(String value) { - amountValue = value.isNotEmpty ? '?tx_amount=' + value : ''; - } + void onChangedAmountValue(String value) => + amountValue = value.isNotEmpty ? '?tx_amount=' + value : ''; @action void validateAmount(String value) { @@ -140,16 +141,19 @@ abstract class WalletStoreBase with Store { if (value.isEmpty) { isValid = true; } else { - String p = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$'; - RegExp regExp = new RegExp(p); + const pattern = '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$'; + final regExp = RegExp(pattern); + if (regExp.hasMatch(value)) { try { - double dValue = double.parse(value); + final dValue = double.parse(value); isValid = dValue <= maxValue; } catch (e) { isValid = false; } - } else isValid = false; + } else { + isValid = false; + } } errorMessage = isValid ? null : S.current.error_text_amount; diff --git a/lib/src/stores/wallet_creation/wallet_creation_state.dart b/lib/src/stores/wallet_creation/wallet_creation_state.dart index f29c40100..43223a1d0 100644 --- a/lib/src/stores/wallet_creation/wallet_creation_state.dart +++ b/lib/src/stores/wallet_creation/wallet_creation_state.dart @@ -9,6 +9,7 @@ class WalletIsCreating extends WalletCreationState {} class WalletCreatedSuccessfully extends WalletCreationState {} class WalletCreationFailure extends WalletCreationState { - String error; WalletCreationFailure({@required this.error}); + + String error; } \ No newline at end of file diff --git a/lib/src/stores/wallet_creation/wallet_creation_store.dart b/lib/src/stores/wallet_creation/wallet_creation_store.dart index 3732b5f27..942603f0a 100644 --- a/lib/src/stores/wallet_creation/wallet_creation_store.dart +++ b/lib/src/stores/wallet_creation/wallet_creation_store.dart @@ -11,6 +11,13 @@ part 'wallet_creation_store.g.dart'; class WalletCreationStore = WalletCreationStoreBase with _$WalletCreationStore; abstract class WalletCreationStoreBase with Store { + WalletCreationStoreBase( + {@required this.authStore, + @required this.walletListService, + @required this.sharedPreferences}) { + state = WalletCreationStateInitial(); + } + final AuthenticationStore authStore; final WalletListService walletListService; final SharedPreferences sharedPreferences; @@ -24,13 +31,6 @@ abstract class WalletCreationStoreBase with Store { @observable bool isValid; - WalletCreationStoreBase( - {@required this.authStore, - @required this.walletListService, - @required this.sharedPreferences}) { - state = WalletCreationStateInitial(); - } - @action Future create({String name}) async { state = WalletCreationStateInitial(); @@ -46,8 +46,8 @@ abstract class WalletCreationStoreBase with Store { } void validateWalletName(String value) { - String p = '^[a-zA-Z0-9_]{1,15}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[a-zA-Z0-9_]{1,15}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_wallet_name; } diff --git a/lib/src/stores/wallet_list/wallet_list_store.dart b/lib/src/stores/wallet_list/wallet_list_store.dart index ee0165d89..2f83a57d2 100644 --- a/lib/src/stores/wallet_list/wallet_list_store.dart +++ b/lib/src/stores/wallet_list/wallet_list_store.dart @@ -9,12 +9,6 @@ part 'wallet_list_store.g.dart'; class WalletListStore = WalletListStoreBase with _$WalletListStore; abstract class WalletListStoreBase with Store { - @observable - List wallets; - - WalletListService _walletListService; - WalletService _walletService; - WalletListStoreBase( {@required WalletListService walletListService, @required WalletService walletService}) { @@ -24,22 +18,27 @@ abstract class WalletListStoreBase with Store { walletListService.getAll().then((walletList) => wallets = walletList); } - bool isCurrentWallet(WalletDescription wallet) { - return _walletService.description?.name == wallet.name; - } + @observable + List wallets; + + WalletListService _walletListService; + WalletService _walletService; + + bool isCurrentWallet(WalletDescription wallet) => + _walletService.description?.name == wallet.name; @action - Future updateWalletList() async { + Future updateWalletList() async { wallets = await _walletListService.getAll(); } @action - Future loadWallet(WalletDescription wallet) async { + Future loadWallet(WalletDescription wallet) async { await _walletListService.openWallet(wallet.name); } @action - Future remove(WalletDescription wallet) async { + Future remove(WalletDescription wallet) async { await _walletListService.remove(wallet); await updateWalletList(); } diff --git a/lib/src/stores/wallet_restoration/wallet_restoration_state.dart b/lib/src/stores/wallet_restoration/wallet_restoration_state.dart index 6597574e7..afd6649e9 100644 --- a/lib/src/stores/wallet_restoration/wallet_restoration_state.dart +++ b/lib/src/stores/wallet_restoration/wallet_restoration_state.dart @@ -9,6 +9,7 @@ class WalletIsRestoring extends WalletRestorationState {} class WalletRestoredSuccessfully extends WalletRestorationState {} class WalletRestorationFailure extends WalletRestorationState { - String error; WalletRestorationFailure({@required this.error}); -} \ No newline at end of file + + String error; +} diff --git a/lib/src/stores/wallet_restoration/wallet_restoration_store.dart b/lib/src/stores/wallet_restoration/wallet_restoration_store.dart index a351c22d7..968e14b85 100644 --- a/lib/src/stores/wallet_restoration/wallet_restoration_store.dart +++ b/lib/src/stores/wallet_restoration/wallet_restoration_store.dart @@ -14,6 +14,14 @@ class WalletRestorationStore = WalleRestorationStoreBase with _$WalletRestorationStore; abstract class WalleRestorationStoreBase with Store { + WalleRestorationStoreBase( + {this.seed, + @required this.authStore, + @required this.walletListService, + @required this.sharedPreferences}) { + state = WalletRestorationStateInitial(); + } + final AuthenticationStore authStore; final WalletListService walletListService; final SharedPreferences sharedPreferences; @@ -30,14 +38,6 @@ abstract class WalleRestorationStoreBase with Store { @observable List seed; - WalleRestorationStoreBase( - {this.seed, - @required this.authStore, - @required this.walletListService, - @required this.sharedPreferences}) { - state = WalletRestorationStateInitial(); - } - @action Future restoreFromSeed({String name, String seed, int restoreHeight}) async { state = WalletRestorationStateInitial(); @@ -110,17 +110,18 @@ abstract class WalleRestorationStoreBase with Store { } void validateWalletName(String value) { - String p = '^[a-zA-Z0-9_]{1,15}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[a-zA-Z0-9_]{1,15}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_wallet_name; } void validateAddress(String value, {CryptoCurrency cryptoCurrency}) { // XMR (95), BTC (34), ETH (42), LTC (34), BCH (42), DASH (34) - String p = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[0-9a-zA-Z]{95}\$|^[0-9a-zA-Z]{34}\$|^[0-9a-zA-Z]{42}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); + if (isValid && cryptoCurrency != null) { switch (cryptoCurrency.toString()) { case 'XMR': @@ -142,12 +143,13 @@ abstract class WalleRestorationStoreBase with Store { isValid = (value.length == 34); } } + errorMessage = isValid ? null : S.current.error_text_address; } void validateKeys(String value) { - String p = '^[A-Fa-f0-9]{64}\$'; - RegExp regExp = new RegExp(p); + const pattern = '^[A-Fa-f0-9]{64}\$'; + final regExp = RegExp(pattern); isValid = regExp.hasMatch(value); errorMessage = isValid ? null : S.current.error_text_keys; } diff --git a/lib/src/stores/wallet_seed/wallet_seed_store.dart b/lib/src/stores/wallet_seed/wallet_seed_store.dart index f3ac71d58..833985d5b 100644 --- a/lib/src/stores/wallet_seed/wallet_seed_store.dart +++ b/lib/src/stores/wallet_seed/wallet_seed_store.dart @@ -7,12 +7,6 @@ part 'wallet_seed_store.g.dart'; class WalletSeedStore = WalletSeedStoreBase with _$WalletSeedStore; abstract class WalletSeedStoreBase with Store { - @observable - String name; - - @observable - String seed; - WalletSeedStoreBase({@required WalletService walletService}) { seed = ''; @@ -21,4 +15,10 @@ abstract class WalletSeedStoreBase with Store { walletService.getName().then((name) => this.name = name); } } + + @observable + String name; + + @observable + String seed; } diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 060b8c760..c457ee485 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -9,17 +9,6 @@ import 'package:cake_wallet/src/domain/common/qr_scanner.dart'; enum AddressTextFieldOption { qrCode, addressBook, subaddressList } class AddressTextField extends StatelessWidget { - static const prefixIconWidth = 34.0; - static const prefixIconHeight = 34.0; - static const spaceBetweenPrefixIcons = 10.0; - - final TextEditingController controller; - final bool isActive; - final String placeholder; - final Function(Uri) onURIScanned; - final List options; - final FormFieldValidator validator; - AddressTextField( {@required this.controller, this.isActive = true, @@ -31,6 +20,17 @@ class AddressTextField extends StatelessWidget { this.onURIScanned, this.validator}); + static const prefixIconWidth = 34.0; + static const prefixIconHeight = 34.0; + static const spaceBetweenPrefixIcons = 10.0; + + final TextEditingController controller; + final bool isActive; + final String placeholder; + final Function(Uri) onURIScanned; + final List options; + final FormFieldValidator validator; + @override Widget build(BuildContext context) { return TextFormField( @@ -105,8 +105,7 @@ class AddressTextField extends StatelessWidget { hintStyle: TextStyle(color: Theme.of(context).hintColor), hintText: placeholder ?? S.current.widgets_address, focusedBorder: UnderlineInputBorder( - borderSide: - BorderSide(color: Palette.cakeGreen, width: 2.0)), + borderSide: BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Theme.of(context).focusColor, width: 1.0)), @@ -115,10 +114,10 @@ class AddressTextField extends StatelessWidget { ); } - Future _presentQRScanner(BuildContext context) async { + Future _presentQRScanner(BuildContext context) async { try { - String code = await presentQRScanner(); - var uri = Uri.parse(code); + final code = await presentQRScanner(); + final uri = Uri.parse(code); var address = ''; if (uri == null) { @@ -137,7 +136,7 @@ class AddressTextField extends StatelessWidget { } } - Future _presetAddressBookPicker(BuildContext context) async { + Future _presetAddressBookPicker(BuildContext context) async { final contact = await Navigator.of(context, rootNavigator: true) .pushNamed(Routes.pickerAddressBook); @@ -146,7 +145,7 @@ class AddressTextField extends StatelessWidget { } } - Future _presetSubaddressListPicker(BuildContext context) async { + Future _presetSubaddressListPicker(BuildContext context) async { final subaddress = await Navigator.of(context, rootNavigator: true) .pushNamed(Routes.subaddressList); diff --git a/lib/src/widgets/nav_bar.dart b/lib/src/widgets/nav_bar.dart index aacedeef8..5e540a09f 100644 --- a/lib/src/widgets/nav_bar.dart +++ b/lib/src/widgets/nav_bar.dart @@ -5,8 +5,23 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget { - static const _originalHeight = 44.0; // iOS nav bar height - static const _height = 60.0; + factory NavBar( + {BuildContext context, + Widget leading, + Widget middle, + Widget trailing, + Color backgroundColor}) { + final _themeChanger = Provider.of(context); + final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme; + + return NavBar._internal( + leading: leading, + middle: middle, + trailing: trailing, + height: _height, + backgroundColor: + _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor); + } factory NavBar.withShadow( {BuildContext context, @@ -37,31 +52,6 @@ class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget { ); } - factory NavBar( - {BuildContext context, - Widget leading, - Widget middle, - Widget trailing, - Color backgroundColor}) { - final _themeChanger = Provider.of(context); - final _isDarkTheme = _themeChanger.getTheme() == Themes.darkTheme; - - return NavBar._internal( - leading: leading, - middle: middle, - trailing: trailing, - height: _height, - backgroundColor: - _isDarkTheme ? Theme.of(context).backgroundColor : backgroundColor); - } - - final Widget leading; - final Widget middle; - final Widget trailing; - final Color backgroundColor; - final BoxDecoration decoration; - final double height; - NavBar._internal( {this.leading, this.middle, @@ -70,6 +60,16 @@ class NavBar extends StatelessWidget implements ObstructingPreferredSizeWidget { this.decoration, this.height = _height}); + static const _originalHeight = 44.0; // iOS nav bar height + static const _height = 60.0; + + final Widget leading; + final Widget middle; + final Widget trailing; + final Color backgroundColor; + final BoxDecoration decoration; + final double height; + @override Widget build(BuildContext context) { final pad = height - _originalHeight; diff --git a/lib/src/widgets/picker.dart b/lib/src/widgets/picker.dart index f16211194..7e34e56b9 100644 --- a/lib/src/widgets/picker.dart +++ b/lib/src/widgets/picker.dart @@ -2,12 +2,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; class Picker extends StatelessWidget { - final int selectedAtIndex; - final List items; - final String title; - final double pickerHeight; - final Function(Item) onItemSelected; - Picker( {@required this.selectedAtIndex, @required this.items, @@ -15,9 +9,14 @@ class Picker extends StatelessWidget { this.pickerHeight = 300, this.onItemSelected}); + final int selectedAtIndex; + final List items; + final String title; + final double pickerHeight; + final Function(Item) onItemSelected; + @override Widget build(BuildContext context) { - return GestureDetector( onTap: () => Navigator.of(context).pop(), child: Container( @@ -57,8 +56,10 @@ class Picker extends StatelessWidget { fontWeight: FontWeight.w600, fontFamily: 'Lato', decoration: TextDecoration.none, - color: Theme.of(context).primaryTextTheme.caption.color - ), + color: Theme.of(context) + .primaryTextTheme + .caption + .color), ), ), ); @@ -88,7 +89,10 @@ class Picker extends StatelessWidget { fontFamily: 'Lato', color: index == selectedAtIndex ? Color.fromRGBO(138, 80, 255, 1) - : Theme.of(context).primaryTextTheme.caption.color), + : Theme.of(context) + .primaryTextTheme + .caption + .color), )), ), ); diff --git a/lib/src/widgets/primary_button.dart b/lib/src/widgets/primary_button.dart index 5571f726d..ce64b1224 100644 --- a/lib/src/widgets/primary_button.dart +++ b/lib/src/widgets/primary_button.dart @@ -3,20 +3,19 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/palette.dart'; class PrimaryButton extends StatelessWidget { - final VoidCallback onPressed; - final Color color; - final Color borderColor; - final String text; - const PrimaryButton( {@required this.onPressed, @required this.text, @required this.color, @required this.borderColor}); + final VoidCallback onPressed; + final Color color; + final Color borderColor; + final String text; + @override Widget build(BuildContext context) { - return ButtonTheme( minWidth: double.infinity, height: 56.0, @@ -35,13 +34,6 @@ class PrimaryButton extends StatelessWidget { } class LoadingPrimaryButton extends StatelessWidget { - final VoidCallback onPressed; - final Color color; - final Color borderColor; - final bool isLoading; - final bool isDisabled; - final String text; - const LoadingPrimaryButton( {@required this.onPressed, @required this.text, @@ -50,9 +42,15 @@ class LoadingPrimaryButton extends StatelessWidget { this.isDisabled = false, this.isLoading = false}); + final VoidCallback onPressed; + final Color color; + final Color borderColor; + final bool isLoading; + final bool isDisabled; + final String text; + @override Widget build(BuildContext context) { - return ButtonTheme( minWidth: double.infinity, height: 56.0, @@ -73,14 +71,6 @@ class LoadingPrimaryButton extends StatelessWidget { } class PrimaryIconButton extends StatelessWidget { - final VoidCallback onPressed; - final IconData iconData; - final Color color; - final Color borderColor; - final Color iconColor; - final Color iconBackgroundColor; - final String text; - const PrimaryIconButton({ @required this.onPressed, @required this.iconData, @@ -91,9 +81,16 @@ class PrimaryIconButton extends StatelessWidget { @required this.iconBackgroundColor, }); + final VoidCallback onPressed; + final IconData iconData; + final Color color; + final Color borderColor; + final Color iconColor; + final Color iconBackgroundColor; + final String text; + @override Widget build(BuildContext context) { - return ButtonTheme( minWidth: double.infinity, height: 56.0, @@ -123,7 +120,8 @@ class PrimaryIconButton extends StatelessWidget { child: Text(text, style: TextStyle( fontSize: 16.0, - color: Theme.of(context).primaryTextTheme.button.color)), + color: + Theme.of(context).primaryTextTheme.button.color)), ), ) ], @@ -133,13 +131,6 @@ class PrimaryIconButton extends StatelessWidget { } class PrimaryImageButton extends StatelessWidget { - final VoidCallback onPressed; - final Image image; - final Color color; - final Color borderColor; - final Color iconColor; - final String text; - const PrimaryImageButton( {@required this.onPressed, @required this.image, @@ -148,6 +139,13 @@ class PrimaryImageButton extends StatelessWidget { this.borderColor = Palette.deepPink, this.iconColor = Colors.black}); + final VoidCallback onPressed; + final Image image; + final Color color; + final Color borderColor; + final Color iconColor; + final String text; + @override Widget build(BuildContext context) { return ButtonTheme( @@ -175,9 +173,13 @@ class PrimaryImageButton extends StatelessWidget { Container( height: 56.0, child: Center( - child: Text(text, style: TextStyle(fontSize: 18.0, - color: Theme.of(context).primaryTextTheme.button.color - )), + child: Text(text, + style: TextStyle( + fontSize: 18.0, + color: Theme.of(context) + .primaryTextTheme + .button + .color)), ), ) ])) diff --git a/lib/src/widgets/scollable_with_bottom_section.dart b/lib/src/widgets/scollable_with_bottom_section.dart index 4cd2fffe8..a653ff588 100644 --- a/lib/src/widgets/scollable_with_bottom_section.dart +++ b/lib/src/widgets/scollable_with_bottom_section.dart @@ -2,17 +2,17 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ScrollableWithBottomSection extends StatefulWidget { - final Widget content; - final Widget bottomSection; - final EdgeInsets contentPadding; - final EdgeInsets bottomSectionPadding; - ScrollableWithBottomSection( {this.content, this.bottomSection, this.contentPadding, this.bottomSectionPadding}); + final Widget content; + final Widget bottomSection; + final EdgeInsets contentPadding; + final EdgeInsets bottomSectionPadding; + @override ScrollableWithBottomSectionState createState() => ScrollableWithBottomSectionState(); diff --git a/lib/src/widgets/seed_widget.dart b/lib/src/widgets/seed_widget.dart index 3328df858..79f112565 100644 --- a/lib/src/widgets/seed_widget.dart +++ b/lib/src/widgets/seed_widget.dart @@ -7,10 +7,11 @@ import 'package:cake_wallet/src/domain/common/mnemotic_item.dart'; import 'package:cake_wallet/generated/i18n.dart'; class SeedWidget extends StatefulWidget { - final Function(List) onMnemoticChange; - SeedWidget({Key key, this.onMnemoticChange}) : super(key: key); + final Function(List) onMnemoticChange; + + @override SeedWidgetState createState() => SeedWidgetState(); } @@ -188,8 +189,7 @@ class SeedWidgetState extends State { hintStyle: TextStyle(color: Theme.of(context).hintColor), hintText: S.of(context).widgets_seed, focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Palette.cakeGreen, width: 2.0)), + borderSide: BorderSide(color: Palette.cakeGreen, width: 2.0)), enabledBorder: UnderlineInputBorder( borderSide: BorderSide( color: diff --git a/lib/src/widgets/standart_switch.dart b/lib/src/widgets/standart_switch.dart index 21347ee81..1232fe57a 100644 --- a/lib/src/widgets/standart_switch.dart +++ b/lib/src/widgets/standart_switch.dart @@ -1,41 +1,31 @@ import 'package:flutter/material.dart'; class StandartSwitch extends StatefulWidget { + const StandartSwitch({@required this.value, @required this.onTaped}); final bool value; final VoidCallback onTaped; - const StandartSwitch({ - @required this.value, - @required this.onTaped}); - @override - createState() => StandartSwitchState(); - + StandartSwitchState createState() => StandartSwitchState(); } class StandartSwitchState extends State { - @override Widget build(BuildContext context) { - return GestureDetector( onTap: widget.onTaped, child: AnimatedContainer( padding: EdgeInsets.only(left: 4.0, right: 4.0), - alignment: widget.value - ? Alignment.centerRight - : Alignment.centerLeft, + alignment: widget.value ? Alignment.centerRight : Alignment.centerLeft, duration: Duration(milliseconds: 250), width: 55.0, height: 33.0, decoration: BoxDecoration( color: Theme.of(context).toggleButtonsTheme.color, border: Border.all( - color: Theme.of(context).toggleButtonsTheme.borderColor - ), - borderRadius: - BorderRadius.all(Radius.circular(10.0))), + color: Theme.of(context).toggleButtonsTheme.borderColor), + borderRadius: BorderRadius.all(Radius.circular(10.0))), child: Container( width: 25.0, height: 25.0, @@ -43,11 +33,9 @@ class StandartSwitchState extends State { color: widget.value ? Theme.of(context).toggleButtonsTheme.selectedColor : Theme.of(context).toggleButtonsTheme.disabledColor, - borderRadius: - BorderRadius.all(Radius.circular(8.0))), - child: Icon(widget.value - ? Icons.check - : Icons.close, + borderRadius: BorderRadius.all(Radius.circular(8.0))), + child: Icon( + widget.value ? Icons.check : Icons.close, color: Colors.white, size: 16.0, ), @@ -55,5 +43,4 @@ class StandartSwitchState extends State { ), ); } - -} \ No newline at end of file +} diff --git a/lib/theme_changer.dart b/lib/theme_changer.dart index f6aa9c69d..c26e0722c 100644 --- a/lib/theme_changer.dart +++ b/lib/theme_changer.dart @@ -1,17 +1,16 @@ import 'package:flutter/material.dart'; class ThemeChanger with ChangeNotifier { + + ThemeChanger(this._themeData); ThemeData _themeData; - ThemeChanger(this._themeData); + ThemeData getTheme() => _themeData; - getTheme() => _themeData; - - setTheme(ThemeData theme){ + void setTheme(ThemeData theme){ _themeData = theme; notifyListeners(); } - } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 7aedeb3a0..a8b5c8ba7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -498,7 +498,7 @@ packages: source: hosted version: "1.5.1" pedantic: - dependency: transitive + dependency: "direct dev" description: name: pedantic url: "https://pub.dartlang.org" diff --git a/pubspec.yaml b/pubspec.yaml index 3ad89668e..c6848a921 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,7 @@ dev_dependencies: mobx_codegen: 0.3.3+1 hive_generator: ^0.6.0 flutter_launcher_icons: ^0.7.4 + pedantic: ^1.8.0 flutter_icons: image_path: "assets/images/app_logo.png" diff --git a/tool/secrets.dart b/tool/secrets.dart index 615e6123d..bc6f4b679 100644 --- a/tool/secrets.dart +++ b/tool/secrets.dart @@ -12,9 +12,9 @@ Future main() async { : secretsTestPath; final inoutContent = File(inputPath).readAsStringSync(); - final config = json.decode(inoutContent); + final config = json.decode(inoutContent) as Map; final output = 'const salt = \'${config["salt"]}\';\nconst key = \'${config["key"]}\';\nconst walletSalt = \'${config["walletSalt"]}\';\nconst shortKey = \'${config["shortKey"]}\';\nconst change_now_api_key = \'${config["change_now_api_key"]}\';'; - File(outputPath).writeAsString(output); + await File(outputPath).writeAsString(output); }