From 229c6c08febc6daa38561521bf344f0df203531d Mon Sep 17 00:00:00 2001 From: tuxpizza Date: Fri, 27 Dec 2024 14:46:23 -0500 Subject: [PATCH] Cleanup & fix merge conflicts (pls) [skip ci] --- .../robots/dashboard_page_robot.dart | 2 +- lib/di.dart | 2 +- lib/src/screens/dashboard/dashboard_page.dart | 442 +++--- .../dashboard/desktop_dashboard_page.dart | 2 +- .../dashboard/pages/balance/balance_page.dart | 88 ++ .../pages/balance/balance_row_widget.dart | 670 ++++++++++ .../pages/balance/crypto_balance_widget.dart | 429 ++++++ .../screens/dashboard/pages/balance_page.dart | 1183 ----------------- .../dashboard/balance_view_model.dart | 66 +- 9 files changed, 1436 insertions(+), 1448 deletions(-) create mode 100644 lib/src/screens/dashboard/pages/balance/balance_page.dart create mode 100644 lib/src/screens/dashboard/pages/balance/balance_row_widget.dart create mode 100644 lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart delete mode 100644 lib/src/screens/dashboard/pages/balance_page.dart diff --git a/integration_test/robots/dashboard_page_robot.dart b/integration_test/robots/dashboard_page_robot.dart index bc5f411ad..8e058d9b2 100644 --- a/integration_test/robots/dashboard_page_robot.dart +++ b/integration_test/robots/dashboard_page_robot.dart @@ -1,6 +1,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/crypto_balance_widget.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter_test/flutter_test.dart'; diff --git a/lib/di.dart b/lib/di.dart index 358f72a77..b3d125862 100644 --- a/lib/di.dart +++ b/lib/di.dart @@ -80,7 +80,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet import 'package:cake_wallet/src/screens/dashboard/edit_token_page.dart'; import 'package:cake_wallet/src/screens/dashboard/home_settings_page.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/address_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/balance_page.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_page.dart'; import 'package:cake_wallet/src/screens/exchange/exchange_template_page.dart'; diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart index 936f41f64..53e6c2b57 100644 --- a/lib/src/screens/dashboard/dashboard_page.dart +++ b/lib/src/screens/dashboard/dashboard_page.dart @@ -25,7 +25,7 @@ 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/menu_widget.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/balance_page.dart'; import 'package:cake_wallet/src/screens/dashboard/pages/transactions_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; @@ -62,14 +62,13 @@ class _DashboardPageState extends State { void initState() { super.initState(); - bool isMobileLayout = responsiveLayoutUtil.screenWidth < - ResponsiveLayoutUtilBase.kMobileThreshold; + bool isMobileLayout = + responsiveLayoutUtil.screenWidth < ResponsiveLayoutUtilBase.kMobileThreshold; reaction((_) => responsiveLayoutUtil.screenWidth, (screenWidth) { // Check if it was previously in mobile layout, and now changing to desktop if (isMobileLayout && - screenWidth > - ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + screenWidth > ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { setState(() { isMobileLayout = false; }); @@ -77,8 +76,7 @@ class _DashboardPageState extends State { // Check if it was previously in desktop layout, and now changing to mobile if (!isMobileLayout && - screenWidth <= - ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { + screenWidth <= ResponsiveLayoutUtilBase.kDesktopMaxDashBoardWidthConstraint) { setState(() { isMobileLayout = true; }); @@ -139,15 +137,14 @@ class _DashboardPageView extends BasePage { @override Widget Function(BuildContext, Widget) get rootWrapper => - (BuildContext context, Widget scaffold) => - GradientBackground(scaffold: scaffold); + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold); @override bool get resizeToAvoidBottomInset => false; @override - Widget get endDrawer => MenuWidget( - dashboardViewModel, ValueKey('dashboard_page_drawer_menu_widget_key')); + Widget get endDrawer => + MenuWidget(dashboardViewModel, ValueKey('dashboard_page_drawer_menu_widget_key')); @override Widget leading(BuildContext context) { @@ -167,8 +164,7 @@ class _DashboardPageView extends BasePage { return SyncIndicator( key: ValueKey('dashboard_page_sync_indicator_button_key'), dashboardViewModel: dashboardViewModel, - onTap: () => Navigator.of(context, rootNavigator: true) - .pushNamed(Routes.connectionSync), + onTap: () => Navigator.of(context, rootNavigator: true).pushNamed(Routes.connectionSync), ); } @@ -176,8 +172,7 @@ class _DashboardPageView extends BasePage { Widget trailing(BuildContext context) { final menuButton = Image.asset( 'assets/images/menu.png', - color: - Theme.of(context).extension()!.pageTitleTextColor, + color: Theme.of(context).extension()!.pageTitleTextColor, ); return Container( @@ -195,8 +190,7 @@ class _DashboardPageView extends BasePage { final BottomSheetService bottomSheetService; final WalletAddressListViewModel addressListViewModel; - int get initialPage => - dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0; + int get initialPage => dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0; ObservableList pages = ObservableList(); bool _isEffectsInstalled = false; StreamSubscription? _onInactiveSub; @@ -246,7 +240,7 @@ class _DashboardPageView extends BasePage { //), Positioned( child: Container( - alignment: Alignment.bottomCenter, + alignment: Alignment.bottomCenter, margin: EdgeInsets.only(bottom: 110), child: Observer( builder: (context) { @@ -279,165 +273,157 @@ class _DashboardPageView extends BasePage { ), ), currentTheme.type == ThemeType.bright - ? Positioned( - child: Observer( - builder: (_) { - return Container( - alignment: Alignment.bottomCenter, - height: 130, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(10), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(75), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(150), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor, - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - ], - ), - ), - child: Container( - // padding: const EdgeInsets.only( - // left: 0, right: 0, bottom: 16, top: 600), - margin: const EdgeInsets.only(left: 16, right: 16, bottom: 16), - child: ClipRRect( - borderRadius: BorderRadius.circular(50), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50), - child: Container( - height: 75, - //clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(50.0), - border: Border.all( - color: Theme.of(context) - .extension()! - .cardBorderColor, - width: 1, - ), - color: Theme.of(context) - .extension()! - .syncedBackgroundColor, - ), - child: Container( - padding: EdgeInsets.symmetric(horizontal: 10), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: MainActions.all - .where((element) => - element.canShow - ?.call(dashboardViewModel) ?? - true) - .map( - (action) => Expanded( - child: Semantics( - button: true, - enabled: (action.isEnabled?.call( - dashboardViewModel) ?? - true), - child: ActionButton( - key: ValueKey( - 'dashboard_page_${action.name(context)}_action_button_key'), - image: Image.asset( - action.image, - height: 24, - width: 24, - color: action.isEnabled?.call( - dashboardViewModel) ?? - true - ? Theme.of(context) - .extension< - DashboardPageTheme>()! - .mainActionsIconColor - : Theme.of(context) - .extension< - BalancePageTheme>()! - .labelTextColor, - ), - title: action.name(context), - onClick: () async => - await action.onTap(context, - dashboardViewModel), - textColor: action.isEnabled?.call( - dashboardViewModel) ?? - true - ? null - : Theme.of(context) - .extension< - BalancePageTheme>()! - .labelTextColor, - ), - ), - ), - ) - .toList(), - ), - ), + ? Positioned( + child: Observer( + builder: (_) { + return Container( + alignment: Alignment.bottomCenter, + height: 130, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(10), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(75), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(150), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor, + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + ], ), ), - // ], - ), - ), - ); - //); - }, - ), - ) - : Positioned( - child: Observer( - builder: (_) { - //return ClipRect( - return Container( - alignment: Alignment.bottomCenter, - height: 130, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(10), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(75), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - .withAlpha(150), - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor, - Theme.of(context) - .extension()! - .thirdGradientBackgroundColor - ], - ), - ), - child: Container( - margin: const EdgeInsets.only( - left: 16, right: 16, bottom: 16), + child: Container( + // padding: const EdgeInsets.only( + // left: 0, right: 0, bottom: 16, top: 600), + margin: const EdgeInsets.only(left: 16, right: 16, bottom: 16), + child: ClipRRect( + borderRadius: BorderRadius.circular(50), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50), + child: Container( + height: 75, + //clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(50.0), + border: Border.all( + color: Theme.of(context) + .extension()! + .cardBorderColor, + width: 1, + ), + color: Theme.of(context) + .extension()! + .syncedBackgroundColor, + ), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: MainActions.all + .where((element) => + element.canShow?.call(dashboardViewModel) ?? true) + .map( + (action) => Expanded( + child: Semantics( + button: true, + enabled: + (action.isEnabled?.call(dashboardViewModel) ?? + true), + child: ActionButton( + key: ValueKey( + 'dashboard_page_${action.name(context)}_action_button_key'), + image: Image.asset( + action.image, + height: 24, + width: 24, + color: action.isEnabled + ?.call(dashboardViewModel) ?? + true + ? Theme.of(context) + .extension()! + .mainActionsIconColor + : Theme.of(context) + .extension()! + .labelTextColor, + ), + title: action.name(context), + onClick: () async => await action.onTap( + context, dashboardViewModel), + textColor: action.isEnabled + ?.call(dashboardViewModel) ?? + true + ? null + : Theme.of(context) + .extension()! + .labelTextColor, + ), + ), + ), + ) + .toList(), + ), + ), + ), + ), + // ], + ), + ), + ); + //); + }, + ), + ) + : Positioned( + child: Observer( + builder: (_) { + //return ClipRect( + return Container( + alignment: Alignment.bottomCenter, + height: 130, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(10), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(75), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + .withAlpha(150), + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor, + Theme.of(context) + .extension()! + .thirdGradientBackgroundColor + ], + ), + ), + child: Container( + margin: const EdgeInsets.only(left: 16, right: 16, bottom: 16), child: Container( //clipBehavior: Clip.hardEdge, - height: 75, + height: 75, decoration: BoxDecoration( borderRadius: BorderRadius.circular(50.0), border: Border.all( @@ -451,75 +437,68 @@ class _DashboardPageView extends BasePage { .syncedBackgroundColor, boxShadow: [ BoxShadow( - color: Theme.of(context).extension()!.cardBorderColor + color: Theme.of(context) + .extension()! + .cardBorderColor .withAlpha(50), spreadRadius: 3, - blurRadius: 7 - ) + blurRadius: 7) ], ), child: Container( padding: EdgeInsets.symmetric(horizontal: 10), child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: MainActions.all .where((element) => - element.canShow - ?.call(dashboardViewModel) ?? - true) + element.canShow?.call(dashboardViewModel) ?? true) .map( (action) => Expanded( - child: Semantics( - button: true, - enabled: (action.isEnabled?.call( - dashboardViewModel) ?? - true), - child: ActionButton( - key: ValueKey( - 'dashboard_page_${action.name(context)}_action_button_key'), - image: Image.asset( - action.image, - height: 24, - width: 24, - color: action.isEnabled?.call( - dashboardViewModel) ?? - true - ? Theme.of(context) - .extension< - DashboardPageTheme>()! - .mainActionsIconColor - : Theme.of(context) - .extension< - BalancePageTheme>()! - .labelTextColor, + child: Semantics( + button: true, + enabled: + (action.isEnabled?.call(dashboardViewModel) ?? + true), + child: ActionButton( + key: ValueKey( + 'dashboard_page_${action.name(context)}_action_button_key'), + image: Image.asset( + action.image, + height: 24, + width: 24, + color: + action.isEnabled?.call(dashboardViewModel) ?? + true + ? Theme.of(context) + .extension()! + .mainActionsIconColor + : Theme.of(context) + .extension()! + .labelTextColor, + ), + title: action.name(context), + onClick: () async => + await action.onTap(context, dashboardViewModel), + textColor: + action.isEnabled?.call(dashboardViewModel) ?? + true + ? null + : Theme.of(context) + .extension()! + .labelTextColor, + ), ), - title: action.name(context), - onClick: () async => - await action.onTap(context, - dashboardViewModel), - textColor: action.isEnabled?.call( - dashboardViewModel) ?? - true - ? null - : Theme.of(context) - .extension< - BalancePageTheme>()! - .labelTextColor, ), - ), - ), - ) + ) .toList(), ), ), ), - ), - - ); - }, - ), - ), + ), + ); + }, + ), + ), ], ), ), @@ -591,10 +570,9 @@ class _DashboardPageView extends BasePage { void _showReleaseNotesPopup(BuildContext context) async { final sharedPrefs = await SharedPreferences.getInstance(); - final currentAppVersion = VersionComparator.getExtendedVersionNumber( - dashboardViewModel.settingsStore.appVersion); - final lastSeenAppVersion = - sharedPrefs.getInt(PreferencesKey.lastSeenAppVersion); + final currentAppVersion = + VersionComparator.getExtendedVersionNumber(dashboardViewModel.settingsStore.appVersion); + final lastSeenAppVersion = sharedPrefs.getInt(PreferencesKey.lastSeenAppVersion); final isNewInstall = sharedPrefs.getBool(PreferencesKey.isNewInstall); if (currentAppVersion != lastSeenAppVersion && !isNewInstall!) { @@ -619,8 +597,7 @@ class _DashboardPageView extends BasePage { } void _showVulnerableSeedsPopup(BuildContext context) async { - final List affectedWalletNames = - await dashboardViewModel.checkAffectedWallets(); + final List affectedWalletNames = await dashboardViewModel.checkAffectedWallets(); if (affectedWalletNames.isNotEmpty) { Future.delayed( @@ -638,8 +615,7 @@ class _DashboardPageView extends BasePage { } void _showHavenPopup(BuildContext context) async { - final List havenWalletList = - await dashboardViewModel.checkForHavenWallets(); + final List havenWalletList = await dashboardViewModel.checkForHavenWallets(); if (havenWalletList.isNotEmpty) { Future.delayed( diff --git a/lib/src/screens/dashboard/desktop_dashboard_page.dart b/lib/src/screens/dashboard/desktop_dashboard_page.dart index b25d0774b..c7cd67dfa 100644 --- a/lib/src/screens/dashboard/desktop_dashboard_page.dart +++ b/lib/src/screens/dashboard/desktop_dashboard_page.dart @@ -8,7 +8,7 @@ import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/version_comparator.dart'; import 'package:flutter/material.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/balance_page.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/balance_page.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/router.dart' as Router; diff --git a/lib/src/screens/dashboard/pages/balance/balance_page.dart b/lib/src/screens/dashboard/pages/balance/balance_page.dart new file mode 100644 index 000000000..6ad8798ea --- /dev/null +++ b/lib/src/screens/dashboard/pages/balance/balance_page.dart @@ -0,0 +1,88 @@ +import 'package:cake_wallet/reactions/wallet_connect.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/crypto_balance_widget.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; +import 'package:cake_wallet/store/settings_store.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; + +class BalancePage extends StatelessWidget { + BalancePage({ + required this.dashboardViewModel, + required this.settingsStore, + required this.nftViewModel, + }); + + final DashboardViewModel dashboardViewModel; + final NFTViewModel nftViewModel; + final SettingsStore settingsStore; + + @override + Widget build(BuildContext context) { + return Observer( + builder: (context) { + final isEVMCompatible = isEVMCompatibleChain(dashboardViewModel.type); + return DefaultTabController( + length: isEVMCompatible ? 2 : 1, + child: Column( + children: [ + if (isEVMCompatible) + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.only(left: 8), + child: TabBar( + indicatorSize: TabBarIndicatorSize.label, + isScrollable: true, + physics: NeverScrollableScrollPhysics(), + labelStyle: TextStyle( + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: + Theme.of(context).extension()!.pageTitleTextColor, + height: 1, + ), + unselectedLabelStyle: TextStyle( + fontSize: 18, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: + Theme.of(context).extension()!.pageTitleTextColor, + height: 1, + ), + labelColor: + Theme.of(context).extension()!.pageTitleTextColor, + dividerColor: Colors.transparent, + indicatorColor: + Theme.of(context).extension()!.pageTitleTextColor, + unselectedLabelColor: Theme.of(context) + .extension()! + .pageTitleTextColor + .withOpacity(0.5), + tabAlignment: TabAlignment.start, + tabs: [ + Tab(text: 'My Crypto'), + Tab(text: 'My NFTs'), + ], + ), + ), + ), + Expanded( + child: TabBarView( + physics: NeverScrollableScrollPhysics(), + children: [ + CryptoBalanceWidget(dashboardViewModel: dashboardViewModel), + if (isEVMCompatible) NFTListingPage(nftViewModel: nftViewModel) + ], + ), + ), + ], + ), + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/pages/balance/balance_row_widget.dart b/lib/src/screens/dashboard/pages/balance/balance_row_widget.dart new file mode 100644 index 000000000..9d26bd007 --- /dev/null +++ b/lib/src/screens/dashboard/pages/balance/balance_row_widget.dart @@ -0,0 +1,670 @@ +import 'dart:math'; + +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; +import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; +import 'package:cake_wallet/utils/payment_request.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:cw_core/crypto_currency.dart'; +import 'package:cw_core/unspent_coin_type.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class BalanceRowWidget extends StatelessWidget { + BalanceRowWidget({ + required this.availableBalanceLabel, + required this.availableBalance, + required this.availableFiatBalance, + required this.additionalBalanceLabel, + required this.additionalBalance, + required this.additionalFiatBalance, + required this.secondAvailableBalanceLabel, + required this.secondAvailableBalance, + required this.secondAvailableFiatBalance, + required this.secondAdditionalBalanceLabel, + required this.secondAdditionalBalance, + required this.secondAdditionalFiatBalance, + required this.frozenBalance, + required this.frozenFiatBalance, + required this.currency, + required this.hasAdditionalBalance, + required this.hasSecondAvailableBalance, + required this.hasSecondAdditionalBalance, + required this.isTestnet, + required this.dashboardViewModel, + super.key, + }); + + final String availableBalanceLabel; + final String availableBalance; + final String availableFiatBalance; + final String additionalBalanceLabel; + final String additionalBalance; + final String additionalFiatBalance; + final String secondAvailableBalanceLabel; + final String secondAvailableBalance; + final String secondAvailableFiatBalance; + final String secondAdditionalBalanceLabel; + final String secondAdditionalBalance; + final String secondAdditionalFiatBalance; + final String frozenBalance; + final String frozenFiatBalance; + final CryptoCurrency currency; + final bool hasAdditionalBalance; + final bool hasSecondAvailableBalance; + final bool hasSecondAdditionalBalance; + final bool isTestnet; + final DashboardViewModel dashboardViewModel; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + margin: const EdgeInsets.only(left: 16, right: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + border: Border.all( + color: Theme.of(context).extension()!.cardBorderColor, + width: 1, + ), + color: Theme.of(context).extension()!.syncedBackgroundColor, + boxShadow: [ + BoxShadow( + color: Theme.of(context).extension()!.cardBorderColor + .withAlpha(50), + spreadRadius: 3, + blurRadius: 7 + ) + ], + ), + child: Container( + margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: hasAdditionalBalance + ? () => _showBalanceDescription( + context, S.of(context).available_balance_description) + : null, + child: Row( + children: [ + Semantics( + hint: 'Double tap to see more information', + container: true, + child: Text('${availableBalanceLabel}', + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1)), + ), + if (hasAdditionalBalance) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ), + ], + ), + ), + SizedBox(height: 6), + AutoSizeText(availableBalance, + style: TextStyle( + fontSize: 24, + fontFamily: 'Lato', + fontWeight: FontWeight.w900, + color: Theme.of(context) + .extension()! + .balanceAmountColor, + height: 1), + maxLines: 1, + textAlign: TextAlign.start), + SizedBox(height: 6), + if (isTestnet) + Text(S.of(context).testnet_coins_no_value, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: + Theme.of(context).extension()!.textColor, + height: 1)), + if (!isTestnet) + Text('${availableFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + color: + Theme.of(context).extension()!.textColor, + height: 1)), + ], + ), + SizedBox( + width: min(MediaQuery.of(context).size.width * 0.2, 100), + child: Center( + child: Column( + children: [ + CakeImageWidget( + imageUrl: currency.iconPath, + height: 40, + width: 40, + displayOnError: Container( + height: 30.0, + width: 30.0, + child: Center( + child: Text( + currency.title.substring(0, min(currency.title.length, 2)), + style: TextStyle(fontSize: 11), + ), + ), + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade400, + ), + ), + ), + const SizedBox(height: 10), + Text( + currency.title, + style: TextStyle( + fontSize: 15, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + ), + ], + ), + ), + ), + ], + ), + ), + if (frozenBalance.isNotEmpty) + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: hasAdditionalBalance + ? () => _showBalanceDescription( + context, S.of(context).unavailable_balance_description) + : null, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 26), + Row( + children: [ + Text( + S.of(context).unavailable_balance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: + Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ), + ], + ), + SizedBox(height: 8), + AutoSizeText( + frozenBalance, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: + Theme.of(context).extension()!.balanceAmountColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + SizedBox(height: 4), + if (!isTestnet) + Text( + frozenFiatBalance, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), + ), + ], + ), + ), + if (hasAdditionalBalance) + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 24), + Text( + '${additionalBalanceLabel}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + ), + SizedBox(height: 8), + AutoSizeText( + additionalBalance, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.assetTitleColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + SizedBox(height: 4), + if (!isTestnet) + Text( + '${additionalFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.textColor, + height: 1, + ), + ), + ], + ), + ), + ], + ), + ), + ), + if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[ + SizedBox(height: 16), + Container( + margin: const EdgeInsets.only(left: 16, right: 16), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30.0), + border: Border.all( + color: Theme.of(context).extension()!.cardBorderColor, + width: 1, + ), + color: Theme.of(context).extension()!.syncedBackgroundColor, + boxShadow: [ + BoxShadow( + color: Theme.of(context).extension()!.cardBorderColor + .withAlpha(50), + spreadRadius: 3, + blurRadius: 7 + ) + ], + ), + child: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16), + child: Stack( + children: [ + if (currency == CryptoCurrency.ltc) + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + padding: EdgeInsets.only(right: 16, top: 0), + child: Column( + children: [ + Container( + child: ImageIcon( + AssetImage('assets/images/mweb_logo.png'), + color: Theme.of(context) + .extension()! + .assetTitleColor, + size: 40, + ), + ), + const SizedBox(height: 10), + Text( + 'MWEB', + style: TextStyle( + fontSize: 15, + fontFamily: 'Lato', + fontWeight: FontWeight.w800, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + ), + ], + ), + ), + ], + ), + if (hasSecondAvailableBalance) + GestureDetector( + onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), + child: Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => launchUrl( + Uri.parse( + "https://docs.cakewallet.com/cryptos/litecoin.html#mweb"), + mode: LaunchMode.externalApplication, + ), + child: Row( + children: [ + Text( + '${secondAvailableBalanceLabel}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ) + ], + ), + ), + SizedBox(height: 8), + AutoSizeText( + secondAvailableBalance, + style: TextStyle( + fontSize: 24, + fontFamily: 'Lato', + fontWeight: FontWeight.w900, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + SizedBox(height: 6), + if (!isTestnet) + Text( + '${secondAvailableFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontFamily: 'Lato', + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .textColor, + height: 1, + ), + ), + ], + ), + ], + ), + ), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 0, left: 24, right: 8, bottom: 16), + child: Stack( + children: [ + if (hasSecondAdditionalBalance) + Row( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 24), + Text( + '${secondAdditionalBalanceLabel}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1, + ), + ), + SizedBox(height: 8), + AutoSizeText( + secondAdditionalBalance, + style: TextStyle( + fontSize: 20, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .assetTitleColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + SizedBox(height: 4), + if (!isTestnet) + Text( + '${secondAdditionalFiatBalance}', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .textColor, + height: 1, + ), + ), + ], + ), + ], + ), + ], + ), + ), + IntrinsicHeight( + child: Container( + padding: EdgeInsets.symmetric(horizontal: 24), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Semantics( + label: S.of(context).litecoin_mweb_pegin, + child: OutlinedButton( + onPressed: () { + final mwebAddress = + bitcoin!.getUnusedMwebAddress(dashboardViewModel.wallet); + PaymentRequest? paymentRequest = null; + if ((mwebAddress?.isNotEmpty ?? false)) { + paymentRequest = PaymentRequest.fromUri( + Uri.parse("litecoin:${mwebAddress}")); + } + Navigator.pushNamed( + context, + Routes.send, + arguments: { + 'paymentRequest': paymentRequest, + 'coinTypeToSpendFrom': UnspentCoinType.nonMweb, + }, + ); + }, + style: OutlinedButton.styleFrom( + backgroundColor: Colors.grey.shade400.withAlpha(50), + side: BorderSide( + color: Colors.grey.shade400.withAlpha(50), width: 0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + ), + child: Container( + padding: EdgeInsets.symmetric(vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + height: 30, + width: 30, + 'assets/images/received.png', + color: Theme.of(context) + .extension()! + .balanceAmountColor, + ), + const SizedBox(width: 8), + Text( + S.of(context).litecoin_mweb_pegin, + style: TextStyle( + color: Theme.of(context) + .extension()! + .textColor, + ), + ), + ], + ), + ), + ), + ), + ), + SizedBox(width: 24), + Expanded( + child: Semantics( + label: S.of(context).litecoin_mweb_pegout, + child: OutlinedButton( + onPressed: () { + final litecoinAddress = + bitcoin!.getUnusedSegwitAddress(dashboardViewModel.wallet); + PaymentRequest? paymentRequest = null; + if ((litecoinAddress?.isNotEmpty ?? false)) { + paymentRequest = PaymentRequest.fromUri( + Uri.parse("litecoin:${litecoinAddress}")); + } + Navigator.pushNamed( + context, + Routes.send, + arguments: { + 'paymentRequest': paymentRequest, + 'coinTypeToSpendFrom': UnspentCoinType.mweb, + }, + ); + }, + style: OutlinedButton.styleFrom( + backgroundColor: Colors.grey.shade400.withAlpha(50), + side: BorderSide( + color: Colors.grey.shade400.withAlpha(50), width: 0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + ), + child: Container( + padding: EdgeInsets.symmetric(vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + height: 30, + width: 30, + 'assets/images/upload.png', + color: Theme.of(context) + .extension()! + .balanceAmountColor, + ), + const SizedBox(width: 8), + Text( + S.of(context).litecoin_mweb_pegout, + style: TextStyle( + color: Theme.of(context) + .extension()! + .textColor, + ), + ), + ], + ), + ), + ), + ), + ), + ], + ), + ), + ), + SizedBox(height: 16), + ], + ), + ), + ), + ], + ], + ); + } + + void _showBalanceDescription(BuildContext context, String content) { + showPopUp(context: context, builder: (_) => InformationPage(information: content)); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart new file mode 100644 index 000000000..5bd001ffe --- /dev/null +++ b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart @@ -0,0 +1,429 @@ +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/dashboard/pages/balance/balance_row_widget.dart'; +import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; +import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; +import 'package:cake_wallet/src/widgets/introducing_card.dart'; +import 'package:cake_wallet/src/widgets/standard_switch.dart'; +import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; +import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; +import 'package:cake_wallet/utils/feature_flag.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class CryptoBalanceWidget extends StatelessWidget { + const CryptoBalanceWidget({ + super.key, + required this.dashboardViewModel, + }); + + final DashboardViewModel dashboardViewModel; + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Observer( + builder: (_) { + if (dashboardViewModel.getMoneroError != null) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: DashBoardRoundedCardWidget( + title: "Invalid monero bindings", + subTitle: dashboardViewModel.getMoneroError.toString(), + onTap: () {}, + ), + ); + } + return Container(); + }, + ), + Observer( + builder: (_) { + if (dashboardViewModel.getWowneroError != null) { + return Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: DashBoardRoundedCardWidget( + title: "Invalid wownero bindings", + subTitle: dashboardViewModel.getWowneroError.toString(), + onTap: () {}, + )); + } + return Container(); + }, + ), + Observer( + builder: (_) => dashboardViewModel.balanceViewModel.hasAccounts + ? HomeScreenAccountWidget( + walletName: dashboardViewModel.name, accountName: dashboardViewModel.subname) + : Column( + children: [ + SizedBox(height: 16), + Container( + margin: const EdgeInsets.only(left: 24, bottom: 16), + child: Observer( + builder: (_) { + return Row( + children: [ + Text( + dashboardViewModel.balanceViewModel.asset, + style: TextStyle( + fontSize: 24, + fontFamily: 'Lato', + fontWeight: FontWeight.w600, + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + height: 1, + ), + maxLines: 1, + textAlign: TextAlign.center, + ), + if (dashboardViewModel.wallet.isHardwareWallet) + Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/hardware_wallet/ledger_nano_x.png', + width: 24, + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + ), + ), + if (dashboardViewModel + .balanceViewModel.isHomeScreenSettingsEnabled) + InkWell( + onTap: () => Navigator.pushNamed(context, Routes.homeSettings, + arguments: dashboardViewModel.balanceViewModel), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Image.asset( + 'assets/images/home_screen_settings_icon.png', + color: Theme.of(context) + .extension()! + .pageTitleTextColor, + ), + ), + ), + ], + ); + }, + ), + ), + ], + )), + Observer( + builder: (_) { + if (dashboardViewModel.balanceViewModel.isShowCard && FeatureFlag.isCakePayEnabled) { + return IntroducingCard( + title: S.of(context).introducing_cake_pay, + subTitle: S.of(context).cake_pay_learn_more, + borderColor: Theme.of(context).extension()!.cardBorderColor, + closeCard: dashboardViewModel.balanceViewModel.disableIntroCakePayCard); + } + return Container(); + }, + ), + Observer(builder: (_) { + if (!dashboardViewModel.showRepWarning) { + return const SizedBox(); + } + return Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + title: S.of(context).rep_warning, + subTitle: S.of(context).rep_warning_sub, + onTap: () => Navigator.of(context).pushNamed(Routes.changeRep), + onClose: () { + dashboardViewModel.settingsStore.shouldShowRepWarning = false; + }, + ), + ); + }), + Observer( + builder: (_) { + return ListView.separated( + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + separatorBuilder: (_, __) => Container(padding: EdgeInsets.only(bottom: 16)), + itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length, + itemBuilder: (__, index) { + final balance = + dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index); + return Observer(builder: (_) { + return BalanceRowWidget( + dashboardViewModel: dashboardViewModel, + availableBalanceLabel: + '${dashboardViewModel.balanceViewModel.availableBalanceLabel}', + availableBalance: balance.availableBalance, + availableFiatBalance: balance.fiatAvailableBalance, + additionalBalanceLabel: + '${dashboardViewModel.balanceViewModel.additionalBalanceLabel}', + additionalBalance: balance.additionalBalance, + additionalFiatBalance: balance.fiatAdditionalBalance, + frozenBalance: balance.frozenBalance, + frozenFiatBalance: balance.fiatFrozenBalance, + currency: balance.asset, + hasAdditionalBalance: + dashboardViewModel.balanceViewModel.hasAdditionalBalance, + hasSecondAdditionalBalance: + dashboardViewModel.balanceViewModel.hasSecondAdditionalBalance, + hasSecondAvailableBalance: + dashboardViewModel.balanceViewModel.hasSecondAvailableBalance, + secondAdditionalBalance: balance.secondAdditionalBalance, + secondAdditionalFiatBalance: balance.fiatSecondAdditionalBalance, + secondAvailableBalance: balance.secondAvailableBalance, + secondAvailableFiatBalance: balance.fiatSecondAvailableBalance, + secondAdditionalBalanceLabel: + '${dashboardViewModel.balanceViewModel.secondAdditionalBalanceLabel}', + secondAvailableBalanceLabel: + '${dashboardViewModel.balanceViewModel.secondAvailableBalanceLabel}', + isTestnet: dashboardViewModel.isTestnet, + ); + }); + }, + ); + }, + ), + SizedBox(height: 150), + Observer(builder: (context) { + return Column( + children: [ + if (dashboardViewModel.isMoneroWalletBrokenReasons.isNotEmpty) ...[ + SizedBox(height: 10), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + customBorder: 30, + title: "This wallet has encountered an issue", + subTitle: "Here are the things that you should note:\n - " + + dashboardViewModel.isMoneroWalletBrokenReasons.join("\n - ") + + "\n\nPlease restart your wallet and if it doesn't help contact our support.", + onTap: () {}, + )) + ], + if (dashboardViewModel.showSilentPaymentsCard) ...[ + SizedBox(height: 16), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + marginV: 0, + marginH: 0, + customBorder: 30, + title: S.of(context).silent_payments, + subTitle: S.of(context).enable_silent_payments_scanning, + hint: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => launchUrl( + Uri.parse( + "https://docs.cakewallet.com/cryptos/bitcoin#silent-payments"), + mode: LaunchMode.externalApplication, + ), + child: Row( + children: [ + Text( + S.of(context).what_is_silent_payments, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context) + .extension()! + .labelTextColor, + height: 1, + ), + softWrap: true, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Icon(Icons.help_outline, + size: 16, + color: Theme.of(context) + .extension()! + .labelTextColor), + ) + ], + ), + ), + Observer( + builder: (_) => StandardSwitch( + value: dashboardViewModel.silentPaymentsScanningActive, + onTaped: () => _toggleSilentPaymentsScanning(context), + ), + ) + ], + ), + ], + ), + onTap: () => _toggleSilentPaymentsScanning(context), + icon: Icon( + Icons.lock, + color: + Theme.of(context).extension()!.pageTitleTextColor, + size: 50, + ), + ), + ), + ], + if (dashboardViewModel.showMwebCard) ...[ + SizedBox(height: 16), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: DashBoardRoundedCardWidget( + marginV: 0, + marginH: 0, + customBorder: 30, + title: S.of(context).litecoin_mweb, + subTitle: S.of(context).litecoin_mweb_description, + hint: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => launchUrl( + Uri.parse("https://docs.cakewallet.com/cryptos/litecoin/#mweb"), + mode: LaunchMode.externalApplication, + ), + child: Text( + S.of(context).learn_more, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: + Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + softWrap: true, + ), + ), + SizedBox(height: 8), + Row( + children: [ + Expanded( + child: ElevatedButton( + onPressed: () => _dismissMweb(context), + style: ElevatedButton.styleFrom( + backgroundColor: Theme.of(context).primaryColor, + ), + child: Text( + S.of(context).litecoin_mweb_dismiss, + style: TextStyle(color: Colors.white), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: ElevatedButton( + onPressed: () => _enableMweb(context), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: Colors.black, + ), + child: Text( + S.of(context).enable, + maxLines: 1, + ), + ), + ), + ], + ), + ], + ), + onTap: () => {}, + icon: Container( + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + child: ImageIcon( + AssetImage('assets/images/mweb_logo.png'), + color: Color.fromARGB(255, 11, 70, 129), + size: 40, + ), + ), + ), + ), + ], + ], + ); + }), + ], + ), + ); + } + + Future _toggleSilentPaymentsScanning(BuildContext context) async { + final isSilentPaymentsScanningActive = dashboardViewModel.silentPaymentsScanningActive; + final newValue = !isSilentPaymentsScanningActive; + + dashboardViewModel.silentPaymentsScanningActive = newValue; + + final needsToSwitch = !isSilentPaymentsScanningActive && + await bitcoin!.getNodeIsElectrsSPEnabled(dashboardViewModel.wallet) == false; + + if (needsToSwitch) { + return showPopUp( + context: context, + builder: (BuildContext context) => AlertWithTwoActions( + alertTitle: S.of(context).change_current_node_title, + alertContent: S.of(context).confirm_silent_payments_switch_node, + rightButtonText: S.of(context).confirm, + leftButtonText: S.of(context).cancel, + actionRightButton: () { + dashboardViewModel.setSilentPaymentsScanning(newValue); + Navigator.of(context).pop(); + }, + actionLeftButton: () { + dashboardViewModel.silentPaymentsScanningActive = isSilentPaymentsScanningActive; + Navigator.of(context).pop(); + }, + )); + } + + return dashboardViewModel.setSilentPaymentsScanning(newValue); + } + + Future _enableMweb(BuildContext context) async { + if (!dashboardViewModel.hasEnabledMwebBefore) { + await showPopUp( + context: context, + builder: (BuildContext context) => AlertWithOneAction( + alertTitle: S.of(context).alert_notice, + alertContent: S.of(context).litecoin_mweb_warning, + buttonText: S.of(context).understand, + buttonAction: () { + Navigator.of(context).pop(); + }, + )); + } + dashboardViewModel.setMwebEnabled(); + } + + Future _dismissMweb(BuildContext context) async { + await showPopUp( + context: context, + builder: (BuildContext context) => AlertWithOneAction( + alertTitle: S.of(context).alert_notice, + alertContent: S.of(context).litecoin_mweb_enable_later, + buttonText: S.of(context).understand, + buttonAction: () { + Navigator.of(context).pop(); + }, + )); + dashboardViewModel.dismissMweb(); + } +} \ No newline at end of file diff --git a/lib/src/screens/dashboard/pages/balance_page.dart b/lib/src/screens/dashboard/pages/balance_page.dart deleted file mode 100644 index b3bc6d775..000000000 --- a/lib/src/screens/dashboard/pages/balance_page.dart +++ /dev/null @@ -1,1183 +0,0 @@ -import 'dart:math'; - -import 'package:auto_size_text/auto_size_text.dart'; -import 'package:cake_wallet/bitcoin/bitcoin.dart'; -import 'package:cake_wallet/generated/i18n.dart'; -import 'package:cake_wallet/reactions/wallet_connect.dart'; -import 'package:cake_wallet/routes.dart'; -import 'package:cake_wallet/src/screens/dashboard/pages/nft_listing_page.dart'; -import 'package:cake_wallet/src/screens/dashboard/widgets/home_screen_account_widget.dart'; -import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; -import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; -import 'package:cake_wallet/src/widgets/cake_image_widget.dart'; -import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart'; -import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; -import 'package:cake_wallet/src/widgets/introducing_card.dart'; -import 'package:cake_wallet/src/widgets/standard_switch.dart'; -import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/themes/extensions/balance_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart'; -import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart'; -import 'package:cake_wallet/utils/feature_flag.dart'; -import 'package:cake_wallet/utils/payment_request.dart'; -import 'package:cake_wallet/utils/show_pop_up.dart'; -import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; -import 'package:cake_wallet/view_model/dashboard/nft_view_model.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/unspent_coin_type.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_mobx/flutter_mobx.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class BalancePage extends StatelessWidget { - BalancePage({ - required this.dashboardViewModel, - required this.settingsStore, - required this.nftViewModel, - }); - - final DashboardViewModel dashboardViewModel; - final NFTViewModel nftViewModel; - final SettingsStore settingsStore; - - @override - Widget build(BuildContext context) { - return Observer( - builder: (context) { - final isEVMCompatible = isEVMCompatibleChain(dashboardViewModel.type); - return DefaultTabController( - length: isEVMCompatible ? 2 : 1, - child: Column( - children: [ - if (isEVMCompatible) - Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.only(left: 8), - child: TabBar( - indicatorSize: TabBarIndicatorSize.label, - isScrollable: true, - physics: NeverScrollableScrollPhysics(), - labelStyle: TextStyle( - fontSize: 18, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: - Theme.of(context).extension()!.pageTitleTextColor, - height: 1, - ), - unselectedLabelStyle: TextStyle( - fontSize: 18, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: - Theme.of(context).extension()!.pageTitleTextColor, - height: 1, - ), - labelColor: - Theme.of(context).extension()!.pageTitleTextColor, - dividerColor: Colors.transparent, - indicatorColor: - Theme.of(context).extension()!.pageTitleTextColor, - unselectedLabelColor: Theme.of(context) - .extension()! - .pageTitleTextColor - .withOpacity(0.5), - tabAlignment: TabAlignment.start, - tabs: [ - Tab(text: 'My Crypto'), - Tab(text: 'My NFTs'), - ], - ), - ), - ), - Expanded( - child: TabBarView( - physics: NeverScrollableScrollPhysics(), - children: [ - CryptoBalanceWidget(dashboardViewModel: dashboardViewModel), - if (isEVMCompatible) NFTListingPage(nftViewModel: nftViewModel) - ], - ), - ), - ], - ), - ); - }, - ); - } -} - -class CryptoBalanceWidget extends StatelessWidget { - const CryptoBalanceWidget({ - super.key, - required this.dashboardViewModel, - }); - - final DashboardViewModel dashboardViewModel; - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Observer( - builder: (_) { - if (dashboardViewModel.getMoneroError != null) { - return Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: DashBoardRoundedCardWidget( - title: "Invalid monero bindings", - subTitle: dashboardViewModel.getMoneroError.toString(), - onTap: () {}, - ), - ); - } - return Container(); - }, - ), - Observer( - builder: (_) { - if (dashboardViewModel.getWowneroError != null) { - return Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - child: DashBoardRoundedCardWidget( - title: "Invalid wownero bindings", - subTitle: dashboardViewModel.getWowneroError.toString(), - onTap: () {}, - )); - } - return Container(); - }, - ), - Observer( - builder: (_) => dashboardViewModel.balanceViewModel.hasAccounts - ? HomeScreenAccountWidget( - walletName: dashboardViewModel.name, - accountName: dashboardViewModel.subname) - : Column( - children: [ - SizedBox(height: 16), - Container( - margin: const EdgeInsets.only(left: 24, bottom: 16), - child: Observer( - builder: (_) { - return Row( - children: [ - Text( - dashboardViewModel.balanceViewModel.asset, - style: TextStyle( - fontSize: 24, - fontFamily: 'Lato', - fontWeight: FontWeight.w600, - color: Theme.of(context) - .extension()! - .pageTitleTextColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - if (dashboardViewModel.wallet.isHardwareWallet) - Padding( - padding: const EdgeInsets.all(8.0), - child: Image.asset( - 'assets/images/hardware_wallet/ledger_nano_x.png', - width: 24, - color: Theme.of(context) - .extension()! - .pageTitleTextColor, - ), - ), - if (dashboardViewModel - .balanceViewModel.isHomeScreenSettingsEnabled) - InkWell( - onTap: () => Navigator.pushNamed( - context, Routes.homeSettings, - arguments: dashboardViewModel.balanceViewModel), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Image.asset( - 'assets/images/home_screen_settings_icon.png', - color: Theme.of(context) - .extension()! - .pageTitleTextColor, - ), - ), - ), - ], - ); - }, - ), - ), - ], - )), - Observer( - builder: (_) { - if (dashboardViewModel.balanceViewModel.isShowCard && - FeatureFlag.isCakePayEnabled) { - return IntroducingCard( - title: S.of(context).introducing_cake_pay, - subTitle: S.of(context).cake_pay_learn_more, - borderColor: Theme.of(context).extension()!.cardBorderColor, - closeCard: dashboardViewModel.balanceViewModel.disableIntroCakePayCard); - } - return Container(); - }, - ), - Observer(builder: (_) { - if (!dashboardViewModel.showRepWarning) { - return const SizedBox(); - } - return Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), - child: DashBoardRoundedCardWidget( - title: S.of(context).rep_warning, - subTitle: S.of(context).rep_warning_sub, - onTap: () => Navigator.of(context).pushNamed(Routes.changeRep), - onClose: () { - dashboardViewModel.settingsStore.shouldShowRepWarning = false; - }, - ), - ); - }), - Observer( - builder: (_) { - return ListView.separated( - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - separatorBuilder: (_, __) => Container(padding: EdgeInsets.only(bottom: 16)), - itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length, - itemBuilder: (__, index) { - final balance = - dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index); - return Observer(builder: (_) { - return BalanceRowWidget( - dashboardViewModel: dashboardViewModel, - availableBalanceLabel: - '${dashboardViewModel.balanceViewModel.availableBalanceLabel}', - availableBalance: balance.availableBalance, - availableFiatBalance: balance.fiatAvailableBalance, - additionalBalanceLabel: - '${dashboardViewModel.balanceViewModel.additionalBalanceLabel}', - additionalBalance: balance.additionalBalance, - additionalFiatBalance: balance.fiatAdditionalBalance, - frozenBalance: balance.frozenBalance, - frozenFiatBalance: balance.fiatFrozenBalance, - currency: balance.asset, - hasAdditionalBalance: - dashboardViewModel.balanceViewModel.hasAdditionalBalance, - hasSecondAdditionalBalance: - dashboardViewModel.balanceViewModel.hasSecondAdditionalBalance, - hasSecondAvailableBalance: - dashboardViewModel.balanceViewModel.hasSecondAvailableBalance, - secondAdditionalBalance: balance.secondAdditionalBalance, - secondAdditionalFiatBalance: balance.fiatSecondAdditionalBalance, - secondAvailableBalance: balance.secondAvailableBalance, - secondAvailableFiatBalance: balance.fiatSecondAvailableBalance, - secondAdditionalBalanceLabel: - '${dashboardViewModel.balanceViewModel.secondAdditionalBalanceLabel}', - secondAvailableBalanceLabel: - '${dashboardViewModel.balanceViewModel.secondAvailableBalanceLabel}', - isTestnet: dashboardViewModel.isTestnet, - ); - }); - }, - ); - }, - ), - SizedBox(height: 150), - Observer(builder: (context) { - return Column( - children: [ - if (dashboardViewModel.isMoneroWalletBrokenReasons.isNotEmpty) ...[ - SizedBox(height: 10), - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), - child: DashBoardRoundedCardWidget( - customBorder: 30, - title: "This wallet has encountered an issue", - subTitle: "Here are the things that you should note:\n - " + - dashboardViewModel.isMoneroWalletBrokenReasons.join("\n - ") + - "\n\nPlease restart your wallet and if it doesn't help contact our support.", - onTap: () {}, - )) - ], - if (dashboardViewModel.showSilentPaymentsCard) ...[ - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), - child: DashBoardRoundedCardWidget( - marginV: 0, - marginH: 0, - customBorder: 30, - title: S.of(context).silent_payments, - subTitle: S.of(context).enable_silent_payments_scanning, - hint: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => launchUrl( - Uri.parse( - "https://docs.cakewallet.com/cryptos/bitcoin#silent-payments"), - mode: LaunchMode.externalApplication, - ), - child: Row( - children: [ - Text( - S.of(context).what_is_silent_payments, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1, - ), - softWrap: true, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Icon(Icons.help_outline, - size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), - ) - ], - ), - ), - Observer( - builder: (_) => StandardSwitch( - value: dashboardViewModel.silentPaymentsScanningActive, - onTaped: () => _toggleSilentPaymentsScanning(context), - ), - ) - ], - ), - ], - ), - onTap: () => _toggleSilentPaymentsScanning(context), - icon: Icon( - Icons.lock, - color: - Theme.of(context).extension()!.pageTitleTextColor, - size: 50, - ), - ), - ), - ], - if (dashboardViewModel.showMwebCard) ...[ - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), - child: DashBoardRoundedCardWidget( - customBorder: 30, - title: S.of(context).litecoin_mweb, - subTitle: S.of(context).litecoin_mweb_description, - hint: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => launchUrl( - Uri.parse( - "https://docs.cakewallet.com/cryptos/litecoin/#mweb"), - mode: LaunchMode.externalApplication, - ), - child: Text( - S.of(context).learn_more, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1, - ), - softWrap: true, - ), - ), - SizedBox(height: 8), - Row( - children: [ - Expanded( - child: ElevatedButton( - onPressed: () => _dismissMweb(context), - style: ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor, - ), - child: Text( - S.of(context).litecoin_mweb_dismiss, - style: TextStyle(color: Colors.white), - ), - ), - ), - const SizedBox(width: 8), - Expanded( - child: ElevatedButton( - onPressed: () => _enableMweb(context), - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: Colors.black, - ), - child: Text( - S.of(context).enable, - maxLines: 1, - ), - ), - ), - ], - ), - ], - ), - onTap: () => {}, - icon: Container( - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: ImageIcon( - AssetImage('assets/images/mweb_logo.png'), - color: Color.fromARGB(255, 11, 70, 129), - size: 40, - ), - ), - ), - ), - ], - ], - ); - }), - ], - ), - ); - } - - Future _toggleSilentPaymentsScanning(BuildContext context) async { - final isSilentPaymentsScanningActive = dashboardViewModel.silentPaymentsScanningActive; - final newValue = !isSilentPaymentsScanningActive; - - dashboardViewModel.silentPaymentsScanningActive = newValue; - - final needsToSwitch = !isSilentPaymentsScanningActive && - await bitcoin!.getNodeIsElectrsSPEnabled(dashboardViewModel.wallet) == false; - - if (needsToSwitch) { - return showPopUp( - context: context, - builder: (BuildContext context) => AlertWithTwoActions( - alertTitle: S.of(context).change_current_node_title, - alertContent: S.of(context).confirm_silent_payments_switch_node, - rightButtonText: S.of(context).confirm, - leftButtonText: S.of(context).cancel, - actionRightButton: () { - dashboardViewModel.setSilentPaymentsScanning(newValue); - Navigator.of(context).pop(); - }, - actionLeftButton: () { - dashboardViewModel.silentPaymentsScanningActive = isSilentPaymentsScanningActive; - Navigator.of(context).pop(); - }, - )); - } - - return dashboardViewModel.setSilentPaymentsScanning(newValue); - } - - Future _enableMweb(BuildContext context) async { - if (!dashboardViewModel.hasEnabledMwebBefore) { - await showPopUp( - context: context, - builder: (BuildContext context) => AlertWithOneAction( - alertTitle: S.of(context).alert_notice, - alertContent: S.of(context).litecoin_mweb_warning, - buttonText: S.of(context).understand, - buttonAction: () { - Navigator.of(context).pop(); - }, - )); - } - dashboardViewModel.setMwebEnabled(); - } - - Future _dismissMweb(BuildContext context) async { - await showPopUp( - context: context, - builder: (BuildContext context) => AlertWithOneAction( - alertTitle: S.of(context).alert_notice, - alertContent: S.of(context).litecoin_mweb_enable_later, - buttonText: S.of(context).understand, - buttonAction: () { - Navigator.of(context).pop(); - }, - )); - dashboardViewModel.dismissMweb(); - } -} - -class BalanceRowWidget extends StatelessWidget { - BalanceRowWidget({ - required this.availableBalanceLabel, - required this.availableBalance, - required this.availableFiatBalance, - required this.additionalBalanceLabel, - required this.additionalBalance, - required this.additionalFiatBalance, - required this.secondAvailableBalanceLabel, - required this.secondAvailableBalance, - required this.secondAvailableFiatBalance, - required this.secondAdditionalBalanceLabel, - required this.secondAdditionalBalance, - required this.secondAdditionalFiatBalance, - required this.frozenBalance, - required this.frozenFiatBalance, - required this.currency, - required this.hasAdditionalBalance, - required this.hasSecondAvailableBalance, - required this.hasSecondAdditionalBalance, - required this.isTestnet, - required this.dashboardViewModel, - super.key, - }); - - final String availableBalanceLabel; - final String availableBalance; - final String availableFiatBalance; - final String additionalBalanceLabel; - final String additionalBalance; - final String additionalFiatBalance; - final String secondAvailableBalanceLabel; - final String secondAvailableBalance; - final String secondAvailableFiatBalance; - final String secondAdditionalBalanceLabel; - final String secondAdditionalBalance; - final String secondAdditionalFiatBalance; - final String frozenBalance; - final String frozenFiatBalance; - final CryptoCurrency currency; - final bool hasAdditionalBalance; - final bool hasSecondAvailableBalance; - final bool hasSecondAdditionalBalance; - final bool isTestnet; - final DashboardViewModel dashboardViewModel; - - // void _showBalanceDescription(BuildContext context) { - // showPopUp( - // context: context, - // builder: (_) => - // InformationPage(information: S.of(context).available_balance_description), - // ); - // } - - @override - Widget build(BuildContext context) { - return Column(children: [ - Container( - margin: const EdgeInsets.only(left: 16, right: 16), - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - color: Theme.of(context).extension()!.cardBorderColor - .withAlpha(50), - spreadRadius: 3, - blurRadius: 7 - ) - ], - borderRadius: BorderRadius.circular(30.0), - border: Border.all( - color: Theme.of(context).extension()!.cardBorderColor, - width: 1, - ), - color: Theme.of(context).extension()!.syncedBackgroundColor, - ), - child: Container( - margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance - ? () => _showBalanceDescription( - context, S.of(context).available_balance_description) - : null, - child: Row( - children: [ - Semantics( - hint: 'Double tap to see more information', - container: true, - child: Text('${availableBalanceLabel}', - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1)), - ), - if (hasAdditionalBalance) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Icon(Icons.help_outline, - size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), - ), - ], - ), - ), - SizedBox(height: 6), - AutoSizeText(availableBalance, - style: TextStyle( - fontSize: 24, - fontFamily: 'Lato', - fontWeight: FontWeight.w900, - color: Theme.of(context) - .extension()! - .balanceAmountColor, - height: 1), - maxLines: 1, - textAlign: TextAlign.start), - SizedBox(height: 6), - if (isTestnet) - Text(S.of(context).testnet_coins_no_value, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1)), - if (!isTestnet) - Text('${availableFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - color: Theme.of(context).extension()!.textColor, - height: 1)), - - ], - ), - - SizedBox( - width: min(MediaQuery.of(context).size.width * 0.2, 100), - child: Center( - child: Column( - children: [ - CakeImageWidget( - imageUrl: currency.iconPath, - height: 40, - width: 40, - displayOnError: Container( - height: 30.0, - width: 30.0, - child: Center( - child: Text( - currency.title.substring(0, min(currency.title.length, 2)), - style: TextStyle(fontSize: 11), - ), - ), - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade400, - ), - ), - ), - const SizedBox(height: 10), - Text( - currency.title, - style: TextStyle( - fontSize: 15, - fontFamily: 'Lato', - fontWeight: FontWeight.w800, - color: - Theme.of(context).extension()!.assetTitleColor, - height: 1, - ), - ), - ], - ), - ), - ), - ], - ), - ), - if (frozenBalance.isNotEmpty) - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: hasAdditionalBalance - ? () => _showBalanceDescription( - context, S.of(context).unavailable_balance_description) - : null, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 26), - Row( - children: [ - Text( - S.of(context).unavailable_balance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: - Theme.of(context).extension()!.labelTextColor, - height: 1, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Icon(Icons.help_outline, - size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), - ), - ], - ), - SizedBox(height: 8), - AutoSizeText( - frozenBalance, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: - Theme.of(context).extension()!.balanceAmountColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 4), - if (!isTestnet) - Text( - frozenFiatBalance, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, - ), - ), - ], - ), - ), - if (hasAdditionalBalance) - GestureDetector( - onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 24), - Text( - '${additionalBalanceLabel}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.labelTextColor, - height: 1, - ), - ), - SizedBox(height: 8), - AutoSizeText( - additionalBalance, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.assetTitleColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 4), - if (!isTestnet) - Text( - '${additionalFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context).extension()!.textColor, - height: 1, - ), - ), - ], - ), - ), - ], - ), - ), - ), - if (hasSecondAdditionalBalance || hasSecondAvailableBalance) ...[ - SizedBox(height: 15), - Container( - margin: const EdgeInsets.only(left: 16, right: 16), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30.0), - border: Border.all( - color: Theme.of(context).extension()!.cardBorderColor, - width: 1, - ), - color: Theme.of(context).extension()!.syncedBackgroundColor, - boxShadow: [ - BoxShadow( - color: Theme.of(context).extension()!.cardBorderColor - .withAlpha(50), - spreadRadius: 3, - blurRadius: 7 - ) - ], - ), - child: Container( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - margin: const EdgeInsets.only(top: 16, left: 24, right: 8, bottom: 16), - child: Stack( - children: [ - if (currency == CryptoCurrency.ltc) - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Container( - padding: EdgeInsets.only(right: 16, top: 0), - child: Column( - children: [ - Container( - child: ImageIcon( - AssetImage('assets/images/mweb_logo.png'), - color: Theme.of(context) - .extension()! - .assetTitleColor, - size: 40, - ), - ), - const SizedBox(height: 10), - Text( - 'MWEB', - style: TextStyle( - fontSize: 15, - fontFamily: 'Lato', - fontWeight: FontWeight.w800, - color: Theme.of(context) - .extension()! - .assetTitleColor, - height: 1, - ), - ), - ], - ), - ), - ], - ), - if (hasSecondAvailableBalance) - GestureDetector( - onTap: () => dashboardViewModel.balanceViewModel.switchBalanceValue(), - child: Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => launchUrl( - Uri.parse( - "https://docs.cakewallet.com/cryptos/litecoin.html#mweb"), - mode: LaunchMode.externalApplication, - ), - child: Row( - children: [ - Text( - '${secondAvailableBalanceLabel}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1, - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Icon(Icons.help_outline, - size: 16, - color: Theme.of(context) - .extension()! - .labelTextColor), - ) - ], - ), - ), - SizedBox(height: 8), - AutoSizeText( - secondAvailableBalance, - style: TextStyle( - fontSize: 24, - fontFamily: 'Lato', - fontWeight: FontWeight.w900, - color: Theme.of(context) - .extension()! - .assetTitleColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 6), - if (!isTestnet) - Text( - '${secondAvailableFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 16, - fontFamily: 'Lato', - fontWeight: FontWeight.w500, - color: Theme.of(context) - .extension()! - .textColor, - height: 1, - ), - ), - ], - ), - ], - ), - ), - ], - ), - ), - Container( - margin: const EdgeInsets.only(top: 0, left: 24, right: 8, bottom: 16), - child: Stack( - children: [ - if (hasSecondAdditionalBalance) - Row( - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 24), - Text( - '${secondAdditionalBalanceLabel}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .labelTextColor, - height: 1, - ), - ), - SizedBox(height: 8), - AutoSizeText( - secondAdditionalBalance, - style: TextStyle( - fontSize: 20, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .assetTitleColor, - height: 1, - ), - maxLines: 1, - textAlign: TextAlign.center, - ), - SizedBox(height: 4), - if (!isTestnet) - Text( - '${secondAdditionalFiatBalance}', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 12, - fontFamily: 'Lato', - fontWeight: FontWeight.w400, - color: Theme.of(context) - .extension()! - .textColor, - height: 1, - ), - ), - ], - ), - ], - ), - ], - ), - ), - IntrinsicHeight( - child: Container( - padding: EdgeInsets.symmetric(horizontal: 24), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Semantics( - label: S.of(context).litecoin_mweb_pegin, - child: OutlinedButton( - onPressed: () { - final mwebAddress = - bitcoin!.getUnusedMwebAddress(dashboardViewModel.wallet); - PaymentRequest? paymentRequest = null; - if ((mwebAddress?.isNotEmpty ?? false)) { - paymentRequest = - PaymentRequest.fromUri(Uri.parse("litecoin:${mwebAddress}")); - } - Navigator.pushNamed( - context, - Routes.send, - arguments: { - 'paymentRequest': paymentRequest, - 'coinTypeToSpendFrom': UnspentCoinType.nonMweb, - }, - ); - }, - style: OutlinedButton.styleFrom( - backgroundColor: Colors.grey.shade400 - .withAlpha(50), - side: BorderSide(color: Colors.grey.shade400 - .withAlpha(50), width: 0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - ), - child: Container( - padding: EdgeInsets.symmetric(vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - height: 30, - width: 30, - 'assets/images/received.png', - color: Theme.of(context) - .extension()! - .balanceAmountColor, - ), - const SizedBox(width: 8), - Text( - S.of(context).litecoin_mweb_pegin, - style: TextStyle( - color: Theme.of(context) - .extension()! - .textColor, - ), - ), - ], - ), - ), - ), - ), - ), - SizedBox(width: 24), - Expanded( - child: Semantics( - label: S.of(context).litecoin_mweb_pegout, - child: OutlinedButton( - onPressed: () { - final litecoinAddress = - bitcoin!.getUnusedSegwitAddress(dashboardViewModel.wallet); - PaymentRequest? paymentRequest = null; - if ((litecoinAddress?.isNotEmpty ?? false)) { - paymentRequest = PaymentRequest.fromUri( - Uri.parse("litecoin:${litecoinAddress}")); - } - Navigator.pushNamed( - context, - Routes.send, - arguments: { - 'paymentRequest': paymentRequest, - 'coinTypeToSpendFrom': UnspentCoinType.mweb, - }, - ); - }, - style: OutlinedButton.styleFrom( - backgroundColor: Colors.grey.shade400 - .withAlpha(50), - side: BorderSide(color: Colors.grey.shade400 - .withAlpha(50), width: 0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20), - ), - ), - child: Container( - padding: EdgeInsets.symmetric(vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Image.asset( - height: 30, - width: 30, - 'assets/images/upload.png', - color: Theme.of(context) - .extension()! - .balanceAmountColor, - ), - const SizedBox(width: 8), - Text( - S.of(context).litecoin_mweb_pegout, - style: TextStyle( - color: Theme.of(context) - .extension()! - .textColor, - ), - ), - ], - ), - ), - ), - ), - ), - ], - ), - ), - ), - SizedBox(height: 16), - ], - ), - ), - ), - ], - ]); - } - - void _showBalanceDescription(BuildContext context, String content) { - showPopUp(context: context, builder: (_) => InformationPage(information: content)); - } -} diff --git a/lib/view_model/dashboard/balance_view_model.dart b/lib/view_model/dashboard/balance_view_model.dart index 075cf6b75..e8e82e033 100644 --- a/lib/view_model/dashboard/balance_view_model.dart +++ b/lib/view_model/dashboard/balance_view_model.dart @@ -21,17 +21,17 @@ part 'balance_view_model.g.dart'; class BalanceRecord { const BalanceRecord( {required this.availableBalance, - required this.additionalBalance, - required this.secondAvailableBalance, - required this.secondAdditionalBalance, - required this.frozenBalance, - required this.fiatAvailableBalance, - required this.fiatAdditionalBalance, - required this.fiatFrozenBalance, - required this.fiatSecondAvailableBalance, - required this.fiatSecondAdditionalBalance, - required this.asset, - required this.formattedAssetTitle}); + required this.additionalBalance, + required this.secondAvailableBalance, + required this.secondAdditionalBalance, + required this.frozenBalance, + required this.fiatAvailableBalance, + required this.fiatAdditionalBalance, + required this.fiatFrozenBalance, + required this.fiatSecondAvailableBalance, + required this.fiatSecondAdditionalBalance, + required this.asset, + required this.formattedAssetTitle}); final String fiatAdditionalBalance; final String fiatAvailableBalance; @@ -109,8 +109,8 @@ abstract class BalanceViewModelBase with Store { @computed bool get isHomeScreenSettingsEnabled => isEVMCompatibleChain(wallet.type) || - wallet.type == WalletType.solana || - wallet.type == WalletType.tron; + wallet.type == WalletType.solana || + wallet.type == WalletType.tron; @computed bool get hasAccounts => wallet.type == WalletType.monero || wallet.type == WalletType.wownero; @@ -158,17 +158,17 @@ abstract class BalanceViewModelBase with Store { case WalletType.banano: case WalletType.solana: case WalletType.tron: + case WalletType.bitcoin: + case WalletType.litecoin: + case WalletType.bitcoinCash: + case WalletType.none: return S.current.xmr_available_balance; - default: - return S.current.confirmed; } } @computed String get additionalBalanceLabel { switch (wallet.type) { - case WalletType.monero: - case WalletType.wownero: case WalletType.haven: case WalletType.ethereum: case WalletType.polygon: @@ -308,32 +308,32 @@ abstract class BalanceViewModelBase with Store { final additionalFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedAdditionalBalance)); + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedAdditionalBalance)); final availableFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedAvailableBalance)); + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedAvailableBalance)); final frozenFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(value))); + ' ' + + _getFiatBalance(price: price, cryptoAmount: getFormattedFrozenBalance(value))); final secondAdditionalFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAdditionalBalance)); + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAdditionalBalance)); final secondAvailableFiatBalance = isFiatDisabled ? '' : (fiatCurrency.toString() + - ' ' + - _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAvailableBalance)); + ' ' + + _getFiatBalance(price: price, cryptoAmount: value.formattedSecondAvailableBalance)); return MapEntry( key, @@ -357,7 +357,12 @@ abstract class BalanceViewModelBase with Store { bool mwebEnabled = false; @computed - bool get hasAdditionalBalance => _hasAdditionalBalanceForWalletType(wallet.type); + bool get hasAdditionalBalance { + bool isWalletTypeActivated = _hasAdditionalBalanceForWalletType(wallet.type); + bool isNotZeroAmount = additionalBalance != "0.0"; + + return isWalletTypeActivated && isNotZeroAmount; + } @computed bool get hasSecondAdditionalBalance => @@ -373,6 +378,9 @@ abstract class BalanceViewModelBase with Store { case WalletType.polygon: case WalletType.solana: case WalletType.tron: + case WalletType.bitcoin: + case WalletType.bitcoinCash: + case WalletType.litecoin: return false; default: return true; @@ -522,4 +530,4 @@ abstract class BalanceViewModelBase with Store { String getFormattedFrozenBalance(Balance walletBalance) => walletBalance.formattedUnAvailableBalance; -} +} \ No newline at end of file