From 5451698b9268d385b737920d114ce20f511fe947 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 30 Sep 2022 15:21:10 -0600 Subject: [PATCH] send from button in trade details --- lib/pages/exchange_view/send_from_view.dart | 172 ++++++++++-------- .../exchange_view/trade_details_view.dart | 41 +++++ lib/route_generator.dart | 20 ++ lib/utilities/constants.dart | 2 + 4 files changed, 161 insertions(+), 74 deletions(-) diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 586ffc0da..74a1f62d4 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -48,6 +48,26 @@ class _SendFromViewState extends ConsumerState { late final String address; late final ExchangeTransaction trade; + String formatAmount(Decimal amount, Coin coin) { + switch (coin) { + case Coin.bitcoin: + case Coin.bitcoincash: + case Coin.dogecoin: + case Coin.epicCash: + case Coin.firo: + case Coin.namecoin: + case Coin.bitcoinTestNet: + case Coin.bitcoincashTestnet: + case Coin.dogecoinTestNet: + case Coin.firoTestNet: + return amount.toStringAsFixed(Constants.decimalPlaces); + case Coin.monero: + return amount.toStringAsFixed(Constants.decimalPlacesMonero); + case Coin.wownero: + return amount.toStringAsFixed(Constants.decimalPlacesWownero); + } + } + @override void initState() { coin = widget.coin; @@ -59,6 +79,11 @@ class _SendFromViewState extends ConsumerState { @override Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + final walletIds = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getWalletIdsFor(coin: coin))); + return Scaffold( backgroundColor: Theme.of(context).extension()!.background, appBar: AppBar( @@ -68,44 +93,41 @@ class _SendFromViewState extends ConsumerState { }, ), title: Text( - "Send ", + "Send from", style: STextStyles.navBarTitle(context), ), ), body: Padding( padding: const EdgeInsets.all(16), - child: Wrap( - // crossAxisAlignment: CrossAxisAlignment.stretch, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Text( - "Choose your ${coin.ticker} wallet", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "You need to send ${amount.toStringAsFixed(coin == Coin.monero ? Constants.satsPerCoinMonero : coin == Coin.wownero ? Constants.satsPerCoinWownero : Constants.satsPerCoin)} ${coin.ticker}", - style: STextStyles.itemSubtitle(context), + Row( + children: [ + Text( + "You need to send ${formatAmount(amount, coin)} ${coin.ticker}", + style: STextStyles.itemSubtitle(context), + ), + ], ), const SizedBox( height: 16, ), - ListView( - shrinkWrap: true, - children: [ - ...ref - .watch(walletsChangeNotifierProvider - .select((value) => value.managers)) - .where((element) => element.coin == coin) - .map((e) => SendFromCard( - walletId: e.walletId, - amount: amount, - address: address, - trade: trade, - )) - .toList(growable: false) - ], + Expanded( + child: ListView.builder( + itemCount: walletIds.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: SendFromCard( + walletId: walletIds[index], + amount: amount, + address: address, + trade: trade, + ), + ); + }, + ), ), ], ), @@ -163,7 +185,7 @@ class _SendFromCardState extends ConsumerState { child: MaterialButton( splashColor: Theme.of(context).extension()!.highlight, key: Key("walletsSheetItemButtonKey_$walletId"), - padding: const EdgeInsets.all(5), + padding: const EdgeInsets.all(8), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( @@ -276,59 +298,61 @@ class _SendFromCardState extends ConsumerState { ), ), child: Padding( - padding: const EdgeInsets.all(4), + padding: const EdgeInsets.all(6), child: SvgPicture.asset( Assets.svg.iconFor(coin: coin), - width: 20, - height: 20, + width: 24, + height: 24, ), ), ), const SizedBox( width: 12, ), - Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - manager.walletName, - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - FutureBuilder( - future: manager.totalBalance, - builder: (builderContext, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - return Text( - "${Format.localizedStringAsFixed( - value: snapshot.data!, - locale: locale, - decimalPlaces: coin == Coin.monero - ? Constants.satsPerCoinMonero - : coin == Coin.wownero - ? Constants.satsPerCoinWownero - : Constants.satsPerCoin, - )} ${coin.ticker}", - style: STextStyles.itemSubtitle(context), - ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Loading balance", - "Loading balance.", - "Loading balance..", - "Loading balance..." - ], - style: STextStyles.itemSubtitle(context), - ); - } - }, - ), - ], + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + manager.walletName, + style: STextStyles.titleBold12(context), + ), + const SizedBox( + height: 2, + ), + FutureBuilder( + future: manager.totalBalance, + builder: (builderContext, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + return Text( + "${Format.localizedStringAsFixed( + value: snapshot.data!, + locale: locale, + decimalPlaces: coin == Coin.monero + ? Constants.decimalPlacesMonero + : coin == Coin.wownero + ? Constants.decimalPlacesWownero + : Constants.decimalPlaces, + )} ${coin.ticker}", + style: STextStyles.itemSubtitle(context), + ); + } else { + return AnimatedText( + stringsToLoopThrough: const [ + "Loading balance", + "Loading balance.", + "Loading balance..", + "Loading balance..." + ], + style: STextStyles.itemSubtitle(context), + ); + } + }, + ), + ], + ), ), ], ), diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 6cb7fbd59..2730be657 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -10,6 +10,7 @@ import 'package:stackwallet/models/exchange/change_now/exchange_transaction_stat import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/pages/exchange_view/edit_trade_note_view.dart'; +import 'package:stackwallet/pages/exchange_view/send_from_view.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/edit_note_view.dart'; import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart'; import 'package:stackwallet/providers/exchange/change_now_provider.dart'; @@ -24,6 +25,7 @@ import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; @@ -60,6 +62,15 @@ class _TradeDetailsViewState extends ConsumerState { String _note = ""; + bool isStackCoin(String ticker) { + try { + coinFromTickerCaseInsensitive(ticker); + return true; + } on ArgumentError catch (_) { + return false; + } + } + @override initState() { tradeId = widget.tradeId; @@ -756,6 +767,36 @@ class _TradeDetailsViewState extends ConsumerState { const SizedBox( height: 12, ), + if (isStackCoin(trade.fromCurrency) && + trade.statusObject != null && + (trade.statusObject!.status == + ChangeNowTransactionStatus.New || + trade.statusObject!.status == + ChangeNowTransactionStatus.Waiting)) + SecondaryButton( + label: "Send from Stack", + onPressed: () { + final amount = sendAmount; + final address = trade.payinAddress; + + final coin = + coinFromTickerCaseInsensitive(trade.fromCurrency); + + print("amount: $amount"); + print("address: $address"); + print("coin: $coin"); + + Navigator.of(context).pushNamed( + SendFromView.routeName, + arguments: Tuple4( + coin, + amount, + address, + trade, + ), + ); + }, + ), ], ), ), diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 811205f6b..368188171 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -1,7 +1,9 @@ +import 'package:decimal/decimal.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/models/contact_address_entry.dart'; +import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'; import 'package:stackwallet/models/exchange/incomplete_exchange.dart'; import 'package:stackwallet/models/paymint/transactions_model.dart'; import 'package:stackwallet/models/send_view_auto_fill_data.dart'; @@ -27,6 +29,7 @@ import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_1_view. import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_3_view.dart'; import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_4_view.dart'; +import 'package:stackwallet/pages/exchange_view/send_from_view.dart'; import 'package:stackwallet/pages/exchange_view/trade_details_view.dart'; import 'package:stackwallet/pages/exchange_view/wallet_initiated_exchange_view.dart'; import 'package:stackwallet/pages/home_view/home_view.dart'; @@ -894,6 +897,23 @@ class RouteGenerator { } return _routeError("${settings.name} invalid args: ${args.toString()}"); + case SendFromView.routeName: + if (args is Tuple4) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => SendFromView( + coin: args.item1, + amount: args.item2, + trade: args.item4, + address: args.item3, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + // == Desktop specific routes ============================================ case CreatePasswordView.routeName: return getRoute( diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index f5139477c..69c1444c3 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -21,6 +21,8 @@ abstract class Constants { static const int satsPerCoinWownero = 100000000000; static const int satsPerCoin = 100000000; static const int decimalPlaces = 8; + static const int decimalPlacesWownero = 11; + static const int decimalPlacesMonero = 12; static const int notificationsMax = 0xFFFFFFFF; static const Duration networkAliveTimerDuration = Duration(seconds: 10);