Reformat the whole codebase with 100 line width (#3403)

This commit is contained in:
Omar Hatem
2026-07-15 01:20:33 +03:00
committed by GitHub
parent 1241b28bec
commit 16ddc0837a
801 changed files with 17517 additions and 17091 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ abstract class InfoPage extends BasePage {
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
Widget? leading(BuildContext context) => null;
+6 -2
View File
@@ -97,7 +97,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
@override
void changeProcessText(String text) {
dismissFlushBar(_authBar);
_progressBar = createBar<void>(text,context, duration: null)..show(_key.currentContext!);
_progressBar = createBar<void>(text, context, duration: null)..show(_key.currentContext!);
}
@override
@@ -137,7 +137,11 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
key: _key,
appBar: CupertinoNavigationBar(
leading: widget.closable
? ModernButton(size: 36, icon: Icon(Icons.close), onPressed: Navigator.of(context).pop, iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
? ModernButton(
size: 36,
icon: Icon(Icons.close),
onPressed: Navigator.of(context).pop,
iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
: Container(),
backgroundColor: Theme.of(context).colorScheme.surface,
border: null),
+5 -6
View File
@@ -108,7 +108,7 @@ class BackupPage extends BasePage {
}
void onExportBackup(BuildContext context) {
if(backupViewModelBase.backupPassword.isEmpty) return;
if (backupViewModelBase.backupPassword.isEmpty) return;
showPopUp<void>(
context: context,
builder: (dialogContext) {
@@ -175,11 +175,10 @@ class BackupPage extends BasePage {
}
Future<void> _saveFile(BackupExportFile backup) async {
String? outputFile = await FilePicker.platform
.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: backup.name,
lockParentWindow: true);
String? outputFile = await FilePicker.platform.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: backup.name,
lockParentWindow: true);
if (outputFile == null) return;
@@ -23,9 +23,8 @@ class _EditBackupPasswordPageState extends State<EditBackupPasswordPage> {
void initState() {
super.initState();
textEditingController.text = widget.editBackupPasswordViewModel.backupPassword;
textEditingController
.addListener(() {
if(textEditingController.text != widget.editBackupPasswordViewModel.backupPassword) {
textEditingController.addListener(() {
if (textEditingController.text != widget.editBackupPasswordViewModel.backupPassword) {
widget.editBackupPasswordViewModel.backupPassword = textEditingController.text;
}
});
+6 -11
View File
@@ -276,8 +276,7 @@ class BuySellPage extends BasePage {
(_) => _onWalletNameChange(
buySellViewModel, buySellViewModel.cryptoCurrency, cryptoCurrencyKey));
reaction(
(_) => buySellViewModel.cryptoCurrency,
reaction((_) => buySellViewModel.cryptoCurrency,
(currency) => _onCurrencyChange(currency, buySellViewModel, cryptoCurrencyKey));
reaction((_) => buySellViewModel.fiatCurrency,
@@ -360,8 +359,7 @@ class BuySellPage extends BasePage {
key.currentState!.changeWalletName(isCurrentTypeWallet ? buySellViewModel.wallet.name : '');
key.currentState!.changeAddress(
address:
isCurrentTypeWallet ? buySellViewModel.wallet.walletAddresses.addressForBuy : '');
address: isCurrentTypeWallet ? buySellViewModel.wallet.walletAddresses.addressForBuy : '');
key.currentState!.changeAmount(amount: '');
}
@@ -414,17 +412,14 @@ class BuySellPage extends BasePage {
borderColor: Theme.of(context).colorScheme.outlineVariant,
onPushPasteButton: (context) async {
final domain = cryptoCurrencyKey.currentState!.addressController.text;
final parsed =
await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
final parsed = await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
if (parsed.isNotEmpty) {
buySellViewModel.cryptoCurrencyAddress = parsed;
}
},
onPushAddressBookButton: (context) async {
final domain = cryptoCurrencyKey.currentState!.addressController.text;
final parsed =
await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
final parsed = await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
if (parsed.isNotEmpty) {
buySellViewModel.cryptoCurrencyAddress = parsed;
}
@@ -554,8 +549,8 @@ class BuySellPage extends BasePage {
String domain,
CryptoCurrency currency,
) async {
final parsedAddresses = await _resolver.resolve(
query: domain, wallet: buySellViewModel.wallet, currency: currency);
final parsedAddresses =
await _resolver.resolve(query: domain, wallet: buySellViewModel.wallet, currency: currency);
return parsedAddresses.isNotEmpty
? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? ''
: '';
+2 -3
View File
@@ -78,9 +78,8 @@ class WebViewPageBodyState extends State<WebViewPageBody> {
return PermissionResponse(
resources: request.resources,
action: permissionGranted
? PermissionResponseAction.GRANT
: PermissionResponseAction.DENY,
action:
permissionGranted ? PermissionResponseAction.GRANT : PermissionResponseAction.DENY,
);
},
);
@@ -164,7 +164,8 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
final isConnected = await widget.hardwareWalletVM.connectDevice(device, widget.walletType);
WidgetsBinding.instance.addPostFrameCallback((_) {
if (isConnected) widget.onConnectDevice(navigatorKey.currentContext!, widget.hardwareWalletVM);
if (isConnected)
widget.onConnectDevice(navigatorKey.currentContext!, widget.hardwareWalletVM);
});
}
@@ -31,7 +31,7 @@ class _MoneroHardwareWalletOptionsForm extends StatefulWidget {
const _MoneroHardwareWalletOptionsForm(this._walletHardwareRestoreVM);
final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
@override
_MoneroHardwareWalletOptionsFormState createState() =>
_MoneroHardwareWalletOptionsFormState(_walletHardwareRestoreVM);
@@ -56,9 +56,9 @@ class DeviceTile extends StatelessWidget {
child: Text(
title,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 20,
fontWeight: FontWeight.w500,
),
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
),
),
+30 -30
View File
@@ -41,7 +41,7 @@ class ContactListPage extends BasePage {
@override
Widget? trailing(BuildContext context) {
if(!showAddButton) return SizedBox.shrink();
if (!showAddButton) return SizedBox.shrink();
return MergeSemantics(
child: Container(
width: 36.0,
@@ -417,32 +417,32 @@ class _ContactListBodyState extends State<ContactListBody> {
ActionPane _actionPane(BuildContext context, ContactRecord contact) {
return ActionPane(
motion: const ScrollMotion(),
extentRatio: 0.4,
children: [
SlidableAction(
onPressed: (_) async => await Navigator.of(context)
.pushNamed(Routes.addressBookAddContact, arguments: contact),
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onSurface,
icon: Icons.edit,
label: S.of(context).edit,
),
SlidableAction(
onPressed: (_) async {
final isDelete = await DialogService.showAlertDialog(context);
if (isDelete) {
await widget.contactListViewModel.delete(contact);
}
},
backgroundColor: Theme.of(context).colorScheme.error,
foregroundColor: Theme.of(context).colorScheme.onSurface,
icon: CupertinoIcons.delete,
label: S.of(context).delete,
),
],
);
motion: const ScrollMotion(),
extentRatio: 0.4,
children: [
SlidableAction(
onPressed: (_) async => await Navigator.of(context)
.pushNamed(Routes.addressBookAddContact, arguments: contact),
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onSurface,
icon: Icons.edit,
label: S.of(context).edit,
),
SlidableAction(
onPressed: (_) async {
final isDelete = await DialogService.showAlertDialog(context);
if (isDelete) {
await widget.contactListViewModel.delete(contact);
}
},
backgroundColor: Theme.of(context).colorScheme.error,
foregroundColor: Theme.of(context).colorScheme.onSurface,
icon: CupertinoIcons.delete,
label: S.of(context).delete,
),
],
);
}
Widget filterButtonWidget(BuildContext context, ContactListViewModel contactListViewModel) {
@@ -525,9 +525,9 @@ class DialogService {
textAlign: TextAlign.center,
walletType: cryptoCurrencyOrTokenToWalletType(contact.type),
evenTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 16,
decoration: TextDecoration.none,
),
fontSize: 16,
decoration: TextDecoration.none,
),
),
rightButtonText: S.of(context).copy,
leftButtonText: S.of(context).cancel,
+17 -16
View File
@@ -24,7 +24,7 @@ class ContactPage extends BasePage {
_nameController = TextEditingController(),
_addressController = TextEditingController(),
_currencyTypeController = TextEditingController(),
addressFocusNode = FocusNode(){
addressFocusNode = FocusNode() {
_nameController.text = contactViewModel.name;
_addressController.text = contactViewModel.address;
_nameController.addListener(() => contactViewModel.name = _nameController.text);
@@ -38,7 +38,8 @@ class ContactPage extends BasePage {
contactViewModel.address = address;
});
autorun((_) => _currencyTypeController.text = "${contactViewModel.currency?.toString() ?? ""} ${contactViewModel.currency?.tag != null ? "(${contactViewModel.currency?.tag})" : ""}");
autorun((_) => _currencyTypeController.text =
"${contactViewModel.currency?.toString() ?? ""} ${contactViewModel.currency?.tag != null ? "(${contactViewModel.currency?.tag})" : ""}");
}
@override
@@ -105,13 +106,13 @@ class ContactPage extends BasePage {
builder: (_) {
return NewSendAddressInput(
focusNode: addressFocusNode,
displayName: contactViewModel.displayName,
addressController: _addressController,
onEditingComplete: () {},
onPushPasteButton: (context) => _extractParsedAddress(context),
validator: AddressValidator(type: contactViewModel.currency!),
selectedCurrency: contactViewModel.currency!,
);
displayName: contactViewModel.displayName,
addressController: _addressController,
onEditingComplete: () {},
onPushPasteButton: (context) => _extractParsedAddress(context),
validator: AddressValidator(type: contactViewModel.currency!),
selectedCurrency: contactViewModel.currency!,
);
},
),
)
@@ -216,17 +217,17 @@ class ContactPage extends BasePage {
}
});
reaction((_)=>contactViewModel.address, (val){
if(val != _addressController.text) {
reaction((_) => contactViewModel.address, (val) {
if (val != _addressController.text) {
_addressController.text = val;
}
});
}
Future<bool> showParsedAddressConfirmationAlert(
BuildContext context,
ParsedAddress parsedAddress,
) async {
BuildContext context,
ParsedAddress parsedAddress,
) async {
final confirmed = await showPopUp<bool>(
context: context,
builder: (BuildContext context) {
@@ -237,8 +238,8 @@ class ContactPage extends BasePage {
? parsedAddress.addressSource.iconPath
: parsedAddress.profileImageUrl,
alertContent: S.of(context).extracted_address_content(
'${parsedAddress.handle} (${parsedAddress.addressSource.label})',
),
'${parsedAddress.handle} (${parsedAddress.addressSource.label})',
),
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop(true),
);
@@ -305,10 +305,9 @@ class _DashboardPageView extends BasePage {
),
),
NewMainNavBar(
dashboardViewModel: dashboardViewModel,
selectedIndex: 0,
onItemTap: (index) {}
),
dashboardViewModel: dashboardViewModel,
selectedIndex: 0,
onItemTap: (index) {}),
],
),
],
@@ -121,7 +121,7 @@ class DesktopDashboardPage extends StatelessWidget {
if (affectedWalletNames.isNotEmpty) {
Future<void>.delayed(
Duration(seconds: 1),
() {
() {
showPopUp<void>(
context: context,
builder: (BuildContext context) {
@@ -50,13 +50,13 @@ class DesktopActionButton extends StatelessWidget {
AutoSizeText(
title,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 24,
fontWeight: FontWeight.bold,
color: isEnabled
? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.onSurfaceVariant,
height: 1,
),
fontSize: 24,
fontWeight: FontWeight.bold,
color: isEnabled
? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.onSurfaceVariant,
height: 1,
),
maxLines: 1,
textAlign: TextAlign.center,
)
@@ -16,72 +16,72 @@ class DesktopDashboardActions extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).colorScheme.surface,
child: Observer(
builder: (_) {
return Column(
children: [
const SizedBox(height: 16),
DesktopActionButton(
title: MainActions.showWalletsAction.name(context),
image: MainActions.showWalletsAction.image,
canShow: MainActions.showWalletsAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.showWalletsAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.showWalletsAction.onTap(context, dashboardViewModel),
),
DesktopActionButton(
title: MainActions.swapAction.name(context),
image: MainActions.swapAction.image,
canShow: MainActions.swapAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.swapAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.swapAction.onTap(context, dashboardViewModel),
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.receiveAction.name(context),
image: MainActions.receiveAction.image,
canShow: MainActions.receiveAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.receiveAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.receiveAction.onTap(context, dashboardViewModel),
),
child: Observer(builder: (_) {
return Column(
children: [
const SizedBox(height: 16),
DesktopActionButton(
title: MainActions.showWalletsAction.name(context),
image: MainActions.showWalletsAction.image,
canShow: MainActions.showWalletsAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.showWalletsAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.showWalletsAction.onTap(context, dashboardViewModel),
),
DesktopActionButton(
title: MainActions.swapAction.name(context),
image: MainActions.swapAction.image,
canShow: MainActions.swapAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.swapAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.swapAction.onTap(context, dashboardViewModel),
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.receiveAction.name(context),
image: MainActions.receiveAction.image,
canShow: MainActions.receiveAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.receiveAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.receiveAction.onTap(context, dashboardViewModel),
),
Expanded(
child: DesktopActionButton(
title: MainActions.sendAction.name(context),
image: MainActions.sendAction.image,
canShow: MainActions.sendAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.sendAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.sendAction.onTap(context, dashboardViewModel),
),
),
Expanded(
child: DesktopActionButton(
title: MainActions.sendAction.name(context),
image: MainActions.sendAction.image,
canShow: MainActions.sendAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.sendAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.sendAction.onTap(context, dashboardViewModel),
),
],
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.tradeAction.name(context),
image: MainActions.tradeAction.image,
canShow: MainActions.tradeAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.tradeAction.isEnabled?.call(dashboardViewModel),
onTap: () async => await MainActions.tradeAction.onTap(context, dashboardViewModel),
),
),
],
),
Row(
children: [
Expanded(
child: DesktopActionButton(
title: MainActions.tradeAction.name(context),
image: MainActions.tradeAction.image,
canShow: MainActions.tradeAction.canShow?.call(dashboardViewModel),
isEnabled: MainActions.tradeAction.isEnabled?.call(dashboardViewModel),
onTap: () async =>
await MainActions.tradeAction.onTap(context, dashboardViewModel),
),
],
),
),
],
),
Expanded(
child: CakeFeaturesPage(
dashboardViewModel: dashboardViewModel,
cakeFeaturesViewModel: getIt.get<CakeFeaturesViewModel>(),
),
),
],
);
}
),
],
);
}),
);
}
}
@@ -20,7 +20,6 @@ class DesktopDashboardNavbar extends StatelessWidget implements ObstructingPrefe
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsetsDirectional.only(end: 24),
color: Theme.of(context).colorScheme.surfaceContainerLowest.withOpacity(0.1),
@@ -40,7 +39,7 @@ class DesktopDashboardNavbar extends StatelessWidget implements ObstructingPrefe
@override
Size get preferredSize => Size.fromHeight(60);
@override
bool shouldFullyObstruct(BuildContext context) => false;
}
@@ -8,7 +8,7 @@ class SideMenu extends StatelessWidget {
required this.bottomItems,
required this.width,
});
final List<SideMenuItem> topItems;
final List<SideMenuItem> bottomItems;
final double width;
@@ -31,25 +31,36 @@ class DesktopWalletSelectionDropDown extends StatefulWidget {
}
class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionDropDown> {
final moneroIcon = Image.asset('assets/new-ui/crypto_full_icons/monero.svg', height: 24, width: 24);
final bitcoinIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg', height: 24, width: 24);
final moneroIcon =
Image.asset('assets/new-ui/crypto_full_icons/monero.svg', height: 24, width: 24);
final bitcoinIcon =
Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg', height: 24, width: 24);
final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24);
final litecoinIcon = Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg', height: 24, width: 24);
final litecoinIcon =
Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.webp', height: 24, width: 24);
final ethereumIcon = Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg', height: 24, width: 24);
final polygonIcon = Image.asset('assets/new-ui/crypto_full_icons/polygon.svg', height: 24, width: 24);
final bitcoinCashIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg', height: 24, width: 24);
final ethereumIcon =
Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg', height: 24, width: 24);
final polygonIcon =
Image.asset('assets/new-ui/crypto_full_icons/polygon.svg', height: 24, width: 24);
final bitcoinCashIcon =
Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg', height: 24, width: 24);
final baseIcon = Image.asset('assets/new-ui/crypto_full_icons/base.svg', height: 24, width: 24);
final arbitrumIcon = Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg', height: 24, width: 24);
final arbitrumIcon =
Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg', height: 24, width: 24);
final bscIcon = Image.asset('assets/new-ui/crypto_full_icons/bnb.svg', height: 24, width: 24);
final nanoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24);
final bananoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24);
final solanaIcon = Image.asset('assets/new-ui/crypto_full_icons/solana.svg', height: 24, width: 24);
final solanaIcon =
Image.asset('assets/new-ui/crypto_full_icons/solana.svg', height: 24, width: 24);
final tronIcon = Image.asset('assets/new-ui/crypto_full_icons/tron.svg', height: 24, width: 24);
final wowneroIcon = Image.asset('assets/new-ui/crypto_full_icons/wownero.svg', height: 24, width: 24);
final wowneroIcon =
Image.asset('assets/new-ui/crypto_full_icons/wownero.svg', height: 24, width: 24);
final zanoIcon = Image.asset('assets/new-ui/crypto_full_icons/zano.svg', height: 24, width: 24);
final decredIcon = Image.asset('assets/new-ui/crypto_full_icons/decred.svg', height: 24, width: 24);
final dogeIcon = Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg', height: 24, width: 24);
final decredIcon =
Image.asset('assets/new-ui/crypto_full_icons/decred.svg', height: 24, width: 24);
final dogeIcon =
Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg', height: 24, width: 24);
final zcashIcon = Image.asset('assets/new-ui/crypto_full_icons/zcash.svg', height: 24, width: 24);
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
@@ -264,7 +275,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
}
void changeProcessText(String text) {
_progressBar = createBar<void>(text,context, duration: null)..show(context);
_progressBar = createBar<void>(text, context, duration: null)..show(context);
}
void hideProgressText() {
@@ -14,9 +14,8 @@ class FavoriteTokenModal extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.vertical(top: Radius.circular(18))
),
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
child: SafeArea(
child: Column(
children: [
@@ -22,7 +22,8 @@ class BalancePage extends StatelessWidget {
Widget build(BuildContext context) {
return Observer(
builder: (context) {
final isNFTActivated = isNFTACtivatedChain(dashboardViewModel.type, chainId: dashboardViewModel.wallet.chainId);
final isNFTActivated = isNFTACtivatedChain(dashboardViewModel.type,
chainId: dashboardViewModel.wallet.chainId);
return DefaultTabController(
key: ValueKey<bool>(isNFTActivated),
length: isNFTActivated ? 2 : 1,
@@ -334,7 +334,7 @@ class CryptoBalanceWidget extends StatelessWidget {
),
),
],
if (dashboardViewModel.showZcashMissingFundsCard) ...[
if (dashboardViewModel.showZcashMissingFundsCard) ...[
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
@@ -349,7 +349,8 @@ class CryptoBalanceWidget extends StatelessWidget {
hintWidget: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => launchUrl(
Uri.parse("https://docs.cakewallet.com/tutorials/zashi/#creating-a-new-zcash-wallet-on-cake"),
Uri.parse(
"https://docs.cakewallet.com/tutorials/zashi/#creating-a-new-zcash-wallet-on-cake"),
mode: LaunchMode.externalApplication,
),
child: Text(
@@ -492,7 +493,7 @@ class CryptoBalanceWidget extends StatelessWidget {
}
dashboardViewModel.setMwebEnabled();
}
Future<void> _rescanInternalChangeZcash(BuildContext context) async {
dashboardViewModel.rescanInternalChangeZcash();
await showPopUp<void>(
@@ -507,7 +508,6 @@ class CryptoBalanceWidget extends StatelessWidget {
),
);
}
Future<void> _dismissMweb(BuildContext context) async {
await showPopUp<void>(
@@ -522,7 +522,7 @@ class CryptoBalanceWidget extends StatelessWidget {
));
dashboardViewModel.dismissMweb();
}
Future<void> _dismissZcash(BuildContext context) async {
await showPopUp<void>(
context: context,
@@ -27,27 +27,27 @@ class CakeFeaturesPage extends StatelessWidget {
Widget build(BuildContext context) {
return GradientBackground(
scaffold: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: IntrinsicHeight(
child: !FeatureFlag.hasNewUi ? _buildOldUi(context) : _buildNewUi(context),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(context),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: IntrinsicHeight(
child: !FeatureFlag.hasNewUi ? _buildOldUi(context) : _buildNewUi(context),
),
);
},
),
),
);
},
),
],
),
),
],
),
),
);
}
@@ -58,9 +58,9 @@ class CakeFeaturesPage extends StatelessWidget {
child: Text(
S.of(context).apps,
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
),
);
}
@@ -72,10 +72,10 @@ class CakeFeaturesPage extends StatelessWidget {
child: Text(
S.of(context).apps,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontSize: 18.0,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
fontSize: 18.0,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
),
),
);
@@ -101,7 +101,8 @@ class CakeFeaturesPage extends StatelessWidget {
onTap: () => Navigator.of(context).pushNamed(Routes.dEuroSavings),
title: S.of(context).deuro_savings,
subTitle: S.of(context).deuro_savings_subtitle,
image: Image.asset('assets/images/deuro_icon.png', height: 80, width: 80, fit: BoxFit.cover),
image: Image.asset('assets/images/deuro_icon.png',
height: 80, width: 80, fit: BoxFit.cover),
);
}
return const SizedBox();
@@ -128,7 +129,10 @@ class CakeFeaturesPage extends StatelessWidget {
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.only(left: 24, bottom: 8),
child: CakeImageWidget(imageUrl: "assets/new-ui/by-cakelabs.svg", height: 20, color: Theme.of(context).colorScheme.onSurfaceVariant),
child: CakeImageWidget(
imageUrl: "assets/new-ui/by-cakelabs.svg",
height: 20,
color: Theme.of(context).colorScheme.onSurfaceVariant),
),
),
AppsWidget(
@@ -163,9 +167,9 @@ class CakeFeaturesPage extends StatelessWidget {
child: Text(
"Featured Apps",
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
),
),
AppsWidget(
@@ -225,4 +229,4 @@ class CakeFeaturesPage extends StatelessWidget {
Navigator.pushNamed(context, Routes.cakePayCardsPage);
}
}
}
}
@@ -42,39 +42,28 @@ class NavigationDock extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: MainActions.all
.where((element) =>
element.canShow?.call(dashboardViewModel) ??
true)
.where((element) => element.canShow?.call(dashboardViewModel) ?? true)
.map(
(action) => Expanded(
child: Semantics(
button: true,
enabled: (action.isEnabled
?.call(dashboardViewModel) ??
true),
enabled: (action.isEnabled?.call(dashboardViewModel) ?? true),
child: ActionButton(
key: action.key,
image: Image.asset(
action.image,
height: 24,
width: 24,
color:
Theme.of(context).colorScheme.primary,
color: Theme.of(context).colorScheme.primary,
),
title: action.name(context),
onClick: (action.isEnabled
?.call(dashboardViewModel) ??
true)
? () async => await action.onTap(
context, dashboardViewModel)
onClick: (action.isEnabled?.call(dashboardViewModel) ?? true)
? () async =>
await action.onTap(context, dashboardViewModel)
: null,
textColor: action.isEnabled
?.call(dashboardViewModel) ??
true
textColor: action.isEnabled?.call(dashboardViewModel) ?? true
? null
: Theme.of(context)
.colorScheme
.onSurface,
: Theme.of(context).colorScheme.onSurface,
),
),
),
@@ -94,8 +94,7 @@ class NFTListWidget extends StatelessWidget {
if (nftViewModel.solanaNftAssetModels.isEmpty) return emptyMessage;
return Padding(
padding: EdgeInsets.only(
bottom: 64),
padding: EdgeInsets.only(bottom: 64),
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
@@ -112,8 +111,7 @@ class NFTListWidget extends StatelessWidget {
if (nftViewModel.nftAssetByWalletModels.isEmpty) return emptyMessage;
return Padding(
padding: EdgeInsets.only(
bottom: 64),
padding: EdgeInsets.only(bottom: 64),
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
@@ -66,8 +66,7 @@ class TransactionsPage extends StatelessWidget {
}),
HeaderRow(
dashboardViewModel: dashboardViewModel,
onExportCsv: () =>
CsvExportService().exportToCsv(dashboardViewModel.items, context),
onExportCsv: () => CsvExportService().exportToCsv(dashboardViewModel.items, context),
key: ValueKey('transactions_page_header_row_key'),
),
Expanded(
@@ -159,7 +158,8 @@ class TransactionsPage extends StatelessWidget {
currency: "BTC",
state: item.status,
amount: dashboardViewModel.appStore.amountParsingProxy
.getDisplayCryptoString(session.amount.toInt(), CryptoCurrency.btc),
.getDisplayCryptoString(
session.amount.toInt(), CryptoCurrency.btc),
createdAt: DateFormat('HH:mm').format(session.inProgressSince!),
isSending: session.isSenderSession,
);
@@ -168,8 +168,7 @@ class TransactionsPage extends StatelessWidget {
if (item is TradeListItem) {
final trade = item.trade;
final tradeFrom =
trade.from;
final tradeFrom = trade.from;
final tradeTo = trade.to;
+6 -8
View File
@@ -17,10 +17,8 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart';
class SignPage extends StatefulWidget {
SignPage(this.signViewModel);
final SignViewModel signViewModel;
@override
State<SignPage> createState() => _SignPageState();
}
@@ -29,7 +27,7 @@ class _SignPageState extends State<SignPage> {
List<Widget> _pages = [];
final signFormKey = GlobalKey<SignFormState>();
final verifyFormKey = GlobalKey<VerifyFormState>();
final PageController _controller = PageController(initialPage: 0) ;
final PageController _controller = PageController(initialPage: 0);
bool _isEffectsInstalled = false;
@@ -55,14 +53,14 @@ class _SignPageState extends State<SignPage> {
return Container(
color: Theme.of(context).colorScheme.surface,
child: SafeArea(
top:false,
top: false,
child: Column(
children: [
ModalTopBar(title: S.current.sign_verify_title,
ModalTopBar(
title: S.current.sign_verify_title,
leadingIcon: Icon(Icons.arrow_back_ios_new),
onLeadingPressed: Navigator
.of(context)
.pop,),
onLeadingPressed: Navigator.of(context).pop,
),
Expanded(
child: KeyboardHideOverlay(
child: Container(
@@ -53,8 +53,7 @@ class ActionButton extends StatelessWidget {
softWrap: false,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
color: textColor ??
Theme.of(context).colorScheme.onSurface,
color: textColor ?? Theme.of(context).colorScheme.onSurface,
),
),
),
@@ -17,8 +17,8 @@ class DateSectionRaw extends StatelessWidget {
child: Text(
title,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
);
}
@@ -13,4 +13,4 @@ class FilterTile extends StatelessWidget {
child: child,
);
}
}
}
@@ -71,9 +71,9 @@ class _FilterWidgetState extends State<FilterWidget> {
child: Text(
S.of(context).filter_by,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
),
),
@@ -97,14 +97,15 @@ class _FilterWidgetState extends State<FilterWidget> {
child: Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
),
),
ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 28.0, vertical: 8.0),
padding:
const EdgeInsets.symmetric(horizontal: 28.0, vertical: 8.0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: section.length,
@@ -138,4 +139,4 @@ class _FilterWidgetState extends State<FilterWidget> {
),
);
}
}
}
@@ -26,8 +26,7 @@ class HeaderRow extends StatelessWidget {
Text(
S.of(context).history,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface),
fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurface),
),
Row(
children: [
@@ -61,8 +60,7 @@ class HeaderRow extends StatelessWidget {
container: true,
child: GestureDetector(
key: ValueKey('transactions_page_header_row_transaction_filter_button_key'),
onTap: () {
},
onTap: () {},
child: Semantics(
label: 'Transaction Filter',
button: true,
@@ -85,4 +83,4 @@ class HeaderRow extends StatelessWidget {
),
);
}
}
}
@@ -27,8 +27,6 @@ class NewMainNavBar extends StatefulWidget {
}
class _NEWNewMainNavBarState extends State<NewMainNavBar> {
static const iconBoxWidth = 48.0;
static const iconWidth = 28.0;
static const iconHeight = 28.0;
@@ -82,9 +80,7 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
}
// Estimate pill width based on text length
double _estimatePillWidthForAction(
BuildContext context, NewMainActions action,
{Color? color}) {
double _estimatePillWidthForAction(BuildContext context, NewMainActions action, {Color? color}) {
final text = action.name(context);
final textPainter = TextPainter(
text: TextSpan(
@@ -94,10 +90,7 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
maxLines: 1,
textDirection: TextDirection.ltr,
)..layout();
return pillIconWidth +
pillIconSpacing +
textPainter.width +
pillHorizontalPadding;
return pillIconWidth + pillIconSpacing + textPainter.width + pillHorizontalPadding;
}
double calcLeft(int index, double pillWidth) {
@@ -113,7 +106,11 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
}
double calcBarWidth(double pillWidth, int visibleActionsLength) {
return (iconWidth + iconHorizontalPadding) * visibleActionsLength + (pillWidth - iconWidth) + barHorizontalPadding + pillIconSpacing / double.infinity - 2;
return (iconWidth + iconHorizontalPadding) * visibleActionsLength +
(pillWidth - iconWidth) +
barHorizontalPadding +
pillIconSpacing / double.infinity -
2;
}
@override
@@ -138,86 +135,92 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
final currentAction = visibleActions[widget.selectedIndex];
return Align(
alignment: Alignment.bottomCenter,
child: SafeArea(
bottom: !(Platform.isIOS),
top: false,
child: Padding(
// tux PLEASE consult me (malik) before removing this padding.
padding: EdgeInsets.only(bottom: NewMainNavBar.barBottomPadding),
child: AnimatedContainer(
duration: barResizeDuration,
curve: Curves.easeOutCubic,
width: barWidth,
child: ClipRSuperellipse(
borderRadius: BorderRadius.circular(barBorderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Container(
height: NewMainNavBar.barHeight,
decoration: ShapeDecoration(
color: backgroundColor,
shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(barBorderRadius),
side: const BorderSide(color: Color(0x14FFFFFF), width: 1),
alignment: Alignment.bottomCenter,
child: SafeArea(
bottom: !(Platform.isIOS),
top: false,
child: Padding(
// tux PLEASE consult me (malik) before removing this padding.
padding: EdgeInsets.only(bottom: NewMainNavBar.barBottomPadding),
child: AnimatedContainer(
duration: barResizeDuration,
curve: Curves.easeOutCubic,
width: barWidth,
child: ClipRSuperellipse(
borderRadius: BorderRadius.circular(barBorderRadius),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Container(
height: NewMainNavBar.barHeight,
decoration: ShapeDecoration(
color: backgroundColor,
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(barBorderRadius),
side: const BorderSide(color: Color(0x14FFFFFF), width: 1),
),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
child: Stack(
alignment: Alignment.center,
children: [
AnimatedPill(
left: calcLeft(widget.selectedIndex, pillWidth),
pillColor: pillColor,
currentAction: currentAction,
pillIconHeight: pillIconHeight,
pillIconWidth: pillIconWidth,
pillIconSpacing: pillIconSpacing,
pillBorderRadius: pillBorderRadius,
contentColor: activeColor,
estimateWidthForAction: pillWidth,
pillTextStyle: pillTextStyle,
pillMoveDuration: pillMoveDuration,
pillResizeDuration: pillResizeDuration,
),
for (int i = 0; i < visibleActions.length; i++)
AnimatedPositioned(
duration: pillResizeDuration,
width: iconBoxWidth,
left: calcLeft(i, pillWidth)+((i == widget.selectedIndex) ? iconHorizontalPadding/100 : 0),
curve: Curves.easeOutCubic,
child: InkWell(
splashFactory: NoSplash.splashFactory,
splashColor: Colors.transparent,
borderRadius: BorderRadius.circular(pillBorderRadius),
onTap: () => _onItemTap(i),
child: AnimatedContainer(
duration: _firstFrame
? Duration.zero
: inactiveIconMoveDuration,
curve: Curves.easeOutCubic,
width:
i == widget.selectedIndex ? pillWidth : iconBoxWidth,
alignment: Alignment.center,
child: AnimatedAlign(
duration: inactiveIconFadeDuration,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
child: Stack(
alignment: Alignment.center,
children: [
AnimatedPill(
left: calcLeft(widget.selectedIndex, pillWidth),
pillColor: pillColor,
currentAction: currentAction,
pillIconHeight: pillIconHeight,
pillIconWidth: pillIconWidth,
pillIconSpacing: pillIconSpacing,
pillBorderRadius: pillBorderRadius,
contentColor: activeColor,
estimateWidthForAction: pillWidth,
pillTextStyle: pillTextStyle,
pillMoveDuration: pillMoveDuration,
pillResizeDuration: pillResizeDuration,
),
for (int i = 0; i < visibleActions.length; i++)
AnimatedPositioned(
duration: pillResizeDuration,
width: iconBoxWidth,
left: calcLeft(i, pillWidth) +
((i == widget.selectedIndex)
? iconHorizontalPadding / 100
: 0),
curve: Curves.easeOutCubic,
child: InkWell(
splashFactory: NoSplash.splashFactory,
splashColor: Colors.transparent,
borderRadius: BorderRadius.circular(pillBorderRadius),
onTap: () => _onItemTap(i),
child: AnimatedContainer(
duration:
_firstFrame ? Duration.zero : inactiveIconMoveDuration,
curve: Curves.easeOutCubic,
width: i == widget.selectedIndex ? pillWidth : iconBoxWidth,
alignment: Alignment.center,
child: AnimatedScale(
duration: inactiveIconAppearDuration,
child: AnimatedAlign(
duration: inactiveIconFadeDuration,
curve: Curves.easeOutCubic,
scale: (i == widget.selectedIndex) ? 0.857 : 1.0,
child: TweenAnimationBuilder<Color?>(
tween: ColorTween(
begin: (i == widget.selectedIndex) ? inactiveColor : activeColor,
end: (i==widget.selectedIndex) ? activeColor : inactiveColor,
),
duration: iconColorChangeDuration,
builder: (context, value, child) {
return Container(
height: NewMainNavBar.barHeight,
child: CakeImageWidget(imageUrl:
visibleActions[i].image,
alignment: Alignment.center,
child: AnimatedScale(
duration: inactiveIconAppearDuration,
curve: Curves.easeOutCubic,
scale: (i == widget.selectedIndex) ? 0.857 : 1.0,
child: TweenAnimationBuilder<Color?>(
tween: ColorTween(
begin: (i == widget.selectedIndex)
? inactiveColor
: activeColor,
end: (i == widget.selectedIndex)
? activeColor
: inactiveColor,
),
duration: iconColorChangeDuration,
builder: (context, value, child) {
return Container(
height: NewMainNavBar.barHeight,
child: CakeImageWidget(
imageUrl: visibleActions[i].image,
width: iconWidth,
height: iconHeight,
//fit: BoxFit.scaleDown,
@@ -226,23 +229,22 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
BlendMode.srcIn,
),
),
);
}
);
}),
),
),
),
),
),
),
],
),
)),
],
),
)),
),
),
),
),
),
),
);
);
},
);
}
@@ -302,7 +304,8 @@ class AnimatedPill extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(padding: EdgeInsets.only(left: pillIconWidth + 2),
Padding(
padding: EdgeInsets.only(left: pillIconWidth + 2),
child: Text(
currentAction.name(context),
style: pillTextStyle.copyWith(color: contentColor),
@@ -44,18 +44,18 @@ class OrderRow extends StatelessWidget {
children: [
_ProviderIcon(path: providerIconPath, title: providerTitle),
if (state != null)
Positioned(
right: 0,
bottom: 2,
child: Container(
height: 8,
width: 8,
decoration: BoxDecoration(
color: _statusColor(context, state!),
borderRadius: BorderRadius.circular(12),
Positioned(
right: 0,
bottom: 2,
child: Container(
height: 8,
width: 8,
decoration: BoxDecoration(
color: _statusColor(context, state!),
borderRadius: BorderRadius.circular(12),
),
),
),
),
],
),
const SizedBox(width: 12),
@@ -76,8 +76,7 @@ class _PageIndicatorState extends State<PageIndicator> {
);
}
double _estimateItemWidthForAction(
BuildContext context, PageIndicatorActions action,
double _estimateItemWidthForAction(BuildContext context, PageIndicatorActions action,
{Color? color}) {
final text = action.name(context);
final textPainter = TextPainter(
@@ -86,15 +85,11 @@ class _PageIndicatorState extends State<PageIndicator> {
textDirection: Directionality.of(context),
textScaler: MediaQuery.of(context).textScaler,
)..layout();
return iconWidth +
iconSpacing +
textPainter.width +
pillHorizontalPadding * 2;
return iconWidth + iconSpacing + textPainter.width + pillHorizontalPadding * 2;
}
@override
Widget build(BuildContext context) {
final visibleActions = PageIndicatorActions.all.where((action) {
return action.isEnabled?.call(widget.dashboardViewModel) ?? true;
}).toList();
@@ -127,34 +122,28 @@ class _PageIndicatorState extends State<PageIndicator> {
];
final totalItemsWidth =
actionWidths.fold(0.0, (sum, width) => sum + width) +
barHorizontalPadding * 2;
actionWidths.fold(0.0, (sum, width) => sum + width) + barHorizontalPadding * 2;
final barWidth = math.min(totalItemsWidth, screenWidth * 0.95);
final count = visibleActions.length;
final firstLeft = edgePadding;
final secondLeft =
barWidth - (isRTL ? actionWidths.first : actionWidths[1]) - edgePadding;
final secondLeft = barWidth - (isRTL ? actionWidths.first : actionWidths[1]) - edgePadding;
final List<double> positions;
if (count == 2) {
positions = [firstLeft, secondLeft];
} else {
final lastLeft = barWidth -
(isRTL ? actionWidths.first : actionWidths.last) -
edgePadding;
final lastLeft = barWidth - (isRTL ? actionWidths.first : actionWidths.last) - edgePadding;
final centerLeft = (isRTL
? actionWidths.last + edgePadding
: actionWidths.first + edgePadding);
final centerLeft =
(isRTL ? actionWidths.last + edgePadding : actionWidths.first + edgePadding);
positions = [firstLeft, centerLeft, lastLeft];
}
final left =
(isRTL ? positions.reversed.toList() : positions)[selectedIndex];
final left = (isRTL ? positions.reversed.toList() : positions)[selectedIndex];
final currentAction = visibleActions[selectedIndex];
return Align(
@@ -191,8 +180,7 @@ class _PageIndicatorState extends State<PageIndicator> {
pillResizeDuration: pillResizeDuration,
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: barHorizontalPadding),
padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
@@ -210,47 +198,36 @@ class _PageIndicatorState extends State<PageIndicator> {
height: barHeight,
width: i == selectedIndex
? pillWidth
: _estimateItemWidthForAction(
context, visibleActions[i]),
: _estimateItemWidthForAction(context, visibleActions[i]),
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
TweenAnimationBuilder<Color?>(
duration: const Duration(
milliseconds: 300),
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
tween: ColorTween(
begin: inactiveColor,
end: i == selectedIndex
? activeColor
: inactiveColor,
end: i == selectedIndex ? activeColor : inactiveColor,
),
builder: (context, color, _) =>
SvgPicture.asset(
builder: (context, color, _) => SvgPicture.asset(
visibleActions[i].image,
width: iconWidth,
height: iconHeight,
colorFilter: ColorFilter.mode(
color!, BlendMode.srcIn),
colorFilter: ColorFilter.mode(color!, BlendMode.srcIn),
),
),
SizedBox(width: iconSpacing),
TweenAnimationBuilder<Color?>(
duration: const Duration(
milliseconds: 300),
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutCubic,
tween: ColorTween(
begin: inactiveColor,
end: i == selectedIndex
? activeColor
: inactiveColor,
end: i == selectedIndex ? activeColor : inactiveColor,
),
builder: (context, color, _) =>
Text(
builder: (context, color, _) => Text(
visibleActions[i].name(context),
style: textStyle.copyWith(
color: color),
style: textStyle.copyWith(color: color),
overflow: TextOverflow.fade,
softWrap: false,
),
@@ -315,9 +292,8 @@ class AnimatedPill extends StatelessWidget {
duration: pillResizeDuration,
curve: Curves.easeOutCubic,
width: estimateWidthForAction,
decoration: BoxDecoration(
color: pillColor,
borderRadius: BorderRadius.circular(pillBorderRadius)),
decoration:
BoxDecoration(color: pillColor, borderRadius: BorderRadius.circular(pillBorderRadius)),
clipBehavior: Clip.hardEdge,
alignment: Alignment.center,
),
@@ -18,7 +18,7 @@ class SignForm extends StatefulWidget {
final WalletType type;
final bool includeAddress;
final int? chainId;
@override
SignFormState createState() => SignFormState();
}
@@ -66,15 +66,13 @@ class SignFormState extends State<SignForm> with AutomaticKeepAliveClientMixin {
const SizedBox(height: 20),
AddressTextField(
controller: addressController,
options: [
AddressTextFieldOption.paste,
AddressTextFieldOption.walletAddresses
],
options: [AddressTextFieldOption.paste, AddressTextFieldOption.walletAddresses],
buttonColor: Theme.of(context).colorScheme.surfaceContainerHighest,
onSelectedContact: (contact) {
addressController.text = contact.address;
},
selectedCurrency: walletTypeToCryptoCurrency(widget.type, chainId: widget.chainId),
selectedCurrency:
walletTypeToCryptoCurrency(widget.type, chainId: widget.chainId),
fillColor: Theme.of(context).colorScheme.surface,
),
],
@@ -61,9 +61,9 @@ class SolanaNFTTileWidget extends StatelessWidget {
Text(
'Symbol: ${nftAsset.symbol ?? '---'}',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
height: 1,
),
color: Theme.of(context).colorScheme.onSurfaceVariant,
height: 1,
),
),
const SizedBox(height: 8),
Text(
@@ -71,10 +71,10 @@ class SolanaNFTTileWidget extends StatelessWidget {
? nftAsset.name!
: (nftAsset.symbol ?? '---'),
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w900,
color: Theme.of(context).colorScheme.onSurface,
height: 1,
),
fontWeight: FontWeight.w900,
color: Theme.of(context).colorScheme.onSurface,
height: 1,
),
),
],
),
@@ -20,7 +20,8 @@ class SyncIndicator extends StatelessWidget {
return Observer(builder: (_) {
final syncIndicatorWidth = 237.0;
final status = dashboardViewModel.status;
final statusText = syncStatusTitle(status, dashboardViewModel.settingsStore.syncStatusDisplayMode);
final statusText =
syncStatusTitle(status, dashboardViewModel.settingsStore.syncStatusDisplayMode);
final progress = status.progress();
final indicatorOffset = progress * syncIndicatorWidth;
final indicatorWidth = progress < 1
@@ -42,13 +42,14 @@ class TransactionRow extends StatelessWidget {
shape: BoxShape.circle,
color: Theme.of(context).colorScheme.surfaceContainerHighest,
),
child: (isShield) ? Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset('assets/images/tx_shield.svg'),
) :
Image.asset(direction == TransactionDirection.incoming
? 'assets/images/down_arrow.png'
: 'assets/images/up_arrow.png'),
child: (isShield)
? Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset('assets/images/tx_shield.svg'),
)
: Image.asset(direction == TransactionDirection.incoming
? 'assets/images/down_arrow.png'
: 'assets/images/up_arrow.png'),
),
SizedBox(width: 12),
Expanded(
@@ -66,7 +67,7 @@ class TransactionRow extends StatelessWidget {
title,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
fontWeight: FontWeight.w600,
overflow: TextOverflow.fade,
overflow: TextOverflow.fade,
),
),
),
@@ -13,7 +13,7 @@ class VerifyForm extends StatefulWidget {
final WalletType type;
final int? chainId;
@override
VerifyFormState createState() => VerifyFormState();
}
+20 -25
View File
@@ -100,7 +100,8 @@ class JsonExplorerPage extends StatelessWidget {
final appDir = await getAppDir();
final filePath = appDir.path + '/.json_dump_temp.json';
await File(filePath).writeAsString(jsonString);
await ShareUtil.shareFile(filePath: filePath, fileName: path.basename(filePath), context: context);
await ShareUtil.shareFile(
filePath: filePath, fileName: path.basename(filePath), context: context);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to share file: $e')),
@@ -143,11 +144,11 @@ class _JsonExplorerState extends State<JsonExplorer> {
void _buildItemList() {
_allItems.clear();
if (widget.data is Map) {
final map = widget.data as Map<String, dynamic>;
final sortedKeys = map.keys.toList()..sort();
for (final key in sortedKeys) {
_allItems.add(CacheItem(
key: key,
@@ -165,7 +166,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
));
}
}
_applyFilter();
}
@@ -175,7 +176,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
} else {
_filteredItems = _allItems.where((item) {
return item.displayKey.toLowerCase().contains(_searchQuery.toLowerCase()) ||
_valueContainsSearch(item.value, _searchQuery.toLowerCase());
_valueContainsSearch(item.value, _searchQuery.toLowerCase());
}).toList();
}
}
@@ -210,10 +211,10 @@ class _JsonExplorerState extends State<JsonExplorer> {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final totalItems = widget.data is Map
? (widget.data as Map).length
: widget.data is List
? (widget.data as List).length
final totalItems = widget.data is Map
? (widget.data as Map).length
: widget.data is List
? (widget.data as List).length
: 0;
return Column(
@@ -230,9 +231,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
prefixIcon: const Icon(Icons.search),
border: const OutlineInputBorder(),
isDense: true,
suffixText: _searchQuery.isNotEmpty
? '${_filteredItems.length} found'
: null,
suffixText: _searchQuery.isNotEmpty ? '${_filteredItems.length} found' : null,
),
onChanged: (value) {
setState(() {
@@ -245,7 +244,6 @@ class _JsonExplorerState extends State<JsonExplorer> {
],
),
),
Expanded(
child: _filteredItems.isEmpty && _searchQuery.isNotEmpty
? Center(
@@ -311,11 +309,11 @@ class CacheItemTile extends StatelessWidget {
Color _getTypeColor(BuildContext context, dynamic value) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
if (value == null) {
return Colors.grey;
}
switch (value.runtimeType) {
case String:
return Colors.green;
@@ -337,22 +335,22 @@ class CacheItemTile extends StatelessWidget {
String _getValuePreview(dynamic value) {
if (value == null) return 'null';
if (value is Map) {
return '{${value.length} items}';
}
if (value is List) {
return '[${value.length} items]';
}
if (value is String) {
if (value.length > 100) {
return '"${value.substring(0, 97)}..."';
}
return '"$value"';
}
final str = value.toString();
if (str.length > 100) {
return '${str.substring(0, 97)}...';
@@ -407,9 +405,7 @@ class CacheItemTile extends StatelessWidget {
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
child: ListTile(
leading: Icon(
canNavigate
? (item.value is Map ? Icons.folder : Icons.list)
: Icons.description,
canNavigate ? (item.value is Map ? Icons.folder : Icons.list) : Icons.description,
color: _getTypeColor(context, item.value),
),
title: _buildHighlightedText(
@@ -433,8 +429,7 @@ class CacheItemTile extends StatelessWidget {
icon: const Icon(Icons.copy, size: 18),
tooltip: 'Copy ${item.displayKey}',
),
if (canNavigate)
const Icon(Icons.chevron_right),
if (canNavigate) const Icon(Icons.chevron_right),
],
),
onTap: canNavigate ? onTap : null,
@@ -442,4 +437,4 @@ class CacheItemTile extends StatelessWidget {
),
);
}
}
}
+8 -17
View File
@@ -24,8 +24,6 @@ class DevMoneroCallProfilerPage extends BasePage {
}
}
class PerformanceDebug extends StatefulWidget {
const PerformanceDebug({super.key});
@@ -68,7 +66,7 @@ class _PerformanceDebugState extends State<PerformanceDebug> {
return debugCallLength["MONERO_Wallet_init"]!.last;
}
late final String perfInfo = """
late final String perfInfo = """
---- Performance tuning
This page lists all calls that take place during the app runtime.-
As per Flutter docs we can read:
@@ -93,8 +91,8 @@ min: fastest execution (% of frame)
max: slowest execution (% of frame)
95th: 95% of the time, the function is faster than this amount of time (% of frame)
"""
.split("-\n")
.join(" ");
.split("-\n")
.join(" ");
late final frameTime = 8333;
late final frameGreenTier = frameTime ~/ 100;
@@ -113,7 +111,6 @@ max: slowest execution (% of frame)
return Colors.red;
}
@override
void initState() {
super.initState();
@@ -144,9 +141,7 @@ max: slowest execution (% of frame)
],
));
final keys = debugCallLength.keys.toList();
keys.sort((s1, s2) =>
_n95th(debugCallLength[s2]!) -
_n95th(debugCallLength[s1]!));
keys.sort((s1, s2) => _n95th(debugCallLength[s2]!) - _n95th(debugCallLength[s1]!));
for (var key in keys) {
final value = debugCallLength[key];
if (value == null) continue;
@@ -172,14 +167,10 @@ max: slowest execution (% of frame)
const Spacer(),
cw("${_str(total / 1000)}ms", perfc(total)),
]),
cw("average: ${_str(avg)}µs (~${_str(avg / (frameTime))}f)",
perfc(avg)),
cw("min: $minµs (~${_str(min / (frameTime) * 100)})",
perfc(min)),
cw("max: $maxµs (~${_str(max / (frameTime) * 100)}%)",
perfc(max)),
cw("95th: $npµs (~${_str(np / (frameTime) * 100)}%)",
perfc(np)),
cw("average: ${_str(avg)}µs (~${_str(avg / (frameTime))}f)", perfc(avg)),
cw("min: $minµs (~${_str(min / (frameTime) * 100)})", perfc(min)),
cw("max: $maxµs (~${_str(max / (frameTime) * 100)}%)", perfc(max)),
cw("95th: $npµs (~${_str(np / (frameTime) * 100)}%)", perfc(np)),
],
),
),
+25 -33
View File
@@ -75,14 +75,16 @@ class DevNetworkRequests extends BasePage {
RequestMethod.delete => Text("DELETE"),
RequestMethod.newHttpClient ||
RequestMethod.newHttpIOClient ||
RequestMethod.newProxySocket => null,
RequestMethod.newProxySocket =>
null,
},
title: Text(item.time.toIso8601String()),
subtitle: switch (item.method) {
RequestMethod.get ||
RequestMethod.post ||
RequestMethod.put ||
RequestMethod.delete => Text("${item.uri}"),
RequestMethod.delete =>
Text("${item.uri}"),
RequestMethod.newHttpClient => Text("newHttpClient"),
RequestMethod.newHttpIOClient => Text("newHttpIOClient"),
RequestMethod.newProxySocket => Text("newProxySocket"),
@@ -115,35 +117,26 @@ class DevRequestDetails extends BasePage {
children: [
_sectionTitle("Time"),
SelectableText(req.time.toString()),
_sectionTitle("Method"),
SelectableText(req.method.toString()),
_sectionTitle("URI"),
SelectableText(req.uri?.toString() ?? "null"),
_sectionTitle("Network"),
SelectableText(req.network.toString()),
if (req.network == RequestNetwork.tor)
...[
_sectionTitle("Tor socks server"),
SelectableText(CakeTor.instance.runtimeType.toString()),
_sectionTitle("Tor socks details"),
SelectableText(CakeTor.instance.toString()),
],
if (req.network == RequestNetwork.tor) ...[
_sectionTitle("Tor socks server"),
SelectableText(CakeTor.instance.runtimeType.toString()),
_sectionTitle("Tor socks details"),
SelectableText(CakeTor.instance.toString()),
],
_sectionTitle("Body (as UTF-8)"),
SelectableText(_tryDecodeBody(req.body)),
_buildJsonExplorer(context, _tryDecodeBody(req.body)),
_sectionTitle("Response"),
SelectableText(req.response?.body ?? "null"),
_buildJsonExplorer(context, req.response?.body ?? "{}"),
_sectionTitle("Error"),
SelectableText(req.error ?? "No error"),
_sectionTitle("Stack Trace"),
SelectableText(req.trace.toString()),
],
@@ -152,22 +145,21 @@ class DevRequestDetails extends BasePage {
Widget _buildJsonExplorer(BuildContext context, String body) {
try {
final jsonData = json.decode(body);
return PrimaryButton(
text: "View JSON",
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return JsonExplorerPage(data: jsonData, title: "body");
},
),
);
},
);
final jsonData = json.decode(body);
return PrimaryButton(
text: "View JSON",
color: Colors.blue,
textColor: Colors.white,
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return JsonExplorerPage(data: jsonData, title: "body");
},
),
);
},
);
} catch (e) {
return SelectableText("Invalid JSON: $e");
}
+8 -9
View File
@@ -19,21 +19,20 @@ class DevQRToolsPage extends BasePage {
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: textCtrl,
maxLines: 8,
onChanged: (value) {
viewModel.input = value;
}
),
controller: textCtrl,
maxLines: 8,
onChanged: (value) {
viewModel.input = value;
}),
Observer(
builder: (_) {
return Expanded(
child: JsonExplorer(data: viewModel.data, title: "result"),
);
child: JsonExplorer(data: viewModel.data, title: "result"),
);
},
),
],
),
);
}
}
}
@@ -38,10 +38,14 @@ class DevSecurePreferencesPage extends BasePage {
Clipboard.setData(ClipboardData(text: key + ": " + values[key].toString()));
},
title: switch (type) {
PreferenceType.bool => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
PreferenceType.int => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
PreferenceType.double => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
PreferenceType.listString => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
PreferenceType.bool => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
PreferenceType.int => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
PreferenceType.double => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
PreferenceType.listString => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
PreferenceType.string => Text(key),
PreferenceType.unknown => Text(key),
},
@@ -49,9 +53,12 @@ class DevSecurePreferencesPage extends BasePage {
PreferenceType.bool => Text("bool: ${values[key]}"),
PreferenceType.int => Text("int: ${values[key]}"),
PreferenceType.double => Text("double: ${values[key]}"),
PreferenceType.listString => values[key].isEmpty as bool ? Text("listString: []") : Text("listString:\n- ${values[key].join("\n- ")}"),
PreferenceType.listString => values[key].isEmpty as bool
? Text("listString: []")
: Text("listString:\n- ${values[key].join("\n- ")}"),
PreferenceType.string => Text("string: ${values[key]}"),
PreferenceType.unknown => Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
PreferenceType.unknown =>
Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
},
);
},
@@ -59,5 +66,4 @@ class DevSecurePreferencesPage extends BasePage {
},
);
}
}
}
@@ -50,10 +50,14 @@ class DevSharedPreferencesPage extends BasePage {
_showEditDialog(context, key, type, values[key]);
},
title: switch (type) {
PreferenceType.bool => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
PreferenceType.int => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
PreferenceType.double => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
PreferenceType.listString => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
PreferenceType.bool => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
PreferenceType.int => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
PreferenceType.double => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
PreferenceType.listString => Text(key,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
PreferenceType.string => Text(key),
PreferenceType.unknown => Text(key),
},
@@ -61,9 +65,12 @@ class DevSharedPreferencesPage extends BasePage {
PreferenceType.bool => Text("bool: ${values[key]}"),
PreferenceType.int => Text("int: ${values[key]}"),
PreferenceType.double => Text("double: ${values[key]}"),
PreferenceType.listString => values[key].isEmpty as bool ? Text("listString: []") : Text("listString:\n- ${values[key].join("\n- ")}"),
PreferenceType.listString => values[key].isEmpty as bool
? Text("listString: []")
: Text("listString:\n- ${values[key].join("\n- ")}"),
PreferenceType.string => Text("string: ${values[key]}"),
PreferenceType.unknown => Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
PreferenceType.unknown =>
Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
},
);
},
@@ -72,12 +79,14 @@ class DevSharedPreferencesPage extends BasePage {
);
}
void _showEditDialog(BuildContext context, String key, PreferenceType type, dynamic currentValue) {
void _showEditDialog(
BuildContext context, String key, PreferenceType type, dynamic currentValue) {
dynamic newValue = currentValue;
bool isListString = type == PreferenceType.listString;
List<String> listItems = isListString ? List<String>.from(currentValue as Iterable<dynamic>) : [];
TextEditingController textController = TextEditingController(
text: isListString ? '' : currentValue?.toString() ?? '');
List<String> listItems =
isListString ? List<String>.from(currentValue as Iterable<dynamic>) : [];
TextEditingController textController =
TextEditingController(text: isListString ? '' : currentValue?.toString() ?? '');
showDialog(
context: context,
@@ -91,10 +100,10 @@ class DevSharedPreferencesPage extends BasePage {
height: double.maxFinite,
child: SingleChildScrollView(
child: _buildDialogContent(
type,
newValue,
listItems,
textController,
type,
newValue,
listItems,
textController,
(value) => setState(() => newValue = value),
(items) => setState(() => listItems = items),
),
@@ -116,12 +125,7 @@ class DevSharedPreferencesPage extends BasePage {
child: Text('Save'),
onPressed: () async {
if (_validateAndUpdateValue(
context,
type,
textController,
listItems,
(value) => newValue = value
)) {
context, type, textController, listItems, (value) => newValue = value)) {
await viewModel.set(key, type, newValue);
Navigator.of(context).pop();
}
@@ -210,9 +214,8 @@ class DevSharedPreferencesPage extends BasePage {
BaseTextFormField(
controller: controller,
hintText: label,
keyboardType: isInteger
? TextInputType.number
: TextInputType.numberWithOptions(decimal: true),
keyboardType:
isInteger ? TextInputType.number : TextInputType.numberWithOptions(decimal: true),
inputFormatters: isInteger
? [FilteringTextInputFormatter.digitsOnly]
: [FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$'))],
@@ -222,7 +225,7 @@ class DevSharedPreferencesPage extends BasePage {
}
Widget _buildListEditor(
List<String> items,
List<String> items,
TextEditingController controller,
Function(List<String>) onListChanged,
) {
@@ -358,7 +361,8 @@ class DevSharedPreferencesPage extends BasePage {
DropdownMenuItem(value: PreferenceType.bool, child: Text('Boolean')),
DropdownMenuItem(value: PreferenceType.int, child: Text('Integer')),
DropdownMenuItem(value: PreferenceType.double, child: Text('Double')),
DropdownMenuItem(value: PreferenceType.listString, child: Text('List of Strings')),
DropdownMenuItem(
value: PreferenceType.listString, child: Text('List of Strings')),
],
onChanged: (value) {
if (value != null) {
@@ -384,14 +388,17 @@ class DevSharedPreferencesPage extends BasePage {
return;
}
viewModel.set(keyController.text, selectedType, switch (selectedType) {
PreferenceType.bool => false,
PreferenceType.int => 0,
PreferenceType.double => 0.0,
PreferenceType.string => '',
PreferenceType.listString => [],
PreferenceType.unknown => null,
});
viewModel.set(
keyController.text,
selectedType,
switch (selectedType) {
PreferenceType.bool => false,
PreferenceType.int => 0,
PreferenceType.double => 0.0,
PreferenceType.string => '',
PreferenceType.listString => [],
PreferenceType.unknown => null,
});
Navigator.of(context).pop();
},
),
@@ -147,7 +147,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
EdgeInsets.only(left: 24.0, top: 10.0, right: 24.0, bottom: 10.0),
child: InkWell(
key: ValueKey('disclaimer_check_key'),
onTap: () => setState(() =>_checked = !_checked),
onTap: () => setState(() => _checked = !_checked),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
+7 -3
View File
@@ -40,7 +40,8 @@ import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
class ExchangePage extends BasePage {
ExchangePage(this.exchangeViewModel, this.authService, this.adrResService, this.initialPaymentRequest) {
ExchangePage(
this.exchangeViewModel, this.authService, this.adrResService, this.initialPaymentRequest) {
depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr
? exchangeViewModel.wallet.name
: null;
@@ -655,8 +656,11 @@ class ExchangePage extends BasePage {
Future<String> fetchParsedAddress(
BuildContext context, String domain, CryptoCurrency currency) async {
final parsedAddresses = await adrResService.resolve(query: domain, wallet:exchangeViewModel.wallet, currency: currency);
return parsedAddresses.isNotEmpty ? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? '' : '';
final parsedAddresses = await adrResService.resolve(
query: domain, wallet: exchangeViewModel.wallet, currency: currency);
return parsedAddresses.isNotEmpty
? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? ''
: '';
}
void _showFeeAlert(BuildContext context) async {
@@ -39,7 +39,7 @@ class CurrencyPickerWidget extends StatelessWidget {
pickListItem(index);
},
title: pickerItemsList[index].name,
iconPath: pickerItemsList[index].iconPath,
iconPath: pickerItemsList[index].iconPath,
tag: pickerItemsList[index].tag,
);
}),
@@ -86,7 +86,7 @@ class _BuySellOptionButtonsState extends State<BuySellOptionButtons> {
Expanded(
flex: 5,
child: SelectButton(
center:true,
center: true,
height: 44,
text: S.of(context).buy,
isSelected: isBuySelected,
@@ -108,7 +108,7 @@ class _BuySellOptionButtonsState extends State<BuySellOptionButtons> {
Expanded(
flex: 5,
child: SelectButton(
center:true,
center: true,
height: 44,
text: S.of(context).sell,
isSelected: !isBuySelected,
@@ -1,9 +1,6 @@
class PickerItem<T> {
PickerItem(this.original,
{required this.title,
required this.iconPath,
required this.tag,
required this.description});
{required this.title, required this.iconPath, required this.tag, required this.description});
final String title;
final String iconPath;
@@ -72,7 +72,8 @@ class ExchangeTradeExternalSendPage extends BasePage {
context,
Routes.fullscreenQR,
arguments: QrViewData(
embeddedImagePath: exchangeTradeViewModel.trade.from?.iconPath,
embeddedImagePath:
exchangeTradeViewModel.trade.from?.iconPath,
data: exchangeTradeViewModel.paymentUri?.toString() ??
exchangeTradeViewModel.trade.inputAddress ??
fetchingLabel,
@@ -96,7 +97,8 @@ class ExchangeTradeExternalSendPage extends BasePage {
data: exchangeTradeViewModel.paymentUri?.toString() ??
exchangeTradeViewModel.trade.inputAddress ??
fetchingLabel,
embeddedImagePath: exchangeTradeViewModel.trade.from?.iconPath,
embeddedImagePath:
exchangeTradeViewModel.trade.from?.iconPath,
size: 230,
),
),
@@ -12,4 +12,4 @@ class ExchangeTradeItem {
bool isCopied;
bool isReceiveDetail;
bool isExternalSendDetail;
}
}
@@ -177,7 +177,6 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
? Theme.of(context).colorScheme.onSecondaryContainer
: Theme.of(context).colorScheme.onPrimary,
),
SizedBox(height: 16),
Observer(
builder: (_) {
@@ -297,12 +296,17 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
final isSwapsXyz = trade.provider == ExchangeProviderDescription.swapsXyz;
final isEVMWallet = widget.exchangeTradeViewModel.sendViewModel.isEVMWallet;
final amountValue = isSwapsXyz && isEVMWallet && !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
final amountValue = isSwapsXyz &&
isEVMWallet &&
!widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
? trade.amount
: widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.amountFormatted;
final fiatAmountValue = isSwapsXyz && isEVMWallet && !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
? widget.exchangeTradeViewModel.sendViewModel.calculateTransactionFiatAmount(amountValue)
final fiatAmountValue = isSwapsXyz &&
isEVMWallet &&
!widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
? widget.exchangeTradeViewModel.sendViewModel
.calculateTransactionFiatAmount(amountValue)
: widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFiatAmountFormatted;
if (context.mounted) {
@@ -328,12 +332,13 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
fee: isEVMCompatibleChain(sendVM.walletType)
? S.of(bottomSheetContext).send_estimated_fee
: S.of(bottomSheetContext).send_fee,
feeValue: sendVM.amountParsingProxy.asDisplayStringWithSymbol(
sendVM.pendingTransaction!.fee),
feeValue: sendVM.amountParsingProxy
.asDisplayStringWithSymbol(sendVM.pendingTransaction!.fee),
feeFiatAmount: sendVM.pendingTransactionFeeFiatAmountFormatted,
outputs: sendVM.outputs,
onSlideActionComplete: () async {
if (bottomSheetContext.mounted && Navigator.canPop(bottomSheetContext)) Navigator.of(bottomSheetContext).pop(true);
if (bottomSheetContext.mounted && Navigator.canPop(bottomSheetContext))
Navigator.of(bottomSheetContext).pop(true);
sendVM.commitTransaction(context);
},
@@ -59,9 +59,9 @@ class TimerWidgetState extends State<TimerWidget> {
? Text(
S.of(context).expired,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.errorContainer,
),
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.errorContainer,
),
)
: Text(
S.of(context).time(_minutes.toString(), _seconds.toString()),
@@ -149,7 +149,7 @@ class DEuroSavingsPage extends BasePage {
await _requireHardwareWallet(context);
_dEuroViewModel.prepareSavingsEdit(amount, false);
}
_editSheetIsOpen = false;
_editSheetIsOpen = false;
}
Future<void> _onReinvestInterest(BuildContext context) async {
@@ -425,9 +425,7 @@ class DEuroSavingsPage extends BasePage {
balanceTitle: isAdding
? S.of(context).deuro_savings_available_to_add
: S.of(context).deuro_savings_available_to_remove,
balance: isAdding
? _dEuroViewModel.accountBalance
: _dEuroViewModel.savingsBalance,
balance: isAdding ? _dEuroViewModel.accountBalance : _dEuroViewModel.savingsBalance,
footerType: FooterType.none,
maxHeight: MediaQuery.of(context).size.height * 0.8,
),
@@ -25,8 +25,7 @@ class NumberPad extends StatelessWidget {
return onDeletePressed();
}
if ([".", ","].contains(keyEvent.logicalKey.keyLabel) &&
onDecimalPressed != null) {
if ([".", ","].contains(keyEvent.logicalKey.keyLabel) && onDecimalPressed != null) {
return onDecimalPressed!();
}
@@ -50,10 +49,10 @@ class NumberPad extends StatelessWidget {
child: Text(
'.',
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.w600,
fontSize: 30,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
fontWeight: FontWeight.w600,
fontSize: 30,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
),
@@ -70,8 +69,7 @@ class NumberPad extends StatelessWidget {
child: TextButton(
onPressed: onDeletePressed,
style: TextButton.styleFrom(
backgroundColor:
Colors.transparent,
backgroundColor: Colors.transparent,
shape: CircleBorder(),
),
child: Image.asset(
@@ -64,7 +64,7 @@ class AccountTile extends StatelessWidget {
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurfaceVariant,
decoration: TextDecoration.none,
),
),
),
),
],
@@ -18,7 +18,7 @@ class WalletGroupDescriptionPage extends BasePage {
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
String get title => S.current.wallet_list_create_new_wallet;
@@ -14,7 +14,7 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
String get title => S.current.wallet_group;
@@ -34,9 +34,10 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
child: Column(
children: [
CakeImageWidget(
imageUrl: currentTheme.isDark ? walletGroupConfirmedImageDark : walletGroupConfirmedImageLight,
height: 200
),
imageUrl: currentTheme.isDark
? walletGroupConfirmedImageDark
: walletGroupConfirmedImageLight,
height: 200),
SizedBox(height: 32),
Expanded(
child: SingleChildScrollView(
@@ -55,10 +56,10 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
TextSpan(
text: S.current.seed_display_path,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 16,
fontWeight: FontWeight.w800,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
fontSize: 16,
fontWeight: FontWeight.w800,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
],
),
@@ -17,7 +17,8 @@ class SelectButton extends StatelessWidget {
this.deviceConnectionTypes,
this.borderRadius,
this.padding,
super.key, this.center = false,
super.key,
this.center = false,
});
final Widget? image;
@@ -38,7 +39,10 @@ class SelectButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
final backgroundColor = color ?? (isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.surfaceContainer);
final backgroundColor = color ??
(isSelected
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.surfaceContainer);
final effectiveTextColor = textColor ??
(isSelected
? Theme.of(context).colorScheme.onPrimary
@@ -81,24 +85,24 @@ class SelectButton extends StatelessWidget {
mainAxisAlignment: center ? MainAxisAlignment.center : MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
if(!center) SizedBox(width:16),
if (!center) SizedBox(width: 16),
image ?? Offstage(),
Padding(
padding: image != null ? EdgeInsets.only(left: 14) : EdgeInsets.only(left: 0),
child: Text(
text,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: textSize,
fontWeight: FontWeight.w500,
color: effectiveTextColor,
),
fontSize: textSize,
fontWeight: FontWeight.w500,
color: effectiveTextColor,
),
),
)
],
),
),
...trailingIcons,
if(!center) SizedBox(width:16),
if (!center) SizedBox(width: 16),
],
),
),
@@ -37,16 +37,15 @@ class NodeCreateOrEditPage extends StatefulWidget {
class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
final _nodeFormKey = GlobalKey<NodeFormState>();
@override
void initState() {
super.initState();
reaction(
(_) => widget.nodeCreateOrEditViewModel.connectionState,
(ExecutionState state) {
(_) => widget.nodeCreateOrEditViewModel.connectionState,
(ExecutionState state) {
if (state is ExecutedSuccessfullyState) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => showPopUp<void>(
(_) => showPopUp<void>(
context: context,
builder: (context) => AlertWithOneAction(
alertTitle: S.of(context).new_node_testing,
@@ -62,7 +61,7 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => showPopUp<void>(
(_) => showPopUp<void>(
context: context,
builder: (context) => AlertWithOneAction(
alertTitle: S.of(context).error,
@@ -76,19 +75,16 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
},
);
reaction((_)=>widget.nodeCreateOrEditViewModel.state, (state) async {
if(state is ExecutedSuccessfullyState) {
reaction((_) => widget.nodeCreateOrEditViewModel.state, (state) async {
if (state is ExecutedSuccessfullyState) {
await Future.delayed(Duration(milliseconds: 100));
if (mounted) Navigator.of(context).pop(widget.nodeCreateOrEditViewModel.editingNode);
}
});
}
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).colorScheme.surface,
child: SafeArea(
@@ -112,49 +108,57 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
child: KeyboardHideOverlay(
child: Container(
padding: const EdgeInsets.only(left: 18, right: 18),
child: Column(
spacing: 18,
children: [NodeForm(
child: Column(spacing: 18, children: [
NodeForm(
key: _nodeFormKey,
nodeViewModel: widget.nodeCreateOrEditViewModel,
),
NewListSections(sections: {"":[
if(widget.editingNode != null)
NewListSections(sections: {
"": [
if (widget.editingNode != null)
ListItemRegularRow(
keyValue: "share",
label: S.of(context).share_this_node,
foregroundColor: Theme.of(context).colorScheme.primary,
showArrow: false,
onTap: () {
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => NodeSharePage(
uri: widget.editingNode!.uri,
currency: walletTypeToCryptoCurrency(widget.type!))));
}),
if (!(widget.editingNode == null ||
!widget.nodeCreateOrEditViewModel.isReady ||
widget.editingNode!.isBuiltin ||
(widget.isSelected ?? false)))
ListItemRegularRow(
keyValue: "delete",
label: S.of(context).delete_this_node,
foregroundColor: Theme.of(context).colorScheme.errorContainer,
showArrow: false,
onTap: () async {
final confirmed = await showPopUp<bool>(
context: context,
builder: (context) => AlertWithTwoActions(
alertTitle: S.of(context).remove_node,
alertContent: S.of(context).remove_node_message,
rightButtonText: S.of(context).remove,
leftButtonText: S.of(context).cancel,
actionRightButton: () => Navigator.pop(context, true),
actionLeftButton: () => Navigator.pop(context, false),
),
) ??
false;
ListItemRegularRow(keyValue: "share", label: S.of(context).share_this_node, foregroundColor: Theme.of(context).colorScheme.primary, showArrow: false, onTap: (){
Navigator.of(context).push(CupertinoPageRoute(builder: (context)=>NodeSharePage(uri: widget.editingNode!.uri, currency: walletTypeToCryptoCurrency(widget.type!))));
}),
if(!(widget.editingNode == null ||
!widget.nodeCreateOrEditViewModel.isReady ||
widget.editingNode!.isBuiltin ||
(widget.isSelected ?? false)))
ListItemRegularRow(keyValue: "delete", label: S.of(context).delete_this_node, foregroundColor: Theme.of(context).colorScheme.errorContainer, showArrow: false, onTap: ()async{
final confirmed = await showPopUp<bool>(
context: context,
builder: (context) => AlertWithTwoActions(
alertTitle: S.of(context).remove_node,
alertContent: S.of(context).remove_node_message,
rightButtonText: S.of(context).remove,
leftButtonText: S.of(context).cancel,
actionRightButton: () => Navigator.pop(context, true),
actionLeftButton: () => Navigator.pop(context, false),
),
) ??
false;
if (confirmed) {
await widget.nodeCreateOrEditViewModel.delete(editingNode: widget.editingNode!);
Navigator.of(context).pop();
}
})
]})
]
),
if (confirmed) {
await widget.nodeCreateOrEditViewModel
.delete(editingNode: widget.editingNode!);
Navigator.of(context).pop();
}
})
]
})
]),
),
),
),
@@ -18,11 +18,7 @@ import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
class PowNodeCreateOrEditPage extends StatefulWidget {
PowNodeCreateOrEditPage(
{required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected})
;
{required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected});
final NodeCreateOrEditViewModel nodeCreateOrEditViewModel;
final Node? editingNode;
@@ -35,7 +31,6 @@ class PowNodeCreateOrEditPage extends StatefulWidget {
class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
final _formKey = GlobalKey<NodeFormState>();
@override
void initState() {
super.initState();
@@ -72,7 +67,6 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).colorScheme.surface,
child: KeyboardHideOverlay(
@@ -82,11 +76,15 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
title: widget.editingNode != null ? S.current.edit_node : S.current.node_new,
leadingIcon: Icon(Icons.arrow_back_ios_new),
onLeadingPressed: Navigator.of(context).pop,
trailingIcon: CakeImageWidget(imageUrl:
"assets/new-ui/scan.svg",width:24,height:24,
colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
trailingIcon: CakeImageWidget(
imageUrl: "assets/new-ui/scan.svg",
width: 24,
height: 24,
colorFilter:
ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
),
onTrailingPressed: () => widget.nodeCreateOrEditViewModel.scanQRCodeForNewNode(context),
onTrailingPressed: () =>
widget.nodeCreateOrEditViewModel.scanQRCodeForNewNode(context),
),
Expanded(
child: Container(
@@ -112,21 +110,25 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).remove_node,
alertContent: S.of(context).remove_node_message,
alertContent:
S.of(context).remove_node_message,
rightButtonText: S.of(context).remove,
leftButtonText: S.of(context).cancel,
actionRightButton: () => Navigator.pop(context, true),
actionLeftButton: () => Navigator.pop(context, false));
actionRightButton: () =>
Navigator.pop(context, true),
actionLeftButton: () =>
Navigator.pop(context, false));
}) ??
false;
if (confirmed) {
await widget.editingNode!.delete();
Navigator.of(context).pop();
}
},
text: S.of(context).delete,
isDisabled: !widget.nodeCreateOrEditViewModel.isReady || (widget.isSelected ?? false),
isDisabled: !widget.nodeCreateOrEditViewModel.isReady ||
(widget.isSelected ?? false),
color: Theme.of(context).colorScheme.errorContainer,
textColor: Theme.of(context).colorScheme.onPrimary,
),
@@ -141,16 +143,17 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
!_formKey.currentState!.validate()) {
return;
}
await widget.nodeCreateOrEditViewModel.save(
saveAsCurrent: widget.isSelected ?? false);
await widget.nodeCreateOrEditViewModel
.save(saveAsCurrent: widget.isSelected ?? false);
Navigator.of(context).pop();
},
text: S.of(context).save,
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
isDisabled: (!widget.nodeCreateOrEditViewModel.isReady) ||
(widget.nodeCreateOrEditViewModel.connectionState is IsExecutingState),
(widget.nodeCreateOrEditViewModel.connectionState
is IsExecutingState),
),
)),
],
+93 -96
View File
@@ -34,7 +34,7 @@ class NodeFormState extends State<NodeForm> {
void initState() {
super.initState();
for(final key in vm.textFieldKeys) {
for (final key in vm.textFieldKeys) {
_controllers[key] = TextEditingController();
_controllers[key]!.text = vm.getTextValue(key);
@@ -61,114 +61,112 @@ class NodeFormState extends State<NodeForm> {
@override
Widget build(BuildContext context) {
return Observer(
builder: (_)=>Form(
builder: (_) => Form(
key: _formKey,
child: NewListSections(
sections: {
if(!(vm.editingNode?.isBuiltin ?? false)) ...{
'main': [
ListItemTextField(
keyValue: vm.nodeLabelUIKey,
label: 'Node label',
initialValue: vm.label,
),
ListItemTextField(
keyValue: vm.nodeAddressUIKey,
label: S.current.node_address,
initialValue: vm.address,
validator: vm.walletType == WalletType.decred
? NodeAddressValidatorDecredBlankException()
: NodeAddressValidator(),
),
if (vm.hasPathSupport)
sections: {
if (!(vm.editingNode?.isBuiltin ?? false)) ...{
'main': [
ListItemTextField(
keyValue: vm.nodePathUIKey,
label: '/path',
initialValue: vm.path,
validator: NodePathValidator(),
),
ListItemTextField(
keyValue: vm.nodePortUIKey,
label: S.current.node_port,
initialValue: '',
//keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
validator: NodePortValidator(),
),
if (vm.hasAuthCredentials) ...[
ListItemTextField(
keyValue: vm.nodeUsernameUIKey,
label: S.current.login,
initialValue: vm.login,
keyValue: vm.nodeLabelUIKey,
label: 'Node label',
initialValue: vm.label,
),
ListItemTextField(
keyValue: vm.nodePasswordUIKey,
label: S.current.password,
initialValue: vm.password,
keyValue: vm.nodeAddressUIKey,
label: S.current.node_address,
initialValue: vm.address,
validator: vm.walletType == WalletType.decred
? NodeAddressValidatorDecredBlankException()
: NodeAddressValidator(),
),
]
],
'advanced': [
ListItemCheckbox(
keyValue: vm.useSSLUIKey,
label: S.current.use_ssl,
value: vm.useSSL,
onChanged: (value) => vm.useSSL = value),
ListItemCheckbox(
keyValue: vm.nodeTrustedUIKey,
label: S.current.trusted,
value: vm.trusted,
onChanged: (value) => vm.trusted = value,
),
if (vm.usesEmbeddedProxy)
if (vm.hasPathSupport)
ListItemTextField(
keyValue: vm.nodePathUIKey,
label: '/path',
initialValue: vm.path,
validator: NodePathValidator(),
),
ListItemTextField(
keyValue: vm.nodePortUIKey,
label: S.current.node_port,
initialValue: '',
//keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
validator: NodePortValidator(),
),
if (vm.hasAuthCredentials) ...[
ListItemTextField(
keyValue: vm.nodeUsernameUIKey,
label: S.current.login,
initialValue: vm.login,
),
ListItemTextField(
keyValue: vm.nodePasswordUIKey,
label: S.current.password,
initialValue: vm.password,
),
]
],
'advanced': [
ListItemCheckbox(
keyValue: vm.nodeEmbeddedTorProxyUIKey,
label: 'Embedded Tor SOCKS Proxy',
value: vm.usesEmbeddedProxy,
onChanged: (_) {},
),
if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
keyValue: vm.useSSLUIKey,
label: S.current.use_ssl,
value: vm.useSSL,
onChanged: (value) => vm.useSSL = value),
ListItemCheckbox(
keyValue: vm.autoSwitchingUIKey,
label: S.current.enable_for_auto_switching,
value: vm.isEnabledForAutoSwitching,
onChanged: (value) => vm.isEnabledForAutoSwitching = value),
],
keyValue: vm.nodeTrustedUIKey,
label: S.current.trusted,
value: vm.trusted,
onChanged: (value) => vm.trusted = value,
),
if (vm.usesEmbeddedProxy)
ListItemCheckbox(
keyValue: vm.nodeEmbeddedTorProxyUIKey,
label: 'Embedded Tor SOCKS Proxy',
value: vm.usesEmbeddedProxy,
onChanged: (_) {},
),
if (FeatureFlag.isAutomaticNodeSwitchingEnabled)
ListItemCheckbox(
keyValue: vm.autoSwitchingUIKey,
label: S.current.enable_for_auto_switching,
value: vm.isEnabledForAutoSwitching,
onChanged: (value) => vm.isEnabledForAutoSwitching = value),
],
},
"proxy": [
ListItemCheckbox(
keyValue: vm.useSocksProxyUIKey,
label: 'Use SOCKS Proxy',
value: vm.useSocksProxy,
onChanged: (value) {
vm.socksProxyAddress = '';
vm.useSocksProxy = value;
},
),
if (vm.useSocksProxy)
ListItemTextField(
keyValue: vm.socksProxyAddressUIKey,
label: 'host:port',
initialValue: vm.socksProxyAddress,
validator: SocksProxyNodeAddressValidator(),
),
]
},
"proxy" : [
ListItemCheckbox(
keyValue: vm.useSocksProxyUIKey,
label: 'Use SOCKS Proxy',
value: vm.useSocksProxy,
onChanged: (value) {
vm.socksProxyAddress = '';
vm.useSocksProxy = value;
},
),
if (vm.useSocksProxy)
ListItemTextField(
keyValue: vm.socksProxyAddressUIKey,
label: 'host:port',
initialValue: vm.socksProxyAddress,
validator: SocksProxyNodeAddressValidator(),
),
]
},
controllers: _controllers,
getCheckboxValue: vm.getCheckboxValue,
updateCheckboxValue: vm.updateCheckboxValue,
tapHandlers: tapHandlers
),
controllers: _controllers,
getCheckboxValue: vm.getCheckboxValue,
updateCheckboxValue: vm.updateCheckboxValue,
tapHandlers: tapHandlers),
),
);
}
Map<String, VoidCallback> get tapHandlers => {
'node_regular_with_drill_in_row_key': () => _showToast('Regular with drill-in row tapped'),
'node_tall_row_key': () => _showToast('Tall row tapped'),
'node_regular_with_trailing_row_key': () => _showToast('Regular with trailing row tapped'),
'node_item_selector_row_key': () => _showToast('Item selector row tapped'),
};
'node_regular_with_drill_in_row_key': () => _showToast('Regular with drill-in row tapped'),
'node_tall_row_key': () => _showToast('Tall row tapped'),
'node_regular_with_trailing_row_key': () => _showToast('Regular with trailing row tapped'),
'node_item_selector_row_key': () => _showToast('Item selector row tapped'),
};
void _showToast(String msg) async {
try {
@@ -179,7 +177,6 @@ class NodeFormState extends State<NodeForm> {
} catch (_) {}
}
void _setupReactions() {
_bindController(() => vm.label, vm.nodeLabelUIKey);
_bindController(() => vm.address, vm.nodeAddressUIKey);
@@ -8,7 +8,7 @@ class NodeListRow extends StatelessWidget {
NodeListRow(
{required this.node,
required this.onTap,
required this.onEditComplete,
required this.onEditComplete,
required this.isSelected,
required this.isPow,
this.speed,
@@ -42,20 +42,36 @@ class NodeListRow extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
leading,
Expanded(
child: Column(crossAxisAlignment:CrossAxisAlignment.start,spacing:4,children: [
Row(
spacing: 4,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(hasLabel ? node.label! : uriText, style: TextStyle(fontSize: 12),),
if(badgePath != null)
CakeImageWidget(imageUrl: badgePath, colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary,BlendMode.srcIn),)
],
),
if(hasLabel) Text(uriText, style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),),
],),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 4,
children: [
Row(
spacing: 4,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
hasLabel ? node.label! : uriText,
style: TextStyle(fontSize: 12),
),
if (badgePath != null)
CakeImageWidget(
imageUrl: badgePath,
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.primary, BlendMode.srcIn),
)
],
),
if (hasLabel)
Text(
uriText,
style: TextStyle(
fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
),
],
),
),
trailing,
],
),
@@ -89,7 +105,8 @@ class NodeListRow extends StatelessWidget {
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () async {
final res = await Navigator.of(context).pushNamed(isPow ? Routes.newPowNode : Routes.newNode,
final res = await Navigator.of(context).pushNamed(
isPow ? Routes.newPowNode : Routes.newNode,
arguments: {'editingNode': node, 'isSelected': isSelected});
await onEditComplete(res);
},
@@ -107,8 +124,8 @@ class NodeListRow extends StatelessWidget {
}
String? get badgePath {
if(node.isOfficial) return "assets/new-ui/official_node.svg";
if(node.isBuiltin) return "assets/new-ui/default_node.svg";
if (node.isOfficial) return "assets/new-ui/official_node.svg";
if (node.isBuiltin) return "assets/new-ui/default_node.svg";
return null;
}
}
+2 -6
View File
@@ -2,12 +2,8 @@ import 'package:flutter/foundation.dart';
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
class PinCode extends PinCodeWidget {
PinCode(
void Function(String pin, PinCodeState state) onFullPin,
void Function(String pin) onChangedPin,
int initialPinLength,
bool hasLengthSwitcher,
Key key)
PinCode(void Function(String pin, PinCodeState state) onFullPin,
void Function(String pin) onChangedPin, int initialPinLength, bool hasLengthSwitcher, Key key)
: super(
key: key,
onFullPin: onFullPin,
@@ -231,7 +231,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
child: TextButton(
onPressed: () => {_pop(), HapticFeedback.mediumImpact()},
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
backgroundColor:
Theme.of(context).colorScheme.surfaceContainer,
shape: CircleBorder(),
),
child: deleteIconImage,
@@ -249,7 +250,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
key: ValueKey('pin_code_button_${index}_key'),
onPressed: () => {_push(index), HapticFeedback.mediumImpact()},
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
backgroundColor:
Theme.of(context).colorScheme.surfaceContainer,
shape: CircleBorder(),
),
child: Text('$index',
@@ -28,9 +28,9 @@ class AnonInvoiceStatusSection extends StatelessWidget {
Text(
S.current.status,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
@@ -50,9 +50,9 @@ class AnonInvoiceStatusSection extends StatelessWidget {
Text(
invoiceInfo.status,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSecondaryContainer,
),
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSecondaryContainer,
),
),
],
),
@@ -66,16 +66,16 @@ class AnonInvoiceStatusSection extends StatelessWidget {
Text(
'ID',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
Text(
invoiceInfo.invoiceId,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurface,
),
),
],
),
@@ -20,8 +20,8 @@ class CopyLinkItem extends StatelessWidget {
Text(
title,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
color: Theme.of(context).colorScheme.onSurface,
),
),
SizedBox(width: 50),
Row(
@@ -47,12 +47,11 @@ class ReleaseNotesScreen extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: DefaultTextStyle(
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
decoration: TextDecoration.none,
fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.onSurface,
),
decoration: TextDecoration.none,
fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.onSurface,
),
child: Text(title),
),
),
@@ -115,11 +114,10 @@ class ReleaseNotesScreen extends StatelessWidget {
children: [
DefaultTextStyle(
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
decoration: TextDecoration.none,
fontSize: 16.0,
color: Theme.of(context).colorScheme.onSurface,
),
decoration: TextDecoration.none,
fontSize: 16.0,
color: Theme.of(context).colorScheme.onSurface,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
-1
View File
@@ -25,7 +25,6 @@ class RescanPage extends StatefulWidget {
class _RescanPageState extends State<RescanPage> {
final TextEditingController _heightController = TextEditingController();
@override
Widget build(BuildContext context) {
Widget child;
@@ -207,14 +207,14 @@ class RestoreFromBackupPage extends BasePage {
}
} catch (e) {
await showPopUp<void>(
context: context,
builder: (_) {
return AlertWithOneAction(
alertTitle: S.current.error,
alertContent: e.toString(),
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
context: context,
builder: (_) {
return AlertWithOneAction(
alertTitle: S.current.error,
alertContent: e.toString(),
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
}
textEditingController.text = '';
}
@@ -23,9 +23,9 @@ class RestoreOptionsPage extends BasePage {
@override
Widget body(BuildContext context) => _RestoreOptionsBody(
isNewInstall: isNewInstall,
themeType: currentTheme.type,
);
isNewInstall: isNewInstall,
themeType: currentTheme.type,
);
}
class _RestoreOptionsBody extends StatefulWidget {
@@ -157,7 +157,7 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
Future<void> _onScanQRCode(BuildContext context) async {
final isCameraPermissionGranted =
await PermissionHandler.checkPermission(Permission.camera, context);
await PermissionHandler.checkPermission(Permission.camera, context);
if (!isCameraPermissionGranted) return;
try {
@@ -180,4 +180,4 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
_showQRScanError(context, e.toString());
}
}
}
}
@@ -11,9 +11,10 @@ class WalletRestoreChooseDerivationPage extends BasePage {
@override
Widget middle(BuildContext context) => Text(
S.current.choose_derivation,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary),
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary),
);
final WalletRestoreChooseDerivationViewModel walletRestoreChooseDerivationViewModel;
@@ -232,27 +232,25 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
bool nanoBased = widget.walletRestoreViewModel.type == WalletType.nano ||
widget.walletRestoreViewModel.type == WalletType.banano;
return Column(
children: [
AddressTextField(
addressKey: ValueKey('wallet_restore_from_key_private_key_textfield_key'),
controller: privateKeyController,
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
options: [AddressTextFieldOption.paste],
onPushPasteButton: (_) {
_pasteText();
},
return Column(children: [
AddressTextField(
addressKey: ValueKey('wallet_restore_from_key_private_key_textfield_key'),
controller: privateKeyController,
placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
options: [AddressTextFieldOption.paste],
onPushPasteButton: (_) {
_pasteText();
},
),
if (widget.walletRestoreViewModel.hasBlockchainHeightSelector)
BlockchainHeightWidget(
key: blockchainHeightKey,
hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven,
onHeightChange: (_) => null,
onHeightOrDateEntered: widget.onHeightOrDateEntered,
walletType: widget.walletRestoreViewModel.type,
),
if (widget.walletRestoreViewModel.hasBlockchainHeightSelector)
BlockchainHeightWidget(
key: blockchainHeightKey,
hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven,
onHeightChange: (_) => null,
onHeightOrDateEntered: widget.onHeightOrDateEntered,
walletType: widget.walletRestoreViewModel.type,
),
]
);
]);
}
return Column(
@@ -161,7 +161,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
onPressed: () async {
final rName = await generateName();
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
nameTextEditingController.text = rName;
nameTextEditingController.selection = TextSelection.fromPosition(
@@ -298,8 +298,7 @@ class WalletRestorePage extends BasePage {
"m/49'/0'/0'",
};
final shouldSkipChooseDerivationScreen =
derivationPathsWithHistory.isNotEmpty &&
final shouldSkipChooseDerivationScreen = derivationPathsWithHistory.isNotEmpty &&
derivationPathsWithHistory.every(scanDerivationPaths.contains);
if (derivationsWithHistory > 1 && !shouldSkipChooseDerivationScreen) {
@@ -537,7 +536,7 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
},
onViewKeyEntered: (bool entered) {
if (widget.walletRestoreViewModel.onlyViewKeyRestore ||
walletRestoreViewModel.type == WalletType.litecoin) {
walletRestoreViewModel.type == WalletType.litecoin) {
walletRestoreViewModel.isButtonEnabled = entered;
}
},
-2
View File
@@ -118,7 +118,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
final uri = Uri.parse('cakewallet://quickaction/${widget.initialQuickAction}');
handleDeepLinking(uri);
}
} catch (e) {
printV(e);
}
@@ -136,7 +135,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
bool requireAuth = await widget.authService.requireAuth();
if (widget.authenticationStore.state == AuthenticationState.allowedCreate) {
requireAuth = false;
}
@@ -21,12 +21,12 @@ class SeedVerificationSuccessView extends StatelessWidget {
children: [
ConstrainedBox(
constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3),
child: CakeImageWidget(
height: 128,
imageUrl: currentTheme.isDark
? 'assets/images/seed_verified_dark.png'
: 'assets/images/seed_verified_light.png',
),
child: CakeImageWidget(
height: 128,
imageUrl: currentTheme.isDark
? 'assets/images/seed_verified_dark.png'
: 'assets/images/seed_verified_light.png',
),
),
SizedBox(height: 40),
Text(
@@ -72,7 +72,9 @@ class SeedVerificationSuccessView extends StatelessWidget {
Navigator.of(context).popUntil((route) => route.isFirst);
}
},
text: (walletType == WalletType.bitcoin) ? S.current.continue_text : S.current.open_wallet,
text: (walletType == WalletType.bitcoin)
? S.current.continue_text
: S.current.open_wallet,
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
),
+10 -9
View File
@@ -21,7 +21,8 @@ class WalletSeedPage extends BasePage {
WalletSeedPage(this.walletSeedViewModel, {required this.isNewWalletCreated});
@override
String get title => '${walletTypeToString(walletSeedViewModel.walletType)} ${S.current.seed_title}';
String get title =>
'${walletTypeToString(walletSeedViewModel.walletType)} ${S.current.seed_title}';
final bool isNewWalletCreated;
final WalletSeedViewModel walletSeedViewModel;
@@ -144,14 +145,14 @@ class WalletSeedPage extends BasePage {
}
void _shareSeed(BuildContext context) async {
switch(defaultTargetPlatform) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
ShareUtil.share(
text: walletSeedViewModel.seed,
context: context,
);
break;
ShareUtil.share(
text: walletSeedViewModel.seed,
context: context,
);
break;
case TargetPlatform.macOS:
case TargetPlatform.windows:
case TargetPlatform.linux:
@@ -160,12 +161,12 @@ class WalletSeedPage extends BasePage {
fileName: "${walletSeedViewModel.name}-seed.txt",
lockParentWindow: true,
);
if(path != null) {
if (path != null) {
final file = File(path);
await file.writeAsString(walletSeedViewModel.seed);
}
default:
break;
break;
}
}
}
+338 -329
View File
@@ -67,7 +67,6 @@ class SendPage extends BasePage {
final currentPage = ValueNotifier<int>(0);
bool _effectsInstalled = false;
ContactRecord? newContactAddress;
@@ -176,323 +175,334 @@ class SendPage extends BasePage {
_setEffects(context);
return ValueListenableBuilder(
valueListenable: currentPage,
builder: (context, value, child) {
return Observer(builder: (_) {
List<Widget> sendCards = [];
List<KeyboardActionsItem> keyboardActions = [];
for (final output in sendViewModel.outputs) {
final isCurrent = sendViewModel.outputs.indexOf(output) == value;
sendCards.add(
SendCard(
currentTheme: currentTheme,
key: output.key,
output: output,
sendViewModel: sendViewModel,
paymentViewModel: paymentViewModel,
walletSwitcherViewModel: walletSwitcherViewModel,
initialPaymentRequest: initialPaymentRequest,
cryptoAmountFocus: isCurrent ? _cryptoAmountFocus : null,
fiatAmountFocus: isCurrent ? _fiatAmountFocus : null,
),
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: _cryptoAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: _fiatAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
);
}
return Stack(
children: [
KeyboardActions(
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Theme.of(context).colorScheme.surface,
nextFocus: false,
actions: keyboardActions,
valueListenable: currentPage,
builder: (context, value, child) {
return Observer(builder: (_) {
List<Widget> sendCards = [];
List<KeyboardActionsItem> keyboardActions = [];
for (final output in sendViewModel.outputs) {
final isCurrent = sendViewModel.outputs.indexOf(output) == value;
sendCards.add(
SendCard(
currentTheme: currentTheme,
key: output.key,
output: output,
sendViewModel: sendViewModel,
paymentViewModel: paymentViewModel,
walletSwitcherViewModel: walletSwitcherViewModel,
initialPaymentRequest: initialPaymentRequest,
cryptoAmountFocus: isCurrent ? _cryptoAmountFocus : null,
fiatAmountFocus: isCurrent ? _fiatAmountFocus : null,
),
child: Container(
height: 0,
color: Colors.transparent,
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: _cryptoAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
),
GestureDetector(
onLongPress: () => sendViewModel.balanceViewModel.isReversing =
!sendViewModel.balanceViewModel.isReversing,
onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
!sendViewModel.balanceViewModel.isReversing,
child: RepaintBoundary(
child: Form(
key: _formKey,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: FocusTraversalGroup(
policy: OrderedTraversalPolicy(),
child: Column(
children: <Widget>[
PageViewHeightAdaptable(
controller: controller,
children: sendCards,
),
SizedBox(height: 10),
Padding(
padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
child: Container(
height: 10,
child: Observer(
builder: (_) {
final count = sendViewModel.outputs.length;
return count > 1
? Semantics(
label: 'Page Indicator',
hint: 'Swipe to change receiver',
excludeSemantics: true,
child: SmoothPageIndicator(
controller: controller,
count: count,
effect: ScrollingDotsEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context)
.colorScheme
.primary
.withAlpha(100),
activeDotColor: Theme.of(context).colorScheme.primary,
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: _fiatAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
);
}
return Stack(
children: [
KeyboardActions(
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Theme.of(context).colorScheme.surface,
nextFocus: false,
actions: keyboardActions,
),
child: Container(
height: 0,
color: Colors.transparent,
),
),
GestureDetector(
onLongPress: () => sendViewModel.balanceViewModel.isReversing =
!sendViewModel.balanceViewModel.isReversing,
onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
!sendViewModel.balanceViewModel.isReversing,
child: RepaintBoundary(
child: Form(
key: _formKey,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: FocusTraversalGroup(
policy: OrderedTraversalPolicy(),
child: Column(
children: <Widget>[
PageViewHeightAdaptable(
controller: controller,
children: sendCards,
),
SizedBox(height: 10),
Padding(
padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
child: Container(
height: 10,
child: Observer(
builder: (_) {
final count = sendViewModel.outputs.length;
return count > 1
? Semantics(
label: 'Page Indicator',
hint: 'Swipe to change receiver',
excludeSemantics: true,
child: SmoothPageIndicator(
controller: controller,
count: count,
effect: ScrollingDotsEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context)
.colorScheme
.primary
.withAlpha(100),
activeDotColor:
Theme.of(context).colorScheme.primary,
),
),
),
)
: Offstage();
},
)
: Offstage();
},
),
),
),
),
Container(
height: 40,
width: double.infinity,
padding: EdgeInsets.only(left: 24),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Observer(
builder: (_) {
final templates = sendViewModel.templates;
final itemCount = templates.length;
return Row(
children: <Widget>[
AddTemplateButton(
key: ValueKey('send_page_add_template_button_key'),
onTap: () =>
Navigator.of(context).pushNamed(Routes.sendTemplate),
currentTemplatesLength: templates.length,
),
ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: itemCount,
itemBuilder: (context, index) {
final template = templates[index];
return TemplateTile(
key: UniqueKey(),
to: template.name,
hasMultipleRecipients:
template.additionalRecipients != null &&
template.additionalRecipients!.length > 1,
amount: template.isCurrencySelected
? template.amount
: template.amountFiat,
from: template.isCurrencySelected
? template.cryptoCurrency
: template.fiatCurrency,
onTap: () async {
sendViewModel.state = LoadingTemplateExecutingState();
if (template.additionalRecipients?.isNotEmpty ??
false) {
sendViewModel.clearOutputs();
for (int i = 0;
i < template.additionalRecipients!.length;
i++) {
Output output;
try {
output = sendViewModel.outputs[i];
} catch (e) {
sendViewModel.addOutput();
output = sendViewModel.outputs[i];
Container(
height: 40,
width: double.infinity,
padding: EdgeInsets.only(left: 24),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Observer(
builder: (_) {
final templates = sendViewModel.templates;
final itemCount = templates.length;
return Row(
children: <Widget>[
AddTemplateButton(
key: ValueKey('send_page_add_template_button_key'),
onTap: () => Navigator.of(context)
.pushNamed(Routes.sendTemplate),
currentTemplatesLength: templates.length,
),
ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: itemCount,
itemBuilder: (context, index) {
final template = templates[index];
return TemplateTile(
key: UniqueKey(),
to: template.name,
hasMultipleRecipients:
template.additionalRecipients != null &&
template.additionalRecipients!.length > 1,
amount: template.isCurrencySelected
? template.amount
: template.amountFiat,
from: template.isCurrencySelected
? template.cryptoCurrency
: template.fiatCurrency,
onTap: () async {
sendViewModel.state =
LoadingTemplateExecutingState();
if (template.additionalRecipients?.isNotEmpty ??
false) {
sendViewModel.clearOutputs();
for (int i = 0;
i < template.additionalRecipients!.length;
i++) {
Output output;
try {
output = sendViewModel.outputs[i];
} catch (e) {
sendViewModel.addOutput();
output = sendViewModel.outputs[i];
}
await _setInputsFromTemplate(
context,
output: output,
template:
template.additionalRecipients![i],
);
}
} else {
final output = _defineCurrentOutput();
await _setInputsFromTemplate(
context,
output: output,
template: template.additionalRecipients![i],
template: template,
);
}
} else {
final output = _defineCurrentOutput();
await _setInputsFromTemplate(
context,
output: output,
template: template,
sendViewModel.state = InitialExecutionState();
},
onRemove: () {
showPopUp<void>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).template,
alertContent: S
.of(context)
.confirm_delete_template,
rightButtonText: S.of(context).delete,
leftButtonText: S.of(context).cancel,
actionRightButton: () {
Navigator.of(dialogContext).pop();
sendViewModel.sendTemplateViewModel
.removeTemplate(
template: template);
},
actionLeftButton: () =>
Navigator.of(dialogContext).pop());
},
);
}
sendViewModel.state = InitialExecutionState();
},
onRemove: () {
showPopUp<void>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).template,
alertContent:
S.of(context).confirm_delete_template,
rightButtonText: S.of(context).delete,
leftButtonText: S.of(context).cancel,
actionRightButton: () {
Navigator.of(dialogContext).pop();
sendViewModel.sendTemplateViewModel
.removeTemplate(template: template);
},
actionLeftButton: () =>
Navigator.of(dialogContext).pop());
},
);
},
);
},
),
],
);
},
},
);
},
),
],
);
},
),
),
),
),
],
],
),
),
),
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Column(
children: [
if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
Padding(
padding: EdgeInsets.only(bottom: 12),
child: PrimaryButton(
key: ValueKey('send_page_add_receiver_button_key'),
onPressed: () {
sendViewModel.addOutput();
Future.delayed(const Duration(milliseconds: 250), () {
controller.jumpToPage(sendViewModel.outputs.length - 1);
});
},
text: S.of(context).add_receiver,
color: Colors.transparent,
textColor: Theme.of(context).colorScheme.onSurfaceVariant,
isDottedBorder: true,
borderColor: Theme.of(context).colorScheme.outline,
)),
Observer(
builder: (_) {
return LoadingPrimaryButton(
key: ValueKey('send_page_send_button_key'),
onPressed: () async {
//Request dummy node to get the focus out of the text fields
FocusScope.of(context).requestFocus(FocusNode());
if (sendViewModel.state is IsExecutingState) return;
if (_formKey.currentState != null &&
!_formKey.currentState!.validate()) {
if (sendViewModel.outputs.length > 1) {
showErrorValidationAlert(context);
}
return;
}
final hasInvalidItems = sendViewModel.outputs.any((item) =>
item.address.isEmpty ||
(item.cryptoAmount.isEmpty && !item.sendAll));
if (hasInvalidItems) {
showErrorValidationAlert(context);
return;
}
if (sendViewModel.wallet.isHardwareWallet) {
if (!sendViewModel.hardwareWalletViewModel!.isConnected(sendViewModel.walletType)) {
await Navigator.of(context).pushNamed(Routes.connectDevices,
arguments: ConnectDevicePageParams(
walletType: sendViewModel.walletType,
hardwareWalletType:
sendViewModel.wallet.walletInfo.hardwareWalletType!,
onConnectDevice: (BuildContext context, _) {
sendViewModel.hardwareWalletViewModel!
.initWallet(sendViewModel.wallet);
Navigator.of(context).pop();
},
));
} else {
sendViewModel.hardwareWalletViewModel!
.initWallet(sendViewModel.wallet);
}
}
if (sendViewModel.wallet.type == WalletType.monero) {
var amount = Money.zero(sendViewModel.wallet.currency);
for (var item in sendViewModel.outputs) {
amount += item.cryptoAmountMoney;
}
if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage,
arguments: monero!.exportOutputsUR(sendViewModel.wallet));
await Future.delayed(
Duration(seconds: 1)); // wait for monero to refresh the state
}
if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Column(
children: [
if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
Padding(
padding: EdgeInsets.only(bottom: 12),
child: PrimaryButton(
key: ValueKey('send_page_add_receiver_button_key'),
onPressed: () {
sendViewModel.addOutput();
Future.delayed(const Duration(milliseconds: 250), () {
controller.jumpToPage(sendViewModel.outputs.length - 1);
});
},
text: S.of(context).add_receiver,
color: Colors.transparent,
textColor: Theme.of(context).colorScheme.onSurfaceVariant,
isDottedBorder: true,
borderColor: Theme.of(context).colorScheme.outline,
)),
Observer(
builder: (_) {
return LoadingPrimaryButton(
key: ValueKey('send_page_send_button_key'),
onPressed: () async {
//Request dummy node to get the focus out of the text fields
FocusScope.of(context).requestFocus(FocusNode());
if (sendViewModel.state is IsExecutingState) return;
if (_formKey.currentState != null &&
!_formKey.currentState!.validate()) {
if (sendViewModel.outputs.length > 1) {
showErrorValidationAlert(context);
}
return;
}
}
final check = sendViewModel.shouldDisplayTotp();
authService.authenticateAction(
context,
conditionToDetermineIfToUse2FA: check,
onAuthSuccess: (value) async {
if (value) {
await sendViewModel.createTransaction();
final hasInvalidItems = sendViewModel.outputs.any((item) =>
item.address.isEmpty ||
(item.cryptoAmount.isEmpty && !item.sendAll));
if (hasInvalidItems) {
showErrorValidationAlert(context);
return;
}
if (sendViewModel.wallet.isHardwareWallet) {
if (!sendViewModel.hardwareWalletViewModel!
.isConnected(sendViewModel.walletType)) {
await Navigator.of(context)
.pushNamed(Routes.connectDevices,
arguments: ConnectDevicePageParams(
walletType: sendViewModel.walletType,
hardwareWalletType: sendViewModel
.wallet.walletInfo.hardwareWalletType!,
onConnectDevice: (BuildContext context, _) {
sendViewModel.hardwareWalletViewModel!
.initWallet(sendViewModel.wallet);
Navigator.of(context).pop();
},
));
} else {
sendViewModel.hardwareWalletViewModel!
.initWallet(sendViewModel.wallet);
}
},
);
},
text: _sendButtonText(context),
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
isLoading: sendViewModel.state is IsExecutingState ||
sendViewModel.state is TransactionCommitting ||
sendViewModel.state is IsAwaitingDeviceResponseState ||
sendViewModel.state is LoadingTemplateExecutingState,
isDisabled: !sendViewModel.isReadyForSend || sendViewModel.state is ExecutedSuccessfullyState,
);
},
)
],
)),
}
if (sendViewModel.wallet.type == WalletType.monero) {
var amount = Money.zero(sendViewModel.wallet.currency);
for (var item in sendViewModel.outputs) {
amount += item.cryptoAmountMoney;
}
if (monero!
.needExportOutputs(sendViewModel.wallet, amount)) {
await Navigator.of(context).pushNamed(
Routes.urqrAnimatedPage,
arguments:
monero!.exportOutputsUR(sendViewModel.wallet));
await Future.delayed(Duration(
seconds: 1)); // wait for monero to refresh the state
}
if (monero!
.needExportOutputs(sendViewModel.wallet, amount)) {
return;
}
}
final check = sendViewModel.shouldDisplayTotp();
authService.authenticateAction(
context,
conditionToDetermineIfToUse2FA: check,
onAuthSuccess: (value) async {
if (value) {
await sendViewModel.createTransaction();
}
},
);
},
text: _sendButtonText(context),
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
isLoading: sendViewModel.state is IsExecutingState ||
sendViewModel.state is TransactionCommitting ||
sendViewModel.state is IsAwaitingDeviceResponseState ||
sendViewModel.state is LoadingTemplateExecutingState,
isDisabled: !sendViewModel.isReadyForSend ||
sendViewModel.state is ExecutedSuccessfullyState,
);
},
)
],
)),
),
),
),
),
],
);
],
);
});
});
}
);
}
BuildContext? dialogContext;
@@ -505,7 +515,7 @@ class SendPage extends BasePage {
bitcoin!.updateFeeRates(sendViewModel.wallet);
}
controller.addListener((){
controller.addListener(() {
if (!controller.hasClients) return;
currentPage.value = controller.page!.round();
});
@@ -572,37 +582,36 @@ class SendPage extends BasePage {
isScrollControlled: true,
builder: (BuildContext bottomSheetContext) {
return Observer(
builder: (_) => ConfirmSendingBottomSheet(
key: ValueKey('send_page_confirm_sending_bottom_sheet_key'),
titleText: S.of(bottomSheetContext).confirm_transaction,
accessibleNavigationModeSlideActionButtonText: S.of(bottomSheetContext).send,
footerType: FooterType.slideActionButton,
isSlideActionEnabled: sendViewModel.isReadyForSend,
walletType: sendViewModel.walletType,
titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath,
currency: sendViewModel.selectedCryptoCurrency,
amount: S.of(bottomSheetContext).send_amount,
amountValue: sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
sendViewModel.pendingTransaction!.amountFormatted,
sendViewModel.selectedCryptoCurrency),
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
fee: isEVMCompatibleChain(sendViewModel.walletType)
? S.of(bottomSheetContext).send_estimated_fee
: S.of(bottomSheetContext).send_fee,
feeValue: "${sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
sendViewModel.pendingTransaction!.feeFormattedValue,
sendViewModel.selectedCryptoCurrency)} ${sendViewModel.amountParsingProxy
.getCryptoSymbol(sendViewModel.wallet.currency)}",
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
outputs: sendViewModel.outputs,
onSlideActionComplete: () async {
Navigator.of(bottomSheetContext).pop(true);
sendViewModel.commitTransaction(context);
},
change: sendViewModel.pendingTransaction!.change,
isOpenCryptoPay: sendViewModel.ocpRequest != null,
amountParsingProxy: sendViewModel.amountParsingProxy,
),);
builder: (_) => ConfirmSendingBottomSheet(
key: ValueKey('send_page_confirm_sending_bottom_sheet_key'),
titleText: S.of(bottomSheetContext).confirm_transaction,
accessibleNavigationModeSlideActionButtonText: S.of(bottomSheetContext).send,
footerType: FooterType.slideActionButton,
isSlideActionEnabled: sendViewModel.isReadyForSend,
walletType: sendViewModel.walletType,
titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath,
currency: sendViewModel.selectedCryptoCurrency,
amount: S.of(bottomSheetContext).send_amount,
amountValue: sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
sendViewModel.pendingTransaction!.amountFormatted,
sendViewModel.selectedCryptoCurrency),
fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
fee: isEVMCompatibleChain(sendViewModel.walletType)
? S.of(bottomSheetContext).send_estimated_fee
: S.of(bottomSheetContext).send_fee,
feeValue:
"${sendViewModel.amountParsingProxy.getDisplayCryptoAmount(sendViewModel.pendingTransaction!.feeFormattedValue, sendViewModel.selectedCryptoCurrency)} ${sendViewModel.amountParsingProxy.getCryptoSymbol(sendViewModel.wallet.currency)}",
feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
outputs: sendViewModel.outputs,
onSlideActionComplete: () async {
Navigator.of(bottomSheetContext).pop(true);
sendViewModel.commitTransaction(context);
},
change: sendViewModel.pendingTransaction!.change,
isOpenCryptoPay: sendViewModel.ocpRequest != null,
amountParsingProxy: sendViewModel.amountParsingProxy,
),
);
},
);
@@ -90,12 +90,11 @@ class ChooseYatAddressButtonsState extends State<ChooseYatAddressButtons> {
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurfaceVariant,
decoration: TextDecoration.none,
),
fontSize: 15,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.onSurfaceVariant,
decoration: TextDecoration.none,
),
),
)
],
+9 -8
View File
@@ -640,8 +640,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
onPushAddressBookButton: (context) async {
output.resetParsedAddress();
},
onSelectedContact: (contact) {
},
onSelectedContact: (contact) {},
validator: validator,
selectedCurrency: sendViewModel.selectedCryptoCurrency,
);
@@ -671,8 +670,10 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
currencyAmountTextFieldWidgetKey:
ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
selectedCurrency: output.useSatoshi ? "SATS" : sendViewModel.selectedCryptoCurrency.title,
selectedCurrencyDecimals: output.useSatoshi ? 0 : sendViewModel.selectedCryptoCurrency.decimals,
selectedCurrency:
output.useSatoshi ? "SATS" : sendViewModel.selectedCryptoCurrency.title,
selectedCurrencyDecimals:
output.useSatoshi ? 0 : sendViewModel.selectedCryptoCurrency.decimals,
amountFocusNode: widget.cryptoAmountFocus,
amountController: cryptoAmountController,
isAmountEditable: true,
@@ -976,8 +977,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
output.setSendAll(await sendViewModel.sendingBalance);
}
output.setCryptoAmount(sendViewModel.amountParsingProxy
.getCanonicalCryptoAmount(cryptoAmountController.text, sendViewModel.selectedCryptoCurrency));
output.setCryptoAmount(sendViewModel.amountParsingProxy.getCanonicalCryptoAmount(
cryptoAmountController.text, sendViewModel.selectedCryptoCurrency));
});
reaction((_) => output.fiatAmount, (String amount) {
@@ -991,8 +992,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
output.sendAll = false;
}
final cryptoAmount = sendViewModel.amountParsingProxy
.getCanonicalCryptoAmount(cryptoAmountController.text, sendViewModel.selectedCryptoCurrency);
final cryptoAmount = sendViewModel.amountParsingProxy.getCanonicalCryptoAmount(
cryptoAmountController.text, sendViewModel.selectedCryptoCurrency);
if (amount != cryptoAmount) {
cryptoAmountController.text = sendViewModel.amountParsingProxy
.getDisplayCryptoAmount(amount, sendViewModel.selectedCryptoCurrency);
+1 -1
View File
@@ -1 +1 @@
enum Attributes {arrow, header, link, switcher, widget, rawWidget}
enum Attributes { arrow, header, link, switcher, widget, rawWidget }
+153 -158
View File
@@ -43,89 +43,87 @@ class ConnectionSyncPage extends BasePage {
mainAxisSize: MainAxisSize.min,
children: [
Observer(
builder: (context) =>
NewListSections(
sections: {
"": [
if (FeatureFlag.isInAppTorEnabled)
ListItemToggle(
keyValue: "enable_builtin_tor",
label: S.of(context).enable_builtin_tor,
value: _connectionSyncViewModel.builtinTor,
onChanged: (val) {
_connectionSyncViewModel.setBuiltinTor(val, context);
}),
ListItemToggle(
keyValue: "disable_automatic_exchange_status_updates",
label: S.of(context).disable_automatic_exchange_status_updates,
value: _connectionSyncViewModel.disableAutomaticExchangeStatusUpdates,
onChanged: (val) {
_connectionSyncViewModel.setDisableAutomaticExchangeStatusUpdates(val);
}),
if (_connectionSyncViewModel.canUseBlinkProtection)
ListItemToggle(
keyValue: "can_use_blink_protection",
label: S.of(context).use_blink_protection,
value: _connectionSyncViewModel.useBlinkProtection,
onChanged: (val) {
_connectionSyncViewModel.setUseBlinkProtection(val);
}),
if (_connectionSyncViewModel.canUseEtherscan)
ListItemToggle(
keyValue: "can_use_etherscan",
label: S.of(context).etherscan_history,
value: _connectionSyncViewModel.useEtherscan,
onChanged: (val) {
_connectionSyncViewModel.setUseEtherscan(val);
}),
if (_connectionSyncViewModel.canUsePolygonScan)
ListItemToggle(
keyValue: "can_use_polygonscan",
label: S.of(context).polygonscan_history,
value: _connectionSyncViewModel.usePolygonScan,
onChanged: (val) {
_connectionSyncViewModel.setUsePolygonScan(val);
}),
if (_connectionSyncViewModel.canUseBaseScan)
ListItemToggle(
keyValue: "can_use_basescan",
label: S.of(context).basescan_history,
value: _connectionSyncViewModel.canUseBaseScan,
onChanged: (val) {
_connectionSyncViewModel.setUseBaseScan(val);
}),
if (_connectionSyncViewModel.canUseArbiScan)
ListItemToggle(
keyValue: "can_use_arbiscan",
label: S.of(context).arbiscan_history,
value: _connectionSyncViewModel.useArbiScan,
onChanged: (val) {
_connectionSyncViewModel.setUseArbiScan(val);
}),
if (_connectionSyncViewModel.canUseBscScan)
ListItemToggle(
keyValue: "can_use_bscscan",
label: S.of(context).bscscan_history,
value: _connectionSyncViewModel.useBscScan,
onChanged: (val) {
_connectionSyncViewModel.setUseBscScan(val);
}),
if (_connectionSyncViewModel.canUseTronGrid)
ListItemToggle(
keyValue: "can_use_trongrid",
label: S.of(context).trongrid_history,
value: _connectionSyncViewModel.useTronGrid,
onChanged: (val) {
_connectionSyncViewModel.setUseTronGrid(val);
}),
if (_connectionSyncViewModel.canUseMempoolFeeAPI)
ListItemToggle(
keyValue: "enable_mempool_api",
label: S.of(context).enable_mempool_api,
value: _connectionSyncViewModel.useMempoolFeeAPI,
onChanged: (bool isEnabled) async {
if (!isEnabled) {
final bool confirmation = await showPopUp<bool>(
builder: (context) => NewListSections(sections: {
"": [
if (FeatureFlag.isInAppTorEnabled)
ListItemToggle(
keyValue: "enable_builtin_tor",
label: S.of(context).enable_builtin_tor,
value: _connectionSyncViewModel.builtinTor,
onChanged: (val) {
_connectionSyncViewModel.setBuiltinTor(val, context);
}),
ListItemToggle(
keyValue: "disable_automatic_exchange_status_updates",
label: S.of(context).disable_automatic_exchange_status_updates,
value: _connectionSyncViewModel.disableAutomaticExchangeStatusUpdates,
onChanged: (val) {
_connectionSyncViewModel.setDisableAutomaticExchangeStatusUpdates(val);
}),
if (_connectionSyncViewModel.canUseBlinkProtection)
ListItemToggle(
keyValue: "can_use_blink_protection",
label: S.of(context).use_blink_protection,
value: _connectionSyncViewModel.useBlinkProtection,
onChanged: (val) {
_connectionSyncViewModel.setUseBlinkProtection(val);
}),
if (_connectionSyncViewModel.canUseEtherscan)
ListItemToggle(
keyValue: "can_use_etherscan",
label: S.of(context).etherscan_history,
value: _connectionSyncViewModel.useEtherscan,
onChanged: (val) {
_connectionSyncViewModel.setUseEtherscan(val);
}),
if (_connectionSyncViewModel.canUsePolygonScan)
ListItemToggle(
keyValue: "can_use_polygonscan",
label: S.of(context).polygonscan_history,
value: _connectionSyncViewModel.usePolygonScan,
onChanged: (val) {
_connectionSyncViewModel.setUsePolygonScan(val);
}),
if (_connectionSyncViewModel.canUseBaseScan)
ListItemToggle(
keyValue: "can_use_basescan",
label: S.of(context).basescan_history,
value: _connectionSyncViewModel.canUseBaseScan,
onChanged: (val) {
_connectionSyncViewModel.setUseBaseScan(val);
}),
if (_connectionSyncViewModel.canUseArbiScan)
ListItemToggle(
keyValue: "can_use_arbiscan",
label: S.of(context).arbiscan_history,
value: _connectionSyncViewModel.useArbiScan,
onChanged: (val) {
_connectionSyncViewModel.setUseArbiScan(val);
}),
if (_connectionSyncViewModel.canUseBscScan)
ListItemToggle(
keyValue: "can_use_bscscan",
label: S.of(context).bscscan_history,
value: _connectionSyncViewModel.useBscScan,
onChanged: (val) {
_connectionSyncViewModel.setUseBscScan(val);
}),
if (_connectionSyncViewModel.canUseTronGrid)
ListItemToggle(
keyValue: "can_use_trongrid",
label: S.of(context).trongrid_history,
value: _connectionSyncViewModel.useTronGrid,
onChanged: (val) {
_connectionSyncViewModel.setUseTronGrid(val);
}),
if (_connectionSyncViewModel.canUseMempoolFeeAPI)
ListItemToggle(
keyValue: "enable_mempool_api",
label: S.of(context).enable_mempool_api,
value: _connectionSyncViewModel.useMempoolFeeAPI,
onChanged: (bool isEnabled) async {
if (!isEnabled) {
final bool confirmation = await showPopUp<bool>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
@@ -133,91 +131,88 @@ class ConnectionSyncPage extends BasePage {
alertContent: S.of(context).disable_fee_api_warning,
rightButtonText: S.of(context).confirm,
leftButtonText: S.of(context).cancel,
actionRightButton: () => Navigator.of(context).pop(true),
actionLeftButton: () => Navigator.of(context).pop(false));
actionRightButton: () =>
Navigator.of(context).pop(true),
actionLeftButton: () =>
Navigator.of(context).pop(false));
}) ??
false;
if (confirmation) {
_connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
}
return;
}
false;
if (confirmation) {
_connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
}),
if (Platform.isAndroid && FeatureFlag.isBackgroundSyncEnabled)
ListItemRegularRow(
keyValue: "background_sync",
label: S.of(context).background_sync,
onTap: () => Navigator.of(context).pushNamed(Routes.backgroundSync)
),
if (_connectionSyncViewModel.hasPowNodes)
ListItemRegularRow(
keyValue: "manage_pow_nodes",
label: S.of(context).manage_pow_nodes,
onTap: () => Navigator.of(context).pushNamed(Routes.managePowNodes),
),
ListItemSelector(
keyValue: "fiat_api",
label: S.of(context).fiat_api,
options: [_connectionSyncViewModel.fiatApiMode.title],
onTap: () async {
final items = FiatApiMode.all;
}
return;
}
final selectedAtIndex =
_connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
}),
if (Platform.isAndroid && FeatureFlag.isBackgroundSyncEnabled)
ListItemRegularRow(
keyValue: "background_sync",
label: S.of(context).background_sync,
onTap: () => Navigator.of(context).pushNamed(Routes.backgroundSync)),
if (_connectionSyncViewModel.hasPowNodes)
ListItemRegularRow(
keyValue: "manage_pow_nodes",
label: S.of(context).manage_pow_nodes,
onTap: () => Navigator.of(context).pushNamed(Routes.managePowNodes),
),
ListItemSelector(
keyValue: "fiat_api",
label: S.of(context).fiat_api,
options: [_connectionSyncViewModel.fiatApiMode.title],
onTap: () async {
final items = FiatApiMode.all;
final selectedAtIndex =
items.indexOf(_connectionSyncViewModel.fiatApiMode);
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (FiatApiMode fiatApiMode) {
_connectionSyncViewModel.setFiatMode(fiatApiMode);
},
isSeparated: false,
),
);
}),
ListItemSelector(
keyValue: "swap",
label: S.of(context).swap,
options: [_connectionSyncViewModel.exchangeStatus.title],
onTap: () async {
final items = ExchangeApiMode.all;
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (FiatApiMode fiatApiMode) {
_connectionSyncViewModel.setFiatMode(fiatApiMode);
},
isSeparated: false,
),
);
}),
ListItemSelector(
keyValue: "swap",
label: S.of(context).swap,
options: [_connectionSyncViewModel.exchangeStatus.title],
onTap: () async {
final items = ExchangeApiMode.all;
final selectedAtIndex =
final selectedAtIndex =
items.indexOf(_connectionSyncViewModel.exchangeStatus);
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (ExchangeApiMode mode) {
_connectionSyncViewModel.setExchangeApiMode(mode);
},
isSeparated: false,
),
);
}),
ListItemRegularRow(
keyValue: "domain_lookups",
label: S.of(context).domain_looks_up,
onTap: () => Navigator.of(context).pushNamed(Routes.domainLookupsPage)
),
if(_connectionSyncViewModel.hasRescan)
ListItemRegularRow(
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (ExchangeApiMode mode) {
_connectionSyncViewModel.setExchangeApiMode(mode);
},
isSeparated: false,
),
);
}),
ListItemRegularRow(
keyValue: "domain_lookups",
label: S.of(context).domain_looks_up,
onTap: () => Navigator.of(context).pushNamed(Routes.domainLookupsPage)),
if (_connectionSyncViewModel.hasRescan)
ListItemRegularRow(
keyValue: "rescan",
label: S.of(context).rescan,
onTap: ()=>Navigator.of(context).pushNamed(Routes.rescan)
)
],
}
)
),
onTap: () => Navigator.of(context).pushNamed(Routes.rescan))
],
})),
],
),
);
@@ -61,9 +61,9 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
}
if ((!widget.dashboardViewModel.isMoneroViewOnly &&
item.name(context) == S.of(context).export_outputs) ||
(!widget.dashboardViewModel.hasMweb &&
item.name(context) == S.of(context).litecoin_mweb_settings)) {
item.name(context) == S.of(context).export_outputs) ||
(!widget.dashboardViewModel.hasMweb &&
item.name(context) == S.of(context).litecoin_mweb_settings)) {
return Container();
}
@@ -103,11 +103,9 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
key: _settingsNavigatorKey,
initialRoute: Routes.empty_no_route,
onGenerateRoute: (settings) => Router.createRoute(settings),
onGenerateInitialRoutes:
(NavigatorState navigator, String initialRouteName) {
onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) {
return [
navigator
.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
];
},
),
@@ -27,7 +27,6 @@ import 'package:image_picker/image_picker.dart';
class DisplaySettingsPage extends StatelessWidget {
DisplaySettingsPage(this._displaySettingsViewModel);
final DisplaySettingsViewModel _displaySettingsViewModel;
@override
@@ -38,198 +37,197 @@ class DisplaySettingsPage extends StatelessWidget {
leadingIcon: Icon(Icons.arrow_back_ios_new),
onLeadingPressed: () => Navigator.of(context).pop(),
),
content: Column(
spacing: 16,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (responsiveLayoutUtil.shouldRenderMobileUI &&
DeviceInfo.instance.isMobile) ...[
Padding(
padding: const EdgeInsets.only(left: 14, top: 14),
child: Text(
S.of(context).appearance,
style: Theme.of(context).textTheme.labelLarge?.copyWith(
content: Column(
spacing: 16,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile) ...[
Padding(
padding: const EdgeInsets.only(left: 14, top: 14),
child: Text(
S.of(context).appearance,
style: Theme.of(context).textTheme.labelLarge?.copyWith(
height: 0.2,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
Container(
decoration: ShapeDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18))),
child: Column(
children: [
SettingsChoicesCell(
ChoicesListItem<ThemeMode>(
title: "",
items: ThemeMode.values,
selectedItem: _displaySettingsViewModel.themeMode,
onItemSelected: (ThemeMode themeMode) =>
_displaySettingsViewModel.setThemeMode(themeMode),
displayItem: (ThemeMode themeMode) {
return themeMode.name[0].toUpperCase() +
themeMode.name.substring(1).toLowerCase();
},
),
useGenericColor: false,
padding: EdgeInsets.all(14),
),
),
Container(
decoration: ShapeDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(18))),
child: Column(
children: [
SettingsChoicesCell(
ChoicesListItem<ThemeMode>(
title: "",
items: ThemeMode.values,
selectedItem: _displaySettingsViewModel.themeMode,
onItemSelected: (ThemeMode themeMode) =>
_displaySettingsViewModel.setThemeMode(themeMode),
displayItem: (ThemeMode themeMode) {
return themeMode.name[0].toUpperCase() +
themeMode.name.substring(1).toLowerCase();
},
Container(
decoration: ShapeDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18))),
child: Column(
children: [
Semantics(
label: S.of(context).color_theme,
child: SettingsThemeChoicesCell(_displaySettingsViewModel),
),
useGenericColor: false,
padding: EdgeInsets.all(14),
),
Container(
decoration: ShapeDecoration(
color: Theme.of(context).colorScheme.surfaceContainer,
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(18))),
child: Column(
children: [
Semantics(
label: S.of(context).color_theme,
child: SettingsThemeChoicesCell(_displaySettingsViewModel),
),
],
),
),
],
],
),
),
),
],
Observer(
builder: (_) => NewListSections(
sections: {
"": [
ListItemToggle(
keyValue: "apps",
label: S.of(context).apps,
value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
onChanged: (val) {
_displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(val);
}),
ListItemToggle(
keyValue: "display_settings_show_address_book_popup",
label: S.of(context).show_address_book_popup,
value: _displaySettingsViewModel.showAddressBookPopup,
onChanged: (val) {
_displaySettingsViewModel.setShowAddressBookPopup(val);
}),
ListItemToggle(
keyValue: "display_settings_disable_buy_button",
label: S.of(context).disable_buy,
value: _displaySettingsViewModel.disableTradeOption,
onChanged: (val) {
_displaySettingsViewModel.setDisableTradeOption(val);
}),
if (_displaySettingsViewModel.showZcashCardSetting)
ListItemToggle(
keyValue: "display_settings_show_zcashcard",
label: S.of(context).show_zcash_card,
value: _displaySettingsViewModel.showZcashCard,
onChanged: (val) {
_displaySettingsViewModel.setShowZcashCard(val);
}),
ListItemSelector(
keyValue: "display_settings_sync_status_display",
label: S.of(context).sync_status_display_mode,
options: [_displaySettingsViewModel.syncStatusDisplayMode.title],
onTap: () async {
final items = SyncStatusDisplayMode.values.toList();
],
),
),
],
Observer(
builder: (_) => NewListSections(
sections: {
"": [
ListItemToggle(
keyValue: "apps",
label: S.of(context).apps,
value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
onChanged: (val) {
_displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(val);
}),
ListItemToggle(
keyValue: "display_settings_show_address_book_popup",
label: S.of(context).show_address_book_popup,
value: _displaySettingsViewModel.showAddressBookPopup,
onChanged: (val) {
_displaySettingsViewModel.setShowAddressBookPopup(val);
}),
ListItemToggle(
keyValue: "display_settings_disable_buy_button",
label: S.of(context).disable_buy,
value: _displaySettingsViewModel.disableTradeOption,
onChanged: (val) {
_displaySettingsViewModel.setDisableTradeOption(val);
}),
if (_displaySettingsViewModel.showZcashCardSetting)
ListItemToggle(
keyValue: "display_settings_show_zcashcard",
label: S.of(context).show_zcash_card,
value: _displaySettingsViewModel.showZcashCard,
onChanged: (val) {
_displaySettingsViewModel.setShowZcashCard(val);
}),
ListItemSelector(
keyValue: "display_settings_sync_status_display",
label: S.of(context).sync_status_display_mode,
options: [_displaySettingsViewModel.syncStatusDisplayMode.title],
onTap: () async {
final items = SyncStatusDisplayMode.values.toList();
final selectedAtIndex =
final selectedAtIndex =
items.indexOf(_displaySettingsViewModel.syncStatusDisplayMode);
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (SyncStatusDisplayMode mode) {
_displaySettingsViewModel.setSyncStatusDisplayMode(mode);
},
displayItem: (SyncStatusDisplayMode mode) => mode.title,
isSeparated: false,
),
);
}),
if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting)
ListItemRegularRow(
keyValue: "display_settings_bitcoin_amount_display",
label: S.of(context).bitcoin_amount_display,
trailingText: _displaySettingsViewModel.displayAmountsInSatoshi.title,
onTap: () async {
final items = BitcoinAmountDisplayMode.all;
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: (SyncStatusDisplayMode mode) {
_displaySettingsViewModel.setSyncStatusDisplayMode(mode);
},
displayItem: (SyncStatusDisplayMode mode) => mode.title,
isSeparated: false,
),
);
}),
if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting)
ListItemRegularRow(
keyValue: "display_settings_bitcoin_amount_display",
label: S.of(context).bitcoin_amount_display,
trailingText: _displaySettingsViewModel.displayAmountsInSatoshi.title,
onTap: () async {
final items = BitcoinAmountDisplayMode.all;
final selectedAtIndex =
final selectedAtIndex =
items.indexOf(_displaySettingsViewModel.displayAmountsInSatoshi);
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi,
displayItem: (BitcoinAmountDisplayMode mode) => mode.title,
isSeparated: false,
),
);
}),
if (!_displaySettingsViewModel.disabledFiatApiMode)
ListItemSelector(
keyValue: "display_settings_fiat_currency",
label: S.of(context).settings_currency,
options: [_displaySettingsViewModel.fiatCurrency.title],
onTap: () => FiatCurrencyPickerSheet.show(
context: context,
selected: _displaySettingsViewModel.fiatCurrency,
onSelected: _displaySettingsViewModel.setFiatCurrency,
)),
ListItemSelector(
keyValue: "display_settings_language",
label: S.of(context).settings_change_language,
options: [LanguageService.list[_displaySettingsViewModel.languageCode] ?? ''],
onTap: () async {
final items = LanguageService.list.keys.toList();
await showPopUp<void>(
context: context,
builder: (_) => Picker(
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi,
displayItem: (BitcoinAmountDisplayMode mode) => mode.title,
isSeparated: false,
),
);
}),
if (!_displaySettingsViewModel.disabledFiatApiMode)
ListItemSelector(
keyValue: "display_settings_fiat_currency",
label: S.of(context).settings_currency,
options: [_displaySettingsViewModel.fiatCurrency.title],
onTap: () => FiatCurrencyPickerSheet.show(
context: context,
selected: _displaySettingsViewModel.fiatCurrency,
onSelected: _displaySettingsViewModel.setFiatCurrency,
)),
ListItemSelector(
keyValue: "display_settings_language",
label: S.of(context).settings_change_language,
options: [LanguageService.list[_displaySettingsViewModel.languageCode] ?? ''],
onTap: () async {
final items = LanguageService.list.keys.toList();
final selectedAtIndex =
final selectedAtIndex =
items.indexOf(_displaySettingsViewModel.languageCode);
await showPopUp<void>(
context: context,
builder: (_) => Picker(
displayItem: (dynamic code) {
return LanguageService.list[code] ?? '';
},
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _displaySettingsViewModel.onLanguageSelected,
images: LanguageService.list.keys
.map((e) => Image.asset(
await showPopUp<void>(
context: context,
builder: (_) => Picker(
displayItem: (dynamic code) {
return LanguageService.list[code] ?? '';
},
items: items,
selectedAtIndex: selectedAtIndex,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _displaySettingsViewModel.onLanguageSelected,
images: LanguageService.list.keys
.map((e) => Image.asset(
"assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
.toList(),
hintText: S.of(context).search_language,
matchingCriteria: (String code, String searchText) {
return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false;
},
isSeparated: true,
),
);
}),
],
},
),
),
if (FeatureFlag.customBackgroundEnabled)
StandardListRow(
title: "Custom background",
isSelected: false,
onTap: (_) => _pickImage(context),
),
],
.toList(),
hintText: S.of(context).search_language,
matchingCriteria: (String code, String searchText) {
return LanguageService.list[code]
?.toLowerCase()
.contains(searchText) ??
false;
},
isSeparated: true,
),
);
}),
],
},
),
),
);
if (FeatureFlag.customBackgroundEnabled)
StandardListRow(
title: "Custom background",
isSelected: false,
onTap: (_) => _pickImage(context),
),
],
),
);
}
// Function to pick an image from the gallery
@@ -25,11 +25,13 @@ class DomainLookupsPage extends BasePage {
.map(
(source) => SettingsSwitcherCell(
title: source.label,
leading: source.iconPath.isNotEmpty ? CakeImageWidget(
imageUrl: source.iconPath,
width: 24,
height: 24,
) : SizedBox(width: 24, height: 24),
leading: source.iconPath.isNotEmpty
? CakeImageWidget(
imageUrl: source.iconPath,
width: 24,
height: 24,
)
: SizedBox(width: 24, height: 24),
value: _connectionsSyncViewModel.lookupValue(source),
onValueChange: (_, bool value) =>
_connectionsSyncViewModel.setLookupValue(source, value),
@@ -15,4 +15,4 @@ class ItemHeaders {
static const termsAndConditions = 'Terms and conditions';
static const faq = 'FAQ';
static const version = 'Version';
}
}
+10 -11
View File
@@ -55,10 +55,10 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
ModernButton(
size: 36,
icon: Icon(Icons.add),
onPressed: ()async {
onPressed: () async {
final res = await Navigator.of(context)
.pushNamed(widget.isPow ? Routes.newPowNode : Routes.newNode);
if(res != null && res is Node) {
.pushNamed(widget.isPow ? Routes.newPowNode : Routes.newNode);
if (res != null && res is Node) {
widget.nodeListViewModel.nodes.add(res);
}
})
@@ -75,12 +75,11 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
// horizontal: 0,
node: widget.nodeListViewModel.currentNode,
speed: widget.nodeListViewModel.nodeSpeedFor(widget.nodeListViewModel.currentNode),
onEditComplete: (res)async{
if(res != null && res is Node) {
widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id);
onEditComplete: (res) async {
if (res != null && res is Node) {
widget.nodeListViewModel.nodes.removeWhere((item) => item.id == res.id);
widget.nodeListViewModel.nodes.add(res);
}
},
onTap: () {},
isSelected: true,
@@ -93,7 +92,7 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
color: Theme.of(context).colorScheme.surfaceContainer,
borderRadius: BorderRadius.circular(18)),
child: ClipRRect(
borderRadius: BorderRadius.circular(18),
borderRadius: BorderRadius.circular(18),
child: Observer(
builder: (BuildContext context) {
int itemsCount = widget.nodeListViewModel.nonCurrentNodes.length;
@@ -119,11 +118,11 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
isPow: widget.isPow,
speed: widget.nodeListViewModel.nodeSpeedFor(node),
onEditComplete: (res) async {
if(res != null && res is Node) {
widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id);
if (res != null && res is Node) {
widget.nodeListViewModel.nodes
.removeWhere((item) => item.id == res.id);
widget.nodeListViewModel.nodes.add(res);
}
},
onTap: () async {
await showPopUp<void>(
+6 -6
View File
@@ -38,7 +38,8 @@ class MwebLogsPage extends BasePage {
padding: EdgeInsets.all(16.0),
child: Text(
snapshot.data!,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontFamily: 'Monospace'),
style:
Theme.of(context).textTheme.bodyMedium!.copyWith(fontFamily: 'Monospace'),
),
),
);
@@ -103,11 +104,10 @@ class MwebLogsPage extends BasePage {
}
Future<void> _saveFile() async {
String? outputFile = await FilePicker.platform
.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: "debug.log",
lockParentWindow: true);
String? outputFile = await FilePicker.platform.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: "debug.log",
lockParentWindow: true);
if (outputFile == null) return;
+20 -21
View File
@@ -7,6 +7,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
import 'package:flutter/material.dart';
class MwebNodePage extends StatefulWidget {
const MwebNodePage(this.mwebSettingsViewModelBase, {super.key});
@@ -30,30 +31,28 @@ class _MwebNodePageState extends State<MwebNodePage> {
Widget build(BuildContext context) {
return SafeArea(
child: ModalPageWrapper(
topBar: ModalTopBar(
topBar: ModalTopBar(
title: S.current.litecoin_mweb_settings,
onLeadingPressed: Navigator.of(context).pop,
leadingIcon: Icon(Icons.arrow_back_ios_new)),
content: Container(
child: NewListSections(
controllers: {
widget.mwebSettingsViewModelBase.mwebNodeUri: _nodeUriController,
},
sections: {
'main': [
ListItemTextField(
keyValue: widget.mwebSettingsViewModelBase.mwebNodeUri,
label: S.current.node_address,
validator: NodePathValidator(),
),
]
}),
),
bottomContent: LoadingPrimaryButton(
onPressed: () => save(context),
text: S.of(context).save,
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
content: Container(
child: NewListSections(controllers: {
widget.mwebSettingsViewModelBase.mwebNodeUri: _nodeUriController,
}, sections: {
'main': [
ListItemTextField(
keyValue: widget.mwebSettingsViewModelBase.mwebNodeUri,
label: S.current.node_address,
validator: NodePathValidator(),
),
]
}),
),
bottomContent: LoadingPrimaryButton(
onPressed: () => save(context),
text: S.of(context).save,
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
),
),
);
+1 -1
View File
@@ -41,7 +41,7 @@ class MwebSettingsPage extends BasePage {
title: S.current.litecoin_mweb_scanning,
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
),
SettingsCellWithArrow(
SettingsCellWithArrow(
title: S.current.litecoin_mweb_logs,
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebLogs),
),
@@ -149,7 +149,8 @@ class OtherSettingsPage extends BasePage {
Navigator.of(context).pushNamed(Routes.signPage);
}),
],
if (_otherSettingsViewModel.walletType == WalletType.bitcoin) "btc_logging": [
if (_otherSettingsViewModel.walletType == WalletType.bitcoin)
"btc_logging": [
ListItemRegularRow(
keyValue: "export_lightning_logs",
label: S.of(context).export_lightning_logs,
@@ -158,72 +159,74 @@ class OtherSettingsPage extends BasePage {
keyValue: "export_payjoin_logs",
label: S.of(context).export_payjoin_logs,
onTap: () => onExportPJLog(context)),
],
"dev": FeatureFlag.hasDevOptions == false ? [] : [
if (_otherSettingsViewModel.walletType == WalletType.monero)
ListItemRegularRow(
keyValue: "[dev] monero background sync",
label: "[dev] monero background sync",
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync)),
if ([WalletType.monero, WalletType.wownero, WalletType.zano]
.contains(_otherSettingsViewModel.walletType))
ListItemRegularRow(
keyValue: "[dev] xmr call profiler",
label: "[dev] xmr call profiler",
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroCallProfiler)),
if ([WalletType.monero].contains(_otherSettingsViewModel.walletType))
ListItemRegularRow(
keyValue: '[dev] xmr wallet cache debug',
label: '[dev] xmr wallet cache debug',
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroWalletCacheDebug)),
ListItemRegularRow(
keyValue: '[dev] shared preferences',
label: '[dev] shared preferences',
onTap: () => Navigator.of(context).pushNamed(Routes.devSharedPreferences)),
ListItemRegularRow(
keyValue: '[dev] secure storage preferences',
label: '[dev] secure storage preferences',
onTap: () => Navigator.of(context).pushNamed(Routes.devSecurePreferences)),
ListItemRegularRow(
keyValue: '[dev] background sync logs',
label: '[dev] background sync logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devBackgroundSyncLogs)),
ListItemRegularRow(
keyValue: '[dev] socket health logs',
label: '[dev] socket health logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devSocketHealthLogs)),
ListItemRegularRow(
keyValue: '[dev] network requests logs',
label: '[dev] network requests logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devNetworkRequests)),
ListItemRegularRow(
keyValue: '[dev] exchange provider logs',
label: '[dev] exchange provider logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
ListItemRegularRow(
keyValue: '[dev] *QR tools',
label: '[dev] *QR tools',
onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
ListItemRegularRow(
keyValue: '[dev] browse sqlite db',
label: '[dev] browse sqlite db',
onTap: () async {
final data = await dumpDb();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db'),
),
);
}),
ListItemRegularRow(
keyValue: '[dev] fake corrupt sqlite db',
label: '[dev] fake corrupt sqlite db',
onTap: () async {
final dbDebugMarker = await sqliteDebugMarkerFile();
dbDebugMarker.create();
}
),
]
],
"dev": FeatureFlag.hasDevOptions == false
? []
: [
if (_otherSettingsViewModel.walletType == WalletType.monero)
ListItemRegularRow(
keyValue: "[dev] monero background sync",
label: "[dev] monero background sync",
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync)),
if ([WalletType.monero, WalletType.wownero, WalletType.zano]
.contains(_otherSettingsViewModel.walletType))
ListItemRegularRow(
keyValue: "[dev] xmr call profiler",
label: "[dev] xmr call profiler",
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroCallProfiler)),
if ([WalletType.monero].contains(_otherSettingsViewModel.walletType))
ListItemRegularRow(
keyValue: '[dev] xmr wallet cache debug',
label: '[dev] xmr wallet cache debug',
onTap: () =>
Navigator.of(context).pushNamed(Routes.devMoneroWalletCacheDebug)),
ListItemRegularRow(
keyValue: '[dev] shared preferences',
label: '[dev] shared preferences',
onTap: () => Navigator.of(context).pushNamed(Routes.devSharedPreferences)),
ListItemRegularRow(
keyValue: '[dev] secure storage preferences',
label: '[dev] secure storage preferences',
onTap: () => Navigator.of(context).pushNamed(Routes.devSecurePreferences)),
ListItemRegularRow(
keyValue: '[dev] background sync logs',
label: '[dev] background sync logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devBackgroundSyncLogs)),
ListItemRegularRow(
keyValue: '[dev] socket health logs',
label: '[dev] socket health logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devSocketHealthLogs)),
ListItemRegularRow(
keyValue: '[dev] network requests logs',
label: '[dev] network requests logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devNetworkRequests)),
ListItemRegularRow(
keyValue: '[dev] exchange provider logs',
label: '[dev] exchange provider logs',
onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
ListItemRegularRow(
keyValue: '[dev] *QR tools',
label: '[dev] *QR tools',
onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
ListItemRegularRow(
keyValue: '[dev] browse sqlite db',
label: '[dev] browse sqlite db',
onTap: () async {
final data = await dumpDb();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db'),
),
);
}),
ListItemRegularRow(
keyValue: '[dev] fake corrupt sqlite db',
label: '[dev] fake corrupt sqlite db',
onTap: () async {
final dbDebugMarker = await sqliteDebugMarkerFile();
dbDebugMarker.create();
}),
]
}),
);
}
+45 -47
View File
@@ -38,44 +38,43 @@ class PrivacyPage extends BasePage {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
NewListSections(
sections: {
"1": [
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
ListItemToggle(
keyValue: "auto_generate_subaddresses",
label: _privacySettingsViewModel.isMoneroWallet
? S.of(context).auto_generate_subaddresses
: S.of(context).auto_generate_addresses,
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
onChanged: (val) {
_privacySettingsViewModel.setAutoGenerateSubaddresses(val);
}),
NewListSections(sections: {
"1": [
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
ListItemToggle(
keyValue: "save_recipient_address",
label: S.of(context).settings_save_recipient_address,
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
keyValue: "auto_generate_subaddresses",
label: _privacySettingsViewModel.isMoneroWallet
? S.of(context).auto_generate_subaddresses
: S.of(context).auto_generate_addresses,
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
onChanged: (val) {
_privacySettingsViewModel.setShouldSaveRecipientAddress(val);
_privacySettingsViewModel.setAutoGenerateSubaddresses(val);
}),
if (_privacySettingsViewModel.canUsePayjoin)
ListItemToggle(
keyValue: "use_payjoin",
label: S.of(context).use_payjoin,
value: _privacySettingsViewModel.usePayjoin,
onChanged: (val) {
_privacySettingsViewModel.setUsePayjoin(val);
}),
if (_privacySettingsViewModel.canUseLightning)
ListItemToggle(
keyValue: "enable_lightning",
label: S.of(context).enable_lightning,
value: _privacySettingsViewModel.useLightning,
onChanged: (val) {
_privacySettingsViewModel.setUseLightning(val);
}),
],
"": [
ListItemToggle(
keyValue: "save_recipient_address",
label: S.of(context).settings_save_recipient_address,
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
onChanged: (val) {
_privacySettingsViewModel.setShouldSaveRecipientAddress(val);
}),
if (_privacySettingsViewModel.canUsePayjoin)
ListItemToggle(
keyValue: "use_payjoin",
label: S.of(context).use_payjoin,
value: _privacySettingsViewModel.usePayjoin,
onChanged: (val) {
_privacySettingsViewModel.setUsePayjoin(val);
}),
if (_privacySettingsViewModel.canUseLightning)
ListItemToggle(
keyValue: "enable_lightning",
label: S.of(context).enable_lightning,
value: _privacySettingsViewModel.useLightning,
onChanged: (val) {
_privacySettingsViewModel.setUseLightning(val);
}),
],
"": [
if (_privacySettingsViewModel.isBitcoin)
ListItemRegularRow(
iconPath: "assets/new-ui/settings_row_icons/silent-payments.svg",
@@ -83,23 +82,22 @@ class PrivacyPage extends BasePage {
label: S.of(context).silent_payments,
onTap: () =>
Navigator.of(context).pushNamed(Routes.silentPaymentsSettings)),
if (_privacySettingsViewModel.hasMWEB)
ListItemRegularRow(
iconPath: "assets/new-ui/settings_row_icons/mweb.svg",
keyValue: "mweb",
label: "MWEB",
onTap: () =>
Navigator.of(context).pushNamed(Routes.mwebSettings)),
if (_privacySettingsViewModel.hasCoinControl)
if (_privacySettingsViewModel.hasMWEB)
ListItemRegularRow(
iconPath: "assets/new-ui/settings_row_icons/mweb.svg",
keyValue: "mweb",
label: "MWEB",
onTap: () => Navigator.of(context).pushNamed(Routes.mwebSettings)),
if (_privacySettingsViewModel.hasCoinControl)
ListItemRegularRow(
iconPath: "assets/new-ui/settings_row_icons/coin-control.svg",
keyValue: "coin_control",
label: "Coin Control",
onTap: () =>
Navigator.of(context).pushNamed(Routes.unspentCoinsList, arguments: CoinControlPageArgs(canEdit: false, coinTypeToSpendFrom: null))),
onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsList,
arguments:
CoinControlPageArgs(canEdit: false, coinTypeToSpendFrom: null))),
],
}
),
}),
],
);
}),
@@ -73,8 +73,8 @@ class SecurityBackupPage extends BasePage {
isAuthenticatedSuccessfully);
}
} else {
_securitySettingsViewModel.setAllowBiometricalAuthentication(
isAuthenticatedSuccessfully);
_securitySettingsViewModel
.setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
}
},
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
@@ -85,13 +85,13 @@ class SecurityBackupPage extends BasePage {
}
}),
if (DeviceInfo.instance.isMobile)
ListItemToggle(
keyValue: "display_settings_prevent_screen_capture",
label: S.of(context).prevent_screenshots,
value: _securitySettingsViewModel.isAppSecure,
onChanged: (val) {
_securitySettingsViewModel.setIsAppSecure(val);
}),
ListItemToggle(
keyValue: "display_settings_prevent_screen_capture",
label: S.of(context).prevent_screenshots,
value: _securitySettingsViewModel.isAppSecure,
onChanged: (val) {
_securitySettingsViewModel.setIsAppSecure(val);
}),
if (FeatureFlag.duressPinEnabled)
ListItemToggle(
keyValue: "security_backup_page_duress_pin_button_key",
@@ -114,8 +114,7 @@ class SecurityBackupPage extends BasePage {
if (confirmation) {
Navigator.of(context).pushNamed(
Routes.setupDuressPin,
arguments:
(PinCodeState<PinCodeWidget> pinCtx, String _) async {
arguments: (PinCodeState<PinCodeWidget> pinCtx, String _) async {
pinCtx.close();
_securitySettingsViewModel.setEnableDuressPin(true);
},
@@ -105,11 +105,10 @@ class SilentPaymentsLogPage extends BasePage {
}
Future<void> _saveFile() async {
String? outputFile = await FilePicker.platform
.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: "debug.log",
lockParentWindow: true);
String? outputFile = await FilePicker.platform.saveFile(
dialogTitle: 'Save Your File to desired location',
fileName: "debug.log",
lockParentWindow: true);
if (outputFile == null) return;
@@ -19,7 +19,11 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
color: Theme.of(context).colorScheme.surface,
child: Column(
children: [
ModalTopBar(title: S.current.silent_payments_settings,leadingIcon: Icon(Icons.arrow_back_ios_new),onLeadingPressed: Navigator.of(context).pop,),
ModalTopBar(
title: S.current.silent_payments_settings,
leadingIcon: Icon(Icons.arrow_back_ios_new),
onLeadingPressed: Navigator.of(context).pop,
),
Expanded(
child: SingleChildScrollView(
child: Observer(builder: (_) {
@@ -27,14 +31,14 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
padding: EdgeInsets.only(top: 10),
child: Column(
children: [
if(!FeatureFlag.hasNewUi)
SettingsSwitcherCell(
title: S.current.silent_payments_display_card,
value: _silentPaymentsSettingsViewModel.silentPaymentsCardDisplay,
onValueChange: (_, bool value) {
_silentPaymentsSettingsViewModel.setSilentPaymentsCardDisplay(value);
},
),
if (!FeatureFlag.hasNewUi)
SettingsSwitcherCell(
title: S.current.silent_payments_display_card,
value: _silentPaymentsSettingsViewModel.silentPaymentsCardDisplay,
onValueChange: (_, bool value) {
_silentPaymentsSettingsViewModel.setSilentPaymentsCardDisplay(value);
},
),
SettingsSwitcherCell(
title: S.current.silent_payments_always_scan,
value: _silentPaymentsSettingsViewModel.silentPaymentsAlwaysScan,
@@ -44,7 +48,8 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
),
SettingsCellWithArrow(
title: S.current.silent_payments_scanning,
handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
handler: (BuildContext context) =>
Navigator.of(context).pushNamed(Routes.rescan),
),
SettingsCellWithArrow(
title: S.current.silent_payments_logs,
@@ -44,9 +44,8 @@ class SettingsChoicesCell extends StatelessWidget {
color: Theme.of(context).colorScheme.surfaceContainerHighest,
width: 1.5,
),
color: useGenericColor
? Theme.of(context).colorScheme.surfaceContainerHighest
: null,
color:
useGenericColor ? Theme.of(context).colorScheme.surfaceContainerHighest : null,
),
child: LayoutBuilder(
builder: (context, constraints) {
@@ -106,4 +105,4 @@ class SettingsChoicesCell extends StatelessWidget {
),
);
}
}
}
@@ -6,4 +6,4 @@ class SettingsPickerRaw extends StatelessWidget {
// TODO: implement build
throw UnimplementedError();
}
}
}
@@ -58,11 +58,13 @@ class SettingsThemeChoicesCell extends StatelessWidget {
curve: Curves.easeInOut,
margin: EdgeInsets.only(right: 24),
decoration: ShapeDecoration(
shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(cellRadius),
side: BorderSide(
color: isSelected ? Theme.of(context).colorScheme.primary : Colors.transparent,
strokeAlign: BorderSide.strokeAlignOutside)
)),
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(cellRadius),
side: BorderSide(
color: isSelected
? Theme.of(context).colorScheme.primary
: Colors.transparent,
strokeAlign: BorderSide.strokeAlignOutside))),
child: ClipRRect(
borderRadius: BorderRadius.circular(cellRadius),
child: CakeImageWidget(
@@ -97,8 +99,8 @@ class SettingsThemeChoicesCell extends StatelessWidget {
children: [
Padding(
padding: EdgeInsets.only(top: 14),
child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)
),
child: Container(
height: 1, color: Theme.of(context).colorScheme.outlineVariant)),
SizedBox(height: cellHeight),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -123,10 +125,14 @@ class SettingsThemeChoicesCell extends StatelessWidget {
duration: Duration(milliseconds: 350),
opacity: isSelected ? 1 : 0,
child: Container(
width:28,height:28,decoration: BoxDecoration(borderRadius: BorderRadius.circular(99999999),border: Border.all(color:Theme.of(context)
.colorScheme
.onSurface))
),
width: 28,
height: 28,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(99999999),
border: Border.all(
color: Theme.of(context)
.colorScheme
.onSurface))),
),
AnimatedScale(
duration: Duration(milliseconds: 350),
@@ -153,19 +159,19 @@ class SettingsThemeChoicesCell extends StatelessWidget {
if (_displaySettingsViewModel.currentTheme is BlackTheme)
Padding(
padding: EdgeInsets.only(top: 12, bottom: 4),
child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)
),
child:
Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)),
if (_displaySettingsViewModel.currentTheme is BlackTheme)
SettingsSwitcherCell(
height: 40,
title: S.current.oled_mode,
value: _displaySettingsViewModel.isBlackThemeOledEnabled,
onValueChange: (_, bool value) {
_displaySettingsViewModel.setBlackThemeOled(value);
},
padding: EdgeInsets.zero,
switchBackgroundColor: currentTheme.colorScheme.secondaryContainer,
),
SettingsSwitcherCell(
height: 40,
title: S.current.oled_mode,
value: _displaySettingsViewModel.isBlackThemeOledEnabled,
onValueChange: (_, bool value) {
_displaySettingsViewModel.setBlackThemeOled(value);
},
padding: EdgeInsets.zero,
switchBackgroundColor: currentTheme.colorScheme.secondaryContainer,
),
],
),
);

Some files were not shown because too many files have changed in this diff Show More