/* * This file is part of Stack Wallet. * * Copyright (c) 2023 Cypher Stack * All Rights Reserved. * The code is distributed under GPLv3 license, see LICENSE file for details. * Generated by Cypher Stack on 2023-05-26 * */ import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:tuple/tuple.dart'; import '../../../app_config.dart'; import '../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../providers/global/locale_provider.dart'; import '../../../providers/global/prefs_provider.dart'; import '../../../providers/global/price_provider.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../themes/stack_colors.dart'; import '../../../themes/theme_providers.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount_formatter.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; import '../../../utilities/text_styles.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../wallets/isar/providers/eth/token_balance_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/rounded_container.dart'; import '../../buy_view/buy_in_wallet_view.dart'; import '../../exchange_view/wallet_initiated_exchange_view.dart'; import '../../receive_view/receive_view.dart'; import '../../send_view/token_send_view.dart'; import '../../wallet_view/sub_widgets/wallet_refresh_button.dart'; class TokenSummary extends ConsumerWidget { const TokenSummary({ super.key, required this.walletId, required this.initialSyncStatus, }); final String walletId; final WalletSyncStatus initialSyncStatus; @override Widget build(BuildContext context, WidgetRef ref) { final token = ref.watch(pCurrentTokenWallet.select((value) => value!.tokenContract)); final balance = ref.watch( pTokenBalance((walletId: walletId, contractAddress: token.address)), ); return Stack( children: [ RoundedContainer( color: Theme.of(context).extension()!.tokenSummaryBG, padding: const EdgeInsets.all(24), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SvgPicture.asset( Assets.svg.walletDesktop, color: Theme.of(context) .extension()! .tokenSummaryTextSecondary, width: 12, height: 12, ), const SizedBox( width: 6, ), Text( ref.watch( pWalletName(walletId), ), style: STextStyles.w500_12(context).copyWith( color: Theme.of(context) .extension()! .tokenSummaryTextSecondary, ), ), ], ), const SizedBox( height: 6, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( ref .watch( pAmountFormatter( Ethereum(CryptoCurrencyNetwork.main), ), ) .format( balance.total, ethContract: token, ), style: STextStyles.pageTitleH1(context).copyWith( color: Theme.of(context) .extension()! .tokenSummaryTextPrimary, ), ), const SizedBox( width: 10, ), CoinTickerTag( walletId: walletId, ), ], ), const SizedBox( height: 6, ), Text( "${(balance.total.decimal * ref.watch( priceAnd24hChangeNotifierProvider.select( (value) => value.getTokenPrice(token.address).item1, ), )).toAmount( fractionDigits: 2, ).fiatString( locale: ref.watch( localeServiceChangeNotifierProvider.select( (value) => value.locale, ), ), )} ${ref.watch( prefsChangeNotifierProvider.select( (value) => value.currency, ), )}", style: STextStyles.subtitle500(context).copyWith( color: Theme.of(context) .extension()! .tokenSummaryTextPrimary, ), ), const SizedBox( height: 20, ), TokenWalletOptions( walletId: walletId, tokenContract: token, ), ], ), ), Positioned( top: 10, right: 10, child: WalletRefreshButton( walletId: walletId, initialSyncStatus: initialSyncStatus, tokenContractAddress: ref.watch( pCurrentTokenWallet.select( (value) => value!.tokenContract.address, ), ), overrideIconColor: Theme.of(context).extension()!.topNavIconPrimary, ), ), ], ); } } class TokenWalletOptions extends ConsumerWidget { const TokenWalletOptions({ super.key, required this.walletId, required this.tokenContract, }); final String walletId; final EthContract tokenContract; CryptoCurrency get ethereum => Ethereum(CryptoCurrencyNetwork.main); void _onExchangePressed(BuildContext context) async { unawaited( Navigator.of(context).pushNamed( WalletInitiatedExchangeView.routeName, arguments: Tuple3( walletId, ethereum, tokenContract, ), ), ); } void _onBuyPressed(BuildContext context) { unawaited( Navigator.of(context).pushNamed( BuyInWalletView.routeName, arguments: Tuple2( ethereum, tokenContract, ), ), ); } @override Widget build(BuildContext context, WidgetRef ref) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TokenOptionsButton( onPressed: () { Navigator.of(context).pushNamed( ReceiveView.routeName, arguments: Tuple2( walletId, tokenContract, ), ); }, subLabel: "Receive", iconAssetPathSVG: Assets.svg.arrowDownLeft, ), const SizedBox( width: 16, ), TokenOptionsButton( onPressed: () { Navigator.of(context).pushNamed( TokenSendView.routeName, arguments: Tuple3( walletId, ethereum, tokenContract, ), ); }, subLabel: "Send", iconAssetPathSVG: Assets.svg.arrowUpRight, ), if (AppConfig.hasFeature(AppFeature.swap)) const SizedBox( width: 16, ), if (AppConfig.hasFeature(AppFeature.swap)) TokenOptionsButton( onPressed: () => _onExchangePressed(context), subLabel: "Swap", iconAssetPathSVG: ref.watch( themeProvider.select( (value) => value.assets.exchange, ), ), ), if (AppConfig.hasFeature(AppFeature.buy)) const SizedBox( width: 16, ), if (AppConfig.hasFeature(AppFeature.buy)) TokenOptionsButton( onPressed: () => _onBuyPressed(context), subLabel: "Buy", iconAssetPathSVG: Assets.svg.creditCard, ), ], ); } } class TokenOptionsButton extends StatelessWidget { const TokenOptionsButton({ super.key, required this.onPressed, required this.subLabel, required this.iconAssetPathSVG, }); final VoidCallback onPressed; final String subLabel; final String iconAssetPathSVG; @override Widget build(BuildContext context) { final iconSize = subLabel == "Send" || subLabel == "Receive" ? 12.0 : 24.0; return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ RawMaterialButton( fillColor: Theme.of(context).extension()!.tokenSummaryButtonBG, elevation: 0, focusElevation: 0, hoverElevation: 0, highlightElevation: 0, constraints: const BoxConstraints(), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), onPressed: onPressed, child: Padding( padding: const EdgeInsets.all(10), child: ConditionalParent( condition: iconSize < 24, builder: (child) => RoundedContainer( padding: const EdgeInsets.all(6), color: Theme.of(context) .extension()! .tokenSummaryIcon .withOpacity(0.4), radiusMultiplier: 10, child: Center( child: child, ), ), child: iconAssetPathSVG.startsWith("assets/") ? SvgPicture.asset( iconAssetPathSVG, color: Theme.of(context) .extension()! .tokenSummaryIcon, width: iconSize, height: iconSize, ) : SvgPicture.file( File(iconAssetPathSVG), color: Theme.of(context) .extension()! .tokenSummaryIcon, width: iconSize, height: iconSize, ), ), ), ), const SizedBox( height: 6, ), Text( subLabel, style: STextStyles.w500_12(context).copyWith( color: Theme.of(context) .extension()! .tokenSummaryTextPrimary, ), ), ], ); } } class CoinTickerTag extends ConsumerWidget { const CoinTickerTag({ super.key, required this.walletId, }); final String walletId; @override Widget build(BuildContext context, WidgetRef ref) { return RoundedContainer( padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), radiusMultiplier: 0.25, color: Theme.of(context).extension()!.ethTagBG, child: Text( ref .watch( pWalletCoin(walletId), ) .ticker, style: STextStyles.w600_12(context).copyWith( color: Theme.of(context).extension()!.ethTagText, ), ), ); } }