diff --git a/ios/Flutter/.last_build_id b/ios/Flutter/.last_build_id index c4f58572f..0c913ed64 100644 --- a/ios/Flutter/.last_build_id +++ b/ios/Flutter/.last_build_id @@ -1 +1 @@ -bc336703210c48e30d7216fac3fe1c0f \ No newline at end of file +4dc2ef1ba73deeed13cd85894dacb10b \ No newline at end of file diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 333591d2d..c0d7cb8e8 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -493,7 +493,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -526,7 +526,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 32J6BB6VUS; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fab2..6613d9583 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,117 +1,96 @@ { "images" : [ { - "size" : "20x20", "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", + "size" : "20x20", "scale" : "2x" }, { - "size" : "20x20", "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", + "size" : "20x20", "scale" : "3x" }, { - "size" : "29x29", "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { - "size" : "29x29", "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", + "size" : "29x29", "scale" : "3x" }, { - "size" : "40x40", "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", + "size" : "40x40", "scale" : "2x" }, { - "size" : "40x40", "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", + "size" : "40x40", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", + "filename" : "cake_xmr_120.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", + "filename" : "cake_xmr_180.png", "scale" : "3x" }, { + "idiom" : "ipad", "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", "scale" : "1x" }, { + "idiom" : "ipad", "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { + "idiom" : "ipad", "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { + "idiom" : "ipad", "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { - "size" : "40x40", "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", + "size" : "40x40", "scale" : "1x" }, { - "size" : "40x40", "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", + "size" : "40x40", "scale" : "2x" }, { - "size" : "76x76", "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", + "size" : "76x76", "scale" : "1x" }, { - "size" : "76x76", "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", + "size" : "76x76", "scale" : "2x" }, { + "idiom" : "ipad", "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", + "filename" : "cake_xmr_1024.png", "scale" : "1x" } ], @@ -119,4 +98,4 @@ "version" : 1, "author" : "xcode" } -} +} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada472..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 28c6bf030..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 2ccbfd967..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f091b6b0b..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cde12118..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index d0ef06e7e..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index dcdc2306c..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 2ccbfd967..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c8f9ed8f5..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index a6d6b8609..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index a6d6b8609..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 75b2d164a..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index c4df70d39..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 6a84f41e1..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index d0e1f5853..000000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_1024.png new file mode 100644 index 000000000..4540659cf Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_120.png new file mode 100644 index 000000000..303625681 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_120.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_180.png new file mode 100644 index 000000000..a22c1f36d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/cake_xmr_180.png differ diff --git a/lib/entities/node.dart b/lib/entities/node.dart index d96834dcb..f307111d2 100644 --- a/lib/entities/node.dart +++ b/lib/entities/node.dart @@ -39,12 +39,17 @@ class Node extends HiveObject with Keyable { int typeRaw; @override - dynamic get keyIndex => key; + dynamic get keyIndex { + _keyIndex ??= key; + return _keyIndex; + } WalletType get type => deserializeFromInt(typeRaw); set type(WalletType type) => typeRaw = serializeToInt(type); + dynamic _keyIndex; + Future requestNode() async { try { switch (type) { diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart index 118394e6f..470b9bc99 100644 --- a/lib/entities/node_list.dart +++ b/lib/entities/node_list.dart @@ -39,9 +39,9 @@ Future> loadElectrumServerList() async { Future resetToDefault(Box nodeSource) async { final moneroNodes = await loadDefaultNodes(); - final bitcoinElectrumServerList = await loadElectrumServerList(); - final nodes = moneroNodes + bitcoinElectrumServerList; + // final bitcoinElectrumServerList = await loadElectrumServerList(); + // final nodes = moneroNodes + bitcoinElectrumServerList; await nodeSource.clear(); - await nodeSource.addAll(nodes); + await nodeSource.addAll(moneroNodes); } diff --git a/lib/monero/monero_subaddress_list.dart b/lib/monero/monero_subaddress_list.dart index 14df05912..1a9c56ec7 100644 --- a/lib/monero/monero_subaddress_list.dart +++ b/lib/monero/monero_subaddress_list.dart @@ -39,8 +39,22 @@ abstract class MoneroSubaddressListBase with Store { } List getAll() { - return subaddress_list - .getAllSubaddresses() + final subaddresses = subaddress_list.getAllSubaddresses(); + if (subaddresses.length > 1) { + // final primary = subaddresses.first; + // final last = subaddresses.last; + // subaddresses[subaddresses.length - 1] = primary; + // subaddresses[0] = last; + + // for (var i = subaddresses.length - 1; i >= 0; i--) { + // final pre = subaddresses[i]; + // final post = subaddresses[subaddresses.length - i]; + // subaddresses[subaddresses.length - i] = pre; + // subaddresses[i] = post; + // } + } + + return subaddresses .map((subaddressRow) => Subaddress.fromRow(subaddressRow)) .toList(); } diff --git a/lib/monero/monero_wallet_service.dart b/lib/monero/monero_wallet_service.dart index cb968e08a..5ff0c032f 100644 --- a/lib/monero/monero_wallet_service.dart +++ b/lib/monero/monero_wallet_service.dart @@ -88,7 +88,7 @@ class MoneroWalletService extends WalletService< Future openWallet(String name, String password) async { try { final path = await pathForWallet(name: name, type: WalletType.monero); - monero_wallet_manager.openWallet(path: path, password: password); + await monero_wallet_manager.openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values.firstWhere( (info) => info.id == WalletBase.idFor(name, WalletType.monero), orElse: () => null); final wallet = MoneroWallet( diff --git a/lib/monero/subaddress.dart b/lib/monero/subaddress.dart index fce417fa9..cb230044a 100644 --- a/lib/monero/subaddress.dart +++ b/lib/monero/subaddress.dart @@ -11,7 +11,10 @@ class Subaddress { Subaddress.fromRow(SubaddressRow row) : this.id = row.getId(), this.address = row.getAddress(), - this.label = row.getLabel(); + this.label = row.getId() == 0 && + row.getLabel().toLowerCase() == 'Primary account'.toLowerCase() + ? 'Primary address' + : row.getLabel(); final int id; final String address; diff --git a/lib/src/screens/auth/auth_page.dart b/lib/src/screens/auth/auth_page.dart index 37f03f5c3..82d765fd6 100644 --- a/lib/src/screens/auth/auth_page.dart +++ b/lib/src/screens/auth/auth_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:flushbar/flushbar.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -29,6 +31,8 @@ class AuthPageState extends State { final _backArrowImageDarkTheme = Image.asset('assets/images/close_button.png'); ReactionDisposer _reaction; + Flushbar _authBar; + Flushbar _progressBar; @override void initState() { @@ -39,37 +43,26 @@ class AuthPageState extends State { if (widget.onAuthenticationFinished != null) { widget.onAuthenticationFinished(true, this); } else { - _key.currentState.showSnackBar( - SnackBar( - content: Text(S.of(context).authenticated), - backgroundColor: Colors.green, - ), - ); + _authBar?.dismiss(); + showBar(context, S.of(context).authenticated); } }); } if (state is IsExecutingState) { WidgetsBinding.instance.addPostFrameCallback((_) { - _key.currentState.showSnackBar( - SnackBar( - content: Text(S.of(context).authentication), - backgroundColor: Colors.green, - ), - ); + _authBar = + createBar(S.of(context).authentication, duration: null) + ..show(context); }); } if (state is FailureState) { 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, - ), - ); + _authBar?.dismiss(); + showBar( + context, S.of(context).failed_authentication(state.error)); if (widget.onAuthenticationFinished != null) { widget.onAuthenticationFinished(false, this); @@ -80,13 +73,9 @@ class AuthPageState extends State { if (state is AuthenticationBanned) { 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, - ), - ); + _authBar?.dismiss(); + showBar( + context, S.of(context).failed_authentication(state.error)); if (widget.onAuthenticationFinished != null) { widget.onAuthenticationFinished(false, this); @@ -111,10 +100,22 @@ class AuthPageState extends State { super.dispose(); } - void changeProcessText(String text) => _key.currentState.showSnackBar( - SnackBar(content: Text(text), backgroundColor: Colors.green)); + void changeProcessText(String text) { + _authBar?.dismiss(); + _progressBar = createBar(text, duration: null) + ..show(_key.currentContext); + } - void close() => Navigator.of(_key.currentContext).pop(); + void hideProgressText() { + _progressBar?.dismiss(); + _progressBar = null; + } + + void close() { + _authBar?.dismiss(); + _progressBar?.dismiss(); + Navigator.of(_key.currentContext).pop(); + } @override Widget build(BuildContext context) { @@ -123,20 +124,20 @@ class AuthPageState extends State { appBar: CupertinoNavigationBar( leading: widget.closable ? Container( - padding: EdgeInsets.only(top: 10), - child: SizedBox( - height: 37, - width: 37, - child: ButtonTheme( - minWidth: double.minPositive, - child: FlatButton( - highlightColor: Colors.transparent, - splashColor: Colors.transparent, - padding: EdgeInsets.all(0), - onPressed: () => Navigator.of(context).pop(), - child: _backArrowImageDarkTheme), - ), - )) + padding: EdgeInsets.only(top: 10), + child: SizedBox( + height: 37, + width: 37, + child: ButtonTheme( + minWidth: double.minPositive, + child: FlatButton( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + padding: EdgeInsets.all(0), + onPressed: () => Navigator.of(context).pop(), + child: _backArrowImageDarkTheme), + ), + )) : Container(), backgroundColor: Theme.of(context).backgroundColor, border: null), diff --git a/lib/src/screens/contact/contact_list_page.dart b/lib/src/screens/contact/contact_list_page.dart index 5344c4736..dee016ee8 100644 --- a/lib/src/screens/contact/contact_list_page.dart +++ b/lib/src/screens/contact/contact_list_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; @@ -56,16 +57,6 @@ class ContactListPage extends BasePage { @override Widget body(BuildContext context) { - final shortDivider = Container( - height: 1, - padding: EdgeInsets.only(left: 24), - color: Theme.of(context).backgroundColor, - child: Container( - height: 1, - color: Theme.of(context).primaryTextTheme.title.backgroundColor, - ), - ); - return Container( padding: EdgeInsets.only(top: 20.0, bottom: 20.0), child: Observer( @@ -92,16 +83,8 @@ class ContactListPage extends BasePage { if (isCopied != null && isCopied) { await Clipboard.setData( ClipboardData(text: contact.address)); - Scaffold.of(context).showSnackBar( - SnackBar( - content: Text( - S.of(context).copied_to_clipboard, - style: TextStyle(color: Colors.white), - ), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 1500), - ), - ); + await showBar(context, + S.of(context).copied_to_clipboard); } }, child: Column( diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart index d06068c89..3d1d80026 100644 --- a/lib/src/screens/dashboard/wallet_menu.dart +++ b/lib/src/screens/dashboard/wallet_menu.dart @@ -13,6 +13,7 @@ class WalletMenu { final List items = [ S.current.reconnect, + S.current.rescan, S.current.wallets, S.current.nodes, S.current.show_seed, @@ -23,6 +24,7 @@ class WalletMenu { final List images = [ Image.asset('assets/images/reconnect_menu.png', height: 16, width: 16), + Image.asset('assets/images/filter_icon.png', height: 16, width: 16), Image.asset('assets/images/wallet_menu.png', height: 16, width: 16), Image.asset('assets/images/nodes_menu.png', height: 16, width: 16), Image.asset('assets/images/eye_menu.png', height: 16, width: 16), @@ -40,12 +42,15 @@ class WalletMenu { _presentReconnectAlert(context); break; case 1: - Navigator.of(context).pushNamed(Routes.walletList); + Navigator.of(context).pushNamed(Routes.rescan); break; case 2: - Navigator.of(context).pushNamed(Routes.nodeList); + Navigator.of(context).pushNamed(Routes.walletList); break; case 3: + Navigator.of(context).pushNamed(Routes.nodeList); + break; + case 4: Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) => isAuthenticatedSuccessfully @@ -53,7 +58,7 @@ class WalletMenu { : null); break; - case 4: + case 5: Navigator.of(context).pushNamed(Routes.auth, arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) => isAuthenticatedSuccessfully @@ -61,10 +66,10 @@ class WalletMenu { .popAndPushNamed(Routes.showKeys) : null); break; - case 5: + case 6: Navigator.of(context).pushNamed(Routes.addressBook); break; - case 6: + case 7: Navigator.of(context).pushNamed(Routes.settings); break; default: diff --git a/lib/src/screens/exchange/widgets/exchange_card.dart b/lib/src/screens/exchange/widgets/exchange_card.dart index e88f1b966..7706e7271 100644 --- a/lib/src/screens/exchange/widgets/exchange_card.dart +++ b/lib/src/screens/exchange/widgets/exchange_card.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; @@ -270,14 +271,8 @@ class ExchangeCardState extends State { onTap: () { Clipboard.setData( ClipboardData(text: addressController.text)); - Scaffold.of(context).showSnackBar(SnackBar( - content: Text( - S.of(context).copied_to_clipboard, - style: TextStyle(color: Colors.white), - ), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 500), - )); + showBar(context, + S.of(context).copied_to_clipboard); }, child: Row( mainAxisSize: MainAxisSize.max, diff --git a/lib/src/screens/exchange_trade/exchange_confirm_page.dart b/lib/src/screens/exchange_trade/exchange_confirm_page.dart index 5e007a250..8fd4883df 100644 --- a/lib/src/screens/exchange_trade/exchange_confirm_page.dart +++ b/lib/src/screens/exchange_trade/exchange_confirm_page.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; @@ -25,91 +26,84 @@ class ExchangeConfirmPage extends BasePage { children: [ Expanded( child: Column( - children: [ - Flexible( - child: Center( - child: Text( - S.of(context).exchange_result_write_down_trade_id, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.title.color), + children: [ + Flexible( + child: Center( + child: Text( + S.of(context).exchange_result_write_down_trade_id, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.w500, + color: Theme.of(context).primaryTextTheme.title.color), + ), + )), + Container( + height: 178, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30)), + border: Border.all( + width: 1, + color: Theme.of(context).accentTextTheme.caption.color), + color: Theme.of(context).accentTextTheme.title.color), + child: Column( + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.all(24), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + S.of(context).trade_id, + style: TextStyle( + fontSize: 12.0, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .primaryTextTheme + .overline + .color), + ), + Text( + trade.id, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Theme.of(context) + .primaryTextTheme + .title + .color), + ), + ], + ), + )), + Padding( + padding: EdgeInsets.fromLTRB(10, 0, 10, 10), + child: Builder( + builder: (context) => PrimaryButton( + onPressed: () { + Clipboard.setData(ClipboardData(text: trade.id)); + showBar( + context, S.of(context).copied_to_clipboard); + }, + text: S.of(context).copy_id, + color: Theme.of(context) + .accentTextTheme + .caption + .backgroundColor, + textColor: + Theme.of(context).primaryTextTheme.title.color), ), ) - ), - Container( - height: 178, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30)), - border: Border.all( - width: 1, - color: Theme.of(context).accentTextTheme.caption.color - ), - color: Theme.of(context).accentTextTheme.title.color - ), - child: Column( - children: [ - Expanded( - child: Padding( - padding: EdgeInsets.all(24), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text( - S.of(context).trade_id, - style: TextStyle( - fontSize: 12.0, - fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.overline.color - ), - ), - Text( - trade.id, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme.title.color - ), - ), - ], - ), - ) - ), - Padding( - padding: EdgeInsets.fromLTRB(10, 0, 10, 10), - child: Builder( - builder: (context) => PrimaryButton( - onPressed: () { - Clipboard.setData(ClipboardData(text: trade.id)); - Scaffold.of(context).showSnackBar(SnackBar( - content: Text( - S.of(context).copied_to_clipboard, - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white), - ), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 1500), - )); - }, - text: S.of(context).copy_id, - color: Theme.of(context).accentTextTheme.caption.backgroundColor, - textColor: Theme.of(context).primaryTextTheme.title.color - ), - ), - ) - ], - ), - ), - Flexible( - child: Offstage() - ), - ], - ) - ), + ], + ), + ), + Flexible(child: Offstage()), + ], + )), PrimaryButton( onPressed: () => Navigator.of(context) .pushReplacementNamed(Routes.exchangeTrade), diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart index 945bb298d..cfadd48ff 100644 --- a/lib/src/screens/exchange_trade/exchange_trade_page.dart +++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart @@ -4,6 +4,7 @@ import 'package:cake_wallet/exchange/exchange_provider_description.dart'; import 'package:cake_wallet/src/screens/exchange_trade/exchange_trade_item.dart'; import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; import 'package:cake_wallet/src/widgets/standart_list_row.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart'; import 'package:mobx/mobx.dart'; @@ -13,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/generated/i18n.dart'; + // import 'package:cake_wallet/src/stores/exchange_trade/exchange_trade_store.dart'; // import 'package:cake_wallet/src/stores/send/send_store.dart'; // import 'package:cake_wallet/src/stores/send/sending_state.dart'; @@ -25,23 +27,21 @@ import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -void showInformation(ExchangeTradeViewModel exchangeTradeViewModel, BuildContext context) { +void showInformation( + ExchangeTradeViewModel exchangeTradeViewModel, BuildContext context) { final fetchingLabel = S.current.fetching; final trade = exchangeTradeViewModel.trade; final walletName = exchangeTradeViewModel.wallet.name; final information = exchangeTradeViewModel.isSendable ? S.current.exchange_result_confirm( - trade.amount ?? fetchingLabel, - trade.from.toString(), - walletName) + trade.amount ?? fetchingLabel, trade.from.toString(), walletName) : S.current.exchange_result_description( - trade.amount ?? fetchingLabel, trade.from.toString()); + trade.amount ?? fetchingLabel, trade.from.toString()); showPopUp( - context: context, - builder: (_) => InformationPage(information: information) - ); + context: context, + builder: (_) => InformationPage(information: information)); } class ExchangeTradePage extends BasePage { @@ -73,7 +73,8 @@ class ExchangeTradePage extends BasePage { } @override - Widget body(BuildContext context) => ExchangeTradeForm(exchangeTradeViewModel); + Widget body(BuildContext context) => + ExchangeTradeForm(exchangeTradeViewModel); } class ExchangeTradeForm extends StatefulWidget { @@ -87,6 +88,7 @@ class ExchangeTradeForm extends StatefulWidget { class ExchangeTradeState extends State { final fetchingLabel = S.current.fetching; + String get title => S.current.exchange; bool _effectsInstalled = false; @@ -104,127 +106,133 @@ class ExchangeTradeState extends State { @override Widget build(BuildContext context) { final copyImage = Image.asset('assets/images/copy_content.png', - height: 16, width: 16, + height: 16, + width: 16, color: Theme.of(context).primaryTextTheme.overline.color); //_setEffects(context); return Container( child: ScrollableWithBottomSection( - contentPadding: EdgeInsets.only(top: 10, bottom: 16), - content: Observer(builder: (_) { - final trade = widget.exchangeTradeViewModel.trade; + contentPadding: EdgeInsets.only(top: 10, bottom: 16), + content: Observer(builder: (_) { + final trade = widget.exchangeTradeViewModel.trade; - return Column( - children: [ - trade.expiredAt != null - ? Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - S.of(context).offer_expires_in, - style: TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w500, - color: Theme.of(context).primaryTextTheme.overline.color), - ), - TimerWidget(trade.expiredAt, - color: Theme.of(context).primaryTextTheme.title.color) - ]) - : Offstage(), - Padding( - padding: EdgeInsets.only(top: 32), - child: Row(children: [ - Spacer(flex: 3), - Flexible( - flex: 4, - child: Center( - child: AspectRatio( - aspectRatio: 1.0, - child: QrImage( - data: trade.inputAddress ?? fetchingLabel, - backgroundColor: Colors.transparent, - foregroundColor: Theme.of(context) - .accentTextTheme.subtitle.color, - )))), - Spacer(flex: 3) - ]), - ), - Padding( - padding: EdgeInsets.only(top: 16), - child: ListView.separated( - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemCount: widget.exchangeTradeViewModel.items.length, - separatorBuilder: (context, index) => Container( - height: 1, - color: Theme.of(context).accentTextTheme.subtitle.backgroundColor, - ), - itemBuilder: (context, index) { - final item = widget.exchangeTradeViewModel.items[index]; - String value; - - final content = Observer( - builder: (_) { - switch (index) { - case 0: - value = '${widget.exchangeTradeViewModel.trade.id ?? fetchingLabel}'; - break; - case 1: - value = '${widget.exchangeTradeViewModel.trade.amount ?? fetchingLabel}'; - break; - case 2: - value = '${widget.exchangeTradeViewModel.trade.state ?? fetchingLabel}'; - break; - case 3: - value = widget.exchangeTradeViewModel.trade.inputAddress ?? fetchingLabel; - break; - } - - return StandartListRow( - title: item.title, - value: value, - valueFontSize: 14, - image: item.isCopied ? copyImage : null, - ); - } - ); - - return item.isCopied - ? Builder( - builder: (context) => - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData(text: value)); - Scaffold.of(context).showSnackBar(SnackBar( - content: Text( - S.of(context).copied_to_clipboard, - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white), - ), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 1500), - )); - }, - child: content, - ) - ) - : content; - }, + return Column( + children: [ + trade.expiredAt != null + ? Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + S.of(context).offer_expires_in, + style: TextStyle( + fontSize: 14.0, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .primaryTextTheme + .overline + .color), + ), + TimerWidget(trade.expiredAt, + color: Theme.of(context) + .primaryTextTheme + .title + .color) + ]) + : Offstage(), + Padding( + padding: EdgeInsets.only(top: 32), + child: Row(children: [ + Spacer(flex: 3), + Flexible( + flex: 4, + child: Center( + child: AspectRatio( + aspectRatio: 1.0, + child: QrImage( + data: trade.inputAddress ?? fetchingLabel, + backgroundColor: Colors.transparent, + foregroundColor: Theme.of(context) + .accentTextTheme + .subtitle + .color, + )))), + Spacer(flex: 3) + ]), ), - ), - ], - ); - }), - bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24), - bottomSection: PrimaryButton( - onPressed: () {}, - text: S.of(context).confirm, - color: Theme.of(context).accentTextTheme.body2.color, - textColor: Colors.white - ) - /*Observer( + Padding( + padding: EdgeInsets.only(top: 16), + child: ListView.separated( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemCount: widget.exchangeTradeViewModel.items.length, + separatorBuilder: (context, index) => Container( + height: 1, + color: Theme.of(context) + .accentTextTheme + .subtitle + .backgroundColor, + ), + itemBuilder: (context, index) { + final item = widget.exchangeTradeViewModel.items[index]; + String value; + + final content = Observer(builder: (_) { + switch (index) { + case 0: + value = + '${widget.exchangeTradeViewModel.trade.id ?? fetchingLabel}'; + break; + case 1: + value = + '${widget.exchangeTradeViewModel.trade.amount ?? fetchingLabel}'; + break; + case 2: + value = + '${widget.exchangeTradeViewModel.trade.state ?? fetchingLabel}'; + break; + case 3: + value = widget.exchangeTradeViewModel.trade + .inputAddress ?? + fetchingLabel; + break; + } + + return StandartListRow( + title: item.title, + value: value, + valueFontSize: 14, + image: item.isCopied ? copyImage : null, + ); + }); + + return item.isCopied + ? Builder( + builder: (context) => GestureDetector( + onTap: () { + Clipboard.setData( + ClipboardData(text: value)); + showBar(context, + S.of(context).copied_to_clipboard); + }, + child: content, + )) + : content; + }, + ), + ), + ], + ); + }), + bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24), + bottomSection: PrimaryButton( + onPressed: () {}, + text: S.of(context).confirm, + color: Theme.of(context).accentTextTheme.body2.color, + textColor: Colors.white) + /*Observer( builder: (_) => tradeStore.trade.from == CryptoCurrency.xmr && !(sendStore.state is TransactionCommitted) ? LoadingPrimaryButton( @@ -242,7 +250,7 @@ class ExchangeTradeState extends State { color: Colors.blue, textColor: Colors.white) : Offstage()),*/ - ), + ), ); } diff --git a/lib/src/screens/login/login_page.dart b/lib/src/screens/login/login_page.dart deleted file mode 100644 index 684a35d70..000000000 --- a/lib/src/screens/login/login_page.dart +++ /dev/null @@ -1,114 +0,0 @@ -// import 'package:cake_wallet/src/stores/auth/auth_state.dart'; -// import 'package:cake_wallet/src/stores/login/login_store.dart'; -// import 'package:flutter/material.dart'; -// import 'package:flutter/cupertino.dart'; -// import 'package:mobx/mobx.dart'; -// import 'package:provider/provider.dart'; -// import 'package:cake_wallet/src/screens/pin_code/pin_code.dart'; -// import 'package:cake_wallet/src/screens/base_page.dart'; - -// class LoginPage extends BasePage { -// @override -// Widget leading(BuildContext context) => Container(); - -// @override -// Widget body(BuildContext context) => _LoginPinCode(); -// } - -// class _LoginPinCode extends PinCode { -// _LoginPinCode([Key key]) : super((_, __) => null, false, key); - -// @override -// _LoginPinCodeState createState() => _LoginPinCodeState(); -// } - -// class _LoginPinCodeState extends PinCodeState<_LoginPinCode> { -// LoginStore _loginStore; -// String title = 'Enter your PIN'; - -// @override -// Future onPinCodeEntered(PinCodeState state) async { -// final password = pin.fold("", (ac, val) => ac + '$val'); - -// await _loginStore.authStore.auth(password: password); -// super.onPinCodeEntered(state); -// } - -// @override -// Widget build(BuildContext context) { -// _setLoginStore(store: Provider.of(context)); -// return body(context); -// } - -// void _setLoginStore({LoginStore store}) { -// if (_loginStore != null) { -// return; -// } - -// _loginStore = store; - -// reaction((_) => _loginStore.authStore.state, (state) { -// if (state is AuthenticationFailure) { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// clear(); -// Scaffold.of(context).showSnackBar( -// SnackBar( -// content: Text(state.error), -// backgroundColor: Colors.red, -// ), -// ); -// }); -// } - -// if (state is AuthenticationBanned) { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// clear(); -// Scaffold.of(context).showSnackBar( -// SnackBar( -// content: Text(state.error), -// backgroundColor: Colors.red, -// ), -// ); -// }); -// } - -// if (state is AuthenticationInProgress) { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// Scaffold.of(context).hideCurrentSnackBar(); -// Scaffold.of(context).showSnackBar( -// SnackBar( -// content: Text('Authentication'), -// backgroundColor: Colors.green, -// ), -// ); -// }); -// } -// }); - -// reaction((_) => _loginStore.state, (state) { -// if (state is LoadedCurrentWalletFailure) { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// clear(); -// Scaffold.of(context).showSnackBar( -// SnackBar( -// content: Text(state.errorMessage), -// backgroundColor: Colors.red, -// ), -// ); -// }); -// } - -// if (state is LoadingCurrentWallet) { -// WidgetsBinding.instance.addPostFrameCallback((_) { -// Scaffold.of(context).hideCurrentSnackBar(); -// Scaffold.of(context).showSnackBar( -// SnackBar( -// content: Text('Loading your wallet'), -// backgroundColor: Colors.green, -// ), -// ); -// }); -// } -// }); -// } -// } diff --git a/lib/src/screens/receive/receive_page.dart b/lib/src/screens/receive/receive_page.dart index b7b06fcdb..1ac4a073b 100644 --- a/lib/src/screens/receive/receive_page.dart +++ b/lib/src/screens/receive/receive_page.dart @@ -95,7 +95,7 @@ class ReceivePage extends BasePage { context: context, builder: (_) => getIt.get()), - title: addressListViewModel.accountLabel, + title: S.of(context).accounts, icon: Icon( Icons.arrow_forward_ios, size: 14, @@ -136,7 +136,7 @@ class ReceivePage extends BasePage { isCurrent: isCurrent, backgroundColor: backgroundColor, textColor: textColor, - onTap: (_) => addressListViewModel.address = item, + onTap: (_) => addressListViewModel.setAddress(item), onEdit: () => Navigator.of(context).pushNamed( Routes.newSubaddress, arguments: item)); diff --git a/lib/src/screens/receive/widgets/qr_widget.dart b/lib/src/screens/receive/widgets/qr_widget.dart index 3a30db535..0e0970000 100644 --- a/lib/src/screens/receive/widgets/qr_widget.dart +++ b/lib/src/screens/receive/widgets/qr_widget.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; @@ -9,13 +10,12 @@ import 'package:cake_wallet/core/amount_validator.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; class QRWidget extends StatelessWidget { - QRWidget({ - @required this.addressListViewModel, - this.isAmountFieldShow = false - }) : amountController = TextEditingController(), - _formKey = GlobalKey() { + QRWidget( + {@required this.addressListViewModel, this.isAmountFieldShow = false}) + : amountController = TextEditingController(), + _formKey = GlobalKey() { amountController.addListener(() => addressListViewModel.amount = - _formKey.currentState.validate() ? amountController.text : ''); + _formKey.currentState.validate() ? amountController.text : ''); } final WalletAddressListViewModel addressListViewModel; @@ -26,7 +26,7 @@ class QRWidget extends StatelessWidget { @override Widget build(BuildContext context) { final copyImage = Image.asset('assets/images/copy_address.png', - color: Theme.of(context).textTheme.subhead.decorationColor); + color: Theme.of(context).textTheme.subhead.decorationColor); final addressTopOffset = isAmountFieldShow ? 60.0 : 40.0; return Column( @@ -36,16 +36,17 @@ class QRWidget extends StatelessWidget { Row(children: [ Spacer(flex: 3), Observer( - builder: (_) => Flexible( - flex: 5, - child: Center( - child: AspectRatio( - aspectRatio: 1.0, - child: QrImage( - data: addressListViewModel.uri.toString(), - backgroundColor: Colors.transparent, - foregroundColor: Theme.of(context).textTheme.headline.color, - ))))), + builder: (_) => Flexible( + flex: 5, + child: Center( + child: AspectRatio( + aspectRatio: 1.0, + child: QrImage( + data: addressListViewModel.uri.toString(), + backgroundColor: Colors.transparent, + foregroundColor: + Theme.of(context).textTheme.headline.color, + ))))), Spacer(flex: 3) ]), Padding( @@ -53,85 +54,80 @@ class QRWidget extends StatelessWidget { child: Text( S.of(context).scan_qr_code, style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w500, - color: Theme.of(context).indicatorColor - ), + fontSize: 12, + fontWeight: FontWeight.w500, + color: Theme.of(context).indicatorColor), ), ), isAmountFieldShow - ? Padding( - padding: EdgeInsets.only(top: 40), - child: Row( - children: [ - Expanded( - child: Form( - key: _formKey, - child: BaseTextFormField( - controller: amountController, - keyboardType: - TextInputType.numberWithOptions(decimal: true), - inputFormatters: [ - BlacklistingTextInputFormatter( - RegExp('[\\-|\\ |\\,]')) - ], - textAlign: TextAlign.center, - hintText: S.of(context).receive_amount, - textColor: Colors.white, - borderColor: Theme.of(context).textTheme.headline.decorationColor, - validator: AmountValidator( - type: addressListViewModel.type, - isAutovalidate: true - ), - autovalidate: true, - placeholderTextStyle: TextStyle( - color: Theme.of(context).hoverColor, - fontSize: 18, - fontWeight: FontWeight.w500)))) - ], - ), - ) - : Offstage(), + ? Padding( + padding: EdgeInsets.only(top: 40), + child: Row( + children: [ + Expanded( + child: Form( + key: _formKey, + child: BaseTextFormField( + controller: amountController, + keyboardType: TextInputType.numberWithOptions( + decimal: true), + inputFormatters: [ + BlacklistingTextInputFormatter( + RegExp('[\\-|\\ |\\,]')) + ], + textAlign: TextAlign.center, + hintText: S.of(context).receive_amount, + textColor: Colors.white, + borderColor: Theme.of(context) + .textTheme + .headline + .decorationColor, + validator: AmountValidator( + type: addressListViewModel.type, + isAutovalidate: true), + autovalidate: true, + placeholderTextStyle: TextStyle( + color: Theme.of(context).hoverColor, + fontSize: 18, + fontWeight: FontWeight.w500)))) + ], + ), + ) + : Offstage(), Padding( padding: EdgeInsets.only(top: addressTopOffset), child: Builder( builder: (context) => Observer( builder: (context) => GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData( - text: addressListViewModel.address.address)); - Scaffold.of(context).showSnackBar(SnackBar( - content: Text( - S.of(context).copied_to_clipboard, - style: TextStyle(color: Colors.white), + onTap: () { + Clipboard.setData(ClipboardData( + text: addressListViewModel.address.address)); + showBar( + context, S.of(context).copied_to_clipboard); + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: Text( + addressListViewModel.address.address, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white), + ), + ), + Padding( + padding: EdgeInsets.only(left: 12), + child: copyImage, + ) + ], ), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 500), - )); - }, - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Expanded( - child: Text( - addressListViewModel.address.address, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.white), - ), - ), - Padding( - padding: EdgeInsets.only(left: 12), - child: copyImage, - ) - ], - ), - ))), + ))), ) ], ); } -} \ No newline at end of file +} diff --git a/lib/src/screens/seed/wallet_seed_page.dart b/lib/src/screens/seed/wallet_seed_page.dart index 92d3b8504..c101561e6 100644 --- a/lib/src/screens/seed/wallet_seed_page.dart +++ b/lib/src/screens/seed/wallet_seed_page.dart @@ -2,6 +2,7 @@ import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -28,16 +29,20 @@ class WalletSeedPage extends BasePage { @override void onClose(BuildContext context) async { if (isNewWalletCreated) { - final confirmed = await showPopUp(context: context, builder: (BuildContext context) { - // FIXME: add translations - return AlertWithTwoActions( - alertTitle: 'Attention', - alertContent: 'The seed is the only way to recover your wallet. Have you written it down?', - leftButtonText: 'Go back', - rightButtonText: 'Yes, I have', - actionLeftButton: () => Navigator.of(context).pop(false), - actionRightButton: () => Navigator.of(context).pop(true)); - }) ?? false; + final confirmed = await showPopUp( + context: context, + builder: (BuildContext context) { + // FIXME: add translations + return AlertWithTwoActions( + alertTitle: 'Attention', + alertContent: + 'The seed is the only way to recover your wallet. Have you written it down?', + leftButtonText: 'Go back', + rightButtonText: 'Yes, I have', + actionLeftButton: () => Navigator.of(context).pop(false), + actionRightButton: () => Navigator.of(context).pop(true)); + }) ?? + false; if (confirmed) { Navigator.of(context).popUntil((route) => route.isFirst); @@ -57,39 +62,31 @@ class WalletSeedPage extends BasePage { Widget trailing(BuildContext context) { return isNewWalletCreated ? GestureDetector( - onTap: () => onClose(context), - child: Container( - width: 100, - height: 32, - alignment: Alignment.center, - margin: EdgeInsets.only(left: 10), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(16)), - color: Theme - .of(context) - .accentTextTheme - .caption - .color), - child: Text( - S - .of(context) - .seed_language_next, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Palette.blueCraiola), - ), - ), - ) + onTap: () => onClose(context), + child: Container( + width: 100, + height: 32, + alignment: Alignment.center, + margin: EdgeInsets.only(left: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(16)), + color: Theme.of(context).accentTextTheme.caption.color), + child: Text( + S.of(context).seed_language_next, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Palette.blueCraiola), + ), + ), + ) : Offstage(); } @override Widget body(BuildContext context) { final image = - getIt - .get() - .isDarkTheme ? imageDark : imageLight; + getIt.get().isDarkTheme ? imageDark : imageLight; return Container( padding: EdgeInsets.all(24), @@ -116,23 +113,21 @@ class WalletSeedPage extends BasePage { style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, - color: Theme - .of(context) + color: Theme.of(context) .primaryTextTheme .title .color), ), Padding( padding: - EdgeInsets.only(top: 20, left: 16, right: 16), + EdgeInsets.only(top: 20, left: 16, right: 16), child: Text( walletSeedViewModel.seed, textAlign: TextAlign.center, style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme - .of(context) + color: Theme.of(context) .primaryTextTheme .caption .color), @@ -146,78 +141,54 @@ class WalletSeedPage extends BasePage { children: [ isNewWalletCreated ? Padding( - padding: EdgeInsets.only( - bottom: 52, left: 43, right: 43), - child: Text( - S - .of(context) - .seed_reminder, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.normal, - color: Theme - .of(context) - .primaryTextTheme - .overline - .color), - ), - ) + padding: EdgeInsets.only( + bottom: 52, left: 43, right: 43), + child: Text( + S.of(context).seed_reminder, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.normal, + color: Theme.of(context) + .primaryTextTheme + .overline + .color), + ), + ) : Offstage(), Row( mainAxisSize: MainAxisSize.max, children: [ Flexible( child: Container( - padding: EdgeInsets.only(right: 8.0), - child: PrimaryButton( - onPressed: () => - Share.text( - S - .of(context) - .seed_share, - walletSeedViewModel.seed, - 'text/plain'), - text: S - .of(context) - .save, - color: Colors.green, - textColor: Colors.white), - )), + padding: EdgeInsets.only(right: 8.0), + child: PrimaryButton( + onPressed: () => Share.text( + S.of(context).seed_share, + walletSeedViewModel.seed, + 'text/plain'), + text: S.of(context).save, + color: Colors.green, + textColor: Colors.white), + )), Flexible( child: Container( - padding: EdgeInsets.only(left: 8.0), - child: Builder( - builder: (context) => - PrimaryButton( - onPressed: () { - Clipboard.setData(ClipboardData( - text: walletSeedViewModel - .seed)); - Scaffold.of(context) - .showSnackBar( - SnackBar( - content: Text(S - .of(context) - .copied_to_clipboard), - backgroundColor: Colors - .green, - duration: - Duration( - milliseconds: 1500), - ), - ); - }, - text: S - .of(context) - .copy, - color: Theme - .of(context) - .accentTextTheme - .body2 - .color, - textColor: Colors.white)), - )) + padding: EdgeInsets.only(left: 8.0), + child: Builder( + builder: (context) => PrimaryButton( + onPressed: () { + Clipboard.setData(ClipboardData( + text: walletSeedViewModel.seed)); + showBar(context, + S.of(context).copied_to_clipboard); + }, + text: S.of(context).copy, + color: Theme.of(context) + .accentTextTheme + .body2 + .color, + textColor: Colors.white)), + )) ], ) ], diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index 4a1a15443..7a856cb43 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -1,5 +1,7 @@ import 'dart:ui'; +import 'package:cake_wallet/entities/transaction_priority.dart'; import 'package:cake_wallet/src/widgets/keyboard_done_button.dart'; +import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -691,19 +693,19 @@ class SendPage extends BasePage { } Future _setTransactionPriority(BuildContext context) async { - // final items = TransactionPriority.all; - // final selectedItem = items.indexOf(sendViewModel.transactionPriority); - // - // await showPopUp( - // builder: (_) => Picker( - // items: items, - // selectedAtIndex: selectedItem, - // title: S.of(context).please_select, - // mainAxisAlignment: MainAxisAlignment.center, - // onItemSelected: (TransactionPriority priority) => null, - // // sendViewModel.setTransactionPriority(priority), - // isAlwaysShowScrollThumb: true, - // ), - // context: context); + final items = TransactionPriority.all; + final selectedItem = items.indexOf(sendViewModel.transactionPriority); + + await showPopUp( + builder: (_) => Picker( + items: items, + selectedAtIndex: selectedItem, + title: S.of(context).please_select, + mainAxisAlignment: MainAxisAlignment.center, + onItemSelected: (TransactionPriority priority) => + sendViewModel.setTransactionPriority(priority), + isAlwaysShowScrollThumb: true, + ), + context: context); } } diff --git a/lib/src/screens/trade_details/trade_details_page.dart b/lib/src/screens/trade_details/trade_details_page.dart index da71e80ac..88e30bae9 100644 --- a/lib/src/screens/trade_details/trade_details_page.dart +++ b/lib/src/screens/trade_details/trade_details_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; @@ -68,14 +69,7 @@ class TradeDetailsPage extends BasePage { return GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: '${item.value}')); - Scaffold.of(context).showSnackBar( - SnackBar( - content: - Text(S.of(context).trade_details_copied(item.title)), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 1500), - ), - ); + showBar(context, S.of(context).copied_to_clipboard); }, child: StandartListRow( title: '${item.title}', diff --git a/lib/src/screens/transaction_details/transaction_details_page.dart b/lib/src/screens/transaction_details/transaction_details_page.dart index 78bc9bd7c..7e9896fa2 100644 --- a/lib/src/screens/transaction_details/transaction_details_page.dart +++ b/lib/src/screens/transaction_details/transaction_details_page.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/utils/show_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:cake_wallet/generated/i18n.dart'; @@ -92,14 +93,8 @@ class TransactionDetailsPage extends BasePage { return GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: item.value)); - Scaffold.of(context).showSnackBar( - SnackBar( - content: Text( - S.of(context).transaction_details_copied(item.title)), - backgroundColor: Colors.green, - duration: Duration(milliseconds: 1500), - ), - ); + showBar(context, + S.of(context).transaction_details_copied(item.title)); }, child: StandartListRow( title: '${item.title}:', diff --git a/lib/src/screens/wallet_keys/wallet_keys_page.dart b/lib/src/screens/wallet_keys/wallet_keys_page.dart index e4a9954e8..48b326d47 100644 --- a/lib/src/screens/wallet_keys/wallet_keys_page.dart +++ b/lib/src/screens/wallet_keys/wallet_keys_page.dart @@ -1,3 +1,5 @@ +import 'package:cake_wallet/utils/show_bar.dart'; +import 'package:flushbar/flushbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; @@ -41,15 +43,8 @@ class WalletKeysPage extends BasePage { return GestureDetector( onTap: () { Clipboard.setData(ClipboardData(text: item.value)); - Scaffold.of(context).showSnackBar(SnackBar( - content: Text( - S.of(context).copied_key_to_clipboard(item.title), - textAlign: TextAlign.center, - style: TextStyle(color: Colors.white), - ), - backgroundColor: Colors.green, - duration: Duration(seconds: 1), - )); + showBar(context, + S.of(context).copied_key_to_clipboard(item.title)); }, child: StandartListRow( title: item.title + ':', diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 0b845f3ed..8b55347c4 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -1,5 +1,8 @@ +import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/wallet_list/widgets/wallet_menu_alert.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; @@ -11,6 +14,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/screens/wallet_list/wallet_menu.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; class WalletListPage extends BasePage { WalletListPage({this.walletListViewModel}); @@ -65,48 +69,61 @@ class WalletListBodyState extends State { itemCount: widget.walletListViewModel.wallets.length, itemBuilder: (__, index) { final wallet = widget.walletListViewModel.wallets[index]; - final walletMenu = WalletMenu(context, widget.walletListViewModel); - final items = - walletMenu.generateItemsForWalletMenu(wallet.isCurrent); final currentColor = wallet.isCurrent - ? Theme.of(context).accentTextTheme.subtitle.decorationColor + ? Theme.of(context) + .accentTextTheme + .subtitle + .decorationColor : Theme.of(context).backgroundColor; + final row = GestureDetector( + onTap: () async { + if (wallet.isCurrent) { + return; + } - return GestureDetector( - onTap: () { - showPopUp( - context: context, - builder: (dialogContext) { - return WalletMenuAlert( - wallet: wallet, - walletMenu: walletMenu, - items: items); - } - ); - }, - child: Container( - height: tileHeight, - width: double.infinity, - child: Row( - children: [ - Container( - height: tileHeight, - width: 4, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topRight: Radius.circular(4), - bottomRight: Radius.circular(4)), - color: currentColor + final confirmed = await showPopUp( + context: context, + builder: (dialogContext) { + // FIXME: + return AlertWithTwoActions( + alertTitle: 'Change current wallet', + alertContent: + 'Do you want to change current wallet to ${wallet.name} ?', + leftButtonText: S.of(context).cancel, + rightButtonText: S.of(context).change, + actionLeftButton: () => + Navigator.of(context).pop(false), + actionRightButton: () => + Navigator.of(context).pop(true)); + }) ?? false; + + if (confirmed) { + await _loadWallet(wallet); + } + }, + child: Container( + height: tileHeight, + width: double.infinity, + child: Row( + children: [ + Container( + height: tileHeight, + width: 4, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topRight: Radius.circular(4), + bottomRight: Radius.circular(4)), + color: currentColor), ), - ), - Expanded( + Expanded( child: Container( height: tileHeight, padding: EdgeInsets.only(left: 20, right: 20), color: Theme.of(context).backgroundColor, alignment: Alignment.centerLeft, child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ _imageFor(type: wallet.type), SizedBox(width: 10), @@ -115,17 +132,33 @@ class WalletListBodyState extends State { style: TextStyle( fontSize: 22, fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme.title.color - ), + color: Theme.of(context) + .primaryTextTheme + .title + .color), ) ], ), ), - ), - ], - ), - ) - ); + ), + ], + ), + )); + + return wallet.isCurrent + ? row + : Slidable( + key: Key('${wallet.key}'), + actionPane: SlidableDrawerActionPane(), + child: row, + secondaryActions: [ + IconSlideAction( + caption: S.of(context).delete, + color: Colors.red, + icon: CupertinoIcons.delete, + onTap: () async => _removeWallet(wallet), + ) + ]); }), ), ), @@ -136,12 +169,13 @@ class WalletListBodyState extends State { image: newWalletImage, text: S.of(context).wallet_list_create_new_wallet, color: Theme.of(context).accentTextTheme.subtitle.decorationColor, - textColor: Theme.of(context).accentTextTheme.headline.decorationColor, + textColor: + Theme.of(context).accentTextTheme.headline.decorationColor, ), SizedBox(height: 10.0), PrimaryImageButton( - onPressed: () => Navigator.of(context) - .pushNamed(Routes.restoreWalletType), + onPressed: () => + Navigator.of(context).pushNamed(Routes.restoreWalletType), image: restoreWalletImage, text: S.of(context).wallet_list_restore_wallet, color: Theme.of(context).accentTextTheme.caption.color, @@ -160,4 +194,47 @@ class WalletListBodyState extends State { return null; } } + + Future _loadWallet(WalletListItem wallet) async { + await 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 widget.walletListViewModel.loadWallet(wallet); + auth.hideProgressText(); + auth.close(); + Navigator.of(context).pop(); + } catch (e) { + auth.changeProcessText(S + .of(context) + .wallet_list_failed_to_load(wallet.name, e.toString())); + } + }); + } + + Future _removeWallet(WalletListItem wallet) async { + await 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 widget.walletListViewModel.remove(wallet); + } catch (e) { + auth.changeProcessText(S + .of(context) + .wallet_list_failed_to_remove(wallet.name, e.toString())); + } + + auth.close(); + }); + } } diff --git a/lib/src/widgets/address_text_field.dart b/lib/src/widgets/address_text_field.dart index 9f46505c8..4ab07f860 100644 --- a/lib/src/widgets/address_text_field.dart +++ b/lib/src/widgets/address_text_field.dart @@ -2,7 +2,7 @@ import 'package:flutter/services.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/entities/contact.dart'; +import 'package:cake_wallet/entities/contact_record.dart'; import 'package:cake_wallet/entities/qr_scanner.dart'; enum AddressTextFieldOption { paste, qrCode, addressBook } @@ -212,7 +212,7 @@ class AddressTextField extends StatelessWidget { final contact = await Navigator.of(context, rootNavigator: true) .pushNamed(Routes.pickerAddressBook); - if (contact is Contact && contact.address != null) { + if (contact is ContactRecord && contact.address != null) { controller.text = contact.address; } } diff --git a/lib/utils/mobx.dart b/lib/utils/mobx.dart index 344e16b64..9e2316af7 100644 --- a/lib/utils/mobx.dart +++ b/lib/utils/mobx.dart @@ -124,10 +124,16 @@ extension HiveBindable on ObservableList { listen().listen((event) => dest.acceptEntityChange(event)); void acceptBoxChange(BoxEvent event, {T transformed}) { + print('---------------------'); + print('event.key: ${event.key}; event.deleted: ${event.deleted};'); if (event.deleted) { - removeWhere((el) => el.keyIndex == event.key); + removeWhere((el) { + print('el.keyIndex ${el.keyIndex}'); + return el.keyIndex == event.key; }); } + print('---------------------'); + final dynamic value = transformed ?? event.value; if (value is T) { diff --git a/lib/utils/show_bar.dart b/lib/utils/show_bar.dart new file mode 100644 index 000000000..8d2355e4f --- /dev/null +++ b/lib/utils/show_bar.dart @@ -0,0 +1,47 @@ +import 'package:flushbar/flushbar.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +Future showBar(BuildContext context, String text, + {bool isDark = false, Duration duration = const Duration(seconds: 1), bool isDismissible = true}) { + final bar = Flushbar( + boxShadows: [ + BoxShadow( + color: Colors.black.withOpacity(0.09), + blurRadius: 8, + offset: Offset(0, 2)) + ], + backgroundColor: isDark ? Colors.black : Colors.white, + borderRadius: 35, + margin: EdgeInsets.all(50), + messageText: Text(text, + textAlign: TextAlign.center, + style: TextStyle(color: isDark ? Colors.white : Colors.black)), + duration: duration, + isDismissible: isDismissible, + flushbarPosition: FlushbarPosition.TOP, + flushbarStyle: FlushbarStyle.FLOATING); + + return bar.show(context); +} + +Flushbar createBar(String text, + {bool isDark = false, Duration duration = const Duration(seconds: 1), bool isDismissible = true}) { + return Flushbar( + boxShadows: [ + BoxShadow( + color: Colors.black.withOpacity(0.09), + blurRadius: 8, + offset: Offset(0, 2)) + ], + backgroundColor: isDark ? Colors.black : Colors.white, + borderRadius: 35, + margin: EdgeInsets.all(50), + messageText: Text(text, + textAlign: TextAlign.center, + style: TextStyle(color: isDark ? Colors.white : Colors.black)), + duration: duration, + isDismissible: isDismissible, + flushbarPosition: FlushbarPosition.TOP, + flushbarStyle: FlushbarStyle.FLOATING); +} diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart index 19678cd03..a37f39341 100644 --- a/lib/view_model/send/send_view_model.dart +++ b/lib/view_model/send/send_view_model.dart @@ -50,14 +50,15 @@ abstract class SendViewModelBase with Store { @observable bool sendAll; + @computed + double get estimatedFee => + _wallet.calculateEstimatedFee(_settingsStore.transactionPriority); + FiatCurrency get fiat => _settingsStore.fiatCurrency; TransactionPriority get transactionPriority => _settingsStore.transactionPriority; - double get estimatedFee => - _wallet.calculateEstimatedFee(_settingsStore.transactionPriority); - CryptoCurrency get currency => _wallet.currency; Validator get amountValidator => AmountValidator(type: _wallet.type); @@ -139,6 +140,10 @@ abstract class SendViewModelBase with Store { _updateCryptoAmount(); } + @action + void setTransactionPriority(TransactionPriority priority) => + _settingsStore.transactionPriority = priority; + @action void _updateFiatAmount() { try { diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart index 382083361..0c8d10502 100644 --- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart +++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart @@ -109,9 +109,6 @@ abstract class WalletAddressListViewModelBase with Store { return addressList; } - set address(WalletAddressListItem address) => null; - // _wallet.address = address.address; - bool hasAccounts; WalletBase _wallet; @@ -129,6 +126,10 @@ abstract class WalletAddressListViewModelBase with Store { return null; } + @action + void setAddress(WalletAddressListItem address) => + _wallet.address = address.address; + void _init() { _baseItems = []; diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index 8bb102620..84885941e 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -31,6 +31,7 @@ abstract class WalletListViewModelBase with Store { await _keyService.getWalletPassword(walletName: wallet.name); final walletService = getIt.get(param1: wallet.type); _appStore.wallet = await walletService.openWallet(wallet.name, password); + _updateList(); } @action diff --git a/pubspec.lock b/pubspec.lock index 8a8469917..e1d6a52a9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -358,6 +358,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.11" + flushbar: + dependency: "direct main" + description: + name: flushbar + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.4" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 541ca0259..73cb7c48e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,6 +65,7 @@ dependencies: get_it: ^4.0.2 connectivity: ^0.4.9+2 keyboard_actions: ^3.3.0 + flushbar: ^1.10.4 dev_dependencies: flutter_test: