mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Reformat the whole codebase with 100 line width (#3403)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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] ?? ''
|
||||
: '';
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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>[
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
)),
|
||||
],
|
||||
|
||||
@@ -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,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: [
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
|
||||
@@ -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
@@ -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,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -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 @@
|
||||
enum Attributes {arrow, header, link, switcher, widget, rawWidget}
|
||||
enum Attributes { arrow, header, link, switcher, widget, rawWidget }
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
}),
|
||||
]
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user