mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-17 01:37:40 +00:00
feat: Testing the Exchange flow section, selecting sending and receiving currencies
This commit is contained in:
parent
8ec38e10ff
commit
66af74f0c0
16 changed files with 315 additions and 64 deletions
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import 'package:cake_wallet/main.dart' as app;
|
import 'package:cake_wallet/main.dart' as app;
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
@ -7,6 +7,7 @@ import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
import 'robots/dashboard_page_robot.dart';
|
import 'robots/dashboard_page_robot.dart';
|
||||||
import 'robots/disclaimer_page_robot.dart';
|
import 'robots/disclaimer_page_robot.dart';
|
||||||
|
import 'robots/exchange_page_robot.dart';
|
||||||
import 'robots/new_wallet_type_page_robot.dart';
|
import 'robots/new_wallet_type_page_robot.dart';
|
||||||
import 'robots/restore_from_seed_or_key_robot.dart';
|
import 'robots/restore_from_seed_or_key_robot.dart';
|
||||||
import 'robots/restore_options_page_robot.dart';
|
import 'robots/restore_options_page_robot.dart';
|
||||||
|
@ -32,6 +33,7 @@ void main() {
|
||||||
NewWalletTypePageRobot newWalletTypePageRobot;
|
NewWalletTypePageRobot newWalletTypePageRobot;
|
||||||
RestoreFromSeedOrKeysPageRobot restoreFromSeedOrKeysPageRobot;
|
RestoreFromSeedOrKeysPageRobot restoreFromSeedOrKeysPageRobot;
|
||||||
DashboardPageRobot dashboardPageRobot;
|
DashboardPageRobot dashboardPageRobot;
|
||||||
|
ExchangePageRobot exchangePageRobot;
|
||||||
|
|
||||||
group('Startup Test', () {
|
group('Startup Test', () {
|
||||||
testWidgets('Test for Exchange flow using Restore Wallet - Exchanging USDT(Sol) to SOL',
|
testWidgets('Test for Exchange flow using Restore Wallet - Exchanging USDT(Sol) to SOL',
|
||||||
|
@ -43,6 +45,7 @@ void main() {
|
||||||
newWalletTypePageRobot = NewWalletTypePageRobot(tester);
|
newWalletTypePageRobot = NewWalletTypePageRobot(tester);
|
||||||
restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(tester);
|
restoreFromSeedOrKeysPageRobot = RestoreFromSeedOrKeysPageRobot(tester);
|
||||||
dashboardPageRobot = DashboardPageRobot(tester);
|
dashboardPageRobot = DashboardPageRobot(tester);
|
||||||
|
exchangePageRobot = ExchangePageRobot(tester);
|
||||||
|
|
||||||
await app.main();
|
await app.main();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
@ -139,14 +142,28 @@ void main() {
|
||||||
await restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonTapped();
|
await restoreFromSeedOrKeysPageRobot.onRestoreWalletButtonTapped();
|
||||||
|
|
||||||
// ----------- RestoreFromSeedOrKeys Page -------------
|
// ----------- RestoreFromSeedOrKeys Page -------------
|
||||||
await dashboardPageRobot.isDashboardPage();
|
// await dashboardPageRobot.isDashboardPage();
|
||||||
dashboardPageRobot.confirmServiceUpdateButtonDisplays();
|
// dashboardPageRobot.confirmServiceUpdateButtonDisplays();
|
||||||
dashboardPageRobot.confirmMenuButtonDisplays();
|
// dashboardPageRobot.confirmMenuButtonDisplays();
|
||||||
dashboardPageRobot.confirmSyncIndicatorButtonDisplays();
|
// dashboardPageRobot.confirmSyncIndicatorButtonDisplays();
|
||||||
await dashboardPageRobot.confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType.solana);
|
// await dashboardPageRobot.confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType.solana);
|
||||||
|
|
||||||
await dashboardPageRobot.navigateToExchangePage();
|
await dashboardPageRobot.navigateToExchangePage();
|
||||||
await Future.delayed(Duration(seconds: 5));
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
|
||||||
|
// ----------- Exchange Page -------------
|
||||||
|
await exchangePageRobot.isExchangePage();
|
||||||
|
exchangePageRobot.hasTitle();
|
||||||
|
exchangePageRobot.hasResetButton();
|
||||||
|
await exchangePageRobot.displayBothExchangeCards();
|
||||||
|
exchangePageRobot.confirmRightComponentsDisplayOnDepositExchangeCards();
|
||||||
|
exchangePageRobot.confirmRightComponentsDisplayOnReceiveExchangeCards();
|
||||||
|
|
||||||
|
await exchangePageRobot.selectDepositCurrency(CryptoCurrency.btc);
|
||||||
|
|
||||||
|
await exchangePageRobot.selectReceiveCurrency(CryptoCurrency.usdtSol);
|
||||||
|
|
||||||
|
await Future.delayed(Duration(seconds: 10));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ class CommonTestCases {
|
||||||
expect(typeWidget, findsOneWidget);
|
expect(typeWidget, findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hasKey(String key) {
|
void hasValueKey(String key) {
|
||||||
final typeWidget = find.byKey(ValueKey(key));
|
final typeWidget = find.byKey(ValueKey(key));
|
||||||
expect(typeWidget, findsOneWidget);
|
expect(typeWidget, findsOneWidget);
|
||||||
}
|
}
|
||||||
|
@ -51,5 +51,19 @@ class CommonTestCases {
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> defaultSleepTime({int seconds = 2})async => await Future.delayed(Duration(seconds: seconds));
|
Future<void> scrollUntilVisible(String childKey, String parentScrollableKey, {double delta = 300}) async {
|
||||||
|
final scrollableWidget = find.descendant(
|
||||||
|
of: find.byKey(Key(parentScrollableKey)),
|
||||||
|
matching: find.byType(Scrollable),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.scrollUntilVisible(
|
||||||
|
find.byKey(ValueKey(childKey)),
|
||||||
|
delta,
|
||||||
|
scrollable: scrollableWidget,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> defaultSleepTime({int seconds = 2}) async =>
|
||||||
|
await Future.delayed(Duration(seconds: seconds));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,15 @@ class DashboardPageRobot {
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmServiceUpdateButtonDisplays() {
|
void confirmServiceUpdateButtonDisplays() {
|
||||||
commonTestCases.hasKey('dashboard_page_services_update_button_key');
|
commonTestCases.hasValueKey('dashboard_page_services_update_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmSyncIndicatorButtonDisplays() {
|
void confirmSyncIndicatorButtonDisplays() {
|
||||||
commonTestCases.hasKey('dashboard_page_sync_indicator_button_key');
|
commonTestCases.hasValueKey('dashboard_page_sync_indicator_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmMenuButtonDisplays() {
|
void confirmMenuButtonDisplays() {
|
||||||
commonTestCases.hasKey('dashboard_page_wallet_menu_button_key');
|
commonTestCases.hasValueKey('dashboard_page_wallet_menu_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType type,
|
Future<void> confirmRightCryptoAssetTitleDisplaysPerPageView(WalletType type,
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/exchange/widgets/exchange_card.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker.dart';
|
||||||
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../components/common_checks.dart';
|
||||||
|
|
||||||
|
class ExchangePageRobot {
|
||||||
|
ExchangePageRobot(this.tester) : commonTestCases = CommonTestCases(tester);
|
||||||
|
|
||||||
|
final WidgetTester tester;
|
||||||
|
late CommonTestCases commonTestCases;
|
||||||
|
|
||||||
|
Future<void> isExchangePage() async {
|
||||||
|
await commonTestCases.isSpecificPage<ExchangePage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hasTitle() {
|
||||||
|
// commonTestCases.hasText(S.current.exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hasResetButton() {
|
||||||
|
commonTestCases.hasText(S.current.reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void displaysPresentProviderPicker() {
|
||||||
|
commonTestCases.hasType<PresentProviderPicker>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> displayBothExchangeCards() async {
|
||||||
|
final ExchangePage exchangeCard = tester.widget<ExchangePage>(
|
||||||
|
find.byType(ExchangePage),
|
||||||
|
);
|
||||||
|
|
||||||
|
final depositKey = exchangeCard.depositKey;
|
||||||
|
final receiveKey = exchangeCard.receiveKey;
|
||||||
|
|
||||||
|
final depositExchangeCard = find.byKey(depositKey);
|
||||||
|
expect(depositExchangeCard, findsOneWidget);
|
||||||
|
|
||||||
|
final receiveExchangeCard = find.byKey(receiveKey);
|
||||||
|
expect(receiveExchangeCard, findsOneWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void confirmRightComponentsDisplayOnDepositExchangeCards() {
|
||||||
|
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||||
|
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||||
|
final depositCardPrefix = 'deposit_exchange_card';
|
||||||
|
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_title_key');
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_currency_picker_button_key');
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_selected_currency_text_key');
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_amount_textfield_key');
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_min_limit_text_key');
|
||||||
|
|
||||||
|
final initialCurrency = exchangeViewModel.depositCurrency;
|
||||||
|
if (initialCurrency.tag != null) {
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_selected_currency_tag_text_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchangeViewModel.hasAllAmount) {
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_send_all_button_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchangeViewModel.isMoneroWallet) {
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_address_book_button_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchangeViewModel.isDepositAddressEnabled) {
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_editable_address_textfield_key');
|
||||||
|
} else {
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_non_editable_address_textfield_key');
|
||||||
|
commonTestCases.hasValueKey('${depositCardPrefix}_copy_refund_address_button_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonTestCases.hasValueKey('${depositCardPrefix}_max_limit_text_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
void confirmRightComponentsDisplayOnReceiveExchangeCards() {
|
||||||
|
ExchangePage exchangePage = tester.widget(find.byType(ExchangePage));
|
||||||
|
final exchangeViewModel = exchangePage.exchangeViewModel;
|
||||||
|
final receiveCardPrefix = 'receive_exchange_card';
|
||||||
|
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_title_key');
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_currency_picker_button_key');
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_selected_currency_text_key');
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_amount_textfield_key');
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_min_limit_text_key');
|
||||||
|
|
||||||
|
final initialCurrency = exchangeViewModel.receiveCurrency;
|
||||||
|
if (initialCurrency.tag != null) {
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_selected_currency_tag_text_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchangeViewModel.hasAllAmount) {
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_send_all_button_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exchangeViewModel.isMoneroWallet) {
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_address_book_button_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
commonTestCases.hasValueKey('${receiveCardPrefix}_editable_address_textfield_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectDepositCurrency(CryptoCurrency depositCurrency) async {
|
||||||
|
final depositPrefix = 'deposit_exchange_card';
|
||||||
|
final currencyPickerKey = '${depositPrefix}_currency_picker_button_key';
|
||||||
|
final currencyPickerDialogKey = '${depositPrefix}_currency_picker_dialog_button_key';
|
||||||
|
|
||||||
|
await commonTestCases.tapItemByKey(currencyPickerKey);
|
||||||
|
commonTestCases.hasValueKey(currencyPickerDialogKey);
|
||||||
|
|
||||||
|
await commonTestCases.scrollUntilVisible(
|
||||||
|
'picker_items_index_${depositCurrency.name}_button_key',
|
||||||
|
'picker_scrollbar_key',
|
||||||
|
);
|
||||||
|
await commonTestCases.defaultSleepTime();
|
||||||
|
|
||||||
|
await commonTestCases.tapItemByKey('picker_items_index_${depositCurrency.name}_button_key');
|
||||||
|
await commonTestCases.defaultSleepTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectReceiveCurrency(CryptoCurrency receiveCurrency) async {
|
||||||
|
final receivePrefix = 'receive_exchange_card';
|
||||||
|
final currencyPickerKey = '${receivePrefix}_currency_picker_button_key';
|
||||||
|
final currencyPickerDialogKey = '${receivePrefix}_currency_picker_dialog_button_key';
|
||||||
|
|
||||||
|
await commonTestCases.tapItemByKey(currencyPickerKey);
|
||||||
|
|
||||||
|
commonTestCases.hasValueKey(currencyPickerDialogKey);
|
||||||
|
|
||||||
|
await commonTestCases.scrollUntilVisible(
|
||||||
|
'picker_items_index_${receiveCurrency.name}_button_key',
|
||||||
|
'picker_scrollbar_key',
|
||||||
|
);
|
||||||
|
await commonTestCases.defaultSleepTime();
|
||||||
|
|
||||||
|
await commonTestCases.tapItemByKey('picker_items_index_${receiveCurrency.name}_button_key');
|
||||||
|
await commonTestCases.defaultSleepTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> enterDepositAddress(String depositAddress) async {
|
||||||
|
final amountTextField = find.byKey(ValueKey('deposit_exchange_card_amount_textfield_key'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> enterReceiveAddress(String receiveAddress) async {}
|
||||||
|
}
|
|
@ -21,10 +21,10 @@ class RestoreFromSeedOrKeysPageRobot {
|
||||||
commonTestCases.hasText(S.current.enter_seed_phrase);
|
commonTestCases.hasText(S.current.enter_seed_phrase);
|
||||||
commonTestCases.hasText(S.current.restore_title_from_seed);
|
commonTestCases.hasText(S.current.restore_title_from_seed);
|
||||||
|
|
||||||
commonTestCases.hasKey('wallet_restore_from_seed_wallet_name_textfield_key');
|
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_name_textfield_key');
|
||||||
commonTestCases.hasKey('wallet_restore_from_seed_wallet_name_refresh_button_key');
|
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_name_refresh_button_key');
|
||||||
commonTestCases.hasKey('wallet_restore_from_seed_wallet_seeds_paste_button_key');
|
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_seeds_paste_button_key');
|
||||||
commonTestCases.hasKey('wallet_restore_from_seed_wallet_seeds_textfield_key');
|
commonTestCases.hasValueKey('wallet_restore_from_seed_wallet_seeds_textfield_key');
|
||||||
|
|
||||||
commonTestCases.hasText(S.current.private_key, hasWidget: false);
|
commonTestCases.hasText(S.current.private_key, hasWidget: false);
|
||||||
commonTestCases.hasText(S.current.restore_title_from_keys, hasWidget: false);
|
commonTestCases.hasText(S.current.restore_title_from_keys, hasWidget: false);
|
||||||
|
@ -43,11 +43,11 @@ class RestoreFromSeedOrKeysPageRobot {
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmRestoreButtonDisplays() {
|
void confirmRestoreButtonDisplays() {
|
||||||
commonTestCases.hasKey('wallet_restore_seed_or_key_restore_button_key');
|
commonTestCases.hasValueKey('wallet_restore_seed_or_key_restore_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmAdvancedSettingButtonDisplays() {
|
void confirmAdvancedSettingButtonDisplays() {
|
||||||
commonTestCases.hasKey('wallet_restore_advanced_settings_button_key');
|
commonTestCases.hasValueKey('wallet_restore_advanced_settings_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> enterWalletNameText(String walletName) async {
|
Future<void> enterWalletNameText(String walletName) async {
|
||||||
|
@ -76,6 +76,6 @@ class RestoreFromSeedOrKeysPageRobot {
|
||||||
|
|
||||||
Future<void> onRestoreWalletButtonTapped() async {
|
Future<void> onRestoreWalletButtonTapped() async {
|
||||||
await commonTestCases.tapItemByKey('wallet_restore_seed_or_key_restore_button_key');
|
await commonTestCases.tapItemByKey('wallet_restore_seed_or_key_restore_button_key');
|
||||||
await commonTestCases.defaultSleepTime(seconds: 15);
|
// await commonTestCases.defaultSleepTime(seconds: 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@ class RestoreOptionsPageRobot {
|
||||||
}
|
}
|
||||||
|
|
||||||
void hasRestoreOptionsButton() {
|
void hasRestoreOptionsButton() {
|
||||||
commonTestCases.hasKey('restore_options_from_seeds_button_key');
|
commonTestCases.hasValueKey('restore_options_from_seeds_button_key');
|
||||||
commonTestCases.hasKey('restore_options_from_backup_button_key');
|
commonTestCases.hasValueKey('restore_options_from_backup_button_key');
|
||||||
commonTestCases.hasKey('restore_options_from_hardware_wallet_button_key');
|
commonTestCases.hasValueKey('restore_options_from_hardware_wallet_button_key');
|
||||||
commonTestCases.hasKey('restore_options_from_qr_button_key');
|
commonTestCases.hasValueKey('restore_options_from_qr_button_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> navigateToRestoreFromSeedsPage() async {
|
Future<void> navigateToRestoreFromSeedsPage() async {
|
||||||
|
|
|
@ -28,11 +28,11 @@ class SetupPinCodeRobot {
|
||||||
void hasNumberButtonsVisible() {
|
void hasNumberButtonsVisible() {
|
||||||
// Confirmation for buttons 1-9
|
// Confirmation for buttons 1-9
|
||||||
for (var i = 1; i < 10; i++) {
|
for (var i = 1; i < 10; i++) {
|
||||||
commonTestCases.hasKey('pin_code_button_${i}_key');
|
commonTestCases.hasValueKey('pin_code_button_${i}_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confirmation for 0 button
|
// Confirmation for 0 button
|
||||||
commonTestCases.hasKey('pin_code_button_0_key');
|
commonTestCases.hasValueKey('pin_code_button_0_key');
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pushPinButton(int index) async {
|
Future<void> pushPinButton(int index) async {
|
||||||
|
|
|
@ -239,6 +239,7 @@ class ExchangePage extends BasePage {
|
||||||
),
|
),
|
||||||
Observer(
|
Observer(
|
||||||
builder: (_) => LoadingPrimaryButton(
|
builder: (_) => LoadingPrimaryButton(
|
||||||
|
key: ValueKey('exchange_page_exchange_button_key'),
|
||||||
text: S.of(context).exchange,
|
text: S.of(context).exchange,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState != null &&
|
if (_formKey.currentState != null &&
|
||||||
|
@ -340,7 +341,6 @@ class ExchangePage extends BasePage {
|
||||||
|
|
||||||
void applyTemplate(
|
void applyTemplate(
|
||||||
BuildContext context, ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async {
|
BuildContext context, ExchangeViewModel exchangeViewModel, ExchangeTemplate template) async {
|
||||||
|
|
||||||
final depositCryptoCurrency = CryptoCurrency.fromString(template.depositCurrency);
|
final depositCryptoCurrency = CryptoCurrency.fromString(template.depositCurrency);
|
||||||
final receiveCryptoCurrency = CryptoCurrency.fromString(template.receiveCurrency);
|
final receiveCryptoCurrency = CryptoCurrency.fromString(template.receiveCurrency);
|
||||||
|
|
||||||
|
@ -354,10 +354,12 @@ class ExchangePage extends BasePage {
|
||||||
exchangeViewModel.isFixedRateMode = false;
|
exchangeViewModel.isFixedRateMode = false;
|
||||||
|
|
||||||
var domain = template.depositAddress;
|
var domain = template.depositAddress;
|
||||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, depositCryptoCurrency);
|
exchangeViewModel.depositAddress =
|
||||||
|
await fetchParsedAddress(context, domain, depositCryptoCurrency);
|
||||||
|
|
||||||
domain = template.receiveAddress;
|
domain = template.receiveAddress;
|
||||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, receiveCryptoCurrency);
|
exchangeViewModel.receiveAddress =
|
||||||
|
await fetchParsedAddress(context, domain, receiveCryptoCurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) {
|
void _setReactions(BuildContext context, ExchangeViewModel exchangeViewModel) {
|
||||||
|
@ -529,14 +531,16 @@ class ExchangePage extends BasePage {
|
||||||
_depositAddressFocus.addListener(() async {
|
_depositAddressFocus.addListener(() async {
|
||||||
if (!_depositAddressFocus.hasFocus && depositAddressController.text.isNotEmpty) {
|
if (!_depositAddressFocus.hasFocus && depositAddressController.text.isNotEmpty) {
|
||||||
final domain = depositAddressController.text;
|
final domain = depositAddressController.text;
|
||||||
exchangeViewModel.depositAddress = await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
|
exchangeViewModel.depositAddress =
|
||||||
|
await fetchParsedAddress(context, domain, exchangeViewModel.depositCurrency);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_receiveAddressFocus.addListener(() async {
|
_receiveAddressFocus.addListener(() async {
|
||||||
if (!_receiveAddressFocus.hasFocus && receiveAddressController.text.isNotEmpty) {
|
if (!_receiveAddressFocus.hasFocus && receiveAddressController.text.isNotEmpty) {
|
||||||
final domain = receiveAddressController.text;
|
final domain = receiveAddressController.text;
|
||||||
exchangeViewModel.receiveAddress = await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
|
exchangeViewModel.receiveAddress =
|
||||||
|
await fetchParsedAddress(context, domain, exchangeViewModel.receiveCurrency);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -589,7 +593,8 @@ class ExchangePage extends BasePage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> fetchParsedAddress(BuildContext context, String domain, CryptoCurrency currency) async {
|
Future<String> fetchParsedAddress(
|
||||||
|
BuildContext context, String domain, CryptoCurrency currency) async {
|
||||||
final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
|
final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
|
||||||
final address = await extractAddressFromParsed(context, parsedAddress);
|
final address = await extractAddressFromParsed(context, parsedAddress);
|
||||||
return address;
|
return address;
|
||||||
|
@ -619,6 +624,7 @@ class ExchangePage extends BasePage {
|
||||||
Widget _exchangeCardsSection(BuildContext context) {
|
Widget _exchangeCardsSection(BuildContext context) {
|
||||||
final firstExchangeCard = Observer(
|
final firstExchangeCard = Observer(
|
||||||
builder: (_) => ExchangeCard(
|
builder: (_) => ExchangeCard(
|
||||||
|
cardInstanceName: 'deposit_exchange_card',
|
||||||
onDispose: disposeBestRateSync,
|
onDispose: disposeBestRateSync,
|
||||||
hasAllAmount: exchangeViewModel.hasAllAmount,
|
hasAllAmount: exchangeViewModel.hasAllAmount,
|
||||||
allAmount: exchangeViewModel.hasAllAmount
|
allAmount: exchangeViewModel.hasAllAmount
|
||||||
|
@ -689,6 +695,7 @@ class ExchangePage extends BasePage {
|
||||||
|
|
||||||
final secondExchangeCard = Observer(
|
final secondExchangeCard = Observer(
|
||||||
builder: (_) => ExchangeCard(
|
builder: (_) => ExchangeCard(
|
||||||
|
cardInstanceName: 'receive_exchange_card',
|
||||||
onDispose: disposeBestRateSync,
|
onDispose: disposeBestRateSync,
|
||||||
amountFocusNode: _receiveAmountFocus,
|
amountFocusNode: _receiveAmountFocus,
|
||||||
addressFocusNode: _receiveAddressFocus,
|
addressFocusNode: _receiveAddressFocus,
|
||||||
|
|
|
@ -121,6 +121,7 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
|
padding: EdgeInsets.fromLTRB(24, 100, 24, 32),
|
||||||
child: Observer(
|
child: Observer(
|
||||||
builder: (_) => ExchangeCard(
|
builder: (_) => ExchangeCard(
|
||||||
|
cardInstanceName: 'deposit_exchange_template_card',
|
||||||
amountFocusNode: _depositAmountFocus,
|
amountFocusNode: _depositAmountFocus,
|
||||||
key: depositKey,
|
key: depositKey,
|
||||||
title: S.of(context).you_will_send,
|
title: S.of(context).you_will_send,
|
||||||
|
@ -157,6 +158,7 @@ class ExchangeTemplatePage extends BasePage {
|
||||||
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
padding: EdgeInsets.only(top: 29, left: 24, right: 24),
|
||||||
child: Observer(
|
child: Observer(
|
||||||
builder: (_) => ExchangeCard(
|
builder: (_) => ExchangeCard(
|
||||||
|
cardInstanceName: 'receive_exchange_template_card',
|
||||||
amountFocusNode: _receiveAmountFocus,
|
amountFocusNode: _receiveAmountFocus,
|
||||||
key: receiveKey,
|
key: receiveKey,
|
||||||
title: S.of(context).you_will_get,
|
title: S.of(context).you_will_get,
|
||||||
|
|
|
@ -12,7 +12,8 @@ class CurrencyPicker extends StatefulWidget {
|
||||||
this.title,
|
this.title,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
this.isMoneroWallet = false,
|
this.isMoneroWallet = false,
|
||||||
this.isConvertFrom = false});
|
this.isConvertFrom = false,
|
||||||
|
super.key});
|
||||||
|
|
||||||
final int selectedAtIndex;
|
final int selectedAtIndex;
|
||||||
final List<Currency> items;
|
final List<Currency> items;
|
||||||
|
|
|
@ -44,8 +44,9 @@ class ExchangeCard extends StatefulWidget {
|
||||||
this.allAmount,
|
this.allAmount,
|
||||||
this.onPushPasteButton,
|
this.onPushPasteButton,
|
||||||
this.onPushAddressBookButton,
|
this.onPushAddressBookButton,
|
||||||
this.onDispose})
|
this.onDispose,
|
||||||
: super(key: key);
|
required this.cardInstanceName,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
final List<CryptoCurrency> currencies;
|
final List<CryptoCurrency> currencies;
|
||||||
final Function(CryptoCurrency) onCurrencySelected;
|
final Function(CryptoCurrency) onCurrencySelected;
|
||||||
|
@ -73,6 +74,7 @@ class ExchangeCard extends StatefulWidget {
|
||||||
final void Function(BuildContext context)? onPushPasteButton;
|
final void Function(BuildContext context)? onPushPasteButton;
|
||||||
final void Function(BuildContext context)? onPushAddressBookButton;
|
final void Function(BuildContext context)? onPushAddressBookButton;
|
||||||
final Function()? onDispose;
|
final Function()? onDispose;
|
||||||
|
final String cardInstanceName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExchangeCardState createState() => ExchangeCardState();
|
ExchangeCardState createState() => ExchangeCardState();
|
||||||
|
@ -88,11 +90,13 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
_walletName = '',
|
_walletName = '',
|
||||||
_selectedCurrency = CryptoCurrency.btc,
|
_selectedCurrency = CryptoCurrency.btc,
|
||||||
_isAmountEstimated = false,
|
_isAmountEstimated = false,
|
||||||
_isMoneroWallet = false;
|
_isMoneroWallet = false,
|
||||||
|
_cardInstanceName = '';
|
||||||
|
|
||||||
final addressController = TextEditingController();
|
final addressController = TextEditingController();
|
||||||
final amountController = TextEditingController();
|
final amountController = TextEditingController();
|
||||||
|
|
||||||
|
String _cardInstanceName;
|
||||||
String _title;
|
String _title;
|
||||||
String? _min;
|
String? _min;
|
||||||
String? _max;
|
String? _max;
|
||||||
|
@ -105,6 +109,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_cardInstanceName = widget.cardInstanceName;
|
||||||
_title = widget.title;
|
_title = widget.title;
|
||||||
_isAmountEditable = widget.initialIsAmountEditable;
|
_isAmountEditable = widget.initialIsAmountEditable;
|
||||||
_isAddressEditable = widget.initialIsAddressEditable;
|
_isAddressEditable = widget.initialIsAddressEditable;
|
||||||
|
@ -183,6 +188,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
|
key: ValueKey('${_cardInstanceName}_title_key'),
|
||||||
_title,
|
_title,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
|
@ -200,6 +206,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
height: 32,
|
height: 32,
|
||||||
color: widget.currencyButtonColor,
|
color: widget.currencyButtonColor,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
key: ValueKey('${_cardInstanceName}_currency_picker_button_key'),
|
||||||
onTap: () => _presentPicker(context),
|
onTap: () => _presentPicker(context),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
@ -209,9 +216,12 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
padding: EdgeInsets.only(right: 5),
|
padding: EdgeInsets.only(right: 5),
|
||||||
child: widget.imageArrow,
|
child: widget.imageArrow,
|
||||||
),
|
),
|
||||||
Text(_selectedCurrency.toString(),
|
Text(
|
||||||
|
key: ValueKey('${_cardInstanceName}_selected_currency_text_key'),
|
||||||
|
_selectedCurrency.toString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white))
|
fontWeight: FontWeight.w600, fontSize: 16, color: Colors.white),
|
||||||
|
)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -227,13 +237,16 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(6.0),
|
padding: const EdgeInsets.all(6.0),
|
||||||
child: Text(_selectedCurrency.tag!,
|
child: Text(
|
||||||
|
key: ValueKey('${_cardInstanceName}_selected_currency_tag_text_key'),
|
||||||
|
_selectedCurrency.tag!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<SendPageTheme>()!
|
.extension<SendPageTheme>()!
|
||||||
.textFieldButtonIconColor)),
|
.textFieldButtonIconColor),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -252,6 +265,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: FocusTraversalOrder(
|
child: FocusTraversalOrder(
|
||||||
order: NumericFocusOrder(1),
|
order: NumericFocusOrder(1),
|
||||||
child: BaseTextFormField(
|
child: BaseTextFormField(
|
||||||
|
key: ValueKey('${_cardInstanceName}_amount_textfield_key'),
|
||||||
focusNode: widget.amountFocusNode,
|
focusNode: widget.amountFocusNode,
|
||||||
controller: amountController,
|
controller: amountController,
|
||||||
enabled: _isAmountEditable,
|
enabled: _isAmountEditable,
|
||||||
|
@ -272,9 +286,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<ExchangePageTheme>()!
|
.extension<ExchangePageTheme>()!
|
||||||
.hintTextColor),
|
.hintTextColor),
|
||||||
validator: _isAmountEditable
|
validator: _isAmountEditable ? widget.currencyValueValidator : null),
|
||||||
? widget.currencyValueValidator
|
|
||||||
: null),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.hasAllAmount)
|
if (widget.hasAllAmount)
|
||||||
|
@ -287,6 +299,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
.textFieldButtonColor,
|
.textFieldButtonColor,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6))),
|
borderRadius: BorderRadius.all(Radius.circular(6))),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
key: ValueKey('${_cardInstanceName}_send_all_button_key'),
|
||||||
onTap: () => widget.allAmount?.call(),
|
onTap: () => widget.allAmount?.call(),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(S.of(context).all,
|
child: Text(S.of(context).all,
|
||||||
|
@ -313,6 +326,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
|
child: Row(mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[
|
||||||
_min != null
|
_min != null
|
||||||
? Text(
|
? Text(
|
||||||
|
key: ValueKey('${_cardInstanceName}_min_limit_text_key'),
|
||||||
S.of(context).min_value(_min ?? '', _selectedCurrency.toString()),
|
S.of(context).min_value(_min ?? '', _selectedCurrency.toString()),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
|
@ -322,11 +336,15 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
: Offstage(),
|
: Offstage(),
|
||||||
_min != null ? SizedBox(width: 10) : Offstage(),
|
_min != null ? SizedBox(width: 10) : Offstage(),
|
||||||
_max != null
|
_max != null
|
||||||
? Text(S.of(context).max_value(_max ?? '', _selectedCurrency.toString()),
|
? Text(
|
||||||
|
key: ValueKey('${_cardInstanceName}_max_limit_text_key'),
|
||||||
|
S.of(context).max_value(_max ?? '', _selectedCurrency.toString()),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
height: 1.2,
|
height: 1.2,
|
||||||
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor))
|
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor,
|
||||||
|
),
|
||||||
|
)
|
||||||
: Offstage(),
|
: Offstage(),
|
||||||
])),
|
])),
|
||||||
),
|
),
|
||||||
|
@ -347,6 +365,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: 20),
|
padding: EdgeInsets.only(top: 20),
|
||||||
child: AddressTextField(
|
child: AddressTextField(
|
||||||
|
key: ValueKey('${_cardInstanceName}_editable_address_textfield_key'),
|
||||||
focusNode: widget.addressFocusNode,
|
focusNode: widget.addressFocusNode,
|
||||||
controller: addressController,
|
controller: addressController,
|
||||||
onURIScanned: (uri) {
|
onURIScanned: (uri) {
|
||||||
|
@ -387,6 +406,8 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
FocusTraversalOrder(
|
FocusTraversalOrder(
|
||||||
order: NumericFocusOrder(3),
|
order: NumericFocusOrder(3),
|
||||||
child: BaseTextFormField(
|
child: BaseTextFormField(
|
||||||
|
key: ValueKey(
|
||||||
|
'${_cardInstanceName}_non_editable_address_textfield_key'),
|
||||||
controller: addressController,
|
controller: addressController,
|
||||||
borderColor: Colors.transparent,
|
borderColor: Colors.transparent,
|
||||||
suffixIcon: SizedBox(width: _isMoneroWallet ? 80 : 36),
|
suffixIcon: SizedBox(width: _isMoneroWallet ? 80 : 36),
|
||||||
|
@ -410,6 +431,8 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: Semantics(
|
child: Semantics(
|
||||||
label: S.of(context).address_book,
|
label: S.of(context).address_book,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
key: ValueKey(
|
||||||
|
'${_cardInstanceName}_address_book_button_key'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final contact =
|
final contact =
|
||||||
await Navigator.of(context).pushNamed(
|
await Navigator.of(context).pushNamed(
|
||||||
|
@ -447,6 +470,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
child: Semantics(
|
child: Semantics(
|
||||||
label: S.of(context).copy_address,
|
label: S.of(context).copy_address,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
|
key: ValueKey('${_cardInstanceName}_copy_refund_address_button_key'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Clipboard.setData(
|
Clipboard.setData(
|
||||||
ClipboardData(text: addressController.text));
|
ClipboardData(text: addressController.text));
|
||||||
|
@ -470,6 +494,7 @@ class ExchangeCardState extends State<ExchangeCard> {
|
||||||
showPopUp<void>(
|
showPopUp<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => CurrencyPicker(
|
builder: (_) => CurrencyPicker(
|
||||||
|
key: ValueKey('${_cardInstanceName}_currency_picker_dialog_button_key'),
|
||||||
selectedAtIndex: widget.currencies.indexOf(_selectedCurrency),
|
selectedAtIndex: widget.currencies.indexOf(_selectedCurrency),
|
||||||
items: widget.currencies,
|
items: widget.currencies,
|
||||||
hintText: S.of(context).search_currency,
|
hintText: S.of(context).search_currency,
|
||||||
|
|
|
@ -32,7 +32,7 @@ class AddressTextField extends StatelessWidget {
|
||||||
this.onPushPasteButton,
|
this.onPushPasteButton,
|
||||||
this.onPushAddressBookButton,
|
this.onPushAddressBookButton,
|
||||||
this.onSelectedContact,
|
this.onSelectedContact,
|
||||||
this.selectedCurrency});
|
this.selectedCurrency, super.key});
|
||||||
|
|
||||||
static const prefixIconWidth = 34.0;
|
static const prefixIconWidth = 34.0;
|
||||||
static const prefixIconHeight = 34.0;
|
static const prefixIconHeight = 34.0;
|
||||||
|
|
|
@ -3,7 +3,12 @@ import 'package:cake_wallet/palette.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AlertCloseButton extends StatelessWidget {
|
class AlertCloseButton extends StatelessWidget {
|
||||||
AlertCloseButton({this.image, this.bottom, this.onTap});
|
AlertCloseButton({
|
||||||
|
this.image,
|
||||||
|
this.bottom,
|
||||||
|
this.onTap,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||||
import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart';
|
import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart';
|
||||||
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
|
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
|
||||||
|
|
||||||
|
//TODO(David): PickerWidget is intertwined and confusing as is, find a way to optimize?
|
||||||
class Picker<Item> extends StatefulWidget {
|
class Picker<Item> extends StatefulWidget {
|
||||||
Picker({
|
Picker({
|
||||||
required this.selectedAtIndex,
|
required this.selectedAtIndex,
|
||||||
|
@ -153,6 +154,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||||
child: Text(
|
child: Text(
|
||||||
|
key: ValueKey('picker_title_text_key'),
|
||||||
widget.title!,
|
widget.title!,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -189,7 +191,10 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: SearchBarWidget(
|
child: SearchBarWidget(
|
||||||
searchController: searchController, hintText: widget.hintText),
|
key: ValueKey('picker_search_bar_key'),
|
||||||
|
searchController: searchController,
|
||||||
|
hintText: widget.hintText,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Divider(
|
Divider(
|
||||||
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
|
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
|
||||||
|
@ -203,6 +208,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
filteredItems.length > 3
|
filteredItems.length > 3
|
||||||
? Scrollbar(
|
? Scrollbar(
|
||||||
|
key: ValueKey('picker_scrollbar_key'),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
child: itemsList(),
|
child: itemsList(),
|
||||||
)
|
)
|
||||||
|
@ -213,6 +219,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
left: padding,
|
left: padding,
|
||||||
right: padding,
|
right: padding,
|
||||||
child: Text(
|
child: Text(
|
||||||
|
key: ValueKey('picker_descriptinon_text_key'),
|
||||||
widget.description!,
|
widget.description!,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -242,6 +249,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
|
|
||||||
if (widget.isWrapped) {
|
if (widget.isWrapped) {
|
||||||
return PickerWrapperWidget(
|
return PickerWrapperWidget(
|
||||||
|
key: ValueKey('picker_wrapper_widget_key'),
|
||||||
hasTitle: widget.title?.isNotEmpty ?? false,
|
hasTitle: widget.title?.isNotEmpty ?? false,
|
||||||
children: [content],
|
children: [content],
|
||||||
);
|
);
|
||||||
|
@ -260,6 +268,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
|
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
|
||||||
child: widget.isGridView
|
child: widget.isGridView
|
||||||
? GridView.builder(
|
? GridView.builder(
|
||||||
|
key: ValueKey('picker_items_grid_view_key'),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
@ -275,6 +284,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
: buildItem(index),
|
: buildItem(index),
|
||||||
)
|
)
|
||||||
: ListView.separated(
|
: ListView.separated(
|
||||||
|
key: ValueKey('picker_items_list_view_key'),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
controller: controller,
|
controller: controller,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
@ -297,6 +307,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
final item = widget.headerEnabled ? filteredItems[index] : items[index];
|
final item = widget.headerEnabled ? filteredItems[index] : items[index];
|
||||||
|
|
||||||
final tag = item is Currency ? item.tag : null;
|
final tag = item is Currency ? item.tag : null;
|
||||||
|
final currencyName = item is Currency ? item.name : '';
|
||||||
final icon = _getItemIcon(item);
|
final icon = _getItemIcon(item);
|
||||||
|
|
||||||
final image = images.isNotEmpty ? filteredImages[index] : icon;
|
final image = images.isNotEmpty ? filteredImages[index] : icon;
|
||||||
|
@ -316,6 +327,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
key: ValueKey('picker_items_index_${currencyName}_text_key'),
|
||||||
widget.displayItem?.call(item) ?? item.toString(),
|
widget.displayItem?.call(item) ?? item.toString(),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -335,6 +347,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
height: 18.0,
|
height: 18.0,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
key: ValueKey('picker_items_index_${index}_tag_key'),
|
||||||
tag,
|
tag,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 7.0,
|
fontSize: 7.0,
|
||||||
|
@ -358,6 +371,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
);
|
);
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
key: ValueKey('picker_items_index_${currencyName}_button_key'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
||||||
onItemSelected(item!);
|
onItemSelected(item!);
|
||||||
|
@ -383,6 +397,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
final item = items[index];
|
final item = items[index];
|
||||||
|
|
||||||
final tag = item is Currency ? item.tag : null;
|
final tag = item is Currency ? item.tag : null;
|
||||||
|
final currencyName = item is Currency ? item.name : '';
|
||||||
final icon = _getItemIcon(item);
|
final icon = _getItemIcon(item);
|
||||||
|
|
||||||
final image = images.isNotEmpty ? images[index] : icon;
|
final image = images.isNotEmpty ? images[index] : icon;
|
||||||
|
@ -390,6 +405,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex;
|
final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex;
|
||||||
|
|
||||||
final itemContent = Row(
|
final itemContent = Row(
|
||||||
|
key: ValueKey('picker_selected_item_row_key'),
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
mainAxisAlignment: widget.mainAxisAlignment,
|
mainAxisAlignment: widget.mainAxisAlignment,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
@ -402,6 +418,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: Text(
|
||||||
|
key: ValueKey('picker_items_index_${currencyName}_selected_item_text_key'),
|
||||||
widget.displayItem?.call(item) ?? item.toString(),
|
widget.displayItem?.call(item) ?? item.toString(),
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
@ -445,6 +462,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
||||||
);
|
);
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
key: ValueKey('picker_items_index_${currencyName}_selected_item_button_key'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
if (widget.closeOnItemSelected) Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,12 @@ import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||||
|
|
||||||
class PickerWrapperWidget extends StatelessWidget {
|
class PickerWrapperWidget extends StatelessWidget {
|
||||||
PickerWrapperWidget({required this.children, this.hasTitle = false, this.onClose});
|
PickerWrapperWidget({
|
||||||
|
required this.children,
|
||||||
|
this.hasTitle = false,
|
||||||
|
this.onClose,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
final bool hasTitle;
|
final bool hasTitle;
|
||||||
|
@ -29,8 +34,8 @@ class PickerWrapperWidget extends StatelessWidget {
|
||||||
final containerBottom = screenCenter - containerCenter;
|
final containerBottom = screenCenter - containerCenter;
|
||||||
|
|
||||||
// position the close button right below the search container
|
// position the close button right below the search container
|
||||||
closeButtonBottom = closeButtonBottom -
|
closeButtonBottom =
|
||||||
containerBottom + (!hasTitle ? padding : padding / 1.5);
|
closeButtonBottom - containerBottom + (!hasTitle ? padding : padding / 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
return AlertBackground(
|
return AlertBackground(
|
||||||
|
@ -46,7 +51,11 @@ class PickerWrapperWidget extends StatelessWidget {
|
||||||
children: children,
|
children: children,
|
||||||
),
|
),
|
||||||
SizedBox(height: ResponsiveLayoutUtilBase.kPopupSpaceHeight),
|
SizedBox(height: ResponsiveLayoutUtilBase.kPopupSpaceHeight),
|
||||||
AlertCloseButton(bottom: closeButtonBottom, onTap: onClose),
|
AlertCloseButton(
|
||||||
|
key: ValueKey('picker_wrapper_close_button_key'),
|
||||||
|
bottom: closeButtonBottom,
|
||||||
|
onTap: onClose,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,6 +7,7 @@ class SearchBarWidget extends StatelessWidget {
|
||||||
required this.searchController,
|
required this.searchController,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
this.borderRadius = 14,
|
this.borderRadius = 14,
|
||||||
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
final TextEditingController searchController;
|
final TextEditingController searchController;
|
||||||
|
|
Loading…
Reference in a new issue