diff --git a/assets/images/birthday_cake.svg b/assets/images/birthday_cake.svg
new file mode 100644
index 000000000..b5e31dddb
--- /dev/null
+++ b/assets/images/birthday_cake.svg
@@ -0,0 +1,31 @@
+
diff --git a/assets/images/contact_icon.svg b/assets/images/contact_icon.svg
new file mode 100644
index 000000000..6dbfcd5f4
--- /dev/null
+++ b/assets/images/contact_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/core/execution_state.dart b/lib/core/execution_state.dart
index 6bc906010..860dfee10 100644
--- a/lib/core/execution_state.dart
+++ b/lib/core/execution_state.dart
@@ -2,6 +2,8 @@ abstract class ExecutionState {}
class InitialExecutionState extends ExecutionState {}
+class LoadingTemplateExecutingState extends ExecutionState {}
+
class IsExecutingState extends ExecutionState {}
class ExecutedSuccessfullyState extends ExecutionState {
diff --git a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
index fc3679104..4ac0cf12d 100644
--- a/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
+++ b/lib/src/screens/cake_pay/cards/cake_pay_confirm_purchase_card_page.dart
@@ -7,10 +7,11 @@ import 'package:cake_wallet/src/screens/cake_pay/widgets/cake_pay_alert_modal.da
import 'package:cake_wallet/src/screens/cake_pay/widgets/image_placeholder.dart';
import 'package:cake_wallet/src/screens/cake_pay/widgets/link_extractor.dart';
import 'package:cake_wallet/src/screens/cake_pay/widgets/text_icon_button.dart';
-import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.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/base_alert_dialog.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
@@ -371,39 +372,39 @@ class CakePayBuyCardDetailPage extends BasePage {
});
final order = cakePayPurchaseViewModel.order;
- final pendingTransaction = cakePayPurchaseViewModel.sendViewModel.pendingTransaction!;
- await showPopUp(
+ showModalBottomSheet(
context: context,
- builder: (popupContext) {
- return Observer(
- builder: (_) => ConfirmSendingAlert(
- alertTitle: S.of(popupContext).confirm_sending,
- paymentId: S.of(popupContext).payment_id,
- paymentIdValue: order?.orderId,
- expirationTime: cakePayPurchaseViewModel.formattedRemainingTime,
- onDispose: () => _handleDispose(disposer),
- amount: S.of(popupContext).send_amount,
- amountValue: pendingTransaction.amountFormatted,
- fiatAmountValue:
- cakePayPurchaseViewModel.sendViewModel.pendingTransactionFiatAmountFormatted,
- fee: S.of(popupContext).send_fee,
- feeValue: pendingTransaction.feeFormatted,
- feeFiatAmount:
- cakePayPurchaseViewModel.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
- feeRate: pendingTransaction.feeRate,
- outputs: cakePayPurchaseViewModel.sendViewModel.outputs,
- rightButtonText: S.of(popupContext).send,
- leftButtonText: S.of(popupContext).cancel,
- actionRightButton: () async {
- Navigator.of(context).pop();
- await cakePayPurchaseViewModel.sendViewModel.commitTransaction(context);
- },
- actionLeftButton: () => Navigator.of(popupContext).pop()));
+ isDismissible: false,
+ isScrollControlled: true,
+ builder: (BuildContext popupContext) {
+ return ConfirmSendingBottomSheet(
+ key: ValueKey('send_page_confirm_sending_dialog_key'),
+ currentTheme: currentTheme,
+ paymentId: S.of(popupContext).payment_id,
+ paymentIdValue: order?.orderId,
+ expirationTime: cakePayPurchaseViewModel.formattedRemainingTime,
+ titleText: 'Confirm Transaction',
+ titleIconPath: cakePayPurchaseViewModel.sendViewModel.selectedCryptoCurrency.iconPath,
+ currency: cakePayPurchaseViewModel.sendViewModel.selectedCryptoCurrency,
+ amount: S.of(popupContext).send_amount,
+ amountValue: cakePayPurchaseViewModel.sendViewModel.pendingTransaction!.amountFormatted,
+ fiatAmountValue: cakePayPurchaseViewModel.sendViewModel.pendingTransactionFiatAmountFormatted,
+ fee: S.of(popupContext).send_fee,
+ feeValue: cakePayPurchaseViewModel.sendViewModel.pendingTransaction!.feeFormatted,
+ feeFiatAmount: cakePayPurchaseViewModel.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
+ outputs: cakePayPurchaseViewModel.sendViewModel.outputs,
+ onSlideComplete: () async {
+ Navigator.of(popupContext).pop();
+ cakePayPurchaseViewModel.sendViewModel.commitTransaction(context);
+ },
+ );
},
);
}
+ BuildContext? loadingBottomSheetContext;
+
void _setEffects(BuildContext context) {
if (_effectsInstalled) {
return;
@@ -416,6 +417,29 @@ class CakePayBuyCardDetailPage extends BasePage {
});
}
+ if (state is! IsExecutingState &&
+ loadingBottomSheetContext != null &&
+ loadingBottomSheetContext!.mounted) {
+ Navigator.of(loadingBottomSheetContext!).pop();
+ }
+
+ if (state is IsExecutingState) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (context.mounted) {
+ showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ builder: (BuildContext context) {
+ loadingBottomSheetContext = context;
+ return LoadingBottomSheet(
+ titleText: 'Generating transaction',
+ );
+ },
+ );
+ }
+ });
+ }
+
if (state is ExecutedSuccessfullyState) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
await _showConfirmSendingAlert(context);
diff --git a/lib/src/screens/exchange_trade/exchange_trade_page.dart b/lib/src/screens/exchange_trade/exchange_trade_page.dart
index 6adb08de8..243ab63c8 100644
--- a/lib/src/screens/exchange_trade/exchange_trade_page.dart
+++ b/lib/src/screens/exchange_trade/exchange_trade_page.dart
@@ -1,7 +1,10 @@
+import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange_trade/widgets/exchange_trade_card_item_widget.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'dart:ui';
@@ -13,7 +16,6 @@ import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
-import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
@@ -209,6 +211,8 @@ class ExchangeTradeState extends State {
);
}
+ BuildContext? loadingBottomSheetContext;
+
void _setEffects() {
if (_effectsInstalled) {
return;
@@ -216,6 +220,13 @@ class ExchangeTradeState extends State {
_exchangeStateReaction = reaction((_) => this.widget.exchangeTradeViewModel.sendViewModel.state,
(ExecutionState state) {
+
+ if (state is! IsExecutingState &&
+ loadingBottomSheetContext != null &&
+ loadingBottomSheetContext!.mounted) {
+ Navigator.of(loadingBottomSheetContext!).pop();
+ }
+
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp(
@@ -232,163 +243,92 @@ class ExchangeTradeState extends State {
});
}
+ if (state is IsExecutingState) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (context.mounted) {
+ showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ builder: (BuildContext context) {
+ loadingBottomSheetContext = context;
+ return LoadingBottomSheet(
+ titleText: 'Generating transaction',
+ );
+ },
+ );
+ }
+ });
+ }
+
if (state is ExecutedSuccessfullyState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
- showPopUp(
+ if (context.mounted) {
+ showModalBottomSheet(
context: context,
- builder: (BuildContext popupContext) {
- return ConfirmSendingAlert(
- key: ValueKey('exchange_trade_page_confirm_sending_dialog_key'),
- alertLeftActionButtonKey: ValueKey('exchange_trade_page_confirm_sending_dialog_cancel_button_key'),
- alertRightActionButtonKey:
- ValueKey('exchange_trade_page_confirm_sending_dialog_send_button_key'),
- alertTitle: S.of(popupContext).confirm_sending,
- amount: S.of(popupContext).send_amount,
- amountValue: widget.exchangeTradeViewModel.sendViewModel
- .pendingTransaction!.amountFormatted,
- fee: S.of(popupContext).send_fee,
- feeValue: widget.exchangeTradeViewModel.sendViewModel
- .pendingTransaction!.feeFormatted,
- feeRate: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeRate,
- rightButtonText: S.of(popupContext).send,
- leftButtonText: S.of(popupContext).cancel,
- actionRightButton: () async {
- Navigator.of(popupContext).pop();
- await widget.exchangeTradeViewModel.sendViewModel
- .commitTransaction(context);
- transactionStatePopup();
- },
- actionLeftButton: () => Navigator.of(popupContext).pop(),
- feeFiatAmount: widget.exchangeTradeViewModel
- .pendingTransactionFeeFiatAmountFormatted,
- fiatAmountValue: widget.exchangeTradeViewModel
- .pendingTransactionFiatAmountValueFormatted,
- outputs: widget.exchangeTradeViewModel.sendViewModel
- .outputs);
- });
+ isDismissible: false,
+ isScrollControlled: true,
+ builder: (BuildContext bottomSheetContext) {
+ return ConfirmSendingBottomSheet(
+ key: ValueKey('exchange_trade_page_confirm_sending_bottom_sheet_key'),
+ currentTheme: widget.currentTheme,
+ titleText: 'Confirm Transaction',
+ titleIconPath: widget.exchangeTradeViewModel.sendViewModel.selectedCryptoCurrency.iconPath,
+ currency: widget.exchangeTradeViewModel.sendViewModel.selectedCryptoCurrency,
+ amount: S.of(bottomSheetContext).send_amount,
+ amountValue: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.amountFormatted,
+ fiatAmountValue: widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFiatAmountFormatted,
+ fee: isEVMCompatibleChain(widget.exchangeTradeViewModel.sendViewModel.walletType)
+ ? S.of(bottomSheetContext).send_estimated_fee
+ : S.of(bottomSheetContext).send_fee,
+ feeValue: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.feeFormatted,
+ feeFiatAmount: widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
+ outputs: widget.exchangeTradeViewModel.sendViewModel.outputs,
+ onSlideComplete: () async {
+ Navigator.of(bottomSheetContext).pop();
+ widget.exchangeTradeViewModel.sendViewModel.commitTransaction(context);
+ },
+ );
+ },
+ );
+ }
});
}
if (state is TransactionCommitted) {
- WidgetsBinding.instance.addPostFrameCallback((_) {
- if (mounted) {
- showPopUp(
- context: context,
- builder: (BuildContext popupContext) {
- return AlertWithOneAction(
- alertTitle: S.of(popupContext).sending,
- alertContent: S.of(popupContext).transaction_sent,
- buttonText: S.of(popupContext).ok,
- buttonAction: () => Navigator.of(popupContext).pop());
- });
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ if (!context.mounted) {
+ return;
}
+
+
+ await showModalBottomSheet(
+ context: context,
+ isScrollControlled: true,
+ builder: (BuildContext bottomSheetContext) {
+ return InfoBottomSheet(
+ currentTheme: widget.currentTheme,
+ titleText: 'Transaction Sent',
+ contentImage: 'assets/images/birthday_cake.svg',
+ actionButtonText: S.of(bottomSheetContext).close,
+ actionButtonKey: ValueKey('send_page_sent_dialog_ok_button_key'),
+ actionButton: () {
+ Navigator.of(bottomSheetContext).pop();
+ Navigator.of(context).pushNamedAndRemoveUntil(
+ Routes.dashboard,
+ (route) => false,
+ );
+ RequestReviewHandler.requestReview();
+ });
+ },
+ );
+
});
}
+
});
_effectsInstalled = true;
}
-
- void transactionStatePopup() {
- if (this.mounted) {
- showPopUp(
- context: context,
- builder: (BuildContext popupContext) {
- return Observer(builder: (_) {
- final state = widget
- .exchangeTradeViewModel.sendViewModel.state;
-
- if (state is TransactionCommitted) {
- return Stack(
- children: [
- Container(
- color: Theme.of(popupContext).colorScheme.background,
- child: Center(
- child: Image.asset(
- 'assets/images/birthday_cake.png'),
- ),
- ),
- Center(
- child: Padding(
- padding: EdgeInsets.only(
- top: 220, left: 24, right: 24),
- child: Text(
- S.of(popupContext).send_success(widget
- .exchangeTradeViewModel
- .wallet
- .currency
- .toString()),
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 22,
- fontWeight: FontWeight.bold,
- color: Theme.of(popupContext).extension()!.titleColor,
- decoration: TextDecoration.none,
- ),
- ),
- ),
- ),
- Positioned(
- left: 24,
- right: 24,
- bottom: 24,
- child: PrimaryButton(
- onPressed: () {
- Navigator.pushNamedAndRemoveUntil(
- popupContext,
- Routes.dashboard,
- (route) => false,
- );
- RequestReviewHandler.requestReview();
- },
- text: S.of(popupContext).got_it,
- color: Theme.of(popupContext).primaryColor,
- textColor: Colors.white))
- ],
- );
- }
-
- return Stack(
- children: [
- Container(
- color: Theme.of(popupContext).colorScheme.background,
- child: Center(
- child: Image.asset(
- 'assets/images/birthday_cake.png'),
- ),
- ),
- BackdropFilter(
- filter: ImageFilter.blur(
- sigmaX: 3.0, sigmaY: 3.0),
- child: Container(
- decoration: BoxDecoration(
- color: Theme.of(popupContext)
- .colorScheme
- .background
- .withOpacity(0.25)),
- child: Center(
- child: Padding(
- padding: EdgeInsets.only(top: 220),
- child: Text(
- S.of(popupContext).send_sending,
- textAlign: TextAlign.center,
- style: TextStyle(
- fontSize: 22,
- fontWeight: FontWeight.bold,
- color: Theme.of(popupContext).extension()!.titleColor,
- decoration: TextDecoration.none,
- ),
- ),
- ),
- ),
- ),
- )
- ],
- );
- });
- });
- }
- }
}
class _ExchangeTradeItemsCardSection extends StatelessWidget {
diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart
index 7e7080d0f..fbbb6c0e1 100644
--- a/lib/src/screens/send/send_page.dart
+++ b/lib/src/screens/send/send_page.dart
@@ -12,18 +12,20 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
-import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
import 'package:cake_wallet/src/widgets/adaptable_page_view.dart';
import 'package:cake_wallet/src/widgets/add_template_button.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/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/template_tile.dart';
import 'package:cake_wallet/src/widgets/trail_button.dart';
+import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
@@ -162,6 +164,8 @@ class SendPage extends BasePage {
});
});
+ bool _bottomSheetOpened = false;
+
@override
Widget body(BuildContext context) {
_setEffects(context);
@@ -290,7 +294,7 @@ class SendPage extends BasePage {
? template.cryptoCurrency
: template.fiatCurrency,
onTap: () async {
- sendViewModel.state = IsExecutingState();
+ sendViewModel.state = LoadingTemplateExecutingState();
if (template.additionalRecipients?.isNotEmpty ??
false) {
sendViewModel.clearOutputs();
@@ -464,7 +468,8 @@ class SendPage extends BasePage {
textColor: Colors.white,
isLoading: sendViewModel.state is IsExecutingState ||
sendViewModel.state is TransactionCommitting ||
- sendViewModel.state is IsAwaitingDeviceResponseState,
+ sendViewModel.state is IsAwaitingDeviceResponseState ||
+ sendViewModel.state is LoadingTemplateExecutingState,
isDisabled: !sendViewModel.isReadyForSend,
);
},
@@ -479,6 +484,7 @@ class SendPage extends BasePage {
}
BuildContext? dialogContext;
+ BuildContext? loadingBottomSheetContext;
void _setEffects(BuildContext context) {
if (_effectsInstalled) {
@@ -494,6 +500,13 @@ class SendPage extends BasePage {
Navigator.of(dialogContext!).pop();
}
+ if (state is! IsExecutingState &&
+ loadingBottomSheetContext != null &&
+ loadingBottomSheetContext!.mounted) {
+ Navigator.of(loadingBottomSheetContext!).pop();
+ }
+
+
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp(
@@ -510,92 +523,110 @@ class SendPage extends BasePage {
});
}
- if (state is ExecutedSuccessfullyState) {
+ if (state is IsExecutingState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (context.mounted) {
- showPopUp(
- context: context,
- builder: (BuildContext _dialogContext) {
- return ConfirmSendingAlert(
- key: ValueKey('send_page_confirm_sending_dialog_key'),
- alertTitle: S.of(_dialogContext).confirm_sending,
- amount: S.of(_dialogContext).send_amount,
- amountValue: sendViewModel.pendingTransaction!.amountFormatted,
- fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
- fee: isEVMCompatibleChain(sendViewModel.walletType)
- ? S.of(_dialogContext).send_estimated_fee
- : S.of(_dialogContext).send_fee,
- feeRate: sendViewModel.pendingTransaction!.feeRate,
- feeValue: sendViewModel.pendingTransaction!.feeFormatted,
- feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
- outputs: sendViewModel.outputs,
- change: sendViewModel.pendingTransaction!.change,
- rightButtonText: S.of(_dialogContext).send,
- leftButtonText: S.of(_dialogContext).cancel,
- alertRightActionButtonKey:
- ValueKey('send_page_confirm_sending_dialog_send_button_key'),
- alertLeftActionButtonKey:
- ValueKey('send_page_confirm_sending_dialog_cancel_button_key'),
- actionRightButton: () async {
- Navigator.of(_dialogContext).pop();
- sendViewModel.commitTransaction(context);
- },
- actionLeftButton: () => Navigator.of(_dialogContext).pop());
- });
+ showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ builder: (BuildContext context) {
+ loadingBottomSheetContext = context;
+ return LoadingBottomSheet(
+ titleText: 'Generating transaction',
+ );
+ },
+ );
}
});
}
+ if (state is ExecutedSuccessfullyState) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (context.mounted) {
+ showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ isScrollControlled: true,
+ builder: (BuildContext bottomSheetContext) {
+ return ConfirmSendingBottomSheet(
+ key: ValueKey('send_page_confirm_sending_dialog_key'),
+ titleText: 'Confirm Transaction',
+ currentTheme: currentTheme,
+ titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath,
+ currency: sendViewModel.selectedCryptoCurrency,
+ amount: S.of(bottomSheetContext).send_amount,
+ amountValue: sendViewModel.pendingTransaction!.amountFormatted,
+ fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
+ fee: isEVMCompatibleChain(sendViewModel.walletType)
+ ? S.of(bottomSheetContext).send_estimated_fee
+ : S.of(bottomSheetContext).send_fee,
+ feeValue: sendViewModel.pendingTransaction!.feeFormatted,
+ feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
+ outputs: sendViewModel.outputs,
+ onSlideComplete: () async {
+ Navigator.of(bottomSheetContext).pop();
+ sendViewModel.commitTransaction(context);
+ },
+ change: sendViewModel.pendingTransaction!.change,
+ );
+ },
+ );
+ }
+ });
+ }
+
+
+
if (state is TransactionCommitted) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (!context.mounted) {
return;
}
- final successMessage =
- S.of(context).send_success(sendViewModel.selectedCryptoCurrency.toString());
-
- final waitMessage = sendViewModel.walletType == WalletType.solana
- ? '. ${S.of(context).waitFewSecondForTxUpdate}'
- : '';
-
- String alertContent = "$successMessage$waitMessage";
-
- await Navigator.of(context)
- .pushNamed(Routes.transactionSuccessPage, arguments: alertContent);
-
newContactAddress = newContactAddress ?? sendViewModel.newContactAddress();
+
if (newContactAddress?.address != null && isRegularElectrumAddress(newContactAddress!.address)) {
newContactAddress = null;
}
- if (sendViewModel.coinTypeToSpendFrom != UnspentCoinType.any) newContactAddress = null;
-
- if (newContactAddress != null && sendViewModel.showAddressBookPopup) {
- await showPopUp(
- context: context,
- builder: (BuildContext _dialogContext) => AlertWithTwoActions(
- alertDialogKey: ValueKey('send_page_sent_dialog_key'),
- alertTitle: '',
- alertContent: S.of(_dialogContext).add_contact_to_address_book,
- rightButtonText: S.of(_dialogContext).add_contact,
- leftButtonText: S.of(_dialogContext).ignor,
- alertLeftActionButtonKey: ValueKey('send_page_sent_dialog_ignore_button_key'),
- alertRightActionButtonKey:
- ValueKey('send_page_sent_dialog_add_contact_button_key'),
- actionRightButton: () {
- Navigator.of(_dialogContext).pop();
- RequestReviewHandler.requestReview();
- Navigator.of(context)
- .pushNamed(Routes.addressBookAddContact, arguments: newContactAddress);
- newContactAddress = null;
- },
- actionLeftButton: () {
- Navigator.of(_dialogContext).pop();
- RequestReviewHandler.requestReview();
- newContactAddress = null;
- }));
- }
+ await showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ builder: (BuildContext bottomSheetContext) {
+ return newContactAddress != null && sendViewModel.showAddressBookPopup
+ ? InfoBottomSheet(
+ currentTheme: currentTheme,
+ showDontAskMeCheckbox: true,
+ onCheckboxChanged: (value) => sendViewModel.setShowAddressBookPopup(!value),
+ titleText: 'Transaction Sent',
+ contentImage: 'assets/images/contact_icon.svg',
+ contentImageColor: Theme.of(context).extension()!.titleColor,
+ content: S.of(bottomSheetContext).add_contact_to_address_book,
+ isTwoAction: true,
+ leftButtonText: 'No',
+ rightButtonText: 'Yes',
+ actionLeftButton: () {
+ Navigator.of(bottomSheetContext).pop();
+ RequestReviewHandler.requestReview();
+ newContactAddress = null;
+ },
+ actionRightButton: () {
+ Navigator.of(bottomSheetContext).pop();
+ RequestReviewHandler.requestReview();
+ Navigator.of(context)
+ .pushNamed(Routes.addressBookAddContact, arguments: newContactAddress);
+ newContactAddress = null;
+ },
+ )
+ : InfoBottomSheet(
+ currentTheme: currentTheme,
+ titleText: 'Transaction Sent',
+ contentImage: 'assets/images/birthday_cake.svg',
+ actionButtonText: S.of(bottomSheetContext).close,
+ actionButtonKey: ValueKey('send_page_sent_dialog_ok_button_key'),
+ actionButton: () => Navigator.of(bottomSheetContext).pop());
+ },
+ );
if (initialPaymentRequest?.callbackUrl?.isNotEmpty ?? false) {
// wait a second so it's not as jarring:
diff --git a/lib/src/screens/transaction_details/rbf_details_page.dart b/lib/src/screens/transaction_details/rbf_details_page.dart
index 2c5edd8b4..3b6513a03 100644
--- a/lib/src/screens/transaction_details/rbf_details_page.dart
+++ b/lib/src/screens/transaction_details/rbf_details_page.dart
@@ -1,7 +1,6 @@
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
-import 'package:cake_wallet/src/screens/send/widgets/confirm_sending_alert.dart';
import 'package:cake_wallet/src/screens/transaction_details/rbf_details_list_fee_picker_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
import 'package:cake_wallet/src/screens/transaction_details/textfield_list_item.dart';
@@ -9,6 +8,8 @@ import 'package:cake_wallet/src/screens/transaction_details/transaction_expandab
import 'package:cake_wallet/src/screens/transaction_details/widgets/textfield_list_row.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/bottom_sheet/confirm_sending_bottom_sheet_widget.dart';
+import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
import 'package:cake_wallet/src/widgets/list_row.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/standard_expandable_list.dart';
@@ -110,12 +111,21 @@ class RBFDetailsPage extends BasePage {
);
}
+ BuildContext? loadingBottomSheetContext;
+
void _setEffects(BuildContext context) {
if (_effectsInstalled) {
return;
}
reaction((_) => transactionDetailsViewModel.sendViewModel.state, (ExecutionState state) {
+
+ if (state is! IsExecutingState &&
+ loadingBottomSheetContext != null &&
+ loadingBottomSheetContext!.mounted) {
+ Navigator.of(loadingBottomSheetContext!).pop();
+ }
+
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp(
@@ -151,35 +161,56 @@ class RBFDetailsPage extends BasePage {
});
}
+ if (state is IsExecutingState) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (context.mounted) {
+ showModalBottomSheet(
+ context: context,
+ isDismissible: false,
+ builder: (BuildContext context) {
+ loadingBottomSheetContext = context;
+ return LoadingBottomSheet(
+ titleText: 'Generating transaction',
+ );
+ },
+ );
+ }
+ });
+ }
+
if (state is ExecutedSuccessfullyState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
- showPopUp(
+ if (context.mounted) {
+ showModalBottomSheet(
context: context,
- builder: (BuildContext popupContext) {
- return ConfirmSendingAlert(
- alertTitle: S.of(popupContext).confirm_sending,
- amount: S.of(popupContext).send_amount,
- amountValue: transactionDetailsViewModel
- .sendViewModel.pendingTransaction!.amountFormatted,
- fee: S.of(popupContext).send_fee,
- feeValue:
- transactionDetailsViewModel.sendViewModel.pendingTransaction!.feeFormatted,
- rightButtonText: S.of(popupContext).send,
- leftButtonText: S.of(popupContext).cancel,
- actionRightButton: () async {
- Navigator.of(popupContext).pop();
- await transactionDetailsViewModel.sendViewModel.commitTransaction(context);
- try {
- Navigator.of(popupContext).pop();
- } catch (_) {}
- },
- actionLeftButton: () => Navigator.of(popupContext).pop(),
- feeFiatAmount:
- transactionDetailsViewModel.pendingTransactionFeeFiatAmountFormatted,
- fiatAmountValue:
- transactionDetailsViewModel.pendingTransactionFiatAmountValueFormatted,
- outputs: transactionDetailsViewModel.sendViewModel.outputs);
- });
+ isDismissible: false,
+ isScrollControlled: true,
+ builder: (BuildContext bottomSheetContext) {
+ return ConfirmSendingBottomSheet(
+ key: ValueKey('rbf_confirm_sending_bottom_sheet'),
+ titleText: 'Confirm Transaction',
+ currentTheme: currentTheme,
+ titleIconPath: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency.iconPath,
+ currency: transactionDetailsViewModel.sendViewModel.selectedCryptoCurrency,
+ amount: S.of(bottomSheetContext).send_amount,
+ amountValue: transactionDetailsViewModel.sendViewModel.pendingTransaction!.amountFormatted,
+ fiatAmountValue: transactionDetailsViewModel.sendViewModel.pendingTransactionFiatAmountFormatted,
+ fee: S.of(bottomSheetContext).send_fee,
+ feeValue: transactionDetailsViewModel.sendViewModel.pendingTransaction!.feeFormatted,
+ feeFiatAmount: transactionDetailsViewModel.sendViewModel.pendingTransactionFeeFiatAmountFormatted,
+ outputs: transactionDetailsViewModel.sendViewModel.outputs,
+ onSlideComplete: () async {
+ Navigator.of(bottomSheetContext).pop();
+ await transactionDetailsViewModel.sendViewModel.commitTransaction(context);
+ try {
+ Navigator.of(bottomSheetContext).pop();
+ } catch (_) {}
+ },
+ change: transactionDetailsViewModel.sendViewModel.pendingTransaction!.change,
+ );
+ },
+ );
+ }
});
}
diff --git a/lib/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart b/lib/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart
new file mode 100644
index 000000000..206780eae
--- /dev/null
+++ b/lib/src/widgets/bottom_sheet/base_bottom_sheet_widget.dart
@@ -0,0 +1,83 @@
+import 'package:flutter/material.dart';
+import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
+
+abstract class BaseBottomSheet extends StatelessWidget {
+ final String titleText;
+ final String? titleIconPath;
+
+ const BaseBottomSheet({required this.titleText, this.titleIconPath});
+
+ Widget headerWidget(BuildContext context) {
+ return Column(
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ child: Row(
+ children: [
+ const Spacer(flex: 4),
+ Expanded(
+ flex: 2,
+ child: Container(
+ height: 6,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(4),
+ color: Theme.of(context).extension()!.titleColor,
+ ),
+ ),
+ ),
+ const Spacer(flex: 4),
+ ],
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ if (titleIconPath != null)
+ Image.asset(titleIconPath!, height: 24, width: 24)
+ else
+ Container(),
+ const SizedBox(width: 6),
+ Text(
+ titleText,
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 20,
+ fontFamily: 'Lato',
+ fontWeight: FontWeight.w600,
+ color: Theme.of(context).extension()!.titleColor,
+ decoration: TextDecoration.none,
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 13),
+ ],
+ );
+ }
+
+ Widget contentWidget(BuildContext context);
+
+ Widget footerWidget(BuildContext context);
+
+ @override
+ Widget build(BuildContext context) {
+ return ConstrainedBox(
+ constraints: BoxConstraints(maxHeight: 600),
+ child: ClipRRect(
+ borderRadius: const BorderRadius.only(
+ topLeft: Radius.circular(30.0), topRight: Radius.circular(30.0)),
+ child: Container(
+ color: Theme.of(context).dialogBackgroundColor,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ headerWidget(context),
+ contentWidget(context),
+ footerWidget(context),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart b/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart
new file mode 100644
index 000000000..bf16695e9
--- /dev/null
+++ b/lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart
@@ -0,0 +1,450 @@
+import 'package:cake_wallet/generated/i18n.dart';
+import 'package:cake_wallet/src/widgets/standard_slide_button_widget.dart';
+import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
+import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
+import 'package:cake_wallet/themes/extensions/filter_theme.dart';
+import 'package:cake_wallet/themes/theme_base.dart';
+import 'package:cake_wallet/view_model/send/output.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/pending_transaction.dart';
+import 'package:flutter/material.dart';
+import 'dart:math' as math;
+
+import 'base_bottom_sheet_widget.dart';
+
+class ConfirmSendingBottomSheet extends BaseBottomSheet {
+ final CryptoCurrency currency;
+ final ThemeBase currentTheme;
+ final String? paymentId;
+ final String? paymentIdValue;
+ final String? expirationTime;
+ final String amount;
+ final String amountValue;
+ final String fiatAmountValue;
+ final String fee;
+ final String feeValue;
+ final String feeFiatAmount;
+ final List