diff --git a/assets/fonts/Poppins-Bold.ttf b/assets/fonts/Poppins-Bold.ttf new file mode 100644 index 000000000..b94d47f3a Binary files /dev/null and b/assets/fonts/Poppins-Bold.ttf differ diff --git a/assets/fonts/Poppins-Medium.ttf b/assets/fonts/Poppins-Medium.ttf new file mode 100644 index 000000000..e90e87ed6 Binary files /dev/null and b/assets/fonts/Poppins-Medium.ttf differ diff --git a/assets/fonts/Poppins-Regular.ttf b/assets/fonts/Poppins-Regular.ttf new file mode 100644 index 000000000..be06e7fdc Binary files /dev/null and b/assets/fonts/Poppins-Regular.ttf differ diff --git a/assets/images/changenow.png b/assets/images/changenow.png new file mode 100644 index 000000000..37593c419 Binary files /dev/null and b/assets/images/changenow.png differ diff --git a/assets/images/download.png b/assets/images/download.png new file mode 100644 index 000000000..1ae875234 Binary files /dev/null and b/assets/images/download.png differ diff --git a/assets/images/filter_icon.png b/assets/images/filter_icon.png new file mode 100644 index 000000000..7226a90e8 Binary files /dev/null and b/assets/images/filter_icon.png differ diff --git a/assets/images/menu.png b/assets/images/menu.png new file mode 100644 index 000000000..e42b77cfc Binary files /dev/null and b/assets/images/menu.png differ diff --git a/assets/images/morph.png b/assets/images/morph.png new file mode 100644 index 000000000..0cc2c3bac Binary files /dev/null and b/assets/images/morph.png differ diff --git a/assets/images/transfer.png b/assets/images/transfer.png new file mode 100644 index 000000000..383c35fb1 Binary files /dev/null and b/assets/images/transfer.png differ diff --git a/assets/images/triangle.png b/assets/images/triangle.png index 0c48a2465..fcef7252a 100644 Binary files a/assets/images/triangle.png and b/assets/images/triangle.png differ diff --git a/assets/images/upload.png b/assets/images/upload.png new file mode 100644 index 000000000..dba320367 Binary files /dev/null and b/assets/images/upload.png differ diff --git a/assets/images/xmrto.png b/assets/images/xmrto.png new file mode 100644 index 000000000..1a68e24cf Binary files /dev/null and b/assets/images/xmrto.png differ diff --git a/lib/bitcoin/bitcoin_transaction_info.dart b/lib/bitcoin/bitcoin_transaction_info.dart index 5850f19d2..583d1615c 100644 --- a/lib/bitcoin/bitcoin_transaction_info.dart +++ b/lib/bitcoin/bitcoin_transaction_info.dart @@ -4,6 +4,7 @@ import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin; import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData; import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; import 'package:cake_wallet/src/domain/common/transaction_info.dart'; +import 'package:cake_wallet/src/domain/common/format_amount.dart'; class BitcoinTransactionInfo extends TransactionInfo { BitcoinTransactionInfo( @@ -62,11 +63,16 @@ class BitcoinTransactionInfo extends TransactionInfo { final String id; - @override - String amountFormatted() => bitcoinAmountToString(amount: amount); + String _fiatAmount; @override - String fiatAmount() => '\$ 24.5'; + String amountFormatted() => '${formatAmount(bitcoinAmountToString(amount: amount))} BTC'; + + @override + String fiatAmount() => _fiatAmount ?? ''; + + @override + void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); Map toJson() { final m = Map(); diff --git a/lib/di.dart b/lib/di.dart index 19a8bc357..99188a2c8 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -1,6 +1,7 @@ import 'package:cake_wallet/core/contact_service.dart'; import 'package:cake_wallet/src/domain/common/contact.dart'; import 'package:cake_wallet/src/domain/common/node.dart'; +import 'package:cake_wallet/src/domain/exchange/trade.dart'; import 'package:cake_wallet/src/screens/contact/contact_list_page.dart'; import 'package:cake_wallet/src/screens/contact/contact_page.dart'; import 'package:cake_wallet/src/screens/nodes/node_create_or_edit_page.dart'; @@ -11,7 +12,7 @@ import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart'; import 'package:cake_wallet/store/contact_list_store.dart'; import 'package:cake_wallet/store/node_list_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/src/stores/price/price_store.dart'; import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/core/key_service.dart'; import 'package:cake_wallet/monero/monero_wallet.dart'; @@ -31,7 +32,8 @@ import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart'; import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/auth_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart'; import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart'; @@ -52,6 +54,9 @@ import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/src/domain/common/wallet_type.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/store/authentication_store.dart'; +import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; final getIt = GetIt.instance; @@ -77,7 +82,9 @@ NodeListStore setupNodeListStore(Box nodeSource) { Future setup( {Box walletInfoSource, Box nodeSource, - Box contactSource}) async { + Box contactSource, + Box tradesSource, + PriceStore priceStore}) async { getIt.registerSingletonAsync( () => SharedPreferences.getInstance()); @@ -97,6 +104,13 @@ Future setup( nodeListStore: getIt.get())); getIt.registerSingleton( ContactService(contactSource, getIt.get().contactListStore)); + getIt.registerSingleton(TradesStore( + tradesSource: tradesSource, + settingsStore: getIt.get())); + getIt.registerSingleton( + TradeFilterStore(wallet: getIt.get().wallet)); + getIt.registerSingleton(TransactionFilterStore()); + getIt.registerFactory( () => KeyService(getIt.get())); @@ -128,7 +142,19 @@ Future setup( () => WalletAddressListViewModel(wallet: getIt.get().wallet)); getIt.registerFactory( - () => DashboardViewModel(appStore: getIt.get())); + () => BalanceViewModel( + wallet: getIt.get().wallet, + settingsStore: getIt.get(), + priceStore: priceStore)); + + getIt.registerFactory( + () => DashboardViewModel( + balanceViewModel: getIt.get(), + appStore: getIt.get(), + tradesStore: getIt.get(), + tradeFilterStore: getIt.get(), + transactionFilterStore: getIt.get() + )); getIt.registerFactory(() => AuthService( secureStorage: getIt.get(), diff --git a/lib/generated/i18n.dart b/lib/generated/i18n.dart index 34f3bbf40..512866c0e 100644 --- a/lib/generated/i18n.dart +++ b/lib/generated/i18n.dart @@ -24,7 +24,6 @@ class S implements WidgetsLocalizations { String get account => "Account"; String get accounts => "Accounts"; String get accounts_subaddresses => "Accounts and subaddresses"; - String get addresses => "Addresses"; String get add => "Add"; String get add_new_node => "Add new node"; String get add_new_word => "Add new word"; @@ -32,6 +31,7 @@ class S implements WidgetsLocalizations { String get address_book_menu => "Address book"; String get address_remove_contact => "Remove contact"; String get address_remove_content => "Are you sure that you want to remove selected contact?"; + String get addresses => "Addresses"; String get all => "ALL"; String get amount => "Amount: "; String get amount_is_estimate => "The receive amount is an estimate"; @@ -643,8 +643,6 @@ class $de extends S { @override String get accounts_subaddresses => "Konten und Unteradressen"; @override - String get addresses => "Addressen"; - @override String get wallet_name => "Walletname"; @override String get error_text_payment_id => "Die Zahlungs-ID kann nur 16 bis 64 hexadezimale Zeichen enthalten"; @@ -1265,8 +1263,6 @@ class $hi extends S { @override String get accounts_subaddresses => "लेखा और उपदेस"; @override - String get addresses => "पतों"; - @override String get wallet_name => "बटुए का नाम"; @override String get error_text_payment_id => "पेमेंट आईडी केवल हेक्स में 16 से 64 चार्ट तक हो सकती है"; @@ -1887,8 +1883,6 @@ class $ru extends S { @override String get accounts_subaddresses => "Аккаунты и субадреса"; @override - String get addresses => "Адреса"; - @override String get wallet_name => "Имя кошелька"; @override String get error_text_payment_id => "Идентификатор платежа может содержать от 16 до 64 символов в hex"; @@ -2509,8 +2503,6 @@ class $ko extends S { @override String get accounts_subaddresses => "계정 및 하위 주소"; @override - String get addresses => "구애"; - @override String get wallet_name => "지갑 이름"; @override String get error_text_payment_id => "지불 ID는 16 ~ 64 자의 16 진 문자 만 포함 할 수 있습니다"; @@ -3131,8 +3123,6 @@ class $pt extends S { @override String get accounts_subaddresses => "Contas e sub-endereços"; @override - String get addresses => "Endereços"; - @override String get wallet_name => "Nome da carteira"; @override String get error_text_payment_id => "O ID de pagamento pode conter apenas de 16 a 64 caracteres em hexadecimal"; @@ -3753,8 +3743,6 @@ class $uk extends S { @override String get accounts_subaddresses => "Акаунти та субадреси"; @override - String get addresses => "Адреси"; - @override String get wallet_name => "Ім'я гаманця"; @override String get error_text_payment_id => "Ідентифікатор платежу може містити від 16 до 64 символів в hex"; @@ -4375,8 +4363,6 @@ class $ja extends S { @override String get accounts_subaddresses => "アカウントとサブアドレス"; @override - String get addresses => "アドレス"; - @override String get wallet_name => "ウォレット名"; @override String get error_text_payment_id => "支払いIDには、16進数で16〜64文字しか含めることができません"; @@ -5001,8 +4987,6 @@ class $pl extends S { @override String get accounts_subaddresses => "Konta i podadresy"; @override - String get addresses => "Adresy"; - @override String get wallet_name => "Nazwa portfela"; @override String get error_text_payment_id => "ID może zawierać od 16 do 64 znaków w formacie szesnastkowym"; @@ -5623,8 +5607,6 @@ class $es extends S { @override String get accounts_subaddresses => "Cuentas y subdirecciones"; @override - String get addresses => "Direcciones"; - @override String get wallet_name => "Nombre de la billetera"; @override String get error_text_payment_id => "La ID de pago solo puede contener de 16 a 64 caracteres en hexadecimal"; @@ -6245,8 +6227,6 @@ class $nl extends S { @override String get accounts_subaddresses => "Accounts en subadressen"; @override - String get addresses => "Adressen"; - @override String get wallet_name => "Portemonnee naam"; @override String get error_text_payment_id => "Betalings-ID kan alleen 16 tot 64 tekens bevatten in hexadecimale volgorde"; @@ -6867,8 +6847,6 @@ class $zh extends S { @override String get accounts_subaddresses => "帳戶和子地址"; @override - String get addresses => "地址"; - @override String get wallet_name => "钱包名称"; @override String get error_text_payment_id => "付款ID只能包含16到64个字符(十六进制)"; diff --git a/lib/main.dart b/lib/main.dart index d4e59fbe2..ce3739970 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -85,13 +85,6 @@ void main() async { final exchangeTemplates = await Hive.openBox(ExchangeTemplate.boxName); - await initialSetup( - sharedPreferences: await SharedPreferences.getInstance(), - nodes: nodes, - walletInfoSource: walletInfoSource, - contactSource: contacts, - initialMigrationVersion: 3); - final sharedPreferences = await SharedPreferences.getInstance(); final walletService = WalletService(); final walletListService = WalletListService( @@ -125,6 +118,15 @@ void main() async { final walletCreationService = WalletCreationService(); final authService = AuthService(); + await initialSetup( + sharedPreferences: await SharedPreferences.getInstance(), + nodes: nodes, + walletInfoSource: walletInfoSource, + contactSource: contacts, + tradesSource: trades, + priceStore: priceStore, + initialMigrationVersion: 3); + setReactions( settingsStore: settingsStore, priceStore: priceStore, @@ -163,6 +165,8 @@ Future initialSetup( @required Box nodes, @required Box walletInfoSource, @required Box contactSource, + @required Box tradesSource, + @required PriceStore priceStore, int initialMigrationVersion = 3}) async { await defaultSettingsMigration( version: initialMigrationVersion, @@ -171,7 +175,9 @@ Future initialSetup( await setup( walletInfoSource: walletInfoSource, nodeSource: nodes, - contactSource: contactSource); + contactSource: contactSource, + tradesSource: tradesSource, + priceStore: priceStore); await bootstrap(); monero_wallet.onStartup(); } diff --git a/lib/palette.dart b/lib/palette.dart index 9d0c5be32..0daa53148 100644 --- a/lib/palette.dart +++ b/lib/palette.dart @@ -20,7 +20,6 @@ class Palette { class PaletteDark { static const Color distantBlue = Color.fromRGBO(70, 85, 133, 1.0); // mainBackgroundColor static const Color lightDistantBlue = Color.fromRGBO(81, 96, 147, 1.0); // borderCardColor - static const Color nightBlue = Color.fromRGBO(45, 56, 95, 1.0); // walletCardBottomEndSync static const Color gray = Color.fromRGBO(140, 153, 201, 1.0); // walletCardText static const Color violetBlue = Color.fromRGBO(51, 63, 104, 1.0); // walletCardAddressField static const Color moderateBlue = Color.fromRGBO(63, 77, 122, 1.0); // walletCardSubAddressField @@ -28,8 +27,21 @@ class PaletteDark { static const Color pigeonBlue = Color.fromRGBO(91, 112, 146, 1.0); // historyPanelText static const Color moderateNightBlue = Color.fromRGBO(39, 53, 96, 1.0); // historyPanelButton static const Color headerNightBlue = Color.fromRGBO(41, 52, 84, 1.0); // menuHeader - static const Color lightNightBlue = Color.fromRGBO(48, 59, 95, 1.0); // menuList + //static const Color lightNightBlue = Color.fromRGBO(48, 59, 95, 1.0); // menuList static const Color moderatePurpleBlue = Color.fromRGBO(57, 74, 95, 1.0); // selectButtonText + + // NEW DESIGN + static const Color backgroundColor = Color.fromRGBO(25, 35, 60, 1.0); + static const Color nightBlue = Color.fromRGBO(35, 47, 79, 1.0); + static const Color wildNightBlue = Color.fromRGBO(39, 53, 96, 1.0); + static const Color cyanBlue = Color.fromRGBO(99, 113, 150, 1.0); + static const Color darkCyanBlue = Color.fromRGBO(91, 112, 146, 1.0); + static const Color orangeYellow = Color.fromRGBO(243, 166, 50, 1.0); + static const Color brightGreen = Color.fromRGBO(88, 243, 50, 1.0); + static const Color oceanBlue = Color.fromRGBO(27, 39, 71, 1.0); + static const Color lightNightBlue = Color.fromRGBO(39, 52, 89, 1.0); + static const Color wildBlue = Color.fromRGBO(165, 176, 205, 1.0); + // FIXME: Rename. static const Color eee = Color.fromRGBO(236, 239, 245, 1.0); static const Color xxx = Color.fromRGBO(72, 89, 109, 1); diff --git a/lib/router.dart b/lib/router.dart index 23fe7ba4f..920e13eae 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; import 'package:cake_wallet/src/screens/seed/wallet_seed_page.dart'; import 'package:cake_wallet/view_model/wallet_new_vm.dart'; import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart'; @@ -249,13 +250,7 @@ class Router { case Routes.dashboard: return CupertinoPageRoute( - builder: (_) => createDashboardPage( - walletService: walletService, - priceStore: priceStore, - settingsStore: settingsStore, - trades: trades, - transactionDescriptions: transactionDescriptions, - walletStore: walletStore)); + builder: (_) => getIt.get()); case Routes.send: return CupertinoPageRoute( diff --git a/lib/src/domain/common/transaction_info.dart b/lib/src/domain/common/transaction_info.dart index ebbb33777..d954fb72f 100644 --- a/lib/src/domain/common/transaction_info.dart +++ b/lib/src/domain/common/transaction_info.dart @@ -8,4 +8,5 @@ abstract class TransactionInfo extends Object { int height; String amountFormatted(); String fiatAmount(); + void changeFiatAmount(String amount); } \ No newline at end of file diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index ed297aec6..b32b72e64 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -2,149 +2,164 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; -import 'package:cake_wallet/view_model/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/src/screens/base_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/wallet_card.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/trade_history_panel.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/menu_widget.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:dots_indicator/dots_indicator.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; class DashboardPage extends BasePage { DashboardPage({@required this.walletViewModel}); @override - Color get backgroundLightColor => Colors.transparent; + Color get backgroundLightColor => PaletteDark.backgroundColor; @override - Color get backgroundDarkColor => Colors.transparent; + Color get backgroundDarkColor => PaletteDark.backgroundColor; @override - Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => Container( - decoration: BoxDecoration( - gradient: LinearGradient(colors: [ - Theme.of(context).scaffoldBackgroundColor, - Theme.of(context).primaryColor - ], begin: Alignment.topLeft, end: Alignment.bottomRight)), - child: scaffold); + Widget middle(BuildContext context) { + return SyncIndicator(dashboardViewModel: walletViewModel); + } @override Widget trailing(BuildContext context) { - final menuButton = Image.asset('assets/images/header.png', - color: Theme.of(context).primaryTextTheme.title.color); + final menuButton = Image.asset('assets/images/menu.png', + color: Colors.white); return Container( alignment: Alignment.centerRight, - child: SizedBox( - width: 24, - child: FlatButton( - highlightColor: Colors.transparent, - splashColor: Colors.transparent, - padding: EdgeInsets.all(0), - onPressed: () async { - await showDialog( - builder: (_) => MenuWidget( - name: walletViewModel.name, - subname: walletViewModel.subname, - type: walletViewModel.type), - context: context); - }, - child: menuButton), - ), + width: 40, + child: FlatButton( + highlightColor: Colors.transparent, + splashColor: Colors.transparent, + padding: EdgeInsets.all(0), + onPressed: () async { + await showDialog( + builder: (_) => MenuWidget( + name: walletViewModel.name, + subname: walletViewModel.subname, + type: walletViewModel.type), + context: context); + }, + child: menuButton + ) ); } final DashboardViewModel walletViewModel; - final sendImage = Image.asset('assets/images/send.png'); - final exchangeImage = Image.asset('assets/images/exchange.png'); - final buyImage = Image.asset('assets/images/coins.png'); + final sendImage = Image.asset('assets/images/upload.png', + height: 22.24, width: 24, color: Colors.white); + final exchangeImage = Image.asset('assets/images/transfer.png', + height: 24.27, width: 22.25, color: Colors.white); + final receiveImage = Image.asset('assets/images/download.png', + height: 22.24, width: 24, color: Colors.white); + final controller = PageController(initialPage: 0); + + var pages = []; + bool _isEffectsInstalled = false; @override Widget body(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - final transactionListMinHeight = - constraints.heightConstraints().maxHeight - 345 - 32; - return SingleChildScrollView( - child: Column(children: [ - Container( - height: 345, - child: Column(children: [ - Padding( - padding: EdgeInsets.only(left: 24, top: 10), - child: WalletCard(walletVM: walletViewModel)), - Container( - padding: EdgeInsets.only(left: 44, right: 44, top: 32), - child: Row( - children: [ - Flexible( - child: actionButton( - context: context, - image: sendImage, - title: S.of(context).send, - route: Routes.send)), - Flexible( - child: actionButton( - context: context, - image: exchangeImage, - title: S.of(context).exchange, - route: Routes.exchange)), - ], + _setEffects(); + + return SafeArea( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: PageView.builder( + controller: controller, + itemCount: pages.length, + itemBuilder: (context, index) { + return pages[index]; + } + ) + ), + Padding( + padding: EdgeInsets.only( + bottom: 24 + ), + child: Observer( + builder: (_) { + return DotsIndicator( + dotsCount: pages.length, + position: walletViewModel.currentPage, + decorator: DotsDecorator( + color: PaletteDark.cyanBlue, + activeColor: Colors.white, + size: Size(6, 6), + activeSize: Size(6, 6), + ), + ); + } + ), + ), + Container( + width: double.infinity, + padding: EdgeInsets.only( + left: 45, + right: 45, + bottom: 24 + ), + child: Row( + children: [ + Flexible( + child: ActionButton( + image: sendImage, + title: S.of(context).send, + route: Routes.send, + alignment: Alignment.centerLeft, + ), ), - ) - ])), - SizedBox(height: 32), - ConstrainedBox( - constraints: BoxConstraints(minHeight: transactionListMinHeight), - child: TradeHistoryPanel(dashboardViewModel: walletViewModel)), -// Column(children: [ -// Text('1'), -// Text('2') -// ]) - ])); + Flexible( + child: ActionButton( + image: exchangeImage, + title: S.of(context).exchange, + route: Routes.exchange + ), + ), + Flexible( + child: ActionButton( + image: receiveImage, + title: S.of(context).receive, + route: Routes.receive, + alignment: Alignment.centerRight, + ), + ) + ], + ), + ) + ], + ) + ); + } + + void _setEffects() { + if (_isEffectsInstalled) { + return; + } + + pages.add(BalancePage(dashboardViewModel: walletViewModel)); + pages.add(TransactionsPage(dashboardViewModel: walletViewModel)); + + controller.addListener(() { + walletViewModel.currentPage = controller.page; }); + + reaction((_) => walletViewModel.currentPage, (double currentPage) { + if (controller.page != currentPage) { + controller.jumpTo(currentPage); + } + }); + + _isEffectsInstalled = true; } } - -Widget actionButton( - {BuildContext context, - @required Image image, - @required String title, - @required String route}) { - return Container( - width: MediaQuery.of(context).size.width, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - GestureDetector( - onTap: () { - if (route.isNotEmpty) { - Navigator.of(context, rootNavigator: true).pushNamed(route); - } - }, - child: Container( - height: 48, - width: 48, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Theme.of(context).primaryTextTheme.subhead.color, - shape: BoxShape.circle), - child: image, - ), - ), - Padding( - padding: EdgeInsets.only(top: 12), - child: Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color.fromRGBO(140, 153, 201, - 0.8) // Theme.of(context).primaryTextTheme.caption.color - ), - ), - ) - ], - ), - ); -} diff --git a/lib/src/screens/dashboard/widgets/action_button.dart b/lib/src/screens/dashboard/widgets/action_button.dart new file mode 100644 index 000000000..a42c4ec8c --- /dev/null +++ b/lib/src/screens/dashboard/widgets/action_button.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; + +class ActionButton extends StatelessWidget{ + ActionButton({ + @required this.image, + @required this.title, + @required this.route, + this.alignment = Alignment.center + }); + + final Image image; + final String title; + final String route; + final Alignment alignment; + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: 93, + alignment: alignment, + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + GestureDetector( + onTap: () { + if (route.isNotEmpty) { + Navigator.of(context, rootNavigator: true).pushNamed(route); + } + }, + child: Container( + height: 60, + width: 60, + alignment: Alignment.center, + decoration: BoxDecoration( + color: PaletteDark.nightBlue, + shape: BoxShape.circle), + child: image, + ), + ), + Text( + title, + style: TextStyle( + fontSize: 14, + color: Colors.white + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/balance_page.dart b/lib/src/screens/dashboard/widgets/balance_page.dart new file mode 100644 index 000000000..9cca31a31 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/balance_page.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class BalancePage extends StatelessWidget { + BalancePage({@required this.dashboardViewModel}); + + final DashboardViewModel dashboardViewModel; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.all(24), + child: Center( + child: Container( + height: 160, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Observer( + builder: (_) { + return Text( + dashboardViewModel.wallet.currency.toString(), + style: TextStyle( + fontSize: 40, + fontWeight: FontWeight.bold, + color: PaletteDark.cyanBlue, + height: 1 + ), + ); + } + ), + Observer( + builder: (_) { + return Text( + dashboardViewModel.balanceViewModel.cryptoBalance, + style: TextStyle( + fontSize: 54, + fontWeight: FontWeight.bold, + color: Colors.white, + height: 1 + ), + ); + } + ), + Observer( + builder: (_) { + return Text( + dashboardViewModel.balanceViewModel.fiatBalance, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, + color: PaletteDark.cyanBlue, + height: 1 + ), + ); + } + ), + ], + ), + ), + ), + ); + } +} + diff --git a/lib/src/screens/dashboard/widgets/button_header.dart b/lib/src/screens/dashboard/widgets/button_header.dart deleted file mode 100644 index 8292704b8..000000000 --- a/lib/src/screens/dashboard/widgets/button_header.dart +++ /dev/null @@ -1,255 +0,0 @@ -import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; -import 'package:cake_wallet/src/stores/action_list/action_list_store.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:provider/provider.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; -import 'package:cake_wallet/themes.dart'; -import 'package:cake_wallet/theme_changer.dart'; - -class ButtonHeader extends SliverPersistentHeaderDelegate { - final sendImage = Image.asset('assets/images/send.png'); - final exchangeImage = Image.asset('assets/images/exchange.png'); - final buyImage = Image.asset('assets/images/coins.png'); - - @override - Widget build( - BuildContext context, double shrinkOffset, bool overlapsContent) { - final _themeChanger = Provider.of(context); - Image filterButton; - - if (_themeChanger.getTheme() == Themes.darkTheme) { - filterButton = Image.asset('assets/images/filter_button.png'); - } else { - filterButton = Image.asset('assets/images/filter_light_button.png'); - } - - return ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(24), topRight: Radius.circular(24)), - child: Container( - color: Colors.red, -// height: 75, - padding: EdgeInsets.only(top: 26, left: 20, right: 20, bottom: 10), -// color: Theme.of(context).backgroundColor, - child: Stack( - children: [ - Center( - child: Text( - S.of(context).transactions, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Theme.of(context).primaryTextTheme.title.color), - )), - Positioned( - right: 0, - height: 36, - child: PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - enabled: false, - value: -1, - child: Text(S.of(context).transactions, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .caption - .color))), -// PopupMenuItem( -// value: 0, -// child: Observer( -// builder: (_) => Row( -// mainAxisAlignment: -// MainAxisAlignment -// .spaceBetween, -// children: [ -// Text(S.of(context).incoming), -// Checkbox( -// value: actionListStore -// .transactionFilterStore -// .displayIncoming, -// onChanged: (value) => -// actionListStore -// .transactionFilterStore -// .toggleIncoming(), -// ) -// ]))), -// PopupMenuItem( -// value: 1, -// child: Observer( -// builder: (_) => Row( -// mainAxisAlignment: -// MainAxisAlignment -// .spaceBetween, -// children: [ -// Text(S.of(context).outgoing), -// Checkbox( -// value: actionListStore -// .transactionFilterStore -// .displayOutgoing, -// onChanged: (value) => -// actionListStore -// .transactionFilterStore -// .toggleOutgoing(), -// ) -// ]))), - PopupMenuItem( - value: 2, - child: Text(S.of(context).transactions_by_date)), - PopupMenuDivider(), - PopupMenuItem( - enabled: false, - value: -1, - child: Text(S.of(context).trades, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .caption - .color))), - PopupMenuItem( - value: 3, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('XMR.TO'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayXMRTO, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .xmrto), -// ) - ]))), - PopupMenuItem( - value: 4, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('Change.NOW'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayChangeNow, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .changeNow), -// ) - ]))), - PopupMenuItem( - value: 5, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('MorphToken'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayMorphToken, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .morphToken), -// ) - ]))) - ], - child: filterButton, - onSelected: (item) async { - if (item == 2) { - final List picked = - await date_rage_picker.showDatePicker( - context: context, - initialFirstDate: - DateTime.now().subtract(Duration(days: 1)), - initialLastDate: (DateTime.now()), - firstDate: DateTime(2015), - lastDate: DateTime.now().add(Duration(days: 1))); - - if (picked != null && picked.length == 2) { -// actionListStore.transactionFilterStore -// .changeStartDate(picked.first); -// actionListStore.transactionFilterStore -// .changeEndDate(picked.last); - } - } - }, - )), - ], - ), - ), - ); - } - - @override - double get maxExtent => 164; - - @override - double get minExtent => 66; - - @override - bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true; - - Widget actionButton( - {BuildContext context, - @required Image image, - @required String title, - @required String route}) { - return Container( - width: MediaQuery.of(context).size.width, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - GestureDetector( - onTap: () { - if (route.isNotEmpty) { - Navigator.of(context, rootNavigator: true).pushNamed(route); - } - }, - child: Container( - height: 48, - width: 48, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Theme.of(context).primaryTextTheme.subhead.color, - shape: BoxShape.circle), - child: image, - ), - ), - Padding( - padding: EdgeInsets.only(top: 12), - child: Text( - title, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Color.fromRGBO(140, 153, 201, - 0.8) // Theme.of(context).primaryTextTheme.caption.color - ), - ), - ) - ], - ), - ); - } -} diff --git a/lib/src/screens/dashboard/widgets/date_section_raw.dart b/lib/src/screens/dashboard/widgets/date_section_raw.dart index f639d3c59..61a6a64de 100644 --- a/lib/src/screens/dashboard/widgets/date_section_raw.dart +++ b/lib/src/screens/dashboard/widgets/date_section_raw.dart @@ -3,6 +3,7 @@ import 'package:intl/intl.dart'; import 'package:cake_wallet/generated/i18n.dart'; import 'package:provider/provider.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart'; +import 'package:cake_wallet/palette.dart'; class DateSectionRaw extends StatelessWidget { DateSectionRaw({this.date}); @@ -35,21 +36,14 @@ class DateSectionRaw extends StatelessWidget { } return Container( - height: 36, - padding: EdgeInsets.only(top: 10, bottom: 10, left: 20, right: 20), + height: 35, alignment: Alignment.center, - decoration: BoxDecoration( - color: Theme.of(context).backgroundColor, - border: Border.all( - width: 1, - color: Theme.of(context).backgroundColor - ), - ), + color: Colors.transparent, child: Text(title, - style: TextStyle( - fontSize: 12, - color: Theme.of(context).primaryTextTheme.headline.color - )) + style: TextStyle( + fontSize: 12, + color: PaletteDark.darkCyanBlue + )) ); } } diff --git a/lib/src/screens/dashboard/widgets/header_row.dart b/lib/src/screens/dashboard/widgets/header_row.dart new file mode 100644 index 000000000..837c23e6f --- /dev/null +++ b/lib/src/screens/dashboard/widgets/header_row.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; +import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class HeaderRow extends StatelessWidget { + HeaderRow({this.dashboardViewModel}); + + final DashboardViewModel dashboardViewModel; + + final filterIcon = Image.asset('assets/images/filter_icon.png', + color: PaletteDark.wildBlue); + + @override + Widget build(BuildContext context) { + return Container( + height: 52, + color: Colors.transparent, + padding: EdgeInsets.only(left: 24, right: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text( + S.of(context).transactions, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: Colors.white + ), + ), + PopupMenuButton( + itemBuilder: (context) => [ + PopupMenuItem( + enabled: false, + value: -1, + child: Text(S.of(context).transactions, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).primaryTextTheme.caption.color))), + PopupMenuItem( + value: 0, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text(S.of(context).incoming), + Checkbox( + value: dashboardViewModel + .transactionFilterStore + .displayIncoming, + onChanged: (value) => dashboardViewModel + .transactionFilterStore + .toggleIncoming() + ) + ]))), + PopupMenuItem( + value: 1, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text(S.of(context).outgoing), + Checkbox( + value: dashboardViewModel + .transactionFilterStore + .displayOutgoing, + onChanged: (value) => dashboardViewModel + .transactionFilterStore + .toggleOutgoing(), + ) + ]))), + PopupMenuItem( + value: 2, + child: + Text(S.of(context).transactions_by_date)), + PopupMenuDivider(), + PopupMenuItem( + enabled: false, + value: -1, + child: Text(S.of(context).trades, + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).primaryTextTheme.caption.color))), + PopupMenuItem( + value: 3, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text('XMR.TO'), + Checkbox( + value: dashboardViewModel + .tradeFilterStore + .displayXMRTO, + onChanged: (value) => dashboardViewModel + .tradeFilterStore + .toggleDisplayExchange( + ExchangeProviderDescription + .xmrto), + ) + ]))), + PopupMenuItem( + value: 4, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text('Change.NOW'), + Checkbox( + value: dashboardViewModel + .tradeFilterStore + .displayChangeNow, + onChanged: (value) => dashboardViewModel + .tradeFilterStore + .toggleDisplayExchange( + ExchangeProviderDescription + .changeNow), + ) + ]))), + PopupMenuItem( + value: 5, + child: Observer( + builder: (_) => Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text('MorphToken'), + Checkbox( + value: dashboardViewModel + .tradeFilterStore + .displayMorphToken, + onChanged: (value) => dashboardViewModel + .tradeFilterStore + .toggleDisplayExchange( + ExchangeProviderDescription + .morphToken), + ) + ]))) + ], + child: Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: PaletteDark.oceanBlue + ), + child: filterIcon, + ), + onSelected: (item) async { + if (item == 2) { + final picked = + await date_rage_picker.showDatePicker( + context: context, + initialFirstDate: DateTime.now() + .subtract(Duration(days: 1)), + initialLastDate: (DateTime.now()), + firstDate: DateTime(2015), + lastDate: DateTime.now() + .add(Duration(days: 1))); + + if (picked != null && picked.length == 2) { + dashboardViewModel.transactionFilterStore + .changeStartDate(picked.first); + dashboardViewModel.transactionFilterStore + .changeEndDate(picked.last); + } + } + }, + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/sync_indicator.dart b/lib/src/screens/dashboard/widgets/sync_indicator.dart new file mode 100644 index 000000000..64b8575c1 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/sync_indicator.dart @@ -0,0 +1,87 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/palette.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/src/domain/common/sync_status.dart'; + +class SyncIndicator extends StatelessWidget { + SyncIndicator({@required this.dashboardViewModel}); + + final DashboardViewModel dashboardViewModel; + + @override + Widget build(BuildContext context) { + return Observer( + builder: (_) { + final syncIndicatorWidth = 250.0; + final status = dashboardViewModel.status; + final statusText = status.title(); + final progress = status.progress(); + final indicatorOffset = progress * syncIndicatorWidth; + final indicatorWidth = + progress <= 1 ? syncIndicatorWidth - indicatorOffset : 0.0; + final indicatorColor = status is SyncedSyncStatus + ? PaletteDark.brightGreen + : PaletteDark.orangeYellow; + + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(15)), + child: Container( + height: 30, + width: syncIndicatorWidth, + color: PaletteDark.lightNightBlue, + child: Stack( + alignment: Alignment.center, + children: [ + progress <= 1 + ? Positioned( + left: indicatorOffset, + top: 0, + bottom: 0, + child: Container( + width: indicatorWidth, + height: 30, + color: PaletteDark.oceanBlue, + ) + ) + : Offstage(), + Padding( + padding: EdgeInsets.only( + left: 24, + right: 24 + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 4, + width: 4, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: indicatorColor + ), + ), + Padding( + padding: EdgeInsets.only(left: 6), + child: Text( + statusText, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: PaletteDark.wildBlue + ), + ), + ) + ], + ), + ) + ], + ), + ), + ); + } + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/trade_history_panel.dart b/lib/src/screens/dashboard/widgets/trade_history_panel.dart deleted file mode 100644 index 174b9cd89..000000000 --- a/lib/src/screens/dashboard/widgets/trade_history_panel.dart +++ /dev/null @@ -1,322 +0,0 @@ -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/theme_changer.dart'; -import 'package:cake_wallet/themes.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/view_model/dashboard_view_model.dart'; -import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; -import 'package:cake_wallet/src/stores/action_list/action_list_store.dart'; -import 'package:cake_wallet/src/stores/action_list/date_section_item.dart'; -import 'package:cake_wallet/src/stores/action_list/trade_list_item.dart'; -import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart'; -import 'package:cake_wallet/src/stores/settings/settings_store.dart'; -import 'date_section_raw.dart'; -import 'trade_row.dart'; -import 'transaction_raw.dart'; -import 'button_header.dart'; -import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker; - -class TradeHistoryPanel extends StatefulWidget { - TradeHistoryPanel({this.dashboardViewModel}); - - final DashboardViewModel dashboardViewModel; - - @override - TradeHistoryPanelState createState() => TradeHistoryPanelState(); -} - -class TradeHistoryPanelState extends State { - final _listObserverKey = GlobalKey(); - final _listKey = GlobalKey(); - - double panelHeight; - double screenHeight; - - @override - void initState() { - panelHeight = 0; - screenHeight = 0; - super.initState(); - WidgetsBinding.instance.addPostFrameCallback(afterLayout); - } - - void afterLayout(dynamic _) { - screenHeight = MediaQuery.of(context).size.height; - setState(() { - panelHeight = screenHeight; - }); - } - - @override - Widget build(BuildContext context) { - // AnimatedContainer( -// width: MediaQuery.of(context).size.width, -// height: panelHeight, -// duration: Duration(milliseconds: 1000), -// curve: Curves.fastOutSlowIn, -// child: ) - - final transactionDateFormat = DateFormat('HH:mm'); - final _themeChanger = Provider.of(context); - final filterButton = Image.asset( - _themeChanger.getTheme() == Themes.darkTheme - ? 'assets/images/filter_button.png' - : 'assets/images/filter_light_button.png', - height: 36); - - return ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20)), - child: Container( - color: Colors.white, - child: Column(children: [ - Container( - padding: - EdgeInsets.only(top: 32, left: 20, right: 20, bottom: 20), - color: Theme.of(context).backgroundColor, - child: Stack( - children: [ - SizedBox(height: 37), // Force stack height - Center( - child: Text(S.of(context).transactions, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .title - .color))), - Positioned( - right: 0, - child: PopupMenuButton( - itemBuilder: (context) => [ - PopupMenuItem( - enabled: false, - value: -1, - child: Text(S.of(context).transactions, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .caption - .color))), -// PopupMenuItem( -// value: 0, -// child: Observer( -// builder: (_) => Row( -// mainAxisAlignment: -// MainAxisAlignment -// .spaceBetween, -// children: [ -// Text(S.of(context).incoming), -// Checkbox( -// value: actionListStore -// .transactionFilterStore -// .displayIncoming, -// onChanged: (value) => -// actionListStore -// .transactionFilterStore -// .toggleIncoming(), -// ) -// ]))), -// PopupMenuItem( -// value: 1, -// child: Observer( -// builder: (_) => Row( -// mainAxisAlignment: -// MainAxisAlignment -// .spaceBetween, -// children: [ -// Text(S.of(context).outgoing), -// Checkbox( -// value: actionListStore -// .transactionFilterStore -// .displayOutgoing, -// onChanged: (value) => -// actionListStore -// .transactionFilterStore -// .toggleOutgoing(), -// ) -// ]))), - PopupMenuItem( - value: 2, - child: - Text(S.of(context).transactions_by_date)), - PopupMenuDivider(), - PopupMenuItem( - enabled: false, - value: -1, - child: Text(S.of(context).trades, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .caption - .color))), - PopupMenuItem( - value: 3, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('XMR.TO'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayXMRTO, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .xmrto), -// ) - ]))), - PopupMenuItem( - value: 4, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('Change.NOW'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayChangeNow, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .changeNow), -// ) - ]))), - PopupMenuItem( - value: 5, - child: Observer( - builder: (_) => Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text('MorphToken'), -// Checkbox( -// value: actionListStore -// .tradeFilterStore -// .displayMorphToken, -// onChanged: (value) => -// actionListStore -// .tradeFilterStore -// .toggleDisplayExchange( -// ExchangeProviderDescription -// .morphToken), -// ) - ]))) - ], - child: filterButton, - onSelected: (item) async { - if (item == 2) { - final picked = - await date_rage_picker.showDatePicker( - context: context, - initialFirstDate: DateTime.now() - .subtract(Duration(days: 1)), - initialLastDate: (DateTime.now()), - firstDate: DateTime(2015), - lastDate: DateTime.now() - .add(Duration(days: 1))); - - if (picked != null && picked.length == 2) { -// actionListStore.transactionFilterStore -// .changeStartDate(picked.first); -// actionListStore.transactionFilterStore -// .changeEndDate(picked.last); - } - } - }, - )), - ], - ), - ), - widget.dashboardViewModel.transactions?.isNotEmpty ?? false - ? ListView.separated( - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: widget.dashboardViewModel.transactions.length, - itemBuilder: (_, index) { - final item = - widget.dashboardViewModel.transactions[index]; - - if (item is DateSectionItem) { - return DateSectionRaw(date: item.date); - } - - if (item is TransactionListItem) { - final transaction = item.transaction; - final savedDisplayMode = BalanceDisplayMode.all; - //settingsStore -// .balanceDisplayMode; - final formattedAmount = savedDisplayMode == - BalanceDisplayMode.hiddenBalance - ? '---' - : transaction.amountFormatted(); - final formattedFiatAmount = savedDisplayMode == - BalanceDisplayMode.hiddenBalance - ? '---' - : transaction.fiatAmount(); // symbol ??? - - return TransactionRow( - onTap: () => Navigator.of(context).pushNamed( - Routes.transactionDetails, - arguments: transaction), - direction: transaction.direction, - formattedDate: transactionDateFormat - .format(transaction.date), - formattedAmount: formattedAmount, - formattedFiatAmount: formattedFiatAmount, - isPending: transaction.isPending); - } - - if (item is TradeListItem) { - final trade = item.trade; - final savedDisplayMode = BalanceDisplayMode.all; - //settingsStore - // .balanceDisplayMode; - final formattedAmount = trade.amount != null - ? savedDisplayMode == - BalanceDisplayMode.hiddenBalance - ? '---' - : trade.amountFormatted() - : trade.amount; - - return TradeRow( - onTap: () => Navigator.of(context).pushNamed( - Routes.tradeDetails, - arguments: trade), - provider: trade.provider, - from: trade.from, - to: trade.to, - createdAtFormattedDate: - transactionDateFormat.format(trade.createdAt), - formattedAmount: formattedAmount); - } - - return Container( - color: Theme.of(context).backgroundColor, - height: 1); - }, - separatorBuilder: (_, __) => - Container(height: 14, color: Colors.white), - ) - : Padding( - padding: EdgeInsets.all(20), - child: Text('Your transactions will be displayed here!', - style: TextStyle(color: Colors.grey))) - ]))); //, - } -} diff --git a/lib/src/screens/dashboard/widgets/trade_row.dart b/lib/src/screens/dashboard/widgets/trade_row.dart index 5461c8ce4..8a7bc7daf 100644 --- a/lib/src/screens/dashboard/widgets/trade_row.dart +++ b/lib/src/screens/dashboard/widgets/trade_row.dart @@ -1,15 +1,16 @@ import 'package:flutter/material.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/palette.dart'; class TradeRow extends StatelessWidget { - TradeRow( - {this.provider, - this.from, - this.to, - this.createdAtFormattedDate, - this.formattedAmount, - @required this.onTap}); + TradeRow({ + this.provider, + this.from, + this.to, + this.createdAtFormattedDate, + this.formattedAmount, + @required this.onTap}); final VoidCallback onTap; final ExchangeProviderDescription provider; @@ -25,58 +26,53 @@ class TradeRow extends StatelessWidget { return InkWell( onTap: onTap, child: Container( - height: 60, - decoration: BoxDecoration( - color: Theme.of(context).backgroundColor, - border: Border.all( - width: 1, - color: Theme.of(context).backgroundColor - ), - ), - padding: EdgeInsets.only(top: 5, bottom: 5, left: 20, right: 20), - child: Row(children: [ - Container( - height: 36, - width: 36, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).backgroundColor - ), - child: _getPoweredImage(provider), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 10), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('${from.toString()} → ${to.toString()}', - style: TextStyle( - fontSize: 16, - color: Theme.of(context).primaryTextTheme.title.color - )), - formattedAmount != null - ? Text(formattedAmount + ' ' + amountCrypto, - style: TextStyle( - fontSize: 16, - color: Theme.of(context).primaryTextTheme.title.color - )) - : Container() - ]), - SizedBox(height: 5), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(createdAtFormattedDate, - style: TextStyle( - fontSize: 14, color: Theme.of(context).primaryTextTheme.headline.color)) - ]), - ], - ), - )) - ]), + height: 52, + color: Colors.transparent, + padding: EdgeInsets.only(left: 24, right: 24), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _getPoweredImage(provider), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 12), + child: Container( + height: 46, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('${from.toString()} → ${to.toString()}', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white + )), + formattedAmount != null + ? Text(formattedAmount + ' ' + amountCrypto, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white + )) + : Container() + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(createdAtFormattedDate, + style: TextStyle( + fontSize: 14, + color: PaletteDark.darkCyanBlue)) + ]), + ], + ), + ), + )) + ]), )); } @@ -84,17 +80,17 @@ class TradeRow extends StatelessWidget { Image image; switch (provider) { case ExchangeProviderDescription.xmrto: - image = Image.asset('assets/images/xmr_btc.png'); + image = Image.asset('assets/images/xmrto.png', height: 36, width: 36); break; case ExchangeProviderDescription.changeNow: - image = Image.asset('assets/images/change_now.png'); + image = Image.asset('assets/images/changenow.png', height: 36, width: 36); break; case ExchangeProviderDescription.morphToken: - image = Image.asset('assets/images/morph_icon.png'); + image = Image.asset('assets/images/morph.png', height: 36, width: 36); break; default: image = null; } return image; } -} +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/transaction_raw.dart b/lib/src/screens/dashboard/widgets/transaction_raw.dart index 5e9a054dc..0d41b42a6 100644 --- a/lib/src/screens/dashboard/widgets/transaction_raw.dart +++ b/lib/src/screens/dashboard/widgets/transaction_raw.dart @@ -4,13 +4,13 @@ import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; import 'package:cake_wallet/generated/i18n.dart'; class TransactionRow extends StatelessWidget { - TransactionRow( - {this.direction, - this.formattedDate, - this.formattedAmount, - this.formattedFiatAmount, - this.isPending, - @required this.onTap}); + TransactionRow({ + this.direction, + this.formattedDate, + this.formattedAmount, + this.formattedFiatAmount, + this.isPending, + @required this.onTap}); final VoidCallback onTap; final TransactionDirection direction; @@ -24,78 +24,74 @@ class TransactionRow extends StatelessWidget { return InkWell( onTap: onTap, child: Container( - height: 41, - color: Theme.of(context).backgroundColor, - padding: EdgeInsets.only(left: 20, right: 20), - child: Row(children: [ - Container( - height: 36, - width: 36, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Theme.of(context).primaryTextTheme.display3.color), - child: Image.asset(direction == TransactionDirection.incoming - ? 'assets/images/down_arrow.png' - : 'assets/images/up_arrow.png'), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 10), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - (direction == TransactionDirection.incoming - ? S.of(context).received - : S.of(context).sent) + - (isPending ? S.of(context).pending : ''), - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .title - .color)), - Text( - direction == TransactionDirection.incoming - ? formattedAmount - : '- ' + formattedAmount, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .primaryTextTheme - .title - .color)) - ]), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(formattedDate, - style: TextStyle( - fontSize: 14, - color: Theme.of(context) - .primaryTextTheme - .headline - .color)), - Text( - direction == TransactionDirection.incoming - ? formattedFiatAmount - : '- ' + formattedFiatAmount, - style: TextStyle( - fontSize: 14, - color: Theme.of(context) - .primaryTextTheme - .headline - .color)) - ]), - ], - ), - )) - ]), + height: 52, + color: Colors.transparent, + padding: EdgeInsets.only(left: 24, right: 24), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: PaletteDark.wildNightBlue + ), + child: Image.asset( + direction == TransactionDirection.incoming + ? 'assets/images/down_arrow.png' + : 'assets/images/up_arrow.png'), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 12), + child: Container( + height: 46, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + (direction == TransactionDirection.incoming + ? S.of(context).received + : S.of(context).sent) + + (isPending ? S.of(context).pending : ''), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white + )), + Text(direction == TransactionDirection.incoming + ? formattedAmount + : '- ' + formattedAmount, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.white + )) + ]), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(formattedDate, + style: TextStyle( + fontSize: 14, + color: PaletteDark.darkCyanBlue)), + Text(direction == TransactionDirection.incoming + ? formattedFiatAmount + : '- ' + formattedFiatAmount, + style: TextStyle( + fontSize: 14, + color: PaletteDark.darkCyanBlue)) + ]), + ], + ), + ), + )) + ]), )); } } diff --git a/lib/src/screens/dashboard/widgets/transactions_page.dart b/lib/src/screens/dashboard/widgets/transactions_page.dart new file mode 100644 index 000000000..d6cbf0ae5 --- /dev/null +++ b/lib/src/screens/dashboard/widgets/transactions_page.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/header_row.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/date_section_raw.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/trade_row.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/transaction_raw.dart'; +import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/date_section_item.dart'; +import 'package:intl/intl.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/generated/i18n.dart'; + +class TransactionsPage extends StatelessWidget { + TransactionsPage({@required this.dashboardViewModel}); + + final DashboardViewModel dashboardViewModel; + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + top: 24, + bottom: 24 + ), + child: Column( + children: [ + HeaderRow(dashboardViewModel: dashboardViewModel), + Expanded( + child: Observer( + builder: (_) { + final items = dashboardViewModel.items; + + return items?.isNotEmpty ?? false + ? ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + + final item = items[index]; + + if (item is DateSectionItem) { + return DateSectionRaw(date: item.date); + } + + if (item is TransactionListItem) { + final transaction = item.transaction; + + return TransactionRow( + onTap: () => Navigator.of(context).pushNamed( + Routes.transactionDetails, + arguments: transaction), + direction: transaction.direction, + formattedDate: DateFormat('HH:mm') + .format(transaction.date), + formattedAmount: item.formattedCryptoAmount, + formattedFiatAmount: item.formattedFiatAmount, + isPending: transaction.isPending); + } + + if (item is TradeListItem) { + final trade = item.trade; + + return TradeRow( + onTap: () => Navigator.of(context).pushNamed( + Routes.tradeDetails, + arguments: trade), + provider: trade.provider, + from: trade.from, + to: trade.to, + createdAtFormattedDate: + DateFormat('HH:mm').format(trade.createdAt), + formattedAmount: item.tradeFormattedAmount + ); + } + + return Container( + color: Theme.of(context).backgroundColor, + height: 1); + } + ) + : Center( + child: Text( + S.of(context).placeholder_transactions, + style: TextStyle( + fontSize: 14, + color: Colors.grey + ), + ), + ); + } + ) + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/widgets/wallet_card.dart b/lib/src/screens/dashboard/widgets/wallet_card.dart deleted file mode 100644 index 041f3e89f..000000000 --- a/lib/src/screens/dashboard/widgets/wallet_card.dart +++ /dev/null @@ -1,508 +0,0 @@ -import 'dart:async'; -import 'package:cake_wallet/palette.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; -import 'package:cake_wallet/src/stores/settings/settings_store.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/src/domain/common/sync_status.dart'; -import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/view_model/dashboard_view_model.dart'; - -class WalletCard extends StatefulWidget { - WalletCard({this.walletVM}); - - final DashboardViewModel walletVM; - - @override - WalletCardState createState() => WalletCardState(); -} - -class WalletCardState extends State { - final _syncingObserverKey = GlobalKey(); - final _balanceObserverKey = GlobalKey(); - final _addressObserverKey = GlobalKey(); - - double cardWidth; - double cardHeight; - double screenWidth; - double opacity; - bool isDraw; - bool isFrontSide; - - @override - void initState() { - cardWidth = 0; - cardHeight = 220; - screenWidth = 0; - opacity = 0; - isDraw = false; - isFrontSide = true; - super.initState(); - WidgetsBinding.instance.addPostFrameCallback(afterLayout); - } - - void afterLayout(dynamic _) { - screenWidth = MediaQuery.of(context).size.width - 20; - setState(() { - cardWidth = screenWidth; - opacity = 1; - }); - Timer(Duration(milliseconds: 500), () => setState(() => isDraw = true)); - } - - @override - Widget build(BuildContext context) { - final colorsSync = [ - Theme.of(context).cardTheme.color, - Theme.of(context).hoverColor - ]; - - return Container( - width: double.infinity, - height: cardHeight, - alignment: Alignment.centerRight, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(14), bottomLeft: Radius.circular(14))), - child: AnimatedContainer( - alignment: Alignment.centerLeft, - width: cardWidth, - height: cardHeight, - duration: Duration(milliseconds: 500), - curve: Curves.fastOutSlowIn, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(14), - bottomLeft: Radius.circular(14)), - color: Theme.of(context).focusColor), - child: ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), bottomLeft: Radius.circular(10)), - child: Container( - width: cardWidth, - height: cardHeight, - color: Theme.of(context).cardColor, - child: isFrontSide - ? frontSide(colorsSync) - : InkWell( - onTap: () => setState(() => isFrontSide = true), - child: backSide(colorsSync)), - ), - )), - ); - } - - Widget frontSide(List colorsSync) { - final settingsStore = Provider.of(context); - final triangleButton = Image.asset( - 'assets/images/triangle.png', - color: Theme.of(context).primaryTextTheme.title.color, - ); - - return Observer( - key: _syncingObserverKey, - builder: (_) { - final status = widget.walletVM.status; - final statusText = status.title(); - final progress = status.progress(); - final indicatorOffset = progress * cardWidth; - final indicatorWidth = - progress <= 1 ? cardWidth - indicatorOffset : 0.0; - var descriptionText = ''; - - if (status is SyncingSyncStatus) { - descriptionText = S.of(context).Blocks_remaining(status.toString()); - } - - if (status is FailedSyncStatus) { - descriptionText = S.of(context).please_try_to_connect_to_another_node; - } - - return Container( - width: cardWidth, - height: cardHeight, - color: Colors.white, - child: Stack( - children: [ - progress <= 1 - ? Positioned( - left: indicatorOffset, - top: 0, - bottom: 0, - child: Container( - width: indicatorWidth, - height: cardHeight, - color: Color.fromRGBO(227, 238, 249, 1), - )) - : Offstage(), - isDraw - ? Positioned( - left: 24, - right: 24, - top: 32, - bottom: 24, - child: Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - InkWell( - onTap: () => Navigator.of(context) - .pushNamed(Routes.walletList), - child: Row( - children: [ - Text( - widget.walletVM.name, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - ), - SizedBox(width: 10), - triangleButton - ], - ), - ), - SizedBox(height: 5), - if (widget.walletVM.subname?.isNotEmpty ?? - false) - Text( - widget.walletVM.subname, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .caption - .color), - ) - ], - ), - InkWell( - onTap: () => - setState(() => isFrontSide = false), - child: Container( - width: 98, - height: 32, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Theme.of(context) - .accentTextTheme - .subtitle - .backgroundColor, - border: Border.all( - color: Color.fromRGBO( - 219, 231, 237, 1)), - // FIXME - borderRadius: BorderRadius.all( - Radius.circular(16))), - child: Text( - 'Receive', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - )), - ) - ], - ), - status is SyncedSyncStatus - ? Observer( - key: _balanceObserverKey, - builder: (_) { - final balanceDisplayMode = - BalanceDisplayMode.availableBalance; -// settingsStore.balanceDisplayMode; - final symbol = - settingsStore.fiatCurrency.toString(); - var balance = '---'; - var fiatBalance = '---'; - - if (balanceDisplayMode == - BalanceDisplayMode.availableBalance) { - balance = widget.walletVM.balance - .unlockedBalance ?? - '0.0'; - fiatBalance = '\$ 0.00'; -// '$symbol ${balanceStore.fiatUnlockedBalance}'; - } - - if (balanceDisplayMode == - BalanceDisplayMode.fullBalance) { - balance = widget.walletVM.balance - .totalBalance ?? - '0.0'; - fiatBalance = '\$ 0.00'; -// '$symbol ${balanceStore.fiatFullBalance}'; - } - - return Row( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - balanceDisplayMode.toString(), - style: TextStyle( - fontSize: 12, - color: Theme.of(context) - .primaryTextTheme - .caption - .color), - ), - SizedBox(height: 5), - Container( - height: 36, - child: Text( - balance, - style: TextStyle( - fontSize: 32, - color: Theme.of(context) - .primaryTextTheme - .title - .color, - fontWeight: - FontWeight.bold), - )) - ], - ), - Text( - fiatBalance, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, -// FIXME -// color: Theme.of(context) -// .primaryTextTheme -// .title -// .color, - color: Color.fromRGBO( - 72, 89, 109, 1)), - ) - ], - ); - }) - : Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - statusText, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .caption - .color), - ), - SizedBox(height: 5), - Text( - descriptionText, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - ) - ], - ) - ], - ) - ], - ), - )) - : Offstage() - ], - ), - ); - }, - ); - } - - Widget backSide(List colorsSync) { - final rightArrow = Image.asset('assets/images/right_arrow.png', - color: Theme.of(context).primaryTextTheme.title.color); - var messageBoxHeight = 0.0; - var messageBoxWidth = cardWidth - 10; - - return Observer( - key: _addressObserverKey, - builder: (_) { - return Container( - width: cardWidth, - height: cardHeight, - alignment: Alignment.topCenter, - child: Stack( - alignment: Alignment.topRight, - children: [ - Container( - width: cardWidth, - height: cardHeight, - padding: - EdgeInsets.only(left: 24, right: 24, top: 32, bottom: 32), - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(10), - bottomLeft: Radius.circular(10)), - gradient: LinearGradient( - colors: colorsSync, - begin: Alignment.topCenter, - end: Alignment.bottomCenter)), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - S.current.card_address, - style: TextStyle( - fontSize: 12, - color: Theme.of(context) - .primaryTextTheme - .caption - .color), - ), - SizedBox(height: 10), - GestureDetector( - onTap: () { - Clipboard.setData(ClipboardData( - text: widget.walletVM.address)); - _addressObserverKey.currentState - .setState(() { - messageBoxHeight = 20; - messageBoxWidth = cardWidth; - }); - Timer(Duration(milliseconds: 1000), () { - try { - _addressObserverKey.currentState - .setState(() { - messageBoxHeight = 0; - messageBoxWidth = cardWidth - 10; - }); - } catch (e) { - print('${e.toString()}'); - } - }); - }, - child: Text( - widget.walletVM.address, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - ), - ) - ], - ), - )), - SizedBox(width: 10), - Container( - width: 90, - height: 90, - child: QrImage( - data: widget.walletVM.address, - backgroundColor: Colors.transparent, - foregroundColor: Theme.of(context) - .primaryTextTheme - .caption - .color), - ) - ], - ), - Container( - height: 44, - padding: EdgeInsets.only(left: 20, right: 20), - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(22)), - color: Theme.of(context) - .primaryTextTheme - .overline - .color), - child: InkWell( - onTap: () => - Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.receive), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - S.of(context).addresses, - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - color: Theme.of(context) - .primaryTextTheme - .title - .color), - ), - rightArrow - ], - ), - ), - ) - ], - ), - ), - AnimatedContainer( - width: messageBoxWidth, - height: messageBoxHeight, - alignment: Alignment.center, - duration: Duration(milliseconds: 500), - curve: Curves.fastOutSlowIn, - decoration: BoxDecoration( - borderRadius: - BorderRadius.only(topLeft: Radius.circular(10)), - color: Colors.green), - child: Text( - S.of(context).copied_to_clipboard, - style: TextStyle(fontSize: 10, color: Colors.white), - ), - ) - ], - ), - ); - }); - } -} diff --git a/lib/store/dashboard/trade_filter_store.dart b/lib/store/dashboard/trade_filter_store.dart new file mode 100644 index 000000000..2e1c7ed62 --- /dev/null +++ b/lib/store/dashboard/trade_filter_store.dart @@ -0,0 +1,62 @@ +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; + +part 'trade_filter_store.g.dart'; + +class TradeFilterStore = TradeFilterStoreBase with _$TradeFilterStore; + +abstract class TradeFilterStoreBase with Store { + TradeFilterStoreBase( + {this.displayXMRTO = true, + this.displayChangeNow = true, + this.displayMorphToken = true, + this.wallet}); + + @observable + bool displayXMRTO; + + @observable + bool displayChangeNow; + + @observable + bool displayMorphToken; + + WalletBase wallet; + + @action + void toggleDisplayExchange(ExchangeProviderDescription provider) { + switch (provider) { + case ExchangeProviderDescription.changeNow: + displayChangeNow = !displayChangeNow; + break; + case ExchangeProviderDescription.xmrto: + displayXMRTO = !displayXMRTO; + break; + case ExchangeProviderDescription.morphToken: + displayMorphToken = !displayMorphToken; + break; + } + } + + List filtered({List trades}) { + final _trades = + trades.where((item) => item.trade.walletId == wallet.id).toList(); + final needToFilter = !displayChangeNow || !displayXMRTO || !displayMorphToken; + + return needToFilter + ? trades + .where((item) => + (displayXMRTO && + item.trade.provider == ExchangeProviderDescription.xmrto) || + (displayChangeNow && + item.trade.provider == + ExchangeProviderDescription.changeNow) || + (displayMorphToken && + item.trade.provider == + ExchangeProviderDescription.morphToken)) + .toList() + : _trades; + } +} \ No newline at end of file diff --git a/lib/store/dashboard/trades_store.dart b/lib/store/dashboard/trades_store.dart new file mode 100644 index 000000000..4f526c637 --- /dev/null +++ b/lib/store/dashboard/trades_store.dart @@ -0,0 +1,35 @@ +import 'dart:async'; +import 'package:cake_wallet/src/domain/exchange/trade.dart'; +import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:hive/hive.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/store/settings_store.dart'; + +part 'trades_store.g.dart'; + +class TradesStore = TradesStoreBase with _$TradesStore; + +abstract class TradesStoreBase with Store { + TradesStoreBase({this.tradesSource, this.settingsStore}) { + trades = []; + + _onTradesChanged = + tradesSource.watch().listen((_) async => await updateTradeList()); + + updateTradeList(); + } + + Box tradesSource; + StreamSubscription _onTradesChanged; + SettingsStore settingsStore; + + @observable + List trades; + + @action + Future updateTradeList() async => trades = + tradesSource.values.map((trade) => TradeListItem( + trade: trade, + displayMode: settingsStore.balanceDisplayMode)).toList(); +} \ No newline at end of file diff --git a/lib/store/dashboard/transaction_filter_store.dart b/lib/store/dashboard/transaction_filter_store.dart new file mode 100644 index 000000000..b55f51795 --- /dev/null +++ b/lib/store/dashboard/transaction_filter_store.dart @@ -0,0 +1,69 @@ +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; +import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; + +part 'transaction_filter_store.g.dart'; + +class TransactionFilterStore = TransactionFilterStoreBase + with _$TransactionFilterStore; + +abstract class TransactionFilterStoreBase with Store { + TransactionFilterStoreBase( + {this.displayIncoming = true, this.displayOutgoing = true}); + + @observable + bool displayIncoming; + + @observable + bool displayOutgoing; + + @observable + DateTime startDate; + + @observable + DateTime endDate; + + @action + void toggleIncoming() => displayIncoming = !displayIncoming; + + @action + void toggleOutgoing() => displayOutgoing = !displayOutgoing; + + @action + void changeStartDate(DateTime date) => startDate = date; + + @action + void changeEndDate(DateTime date) => endDate = date; + + List filtered({List transactions}) { + var _transactions = []; + final needToFilter = !displayOutgoing || + !displayIncoming || + (startDate != null && endDate != null); + + if (needToFilter) { + _transactions = transactions.where((item) { + var allowed = true; + + if (allowed && startDate != null && endDate != null) { + allowed = startDate.isBefore(item.transaction.date) && + endDate.isAfter(item.transaction.date); + } + + if (allowed && (!displayOutgoing || !displayIncoming)) { + allowed = (displayOutgoing && + item.transaction.direction == + TransactionDirection.outgoing) || + (displayIncoming && + item.transaction.direction == TransactionDirection.incoming); + } + + return allowed; + }).toList(); + } else { + _transactions = transactions; + } + + return _transactions; + } +} \ No newline at end of file diff --git a/lib/themes.dart b/lib/themes.dart index 6112394dc..a0b3d19c7 100644 --- a/lib/themes.dart +++ b/lib/themes.dart @@ -4,7 +4,7 @@ import 'palette.dart'; class Themes { static final ThemeData lightTheme = ThemeData( - fontFamily: 'Avenir Next', + fontFamily: 'Poppins', brightness: Brightness.light, backgroundColor: Colors.white, focusColor: Colors.white, // wallet card border @@ -73,7 +73,7 @@ class Themes { static final ThemeData darkTheme = ThemeData( - fontFamily: 'Avenir Next', + fontFamily: 'Poppins', brightness: Brightness.dark, backgroundColor: PaletteDark.darkNightBlue, focusColor: PaletteDark.lightDistantBlue, // wallet card border diff --git a/lib/view_model/dashboard/action_list_display_mode.dart b/lib/view_model/dashboard/action_list_display_mode.dart new file mode 100644 index 000000000..1a0708a1d --- /dev/null +++ b/lib/view_model/dashboard/action_list_display_mode.dart @@ -0,0 +1,32 @@ +enum ActionListDisplayMode { transactions, trades } + +int serializeActionlistDisplayModes(List modes) { + var i = 0; + + for (final mode in modes) { + switch (mode) { + case ActionListDisplayMode.trades: + i += 1; + break; + case ActionListDisplayMode.transactions: + i += 10; + break; + } + } + + return i; +} + +List deserializeActionlistDisplayModes(int raw) { + final modes = List(); + + if (raw == 1 || raw - 10 == 1) { + modes.add(ActionListDisplayMode.trades); + } + + if (raw >= 10) { + modes.add(ActionListDisplayMode.transactions); + } + + return modes; +} diff --git a/lib/view_model/dashboard/action_list_item.dart b/lib/view_model/dashboard/action_list_item.dart new file mode 100644 index 000000000..b03bd1bdc --- /dev/null +++ b/lib/view_model/dashboard/action_list_item.dart @@ -0,0 +1,3 @@ +abstract class ActionListItem { + DateTime get date; +} \ No newline at end of file diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart new file mode 100644 index 000000000..afb8eae62 --- /dev/null +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -0,0 +1,115 @@ +import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:cake_wallet/monero/monero_wallet.dart'; +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; +import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/view_model/dashboard/wallet_balance.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/src/stores/price/price_store.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:mobx/mobx.dart'; + +part 'balance_view_model.g.dart'; + +class BalanceViewModel = BalanceViewModelBase with _$BalanceViewModel; + +abstract class BalanceViewModelBase with Store { + BalanceViewModelBase({ + @required this.wallet, + @required this.settingsStore, + @required this.priceStore + }); + + final WalletBase wallet; + final SettingsStore settingsStore; + final PriceStore priceStore; + + WalletBalance _getWalletBalance() { + final _wallet = wallet; + + if (_wallet is MoneroWallet) { + return WalletBalance( + unlockedBalance: _wallet.balance.formattedUnlockedBalance, + totalBalance: _wallet.balance.formattedFullBalance); + } + + if (_wallet is BitcoinWallet) { + return WalletBalance( + unlockedBalance: _wallet.balance.confirmedFormatted, + totalBalance: _wallet.balance.unconfirmedFormatted); + } + } + + String _getFiatBalance({double price, String cryptoAmount}) { + if (cryptoAmount == null) { + return '0.00'; + } + + return calculateFiatAmount(price: price, cryptoAmount: cryptoAmount); + } + + @computed + double get price { + String symbol; + final _wallet = wallet; + + if (_wallet is MoneroWallet) { + symbol = PriceStoreBase.generateSymbolForPair( + fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.xmr); + } + + if (_wallet is BitcoinWallet) { + symbol = PriceStoreBase.generateSymbolForPair( + fiat: settingsStore.fiatCurrency, crypto: CryptoCurrency.btc); + } + + return priceStore.prices[symbol]; + } + + @computed + String get cryptoBalance { + final walletBalance = _getWalletBalance(); + final displayMode = settingsStore.balanceDisplayMode; + var balance = '---'; + + if (displayMode == BalanceDisplayMode.availableBalance) { + balance = walletBalance.unlockedBalance ?? '0.0'; + } + + if (displayMode == BalanceDisplayMode.fullBalance) { + balance = walletBalance.totalBalance ?? '0.0'; + } + + return balance; + } + + @computed + String get fiatBalance { + final walletBalance = _getWalletBalance(); + final displayMode = settingsStore.balanceDisplayMode; + final fiatCurrency = settingsStore.fiatCurrency; + var balance = '---'; + + final totalBalance = _getFiatBalance( + price: price, + cryptoAmount: walletBalance.totalBalance + ); + + final unlockedBalance = _getFiatBalance( + price: price, + cryptoAmount: walletBalance.unlockedBalance + ); + + if (displayMode == BalanceDisplayMode.availableBalance) { + balance = fiatCurrency.toString() + ' ' + unlockedBalance ?? '0.00'; + } + + if (displayMode == BalanceDisplayMode.fullBalance) { + balance = fiatCurrency.toString() + ' ' + totalBalance ?? '0.00'; + } + + return balance; + } + +} \ No newline at end of file diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart new file mode 100644 index 000000000..fac416af8 --- /dev/null +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -0,0 +1,145 @@ +import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; +import 'package:cake_wallet/monero/monero_wallet.dart'; +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; +import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; +import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; +import 'package:cake_wallet/src/domain/common/transaction_info.dart'; +import 'package:cake_wallet/src/domain/exchange/exchange_provider_description.dart'; +import 'package:cake_wallet/src/domain/exchange/trade.dart'; +import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/action_list_display_mode.dart'; +import 'package:mobx/mobx.dart'; +import 'package:cake_wallet/core/wallet_base.dart'; +import 'package:cake_wallet/src/domain/common/sync_status.dart'; +import 'package:cake_wallet/src/domain/common/wallet_type.dart'; +import 'package:cake_wallet/store/app_store.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/store/dashboard/trades_store.dart'; +import 'package:cake_wallet/store/dashboard/trade_filter_store.dart'; +import 'package:cake_wallet/store/dashboard/transaction_filter_store.dart'; +import 'package:cake_wallet/view_model/dashboard/formatted_item_list.dart'; + +part 'dashboard_view_model.g.dart'; + +class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel; + +abstract class DashboardViewModelBase with Store { + DashboardViewModelBase({ + this.balanceViewModel, + this.appStore, + this.tradesStore, + this.tradeFilterStore, + this.transactionFilterStore}) { + + name = appStore.wallet?.name; + wallet ??= appStore.wallet; + type = wallet.type; + + transactions = ObservableList.of(wallet.transactionHistory.transactions + .map((transaction) => TransactionListItem( + transaction: transaction, + price: price, + fiatCurrency: appStore.settingsStore.fiatCurrency, + displayMode: balanceDisplayMode))); + + _reaction = reaction((_) => appStore.wallet, _onWalletChange); + + final _wallet = wallet; + + if (_wallet is MoneroWallet) { + subname = _wallet.account?.label; + } + + currentPage = 0; + } + + @observable + WalletType type; + + @observable + String name; + + @observable + double currentPage; + + @observable + ObservableList transactions; + + @observable + String subname; + + @computed + String get address => wallet.address; + + @computed + SyncStatus get status => wallet.syncStatus; + + @computed + String get syncStatusText { + var statusText = ''; + + if (status is SyncingSyncStatus) { + statusText = S.current + .Blocks_remaining( + status.toString()); + } + + if (status is FailedSyncStatus) { + statusText = S + .current + .please_try_to_connect_to_another_node; + } + + return statusText; + } + + @computed + BalanceDisplayMode get balanceDisplayMode => + appStore.settingsStore.balanceDisplayMode; + + @computed + List get trades => tradesStore.trades; + + @computed + double get price => balanceViewModel.price; + + @computed + List get items { + final _items = []; + + _items + .addAll(transactionFilterStore.filtered(transactions: transactions)); + _items.addAll(tradeFilterStore.filtered(trades: trades)); + + return formattedItemsList(_items); + } + + WalletBase wallet; + + BalanceViewModel balanceViewModel; + + AppStore appStore; + + TradesStore tradesStore; + + TradeFilterStore tradeFilterStore; + + TransactionFilterStore transactionFilterStore; + + ReactionDisposer _reaction; + + void _onWalletChange(WalletBase wallet) { + name = wallet.name; + transactions.clear(); + transactions.addAll(wallet.transactionHistory.transactions + .map((transaction) => TransactionListItem( + transaction: transaction, + price: price, + fiatCurrency: appStore.settingsStore.fiatCurrency, + displayMode: balanceDisplayMode))); + } +} diff --git a/lib/view_model/dashboard/date_section_item.dart b/lib/view_model/dashboard/date_section_item.dart new file mode 100644 index 000000000..0b361ecce --- /dev/null +++ b/lib/view_model/dashboard/date_section_item.dart @@ -0,0 +1,8 @@ +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; + +class DateSectionItem extends ActionListItem { + DateSectionItem(this.date); + + @override + final DateTime date; +} \ No newline at end of file diff --git a/lib/view_model/dashboard/formatted_item_list.dart b/lib/view_model/dashboard/formatted_item_list.dart new file mode 100644 index 000000000..9e43cb95f --- /dev/null +++ b/lib/view_model/dashboard/formatted_item_list.dart @@ -0,0 +1,34 @@ +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import 'package:cake_wallet/view_model/dashboard/date_section_item.dart'; + +List formattedItemsList(List items) { + final formattedList = []; + DateTime lastDate; + items.sort((a, b) => b.date.compareTo(a.date)); + + for (var i = 0; i < items.length; i++) { + final transaction = items[i]; + + if (lastDate == null) { + lastDate = transaction.date; + formattedList.add(DateSectionItem(transaction.date)); + formattedList.add(transaction); + continue; + } + + final isCurrentDay = lastDate.year == transaction.date.year && + lastDate.month == transaction.date.month && + lastDate.day == transaction.date.day; + + if (isCurrentDay) { + formattedList.add(transaction); + continue; + } + + lastDate = transaction.date; + formattedList.add(DateSectionItem(transaction.date)); + formattedList.add(transaction); + } + + return formattedList; +} \ No newline at end of file diff --git a/lib/view_model/dashboard/trade_list_item.dart b/lib/view_model/dashboard/trade_list_item.dart new file mode 100644 index 000000000..a0fa24ca3 --- /dev/null +++ b/lib/view_model/dashboard/trade_list_item.dart @@ -0,0 +1,21 @@ +import 'package:cake_wallet/src/domain/exchange/trade.dart'; +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; + +class TradeListItem extends ActionListItem { + TradeListItem({this.trade, this.displayMode}); + + final Trade trade; + final BalanceDisplayMode displayMode; + + String get tradeFormattedAmount { + return trade.amount != null + ? displayMode == BalanceDisplayMode.hiddenBalance + ? '---' + : trade.amountFormatted() + : trade.amount; + } + + @override + DateTime get date => trade.createdAt; +} diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart new file mode 100644 index 000000000..6081ef8eb --- /dev/null +++ b/lib/view_model/dashboard/transaction_list_item.dart @@ -0,0 +1,54 @@ +import 'package:cake_wallet/src/domain/common/balance_display_mode.dart'; +import 'package:cake_wallet/src/domain/common/fiat_currency.dart'; +import 'package:cake_wallet/src/domain/common/transaction_info.dart'; +import 'package:cake_wallet/view_model/dashboard/action_list_item.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart'; +import 'package:cake_wallet/src/domain/monero/monero_transaction_info.dart'; +import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart'; +import 'package:cake_wallet/bitcoin/bitcoin_amount_format.dart'; +import 'package:cake_wallet/src/domain/common/calculate_fiat_amount_raw.dart'; + +class TransactionListItem extends ActionListItem { + TransactionListItem({ + this.transaction, + this.price, + this.fiatCurrency, + this.displayMode + }); + + final TransactionInfo transaction; + final double price; + final FiatCurrency fiatCurrency; + final BalanceDisplayMode displayMode; + + String get formattedCryptoAmount { + + return displayMode == BalanceDisplayMode.hiddenBalance + ? '---' + : transaction.amountFormatted(); + } + + String get formattedFiatAmount { + + if (transaction is MoneroTransactionInfo) { + final amount = calculateFiatAmountRaw( + cryptoAmount: moneroAmountToDouble(amount: transaction.amount), + price: price); + transaction.changeFiatAmount(amount); + } + + if (transaction is BitcoinTransactionInfo) { + final amount = calculateFiatAmountRaw( + cryptoAmount: bitcoinAmountToDouble(amount: transaction.amount), + price: price); + transaction.changeFiatAmount(amount); + } + + return displayMode == BalanceDisplayMode.hiddenBalance + ? '---' + : fiatCurrency.title + ' ' + transaction.fiatAmount(); + } + + @override + DateTime get date => transaction.date; +} \ No newline at end of file diff --git a/lib/view_model/dashboard/wallet_balance.dart b/lib/view_model/dashboard/wallet_balance.dart new file mode 100644 index 000000000..4a142dd30 --- /dev/null +++ b/lib/view_model/dashboard/wallet_balance.dart @@ -0,0 +1,6 @@ +class WalletBalance { + WalletBalance({this.unlockedBalance, this.totalBalance}); + + String unlockedBalance; + String totalBalance; +} \ No newline at end of file diff --git a/lib/view_model/dashboard_view_model.dart b/lib/view_model/dashboard_view_model.dart deleted file mode 100644 index ded80b3bc..000000000 --- a/lib/view_model/dashboard_view_model.dart +++ /dev/null @@ -1,169 +0,0 @@ -import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart'; -import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart'; -import 'package:cake_wallet/monero/monero_wallet.dart'; -import 'package:cake_wallet/src/domain/common/transaction_direction.dart'; -import 'package:cake_wallet/src/domain/common/transaction_info.dart'; -import 'package:cake_wallet/src/stores/action_list/transaction_list_item.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/core/wallet_base.dart'; -import 'package:cake_wallet/src/domain/common/sync_status.dart'; -import 'package:cake_wallet/src/domain/common/wallet_type.dart'; -import 'package:cake_wallet/store/app_store.dart'; - -part 'dashboard_view_model.g.dart'; - -class DashboardViewModel = DashboardViewModelBase with _$DashboardViewModel; - -class WalletBalace { - WalletBalace({this.unlockedBalance, this.totalBalance}); - - final String unlockedBalance; - final String totalBalance; -} - -abstract class DashboardViewModelBase with Store { - DashboardViewModelBase({this.appStore}) { - name = appStore.wallet?.name; - wallet ??= appStore.wallet; - type = wallet.type; - transactions = ObservableList.of(wallet.transactionHistory.transactions - .map((transaction) => TransactionListItem(transaction: transaction))); - _reaction = reaction((_) => appStore.wallet, _onWalletChange); - - final _wallet = wallet; - - if (_wallet is MoneroWallet) { - subname = _wallet.account?.label; - } - } - - @observable - WalletType type; - - @observable - String name; - - @computed - String get address => wallet.address; - - @computed - SyncStatus get status => wallet.syncStatus; - - @computed - WalletBalace get balance { - final wallet = this.wallet; - - if (wallet is MoneroWallet) { - return WalletBalace( - unlockedBalance: wallet.balance.formattedUnlockedBalance, - totalBalance: wallet.balance.formattedFullBalance); - } - - if (wallet is BitcoinWallet) { - return WalletBalace( - unlockedBalance: wallet.balance.confirmedFormatted, - totalBalance: wallet.balance.unconfirmedFormatted); - } - } - - @observable - ObservableList transactions; -// ObservableList.of([ -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// TransactionListItem(transaction: BitcoinTransactionInfo( -// id: '', -// height: 0, -// amount: 0, -// direction: TransactionDirection.incoming, -// date: DateTime.now(), -// isPending: false -// )), -// ]); - - @observable - String subname; - - WalletBase wallet; - - AppStore appStore; - - ReactionDisposer _reaction; - - void _onWalletChange(WalletBase wallet) { - name = wallet.name; - transactions.clear(); - transactions.addAll(wallet.transactionHistory.transactions - .map((transaction) => TransactionListItem(transaction: transaction))); - } -} diff --git a/pubspec.lock b/pubspec.lock index 7f3229605..f8e7304da 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -267,6 +267,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.7" + dots_indicator: + dependency: "direct main" + description: + name: dots_indicator + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" dotted_border: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 7e3b3639d..cbc8b5c67 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: devicelocale: ^0.2.1 auto_size_text: ^2.1.0 dotted_border: ^1.0.5 + dots_indicator: ^1.2.0 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. @@ -107,6 +108,11 @@ flutter: - asset: assets/fonts/Montserrat-Regular.ttf - asset: assets/fonts/Montserrat-Bold.ttf - asset: assets/fonts/Montserrat-SemiBold.ttf + - family: Poppins + fonts: + - asset: assets/fonts/Poppins-Regular.ttf + - asset: assets/fonts/Poppins-Medium.ttf + - asset: assets/fonts/Poppins-Bold.ttf # To add assets to your application, add an assets section, like this: diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index b78aad690..64f3722a8 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -137,6 +137,7 @@ "share_address" : "Share address", "receive_amount" : "Amount", "subaddresses" : "Subaddresses", + "addresses" : "Addresses", "rename" : "Rename", "choose_account" : "Choose account", "create_new_account" : "Create new account",