1
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
2
import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
3
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
4
-import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
5
-import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
4
import 'package:cake_wallet/core/auth_service.dart';
5
import 'package:cake_wallet/di.dart';
6
import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
7
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
8
import 'package:cake_wallet/src/widgets/add_template_button.dart';
11
-import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
12
-import 'package:cake_wallet/themes/theme_base.dart';
9
+import 'package:cake_wallet/themes/core/material_base_theme.dart';
10
import 'package:cake_wallet/utils/debounce.dart';
11
import 'package:cake_wallet/utils/payment_request.dart';
12
import 'package:cake_wallet/utils/responsive_layout_util.dart';
104
mainAxisAlignment: MainAxisAlignment.center,
105
children: [
106
Padding(
110
- padding: const EdgeInsets.only(right: 6.0),
111
- child: Observer(
112
- builder: (_) =>
113
- SyncIndicatorIcon(isSynced: exchangeViewModel.status is SyncedSyncStatus),
114
- )),
107
+ padding: const EdgeInsets.only(right: 6.0),
108
+ child: Observer(
109
+ builder: (_) =>
110
+ SyncIndicatorIcon(isSynced: exchangeViewModel.status is SyncedSyncStatus),
111
+ ),
112
+ ),
113
PresentProviderPicker(exchangeViewModel: exchangeViewModel)
114
],
115
);
116
117
@override
118
Widget trailing(BuildContext context) => TrailButton(
121
- caption: S.of(context).reset,
122
- onPressed: () {
123
- _formKey.currentState?.reset();
124
- exchangeViewModel.reset();
125
- });
119
+ caption: S.of(context).reset,
120
+ onPressed: () {
121
+ _formKey.currentState?.reset();
122
+ exchangeViewModel.reset();
123
+ },
124
+ );
125
126
@override
127
Widget? leading(BuildContext context) {
128
final _backButton = Icon(
129
Icons.arrow_back_ios,
131
- color: titleColor(context),
130
+ color: Theme.of(context).colorScheme.primary,
131
size: 16,
132
);
133
final _closeButton =
135
- currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
134
+ currentTheme.isDark ? closeButtonImageDarkTheme : closeButtonImage;
135
136
bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI;
137
145
label: !isMobileView ? S.of(context).close : S.of(context).seed_alert_back,
146
child: TextButton(
147
style: ButtonStyle(
149
- overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
148
+ overlayColor: WidgetStateColor.resolveWith((states) => Colors.transparent),
149
),
150
onPressed: () => onClose(context),
151
child: !isMobileView ? _closeButton : _backButton,
161
WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context, exchangeViewModel));
162
163
return KeyboardActions(
165
- disableScroll: true,
166
- config: KeyboardActionsConfig(
167
- keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
168
- keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
169
- nextFocus: false,
170
- actions: [
171
- KeyboardActionsItem(
172
- focusNode: _depositAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]),
173
- KeyboardActionsItem(
174
- focusNode: _receiveAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()])
175
- ]),
176
- child: Container(
177
- color: Theme.of(context).colorScheme.background,
178
- child: Form(
179
- key: _formKey,
180
- child: ScrollableWithBottomSection(
181
- contentPadding: EdgeInsets.only(bottom: 24),
182
- content: Observer(
183
- builder: (_) => Column(
184
- children: <Widget>[
185
- _exchangeCardsSection(context),
186
- Padding(
187
- padding: EdgeInsets.only(top: 12, left: 24),
188
- child: Row(
189
- mainAxisAlignment: MainAxisAlignment.start,
190
- children: [
191
- StandardCheckbox(
192
- value: exchangeViewModel.isFixedRateMode,
193
- caption: S.of(context).fixed_rate,
194
- onChanged: (value) {
195
- if (value) {
196
- exchangeViewModel.enableFixedRateMode();
197
- } else {
198
- exchangeViewModel.isFixedRateMode = false;
199
- }
200
- },
201
- ),
202
- ],
203
- )),
204
- SizedBox(height: 30),
205
- _buildTemplateSection(context)
206
- ],
207
- ),
208
- ),
209
- bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
210
- bottomSection: Column(children: <Widget>[
164
+ disableScroll: true,
165
+ config: KeyboardActionsConfig(
166
+ keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
167
+ keyboardBarColor: Theme.of(context).colorScheme.surfaceContainerHighest,
168
+ nextFocus: false,
169
+ actions: [
170
+ KeyboardActionsItem(
171
+ focusNode: _depositAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]),
172
+ KeyboardActionsItem(
173
+ focusNode: _receiveAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()])
174
+ ],
175
+ ),
176
+ child: Container(
177
+ color: Theme.of(context).colorScheme.surface,
178
+ child: Form(
179
+ key: _formKey,
180
+ child: ScrollableWithBottomSection(
181
+ contentPadding: EdgeInsets.only(bottom: 24),
182
+ content: Observer(
183
+ builder: (_) => Column(
184
+ children: <Widget>[
185
+ _exchangeCardsSection(context),
186
Padding(
212
- padding: EdgeInsets.only(bottom: 15),
213
- child: Observer(builder: (_) {
187
+ padding: EdgeInsets.only(top: 12, left: 24),
188
+ child: Row(
189
+ mainAxisAlignment: MainAxisAlignment.start,
190
+ children: [
191
+ StandardCheckbox(
192
+ value: exchangeViewModel.isFixedRateMode,
193
+ caption: S.of(context).fixed_rate,
194
+ onChanged: (value) {
195
+ if (value) {
196
+ exchangeViewModel.enableFixedRateMode();
197
+ } else {
198
+ exchangeViewModel.isFixedRateMode = false;
199
+ }
200
+ },
201
+ ),
202
+ ],
203
+ ),
204
+ ),
205
+ SizedBox(height: 30),
206
+ _buildTemplateSection(context)
207
+ ],
208
+ ),
209
+ ),
210
+ bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
211
+ bottomSection: Column(
212
+ children: <Widget>[
213
+ Padding(
214
+ padding: EdgeInsets.only(bottom: 15),
215
+ child: Observer(
216
+ builder: (_) {
217
final description = exchangeViewModel.isFixedRateMode
218
? exchangeViewModel.isAvailableInSelected
219
? S.of(context).amount_is_guaranteed
223
: S.of(context).this_pair_is_not_supported_warning;
224
return Row(
225
children: [
223
- if(description == S.of(context).this_pair_is_not_supported_warning)
226
+ if (description == S.of(context).this_pair_is_not_supported_warning)
227
Expanded(
225
- child: Container(
226
- alignment: Alignment.centerRight,
227
- child: Icon(Icons.warning_amber_rounded,
228
- color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor,
229
- size: 26),
228
+ child: Container(
229
+ alignment: Alignment.centerRight,
230
+ child: Icon(Icons.warning_amber_rounded,
231
+ color: Theme.of(context).colorScheme.error, size: 26),
232
+ ),
233
),
231
- ),
234
Expanded(
235
flex: 8,
236
child: Text(
239
softWrap: true,
240
overflow: TextOverflow.ellipsis,
241
maxLines: 3,
240
- style: TextStyle(
241
- color: Theme.of(context)
242
- .extension<ExchangePageTheme>()!
243
- .receiveAmountColor,
244
- fontWeight: FontWeight.w500,
245
- fontSize: 12,
246
- ),
242
+ style: Theme.of(context).textTheme.bodySmall?.copyWith(
243
+ color: Theme.of(context).colorScheme.onSurfaceVariant,
244
+ fontWeight: FontWeight.w500,
245
+ ),
246
),
247
),
248
],
249
);
251
- }),
250
+ },
251
),
253
- Observer(
254
- builder: (_) => LoadingPrimaryButton(
255
- key: ValueKey('exchange_page_exchange_button_key'),
256
- text: exchangeViewModel.isAvailableInSelected ? S.of(context).swap : S.of(context).change_selected_exchanges,
257
- onPressed: exchangeViewModel.isAvailableInSelected ? () {
252
+ ),
253
+ Observer(
254
+ builder: (_) => LoadingPrimaryButton(
255
+ key: ValueKey('exchange_page_exchange_button_key'),
256
+ text: exchangeViewModel.isAvailableInSelected
257
+ ? S.of(context).swap
258
+ : S.of(context).change_selected_exchanges,
259
+ onPressed: exchangeViewModel.isAvailableInSelected
260
+ ? () {
261
FocusScope.of(context).unfocus();
262
260
- if (_formKey.currentState != null &&
261
- _formKey.currentState!.validate()) {
262
- if (_shouldWaitTillSynced) {
263
- showPopUp<void>(
264
- context: context,
265
- builder: (BuildContext context) {
266
- return AlertWithOneAction(
267
- alertTitle: S.of(context).exchange,
268
- alertContent:
269
- S.of(context).exchange_sync_alert_content,
270
- buttonText: S.of(context).ok,
271
- buttonAction: () => Navigator.of(context).pop(),
272
- );
273
- });
274
- } else {
263
+ if (_formKey.currentState != null &&
264
+ _formKey.currentState!.validate()) {
265
+ if (_shouldWaitTillSynced) {
266
+ showPopUp<void>(
267
+ context: context,
268
+ builder: (BuildContext context) {
269
+ return AlertWithOneAction(
270
+ alertTitle: S.of(context).exchange,
271
+ alertContent: S.of(context).exchange_sync_alert_content,
272
+ buttonText: S.of(context).ok,
273
+ buttonAction: () => Navigator.of(context).pop(),
274
+ );
275
+ },
276
+ );
277
+ } else {
278
final check = exchangeViewModel.shouldDisplayTOTP();
279
authService.authenticateAction(
280
context,
287
);
288
}
289
}
287
- } : () => PresentProviderPicker(exchangeViewModel: exchangeViewModel).presentProviderPicker(context),
288
- color: Theme.of(context).primaryColor,
289
- textColor: Colors.white,
290
- isDisabled: exchangeViewModel.selectedProviders.isEmpty,
291
- isLoading: exchangeViewModel.tradeState is TradeIsCreating)),
292
- ]),
293
- )),
294
- ));
290
+ }
291
+ : () => PresentProviderPicker(exchangeViewModel: exchangeViewModel)
292
+ .presentProviderPicker(context),
293
+ color: Theme.of(context).colorScheme.primary,
294
+ textColor: Theme.of(context).colorScheme.onPrimary,
295
+ isDisabled: exchangeViewModel.selectedProviders.isEmpty,
296
+ isLoading: exchangeViewModel.tradeState is TradeIsCreating,
297
+ ),
298
+ ),
299
+ ],
300
+ ),
301
+ ),
302
+ ),
303
+ ),
304
+ );
305
}
306
307
Widget _buildTemplateSection(BuildContext context) {
339
},
340
onRemove: () {
341
showPopUp<void>(
332
- context: context,
333
- builder: (dialogContext) {
334
- return AlertWithTwoActions(
335
- alertTitle: S.of(context).template,
336
- alertContent: S.of(context).confirm_delete_template,
337
- rightButtonText: S.of(context).delete,
338
- leftButtonText: S.of(context).cancel,
339
- actionRightButton: () {
340
- Navigator.of(dialogContext).pop();
341
- exchangeViewModel.removeTemplate(template: template);
342
- exchangeViewModel.updateTemplate();
343
- },
344
- actionLeftButton: () => Navigator.of(dialogContext).pop());
345
- });
342
+ context: context,
343
+ builder: (dialogContext) {
344
+ return AlertWithTwoActions(
345
+ alertTitle: S.of(context).template,
346
+ alertContent: S.of(context).confirm_delete_template,
347
+ rightButtonText: S.of(context).delete,
348
+ leftButtonText: S.of(context).cancel,
349
+ actionRightButton: () {
350
+ Navigator.of(dialogContext).pop();
351
+ exchangeViewModel.removeTemplate(template: template);
352
+ exchangeViewModel.updateTemplate();
353
+ },
354
+ actionLeftButton: () => Navigator.of(dialogContext).pop(),
355
+ );
356
+ },
357
+ );
358
},
359
);
360
},
482
if (state is TradeIsCreatedSuccessfully) {
483
exchangeViewModel.reset();
484
(exchangeViewModel.tradesStore.trade?.provider == ExchangeProviderDescription.thorChain ||
473
- exchangeViewModel.tradesStore.trade?.provider == ExchangeProviderDescription.chainflip)
485
+ exchangeViewModel.tradesStore.trade?.provider ==
486
+ ExchangeProviderDescription.chainflip)
487
? Navigator.of(context).pushReplacementNamed(Routes.exchangeTrade)
488
: Navigator.of(context).pushReplacementNamed(Routes.exchangeConfirm);
489
}
618
key.currentState!.changeWalletName(isCurrentTypeWallet ? exchangeViewModel.wallet.name : '');
619
620
key.currentState!.changeAddress(
608
- address: isCurrentTypeWallet ? exchangeViewModel.wallet.walletAddresses.addressForExchange : '');
621
+ address:
622
+ isCurrentTypeWallet ? exchangeViewModel.wallet.walletAddresses.addressForExchange : '');
623
624
key.currentState!.changeAmount(amount: '');
625
}
630
631
if (isCurrentTypeWallet) {
632
key.currentState!.changeWalletName(exchangeViewModel.wallet.name);
619
- key.currentState!.addressController.text = exchangeViewModel.wallet.walletAddresses.addressForExchange;
633
+ key.currentState!.addressController.text =
634
+ exchangeViewModel.wallet.walletAddresses.addressForExchange;
635
} else if (key.currentState!.addressController.text ==
636
exchangeViewModel.wallet.walletAddresses.addressForExchange) {
637
key.currentState!.changeWalletName('');
661
}) ??
662
false;
663
if (confirmed) {
649
- exchangeViewModel.feesViewModel .setDefaultTransactionPriority();
664
+ exchangeViewModel.feesViewModel.setDefaultTransactionPriority();
665
}
666
}
667
669
670
Widget _exchangeCardsSection(BuildContext context) {
671
final firstExchangeCard = Observer(
657
- builder: (_) => ExchangeCard(
658
- cardInstanceName: 'deposit_exchange_card',
659
- onDispose: disposeBestRateSync,
660
- hasAllAmount: exchangeViewModel.hasAllAmount,
661
- allAmount: exchangeViewModel.hasAllAmount
662
- ? () => exchangeViewModel.enableSendAllAmount()
663
- : null,
664
- isAllAmountEnabled: exchangeViewModel.isSendAllEnabled,
665
- amountFocusNode: _depositAmountFocus,
666
- addressFocusNode: _depositAddressFocus,
667
- key: depositKey,
668
- title: S.of(context).you_will_send,
669
- initialCurrency: exchangeViewModel.depositCurrency,
670
- initialWalletName: depositWalletName ?? '',
671
- initialAddress: exchangeViewModel.depositCurrency == exchangeViewModel.wallet.currency
672
- ? exchangeViewModel.wallet.walletAddresses.addressForExchange
673
- : exchangeViewModel.depositAddress,
674
- initialIsAmountEditable: true,
675
- initialIsAddressEditable: exchangeViewModel.isDepositAddressEnabled,
676
- isAmountEstimated: false,
677
- hasRefundAddress: true,
678
- isMoneroWallet: exchangeViewModel.isMoneroWallet,
679
- currencies: exchangeViewModel.depositCurrencies,
680
- onCurrencySelected: (currency) {
681
- // FIXME: need to move it into view model
682
- if (currency == CryptoCurrency.xmr &&
683
- exchangeViewModel.wallet.type != WalletType.monero) {
684
- showPopUp<void>(
685
- context: context,
686
- builder: (dialogContext) {
687
- return AlertWithOneAction(
688
- alertTitle: S.of(context).error,
689
- alertContent: S.of(context).exchange_incorrect_current_wallet_for_xmr,
690
- buttonText: S.of(context).ok,
691
- buttonAction: () => Navigator.of(dialogContext).pop());
692
- });
693
- return;
694
- }
695
-
696
- exchangeViewModel.changeDepositCurrency(currency: currency);
697
- },
698
- currencyButtonColor: Colors.transparent,
699
- addressButtonsColor:
700
- Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
701
- borderColor:
702
- Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor,
703
- currencyValueValidator: (value) {
704
- return !exchangeViewModel.isFixedRateMode && value != S.of(context).all
705
- ? AmountValidator(
706
- isAutovalidate: true,
707
- currency: exchangeViewModel.depositCurrency,
708
- minValue: exchangeViewModel.limits.min.toString(),
709
- maxValue: exchangeViewModel.limits.max.toString(),
710
- ).call(value)
711
- : null;
712
- },
713
- addressTextFieldValidator: AddressValidator(type: exchangeViewModel.depositCurrency),
714
- onPushPasteButton: (context) async {
715
- final domain = exchangeViewModel.depositAddress;
716
- exchangeViewModel.depositAddress =
717
- await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
718
- },
719
- onPushAddressBookButton: (context) async {
720
- final domain = exchangeViewModel.depositAddress;
721
- exchangeViewModel.depositAddress =
722
- await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
723
- },
724
- ));
672
+ builder: (_) => ExchangeCard(
673
+ cardInstanceName: 'deposit_exchange_card',
674
+ onDispose: disposeBestRateSync,
675
+ hasAllAmount: exchangeViewModel.hasAllAmount,
676
+ allAmount:
677
+ exchangeViewModel.hasAllAmount ? () => exchangeViewModel.enableSendAllAmount() : null,
678
+ isAllAmountEnabled: exchangeViewModel.isSendAllEnabled,
679
+ amountFocusNode: _depositAmountFocus,
680
+ addressFocusNode: _depositAddressFocus,
681
+ key: depositKey,
682
+ title: S.of(context).you_will_send,
683
+ initialCurrency: exchangeViewModel.depositCurrency,
684
+ initialWalletName: depositWalletName ?? '',
685
+ initialAddress: exchangeViewModel.depositCurrency == exchangeViewModel.wallet.currency
686
+ ? exchangeViewModel.wallet.walletAddresses.addressForExchange
687
+ : exchangeViewModel.depositAddress,
688
+ initialIsAmountEditable: true,
689
+ initialIsAddressEditable: exchangeViewModel.isDepositAddressEnabled,
690
+ isAmountEstimated: false,
691
+ hasRefundAddress: true,
692
+ isMoneroWallet: exchangeViewModel.isMoneroWallet,
693
+ currencies: exchangeViewModel.depositCurrencies,
694
+ onCurrencySelected: (currency) {
695
+ // FIXME: need to move it into view model
696
+ if (currency == CryptoCurrency.xmr &&
697
+ exchangeViewModel.wallet.type != WalletType.monero) {
698
+ showPopUp<void>(
699
+ context: context,
700
+ builder: (dialogContext) {
701
+ return AlertWithOneAction(
702
+ alertTitle: S.of(context).error,
703
+ alertContent: S.of(context).exchange_incorrect_current_wallet_for_xmr,
704
+ buttonText: S.of(context).ok,
705
+ buttonAction: () => Navigator.of(dialogContext).pop(),
706
+ );
707
+ });
708
+ return;
709
+ }
710
+
711
+ exchangeViewModel.changeDepositCurrency(currency: currency);
712
+ },
713
+ currencyButtonColor: Colors.transparent,
714
+ addressButtonsColor: Colors.transparent,
715
+ borderColor: Theme.of(context).colorScheme.outlineVariant,
716
+ fillColor: Theme.of(context).colorScheme.surfaceContainer,
717
+ currencyValueValidator: (value) {
718
+ return !exchangeViewModel.isFixedRateMode && value != S.of(context).all
719
+ ? AmountValidator(
720
+ isAutovalidate: true,
721
+ currency: exchangeViewModel.depositCurrency,
722
+ minValue: exchangeViewModel.limits.min.toString(),
723
+ maxValue: exchangeViewModel.limits.max.toString(),
724
+ ).call(value)
725
+ : null;
726
+ },
727
+ addressTextFieldValidator: AddressValidator(type: exchangeViewModel.depositCurrency),
728
+ onPushPasteButton: (context) async {
729
+ final domain = exchangeViewModel.depositAddress;
730
+ exchangeViewModel.depositAddress =
731
+ await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
732
+ },
733
+ onPushAddressBookButton: (context) async {
734
+ final domain = exchangeViewModel.depositAddress;
735
+ exchangeViewModel.depositAddress =
736
+ await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
737
+ },
738
+ ),
739
+ );
740
741
final secondExchangeCard = Observer(
727
- builder: (_) => ExchangeCard(
728
- cardInstanceName: 'receive_exchange_card',
729
- onDispose: disposeBestRateSync,
730
- amountFocusNode: _receiveAmountFocus,
731
- addressFocusNode: _receiveAddressFocus,
732
- key: receiveKey,
733
- title: S.of(context).you_will_get,
734
- initialCurrency: exchangeViewModel.receiveCurrency,
735
- initialWalletName: receiveWalletName ?? '',
736
- initialAddress: exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency
737
- ? exchangeViewModel.wallet.walletAddresses.addressForExchange
738
- : exchangeViewModel.receiveAddress,
739
- initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable,
740
- isAmountEstimated: true,
741
- isMoneroWallet: exchangeViewModel.isMoneroWallet,
742
- currencies: exchangeViewModel.receiveCurrencies,
743
- onCurrencySelected: (currency) =>
744
- exchangeViewModel.changeReceiveCurrency(currency: currency),
745
- currencyButtonColor: Colors.transparent,
746
- addressButtonsColor:
747
- Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
748
- borderColor:
749
- Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
750
- currencyValueValidator: (value) {
751
- return exchangeViewModel.isFixedRateMode
752
- ? AmountValidator(
753
- isAutovalidate: true,
754
- currency: exchangeViewModel.receiveCurrency,
755
- minValue: exchangeViewModel.limits.min.toString(),
756
- maxValue: exchangeViewModel.limits.max.toString(),
757
- ).call(value)
758
- : null;
759
- },
760
- addressTextFieldValidator: AddressValidator(type: exchangeViewModel.receiveCurrency),
761
- onPushPasteButton: (context) async {
762
- final domain = exchangeViewModel.receiveAddress;
763
- exchangeViewModel.receiveAddress =
764
- await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
765
- },
766
- onPushAddressBookButton: (context) async {
767
- final domain = exchangeViewModel.receiveAddress;
768
- exchangeViewModel.receiveAddress =
769
- await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
770
- },
771
- ));
772
-
773
- if (responsiveLayoutUtil.shouldRenderMobileUI) {
774
- return MobileExchangeCardsSection(
775
- firstExchangeCard: firstExchangeCard,
776
- secondExchangeCard: secondExchangeCard,
777
- );
778
- }
779
-
780
- return DesktopExchangeCardsSection(
781
- firstExchangeCard: firstExchangeCard,
782
- secondExchangeCard: secondExchangeCard,
742
+ builder: (_) => ExchangeCard(
743
+ cardInstanceName: 'receive_exchange_card',
744
+ onDispose: disposeBestRateSync,
745
+ amountFocusNode: _receiveAmountFocus,
746
+ addressFocusNode: _receiveAddressFocus,
747
+ key: receiveKey,
748
+ title: S.of(context).you_will_get,
749
+ initialCurrency: exchangeViewModel.receiveCurrency,
750
+ initialWalletName: receiveWalletName ?? '',
751
+ initialAddress: exchangeViewModel.receiveCurrency == exchangeViewModel.wallet.currency
752
+ ? exchangeViewModel.wallet.walletAddresses.addressForExchange
753
+ : exchangeViewModel.receiveAddress,
754
+ initialIsAmountEditable: exchangeViewModel.isReceiveAmountEditable,
755
+ isAmountEstimated: true,
756
+ isMoneroWallet: exchangeViewModel.isMoneroWallet,
757
+ currencies: exchangeViewModel.receiveCurrencies,
758
+ onCurrencySelected: (currency) =>
759
+ exchangeViewModel.changeReceiveCurrency(currency: currency),
760
+ currencyButtonColor: Colors.transparent,
761
+ addressButtonsColor: Colors.transparent,
762
+ borderColor: Theme.of(context).colorScheme.outlineVariant,
763
+ fillColor: Theme.of(context).colorScheme.surfaceContainerLow,
764
+ currencyValueValidator: (value) {
765
+ return exchangeViewModel.isFixedRateMode
766
+ ? AmountValidator(
767
+ isAutovalidate: true,
768
+ currency: exchangeViewModel.receiveCurrency,
769
+ minValue: exchangeViewModel.limits.min.toString(),
770
+ maxValue: exchangeViewModel.limits.max.toString(),
771
+ ).call(value)
772
+ : null;
773
+ },
774
+ addressTextFieldValidator: AddressValidator(type: exchangeViewModel.receiveCurrency),
775
+ onPushPasteButton: (context) async {
776
+ final domain = exchangeViewModel.receiveAddress;
777
+ exchangeViewModel.receiveAddress =
778
+ await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
779
+ },
780
+ onPushAddressBookButton: (context) async {
781
+ final domain = exchangeViewModel.receiveAddress;
782
+ exchangeViewModel.receiveAddress =
783
+ await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
784
+ },
785
+ ),
786
);
787
+
788
+ return responsiveLayoutUtil.shouldRenderMobileUI
789
+ ? MobileExchangeCardsSection(
790
+ firstExchangeCard: firstExchangeCard,
791
+ secondExchangeCard: secondExchangeCard,
792
+ )
793
+ : DesktopExchangeCardsSection(
794
+ firstExchangeCard: firstExchangeCard,
795
+ secondExchangeCard: secondExchangeCard,
796
+ );
797
}
798
}