mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Cw 1379 add monero support to trezor rebase dev (#3273)
* refactor: migrate hardware wallet resources to `new-ui`, add Trezor model support, and streamline hardware wallet handling across services * refactor: migrate hardware wallet resources to `new-ui`, add Trezor model support, and streamline hardware wallet handling across services * fix: correctly check for Ledger hardware wallet type in `isHardwareWallet` logic * refactor: unify `isConnected` method for hardware wallets, add Trezor-specific support, and update Monero sync logic * refactor: add Trezor transaction signing support, streamline hardware wallet handling, and update Monero dependency * refactor: improve Trezor transaction handling, adjust hardware wallet state logic, and update Monero dependency references * fix: non-hww tx commit() in xmr fix: prod monero_c fix: keyImage import workaround for Trezor/Cupcake chore: add kotlin's .salive to .gitignore * fix: universal_ble builds on iOS chore: remove prints fix: proper CI prebuilt for linux * new trezor connection ui * fix page title * typo * fix page title anim * refactor: enhance Trezor pairing flow, update state management, and simplify UI logic in hardware wallet integration * fix: correct widget indentation in Trezor pairing failure state UI * fix: extract Trezor pairing failure state UI to `_errorBox` widget and update Trezor dependency reference * refactor: simplify hardware wallet pairing error UI, optimize `_errorBox` layout, and streamline widget logic * Update cw_monero/lib/pending_monero_transaction.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Update lib/buy/robinhood/robinhood_buy_provider.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * feat: add USB intent filters, device filter for hardware wallets, and update Trezor dependency reference * Update cw_monero/pubspec.yaml [skip ci] * Update cw_wownero/pubspec.yaml [skip ci] * Update cw_zano/pubspec.yaml [skip ci] * fix: use CryptoCurrency.title instead of amount-refactor-only .symbol getter new_wallet_type_page used curr.symbol, which only exists on the amount-refactor branch (String get symbol => title). On dev the equivalent is curr.title. Adapts the Trezor feature to dev's API without pulling in amount-refactor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix wallet list screen not scrollable minor fixes --------- Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com> Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net> Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com> Co-authored-by: Konstantin Ullrich <konstantin@cakewallet.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Konstantin Ullrich
Czarek Nakamoto
Robert Malikowski
Konstantin Ullrich
Claude Opus 4.8
parent
6c1ee16513
commit
5b2a8f6755
@@ -3,10 +3,13 @@ import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/entities/hardware_wallet/hardware_wallet_device.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/connect_device/widgets/device_tile.dart';
|
||||
import 'package:cake_wallet/src/widgets/bottom_sheet/info_steps_bottom_sheet_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/core/material_base_theme.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
@@ -91,6 +94,8 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||
var bleDevices = <HardwareWalletDevice>[];
|
||||
var usbDevices = <HardwareWalletDevice>[];
|
||||
|
||||
List<HardwareWalletDevice> get allDevices => [...bleDevices, ...usbDevices];
|
||||
|
||||
late Timer? _usbRefreshTimer = null;
|
||||
late Timer? _bleRefreshTimer = null;
|
||||
late Timer? _bleStateTimer = null;
|
||||
@@ -158,24 +163,38 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||
|
||||
Future<void> _connectToDevice(HardwareWalletDevice device) async {
|
||||
final isConnected = await widget.hardwareWalletVM.connectDevice(device, widget.walletType);
|
||||
if (isConnected) widget.onConnectDevice(context, widget.hardwareWalletVM);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (isConnected) widget.onConnectDevice(navigatorKey.currentContext!, widget.hardwareWalletVM);
|
||||
});
|
||||
}
|
||||
|
||||
String _getDeviceTileLeading(HardwareWalletDeviceType deviceType) {
|
||||
switch (deviceType) {
|
||||
case HardwareWalletDeviceType.ledgerNanoX:
|
||||
return 'assets/images/hardware_wallet/ledger_nano_x.png';
|
||||
return 'assets/new-ui/hardware_wallets/ledger_nano_x.svg';
|
||||
case HardwareWalletDeviceType.ledgerNanoGen5:
|
||||
return 'assets/images/hardware_wallet/device_ledger_nano_gen_5.svg';
|
||||
return 'assets/new-ui/hardware_wallets/device_ledger_nano_gen_5.svg';
|
||||
case HardwareWalletDeviceType.ledgerStax:
|
||||
return 'assets/images/hardware_wallet/ledger_stax.png';
|
||||
return 'assets/new-ui/hardware_wallets/ledger_stax.svg';
|
||||
case HardwareWalletDeviceType.ledgerFlex:
|
||||
return 'assets/images/hardware_wallet/ledger_flex.png';
|
||||
return 'assets/new-ui/hardware_wallets/ledger_flex.svg';
|
||||
case HardwareWalletDeviceType.BitBox02:
|
||||
return 'assets/images/hardware_wallet/device_bitbox.svg';
|
||||
case HardwareWalletDeviceType.BitBox02Nova:
|
||||
return 'assets/new-ui/hardware_wallets/device_bitbox.svg';
|
||||
case HardwareWalletDeviceType.trezorModelOne:
|
||||
return 'assets/new-ui/hardware_wallets/device_trezor_model_one.svg';
|
||||
case HardwareWalletDeviceType.trezorModelT:
|
||||
return 'assets/new-ui/hardware_wallets/device_trezor_model_t.svg';
|
||||
case HardwareWalletDeviceType.trezorSafe3:
|
||||
return 'assets/new-ui/hardware_wallets/device_trezor_safe_3.svg';
|
||||
case HardwareWalletDeviceType.trezorSafe5:
|
||||
return 'assets/new-ui/hardware_wallets/device_trezor_safe_5.svg';
|
||||
case HardwareWalletDeviceType.trezorSafe7:
|
||||
return 'assets/new-ui/hardware_wallets/device_trezor_safe_7.svg';
|
||||
|
||||
default:
|
||||
return 'assets/images/hardware_wallet/ledger_nano_x.png';
|
||||
return 'assets/new-ui/hardware_wallets/ledger_nano_x.svg';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,25 +216,15 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
|
||||
child: Text(
|
||||
description,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/hardware_wallet.svg",
|
||||
),
|
||||
Offstage(
|
||||
offstage: !longWait,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
|
||||
child: Text(
|
||||
S.of(context).if_you_dont_see_your_device,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
description,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => Offstage(
|
||||
@@ -231,56 +240,69 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (bleDevices.length > 0) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
S.of(context).bluetooth,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
...bleDevices
|
||||
.map(
|
||||
(device) => Padding(
|
||||
padding: EdgeInsets.only(bottom: 20),
|
||||
child: DeviceTile(
|
||||
onPressed: () => _connectToDevice(device),
|
||||
title: device.name,
|
||||
leading: _getDeviceTileLeading(device.type),
|
||||
connectionType: device.connectionType,
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(18)),
|
||||
child: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
final item = allDevices[index];
|
||||
return GestureDetector(
|
||||
onTap: () => _connectToDevice(item),
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
CakeImageWidget(
|
||||
imageUrl: _getDeviceTileLeading(item.type),
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
BlendMode.srcIn),
|
||||
),
|
||||
Text(item.name)
|
||||
],
|
||||
),
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
if (item.connectionType ==
|
||||
HardwareWalletConnectionType.ble)
|
||||
CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/bluetooth.svg",
|
||||
width: 24,
|
||||
height: 24,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.primary,
|
||||
BlendMode.srcIn),
|
||||
),
|
||||
CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/arrow_forward.svg",
|
||||
height: 16,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
BlendMode.srcIn))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList()
|
||||
],
|
||||
if (usbDevices.length > 0) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
S.of(context).usb,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
...usbDevices
|
||||
.map(
|
||||
(device) => Padding(
|
||||
padding: EdgeInsets.only(bottom: 20),
|
||||
child: DeviceTile(
|
||||
onPressed: () => _connectToDevice(device),
|
||||
title: device.name,
|
||||
leading: _getDeviceTileLeading(device.type),
|
||||
connectionType: device.connectionType,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
],
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => Container(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh),
|
||||
itemCount: allDevices.length),
|
||||
),
|
||||
if (widget.allowChangeWallet) ...[
|
||||
PrimaryButton(
|
||||
text: S.of(context).wallets,
|
||||
@@ -293,10 +315,10 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
||||
),
|
||||
),
|
||||
),
|
||||
PrimaryButton(
|
||||
NewPrimaryButton(
|
||||
text: S.of(context).how_to_connect,
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
textColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
textColor: Theme.of(context).colorScheme.primary,
|
||||
onPressed: () => _onHowToConnect(context),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:cake_wallet/entities/hardware_wallet/hardware_wallet_device.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
@@ -43,14 +44,12 @@ class DeviceTile extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (leading != null && !leading!.endsWith(".svg"))
|
||||
Image.asset(
|
||||
leading!,
|
||||
height: 30,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
if (leading != null && leading!.endsWith(".svg"))
|
||||
SvgPicture.asset(leading!, height: 30),
|
||||
CakeImageWidget(
|
||||
height: 30,
|
||||
imageUrl: leading,
|
||||
colorFilter:
|
||||
ColorFilter.mode(Theme.of(context).colorScheme.onSurface, BlendMode.srcIn),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 16),
|
||||
|
||||
@@ -34,11 +34,11 @@ class CryptoBalanceWidget extends StatelessWidget {
|
||||
case null:
|
||||
return null;
|
||||
case HardwareWalletType.bitbox:
|
||||
return "assets/images/hardware_wallet/device_bitbox.svg";
|
||||
return "assets/new-ui/hardware_wallets/device_bitbox.svg";
|
||||
case HardwareWalletType.ledger:
|
||||
return "assets/images/hardware_wallet/device_ledger_nano_x.svg";
|
||||
return "assets/new-ui/hardware_wallets/device_ledger_nano_x.svg";
|
||||
case HardwareWalletType.trezor:
|
||||
return "assets/images/hardware_wallet/device_trezor_safe_5.svg";
|
||||
return "assets/new-ui/hardware_wallets/device_trezor_safe_5.svg";
|
||||
case HardwareWalletType.cupcake:
|
||||
return "assets/images/cupcake.svg";
|
||||
case HardwareWalletType.coldcard:
|
||||
|
||||
@@ -213,7 +213,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
|
||||
final sendVM = widget.exchangeTradeViewModel.sendViewModel;
|
||||
|
||||
if (sendVM.wallet.isHardwareWallet) {
|
||||
if (!sendVM.hardwareWalletViewModel!.isConnected) {
|
||||
if (!sendVM.hardwareWalletViewModel!.isConnected(sendVM.walletType)) {
|
||||
await Navigator.of(context).pushNamed(Routes.connectDevices,
|
||||
arguments: ConnectDevicePageParams(
|
||||
walletType: sendVM.walletType,
|
||||
|
||||
@@ -160,7 +160,7 @@ class DEuroSavingsPage extends BasePage {
|
||||
|
||||
Future<void> _requireHardwareWallet(BuildContext context) async {
|
||||
if (_dEuroViewModel.wallet.isHardwareWallet) {
|
||||
if (!_dEuroViewModel.hardwareWalletViewModel!.isConnected) {
|
||||
if (!_dEuroViewModel.hardwareWalletViewModel!.isConnected(_dEuroViewModel.wallet.type)) {
|
||||
await Navigator.of(context).pushNamed(Routes.connectDevices,
|
||||
arguments: ConnectDevicePageParams(
|
||||
walletType: _dEuroViewModel.wallet.type,
|
||||
|
||||
@@ -6,14 +6,8 @@ import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_utils.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
|
||||
import 'package:cake_wallet/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/search_bar_widget.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/wallet_types.g.dart';
|
||||
import 'package:cw_core/currency_for_wallet_type.dart';
|
||||
import 'package:cw_core/hardware/device_connection_type.dart';
|
||||
@@ -21,10 +15,38 @@ import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NewWalletTypePageHeader extends StatelessWidget {
|
||||
const NewWalletTypePageHeader({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => const SizedBox(
|
||||
width: 138,
|
||||
height: 75,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
child: CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/hardware_wallet.svg",
|
||||
width: 75,
|
||||
height: 75,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 63,
|
||||
child: CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/cake_coin.svg",
|
||||
width: 75,
|
||||
height: 75,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class NewWalletTypePage extends BasePage {
|
||||
NewWalletTypePage({
|
||||
required this.newWalletTypeArguments,
|
||||
});
|
||||
NewWalletTypePage({required this.newWalletTypeArguments});
|
||||
|
||||
final NewWalletTypeArguments newWalletTypeArguments;
|
||||
|
||||
@@ -38,23 +60,21 @@ class NewWalletTypePage extends BasePage {
|
||||
|
||||
@override
|
||||
Function(BuildContext)? get pushToNextWidget => (context) {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.focusedChild?.unfocus();
|
||||
}
|
||||
};
|
||||
final currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) currentFocus.focusedChild?.unfocus();
|
||||
};
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => WalletTypeForm(
|
||||
walletImage: currentTheme.isDark ? walletTypeImage : walletTypeLightImage,
|
||||
isCreate: newWalletTypeArguments.isCreate,
|
||||
onTypeSelected: newWalletTypeArguments.onTypeSelected,
|
||||
hardwareWalletType: newWalletTypeArguments.hardwareWalletType,
|
||||
);
|
||||
walletImage: currentTheme.isDark ? walletTypeImage : walletTypeLightImage,
|
||||
isCreate: newWalletTypeArguments.isCreate,
|
||||
onTypeSelected: newWalletTypeArguments.onTypeSelected,
|
||||
hardwareWalletType: newWalletTypeArguments.hardwareWalletType,
|
||||
);
|
||||
}
|
||||
|
||||
class WalletTypeForm extends StatefulWidget {
|
||||
WalletTypeForm({
|
||||
const WalletTypeForm({
|
||||
required this.walletImage,
|
||||
required this.isCreate,
|
||||
this.onTypeSelected,
|
||||
@@ -77,9 +97,6 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
||||
|
||||
static const aspectRatioImage = 1.22;
|
||||
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
|
||||
WalletType? selected;
|
||||
List<WalletType> types;
|
||||
List<WalletType> filteredTypes = [];
|
||||
|
||||
@@ -87,21 +104,12 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
||||
void initState() {
|
||||
types = filteredTypes = availableWalletTypes
|
||||
.where((element) =>
|
||||
!widget.isHardwareWallet ||
|
||||
DeviceConnectionType.supportedConnectionTypes(
|
||||
element, widget.hardwareWalletType!, Platform.isIOS)
|
||||
.isNotEmpty)
|
||||
!widget.isHardwareWallet ||
|
||||
DeviceConnectionType.supportedConnectionTypes(
|
||||
element, widget.hardwareWalletType!, Platform.isIOS)
|
||||
.isNotEmpty)
|
||||
.toList();
|
||||
super.initState();
|
||||
|
||||
searchController.addListener(() {
|
||||
setState(() {
|
||||
filteredTypes = List.from(types.where((type) => walletTypeToDisplayName(type)
|
||||
.toLowerCase()
|
||||
.contains(searchController.text.toLowerCase())));
|
||||
return;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -110,96 +118,102 @@ class WalletTypeFormState extends State<WalletTypeForm> {
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: ResponsiveLayoutUtilBase.kDesktopMaxWidthConstraint),
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 48),
|
||||
child: Text(
|
||||
S.of(context).choose_wallet_currency,
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const NewWalletTypePageHeader(),
|
||||
Text(
|
||||
S.of(context).choose_wallet_currency,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 12),
|
||||
child: SearchBarWidget(searchController: searchController),
|
||||
),
|
||||
Expanded(
|
||||
child: ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
scrollableKey: ValueKey('new_wallet_type_scrollable_key'),
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
...filteredTypes.map(
|
||||
(type) => Padding(
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
child: SelectButton(
|
||||
key: ValueKey('new_wallet_type_${type.name}_button_key'),
|
||||
image: CakeImageWidget(
|
||||
imageUrl: getCryptoCurrencyIconForWalletListItem(type),
|
||||
height: 24,
|
||||
width: 24,
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
),
|
||||
child: ListView.separated(
|
||||
key: const ValueKey('new_wallet_type_scrollable_key'),
|
||||
itemCount: filteredTypes.length,
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
final item = filteredTypes[index];
|
||||
final curr = getCryptoCurrencyForWalletListItem(item);
|
||||
|
||||
return GestureDetector(
|
||||
key: ValueKey('new_wallet_type_${item.name}_button_key'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
onTypeSelected(item);
|
||||
},
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CakeImageWidget(
|
||||
height: 24,
|
||||
width: 24,
|
||||
imageUrl: curr.iconPath,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(curr.fullName ?? curr.name),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
curr.title,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/arrow_forward.svg",
|
||||
height: 16,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
text: walletTypeToDisplayName(type),
|
||||
showTrailingIcon: false,
|
||||
height: 54,
|
||||
isSelected: selected == type,
|
||||
onTap: () => setState(() => selected = type),
|
||||
deviceConnectionTypes: widget.isHardwareWallet
|
||||
? DeviceConnectionType.supportedConnectionTypes(
|
||||
type, widget.hardwareWalletType!, Platform.isIOS)
|
||||
: [],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => Container(
|
||||
height: 1,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
|
||||
bottomSection: PrimaryButton(
|
||||
key: ValueKey('new_wallet_type_next_button_key'),
|
||||
onPressed: () => onTypeSelected(),
|
||||
text: S.of(context).seed_language_next,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
isDisabled: selected == null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onTypeSelected() async {
|
||||
if (selected == null) throw Exception('Wallet Type is not selected yet.');
|
||||
|
||||
if (selected == WalletType.haven && widget.isCreate) {
|
||||
return await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => PopUpCancellableAlertDialog(
|
||||
contentText: S.of(context).pause_wallet_creation,
|
||||
actionButtonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onTypeSelected(WalletType selected) async {
|
||||
// If it's a restore flow, trigger the external callback
|
||||
// If it's not a BIP39 Wallet or if there are no other wallets, route to the newWallet page
|
||||
// Any other scenario, route to pre-existing seed page
|
||||
final walletList = await WalletInfo.getAll();
|
||||
if (!widget.isCreate) {
|
||||
widget.onTypeSelected!(context, selected!);
|
||||
} else if (!isBIP39Wallet(selected!) || walletList.isEmpty) {
|
||||
widget.onTypeSelected!(context, selected);
|
||||
} else if (!isBIP39Wallet(selected) || walletList.isEmpty) {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.newWallet,
|
||||
arguments: NewWalletArguments(type: selected!),
|
||||
arguments: NewWalletArguments(type: selected),
|
||||
);
|
||||
} else {
|
||||
Navigator.of(context).pushNamed(Routes.walletGroupDescription, arguments: selected!);
|
||||
Navigator.of(context).pushNamed(Routes.walletGroupDescription, arguments: selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +426,7 @@ class SendPage extends BasePage {
|
||||
}
|
||||
|
||||
if (sendViewModel.wallet.isHardwareWallet) {
|
||||
if (!sendViewModel.hardwareWalletViewModel!.isConnected) {
|
||||
if (!sendViewModel.hardwareWalletViewModel!.isConnected(sendViewModel.walletType)) {
|
||||
await Navigator.of(context).pushNamed(Routes.connectDevices,
|
||||
arguments: ConnectDevicePageParams(
|
||||
walletType: sendViewModel.walletType,
|
||||
|
||||
Reference in New Issue
Block a user