diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index c87175955..59675e4e4 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -7,6 +7,7 @@ import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/models/exchange/response_objects/trade.dart'; import 'package:stackwallet/pages/exchange_view/confirm_change_now_send.dart'; import 'package:stackwallet/pages/home_view/home_view.dart'; +import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/route_generator.dart'; @@ -19,13 +20,18 @@ import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; import 'package:stackwallet/utilities/format.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/animated_text.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:stackwallet/widgets/expandable.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; +import '../../pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; + class SendFromView extends ConsumerStatefulWidget { const SendFromView({ Key? key, @@ -90,21 +96,68 @@ class _SendFromViewState extends ConsumerState { final walletIds = ref.watch(walletsChangeNotifierProvider .select((value) => value.getWalletIdsFor(coin: coin))); - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, + final isDesktop = Util.isDesktop; + + return ConditionalParent( + condition: !isDesktop, + builder: (child) { + return Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Send from", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), + ); + }, + child: ConditionalParent( + condition: isDesktop, + builder: (child) => DesktopDialog( + maxHeight: double.infinity, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 32, + ), + child: Text( + "Send from Stack", + style: STextStyles.desktopH3(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: Navigator.of( + context, + rootNavigator: false, + ).pop, + ), + ], + ), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: child, + ), + ], + ), ), - title: Text( - "Send from", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -112,15 +165,23 @@ class _SendFromViewState extends ConsumerState { children: [ Text( "You need to send ${formatAmount(amount, coin)} ${coin.ticker}", - style: STextStyles.itemSubtitle(context), + style: isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.itemSubtitle(context), ), ], ), const SizedBox( height: 16, ), - Expanded( + ConditionalParent( + condition: !isDesktop, + builder: (child) => Expanded( + child: child, + ), child: ListView.builder( + primary: isDesktop ? false : null, + shrinkWrap: isDesktop, itemCount: walletIds.length, itemBuilder: (context, index) { return Padding( @@ -339,10 +400,67 @@ class _SendFromCardState extends ConsumerState { Constants.size.circularBorderRadius, ), ), - onPressed: () => _send( - manager, - shouldSendPublicFiroFunds: false, - ), + onPressed: () async { + final dynamic unlocked; + + if (Util.isDesktop) { + unlocked = await showDialog( + context: context, + builder: (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + DesktopDialogCloseButton(), + ], + ), + const Padding( + padding: EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(), + ), + ], + ), + ), + ); + } else { + unlocked = await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: "Confirm Transaction", + ), + settings: + const RouteSettings(name: "/confirmsendlockscreen"), + ), + ); + } + + if (unlocked is bool && unlocked && mounted) { + unawaited( + _send( + manager, + shouldSendPublicFiroFunds: false, + ), + ); + } + }, child: Container( color: Colors.transparent, child: Padding( @@ -418,10 +536,67 @@ class _SendFromCardState extends ConsumerState { Constants.size.circularBorderRadius, ), ), - onPressed: () => _send( - manager, - shouldSendPublicFiroFunds: true, - ), + onPressed: () async { + final dynamic unlocked; + + if (Util.isDesktop) { + unlocked = await showDialog( + context: context, + builder: (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + DesktopDialogCloseButton(), + ], + ), + const Padding( + padding: EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(), + ), + ], + ), + ), + ); + } else { + unlocked = await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: "Confirm Transaction", + ), + settings: + const RouteSettings(name: "/confirmsendlockscreen"), + ), + ); + } + + if (unlocked is bool && unlocked && mounted) { + unawaited( + _send( + manager, + shouldSendPublicFiroFunds: true, + ), + ); + } + }, child: Container( color: Colors.transparent, child: Padding( @@ -504,7 +679,63 @@ class _SendFromCardState extends ConsumerState { Constants.size.circularBorderRadius, ), ), - onPressed: () => _send(manager), + onPressed: () async { + final dynamic unlocked; + + if (Util.isDesktop) { + unlocked = await showDialog( + context: context, + builder: (context) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + DesktopDialogCloseButton(), + ], + ), + const Padding( + padding: EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + ), + child: DesktopAuthSend(), + ), + ], + ), + ), + ); + } else { + unlocked = await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: (_) => const LockscreenView( + showBackButton: true, + popOnSuccess: true, + routeOnSuccessArguments: true, + routeOnSuccess: "", + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to send transaction", + biometricsAuthenticationTitle: "Confirm Transaction", + ), + settings: + const RouteSettings(name: "/confirmsendlockscreen"), + ), + ); + } + + if (unlocked is bool && unlocked && mounted) { + unawaited( + _send(manager), + ); + } + }, child: child, ), child: Row( diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 8f7afb0bb..276203804 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -37,6 +37,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget { required this.transactionInfo, required this.walletId, this.routeOnSuccessName = WalletView.routeName, + this.isTradeTransaction = false, }) : super(key: key); static const String routeName = "/confirmTransactionView"; @@ -44,6 +45,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget { final Map transactionInfo; final String walletId; final String routeOnSuccessName; + final bool isTradeTransaction; @override ConsumerState createState() => @@ -833,8 +835,19 @@ class _ConfirmTransactionViewState ); } - if (unlocked is bool && unlocked && mounted) { - unawaited(_attemptSend(context)); + if (mounted) { + if (unlocked == true) { + unawaited(_attemptSend(context)); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: Util.isDesktop + ? "Invalid passphrase" + : "Invalid PIN", + context: context), + ); + } } }, ), diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart index 9f863c8a4..a8d1ea497 100644 --- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -10,6 +12,9 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; +import '../../../../../notifications/show_flush_bar.dart'; +import '../../../../../widgets/loading_indicator.dart'; + class DesktopAuthSend extends ConsumerStatefulWidget { const DesktopAuthSend({Key? key}) : super(key: key); @@ -155,12 +160,35 @@ class _DesktopAuthSendState extends ConsumerState { label: "Confirm", buttonHeight: ButtonHeight.l, onPressed: () async { - // TODO show spinner while verifying passphrase + unawaited( + showDialog( + context: context, + builder: (context) => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: const [ + LoadingIndicator( + width: 200, + height: 200, + ), + ], + ), + ), + ); + + await Future.delayed(const Duration(seconds: 1)); final passwordIsValid = await verifyPassphrase(); if (mounted) { - Navigator.of(context).pop(passwordIsValid); + Navigator.of(context).pop(); + Navigator.of( + context, + rootNavigator: true, + ).pop(passwordIsValid); + await Future.delayed(const Duration( + milliseconds: 100, + )); } }, ),