Merge branch 'cake-tech:dev' into dev
@@ -252,6 +252,7 @@ import 'package:cake_wallet/view_model/send/fees_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_template_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/send/send_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
|
||||
import 'package:cake_wallet/view_model/settings/connection_sync_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
||||
@@ -1131,7 +1132,9 @@ Future<void> setup({
|
||||
return PowNodeListViewModel(_powNodeSource, appStore);
|
||||
});
|
||||
|
||||
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
|
||||
getIt.registerFactory(() => ConnectionSyncViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
|
||||
|
||||
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<ConnectionSyncViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(),
|
||||
getIt.get<AuthService>(), getIt.get<AppStore>().wallet!.isHardwareWallet));
|
||||
@@ -1140,7 +1143,7 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactory(() => TrocadorProvidersPage(getIt.get<TrocadorProvidersViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => DomainLookupsPage(getIt.get<PrivacySettingsViewModel>()));
|
||||
getIt.registerFactory(() => DomainLookupsPage(getIt.get<ConnectionSyncViewModel>()));
|
||||
|
||||
getIt.registerFactory(() => DisplaySettingsPage(getIt.get<DisplaySettingsViewModel>()));
|
||||
|
||||
@@ -1691,9 +1694,9 @@ Future<void> setup({
|
||||
|
||||
getIt.registerFactoryParam<ManageNodesPage, bool, void>((bool isPow, _) {
|
||||
if (isPow) {
|
||||
return ManageNodesPage(isPow, powNodeListViewModel: getIt.get<PowNodeListViewModel>());
|
||||
return ManageNodesPage(isPow, powNodeListViewModel: getIt.get<PowNodeListViewModel>(), dashboardViewModel: getIt.get<DashboardViewModel>());
|
||||
}
|
||||
return ManageNodesPage(isPow, nodeListViewModel: getIt.get<NodeListViewModel>());
|
||||
return ManageNodesPage(isPow, nodeListViewModel: getIt.get<NodeListViewModel>(), dashboardViewModel: getIt.get<DashboardViewModel>());
|
||||
});
|
||||
|
||||
getIt.registerFactory(
|
||||
|
||||
@@ -2,11 +2,11 @@ import 'dart:math';
|
||||
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
// written by people who happened to read my slack message in 2025
|
||||
@@ -52,61 +52,60 @@ class _AboutPageState extends State<AboutPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(children: [
|
||||
ModalTopBar(
|
||||
title: S.of(context).about,
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: Navigator.of(context).pop,
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
SizedBox(),
|
||||
GestureDetector(
|
||||
onTap: _easterEgg,
|
||||
child: CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/cake_squircle_icon.svg",
|
||||
width: 128,
|
||||
height: 128,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
"Cake Wallet",
|
||||
style: TextStyle(fontSize: 32, fontWeight: FontWeight.w500),
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: S.of(context).about,
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: Navigator.of(context).pop,
|
||||
),
|
||||
content: Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Column(children: [
|
||||
Column(
|
||||
children: [
|
||||
Column(
|
||||
spacing: 16,
|
||||
children: [
|
||||
SizedBox(),
|
||||
GestureDetector(
|
||||
onTap: _easterEgg,
|
||||
child: CakeImageWidget(
|
||||
imageUrl: "assets/new-ui/cake_squircle_icon.svg",
|
||||
width: 128,
|
||||
height: 128,
|
||||
),
|
||||
Text(widget.appVersion,
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant))
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Wrap(
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
_bottomText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
"Cake Wallet",
|
||||
style: TextStyle(fontSize: 32, fontWeight: FontWeight.w500),
|
||||
),
|
||||
Text(widget.appVersion,
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant))
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: NewListSections(sections: {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: Wrap(
|
||||
children: [
|
||||
Text(
|
||||
_bottomText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 32),
|
||||
NewListSections(sections: {
|
||||
"": [
|
||||
ListItemRegularRow(
|
||||
keyValue: "official website",
|
||||
@@ -146,10 +145,10 @@ class _AboutPageState extends State<AboutPage> {
|
||||
foregroundColor: Theme.of(context).colorScheme.primary,
|
||||
trailingIconSize: 10)
|
||||
]
|
||||
}),
|
||||
)
|
||||
],
|
||||
)
|
||||
]));
|
||||
})
|
||||
],
|
||||
)
|
||||
])),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,18 +144,21 @@ class _NewHomePageState extends State<NewHomePage> {
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => AssetsHistorySection(
|
||||
nftViewModel: widget.nftViewModel,
|
||||
dashboardViewModel: widget.dashboardViewModel,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 80.0)
|
||||
],
|
||||
),
|
||||
),]
|
||||
),
|
||||
Container(
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(height: 80.0),
|
||||
)
|
||||
]),
|
||||
Container(
|
||||
height: (MediaQuery.of(context).padding.top),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
|
||||
@@ -449,6 +449,11 @@ class _NewSendPageState extends State<NewSendPage> {
|
||||
fiatInputMode: _fiatInputMode,
|
||||
onSwitchButtonPressed: () {
|
||||
setState(() {
|
||||
if(!_fiatInputMode) {
|
||||
widget.sendViewModel.outputs[_selectedOutput]
|
||||
.cryptoAmount =
|
||||
_amountControllers[_selectedOutput].text;
|
||||
}
|
||||
_fiatInputMode = !_fiatInputMode;
|
||||
_amountControllers[_selectedOutput].text =
|
||||
_fiatInputMode
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||
import "package:cw_core/wallet_type.dart";
|
||||
|
||||
@@ -18,8 +19,12 @@ bool _falseFunc(DashboardViewModel _) => false;
|
||||
|
||||
bool _isBtc(DashboardViewModel vm) => vm.wallet.type == WalletType.bitcoin;
|
||||
|
||||
bool _hasLightning(DashboardViewModel vm) => vm.hasLightning;
|
||||
|
||||
bool _hasMweb(DashboardViewModel vm) => vm.hasMweb;
|
||||
|
||||
bool _hasWalletConnect(DashboardViewModel vm) => vm.hasWalletConnect;
|
||||
|
||||
bool _isCupcake(DashboardViewModel vm) => vm.wallet.hardwareWalletType == HardwareWalletType.cupcake;
|
||||
|
||||
class SettingsListItem {
|
||||
@@ -42,21 +47,21 @@ class SettingsSectionData {
|
||||
const SettingsSectionData(this.title, this.titleIconPath, this.items);
|
||||
|
||||
static SettingsSectionData walletSettings =
|
||||
SettingsSectionData(S.current.wallet_settings, "assets/new-ui/wallet_settings.svg", [
|
||||
SettingsSectionData(S.current.wallet_settings, "assets/new-ui/wallet-setting.svg", [
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/nodes.svg", S.current.nodes, Routes.manageNodes),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/privacy.svg", S.current.privacy, Routes.privacyPage),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/seed.svg", S.current.seed_and_keys, Routes.showKeys,
|
||||
routeArgs: true, requireAuth: true, use2fa: (vm)=>vm.settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/lightning_username.svg",
|
||||
"Lightning ${S.current.username}", Routes.lightningUsernamePage, condition: _isBtc),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/silent-payments.svg", S.current.silent_payments_settings, Routes.silentPaymentsSettings, condition: _isBtc),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/mweb.svg", S.current.litecoin_mweb_settings, Routes.mwebSettings, condition: _hasMweb),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/lightning_username.svg", "Lightning ${S.current.username}", Routes.lightningUsernamePage, condition: _hasLightning),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/wc.svg", S.current.walletConnect, Routes.walletConnectConnectionsListing, condition: _hasWalletConnect),
|
||||
//SettingsListItem("assets/new-ui/settings_row_icons/silent-payments.svg", S.current.silent_payments_settings, Routes.silentPaymentsSettings, condition: _isBtc),
|
||||
//SettingsListItem("assets/new-ui/settings_row_icons/mweb.svg", S.current.litecoin_mweb_settings, Routes.mwebSettings, condition: _hasMweb),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/cupcake.svg", S.current.export_outputs, Routes.urqrAnimatedPage, routeArgs: {'export-outputs': 'export-outputs'}, condition: _isCupcake),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/other.svg", S.current.other, Routes.otherSettingsPage),
|
||||
]);
|
||||
|
||||
static SettingsSectionData appSettings =
|
||||
SettingsSectionData(S.current.app_settings, "assets/new-ui/app_settings.svg", [
|
||||
SettingsSectionData(S.current.app_settings, "assets/new-ui/cake-setting.svg", [
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/connections.svg", S.current.connections, Routes.connectionSync),
|
||||
// SettingsListItem("assets/new-ui/settings_row_icons/defaults.svg", "Defaults", ""),
|
||||
SettingsListItem("assets/new-ui/settings_row_icons/display.svg", S.current.display, Routes.displaySettingsPage),
|
||||
@@ -97,29 +102,26 @@ class SettingsMainPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Map<String, List<ListItem>> sections =
|
||||
Map.fromEntries(SettingsSectionData.all.map((section) => MapEntry(
|
||||
section.title,
|
||||
section.items
|
||||
.map((item) => item.condition(dashboardViewModel)
|
||||
? ListItemRegularRow(
|
||||
keyValue: item.title,
|
||||
label: item.title,
|
||||
iconPath: item.iconPath,
|
||||
onTap: () {
|
||||
if (item.route.isNotEmpty) {
|
||||
if(item.requireAuth) {
|
||||
authService.authenticateAction(context,
|
||||
conditionToDetermineIfToUse2FA: item.use2fa(dashboardViewModel),
|
||||
route: item.route);
|
||||
} else {
|
||||
Navigator.of(context).pushNamed(item.route, arguments: item.routeArgs);
|
||||
}
|
||||
}
|
||||
})
|
||||
: null)
|
||||
.whereType<ListItem>()
|
||||
.toList())));
|
||||
List<ListItem> buildItems(SettingsSectionData section) => section.items
|
||||
.map((item) => item.condition(dashboardViewModel)
|
||||
? ListItemRegularRow(
|
||||
keyValue: item.title,
|
||||
label: item.title,
|
||||
iconPath: item.iconPath,
|
||||
onTap: () {
|
||||
if (item.route.isNotEmpty) {
|
||||
if (item.requireAuth) {
|
||||
authService.authenticateAction(context,
|
||||
conditionToDetermineIfToUse2FA: item.use2fa(dashboardViewModel),
|
||||
route: item.route);
|
||||
} else {
|
||||
Navigator.of(context).pushNamed(item.route, arguments: item.routeArgs);
|
||||
}
|
||||
}
|
||||
})
|
||||
: null)
|
||||
.whereType<ListItem>()
|
||||
.toList();
|
||||
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
@@ -131,12 +133,31 @@ class SettingsMainPage extends StatelessWidget {
|
||||
onTrailingPressed: () {},
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
controller: ModalScrollController.of(context),
|
||||
children: [Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 20.0),
|
||||
child: NewListSections(
|
||||
sections: sections,
|
||||
child: ListView(controller: ModalScrollController.of(context), children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
children: SettingsSectionData.all.expand((section) {
|
||||
return [
|
||||
if (section.titleIconPath.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
SvgPicture.asset(section.titleIconPath,
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
BlendMode.srcIn,
|
||||
)),
|
||||
Text(section.title, style: Theme.of(context).textTheme.titleMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
NewListSections(sections: {section.title: buildItems(section)}),
|
||||
];
|
||||
}).toList(),
|
||||
),
|
||||
),]
|
||||
),
|
||||
|
||||
@@ -480,133 +480,135 @@ class _NewSwapPageState extends State<NewSwapPage> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
Observer(
|
||||
builder: (_) => SwapAmountBox(
|
||||
isReceiverCard: false,
|
||||
walletSwitcherViewModel: widget.walletSwitcherViewModel,
|
||||
exchangeViewModel: widget.exchangeViewModel,
|
||||
onDispose: disposeBestRateSync,
|
||||
hasAllAmount: widget.exchangeViewModel.hasAllAmount,
|
||||
allAmount: widget.exchangeViewModel.hasAllAmount
|
||||
? () => widget.exchangeViewModel.enableSendAllAmount()
|
||||
: null,
|
||||
key: depositKey,
|
||||
title: S.of(context).send,
|
||||
initialCurrency: widget.exchangeViewModel.depositCurrency,
|
||||
hasRefundAddress: true,
|
||||
currencies: widget.exchangeViewModel.depositCurrencies,
|
||||
onCurrencySelected: (currency) {
|
||||
if (currency is CryptoCurrency) {
|
||||
widget.exchangeViewModel
|
||||
.changeDepositCurrency(currency: currency);
|
||||
}
|
||||
},
|
||||
currencyValueValidator: (value) {
|
||||
return !widget.exchangeViewModel.isFixedRateMode &&
|
||||
value != S.of(context).all
|
||||
? AmountValidator(
|
||||
isAutovalidate: true,
|
||||
currency: widget.exchangeViewModel.isFixedRateMode
|
||||
? widget.exchangeViewModel.receiveCurrency
|
||||
: widget.exchangeViewModel.depositCurrency,
|
||||
minValue: widget.exchangeViewModel.limits.min.toString(),
|
||||
maxValue: widget.exchangeViewModel.limits.max.toString(),
|
||||
amountParsingProxy:
|
||||
widget.exchangeViewModel.amountParsingProxy,
|
||||
).call(value)
|
||||
: null;
|
||||
},
|
||||
addressTextFieldValidator: AddressValidator(
|
||||
type: widget.exchangeViewModel.depositCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
widget.exchangeViewModel.depositAddress = clipboard?.text ?? '';
|
||||
RepaintBoundary(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
Observer(
|
||||
builder: (_) => SwapAmountBox(
|
||||
isReceiverCard: false,
|
||||
walletSwitcherViewModel: widget.walletSwitcherViewModel,
|
||||
exchangeViewModel: widget.exchangeViewModel,
|
||||
onDispose: disposeBestRateSync,
|
||||
hasAllAmount: widget.exchangeViewModel.hasAllAmount,
|
||||
allAmount: widget.exchangeViewModel.hasAllAmount
|
||||
? () => widget.exchangeViewModel.enableSendAllAmount()
|
||||
: null,
|
||||
key: depositKey,
|
||||
title: S.of(context).send,
|
||||
initialCurrency: widget.exchangeViewModel.depositCurrency,
|
||||
hasRefundAddress: true,
|
||||
currencies: widget.exchangeViewModel.depositCurrencies,
|
||||
onCurrencySelected: (currency) {
|
||||
if (currency is CryptoCurrency) {
|
||||
widget.exchangeViewModel
|
||||
.changeDepositCurrency(currency: currency);
|
||||
}
|
||||
},
|
||||
currencyValueValidator: (value) {
|
||||
return !widget.exchangeViewModel.isFixedRateMode &&
|
||||
value != S.of(context).all
|
||||
? AmountValidator(
|
||||
isAutovalidate: true,
|
||||
currency: widget.exchangeViewModel.isFixedRateMode
|
||||
? widget.exchangeViewModel.receiveCurrency
|
||||
: widget.exchangeViewModel.depositCurrency,
|
||||
minValue: widget.exchangeViewModel.limits.min.toString(),
|
||||
maxValue: widget.exchangeViewModel.limits.max.toString(),
|
||||
amountParsingProxy:
|
||||
widget.exchangeViewModel.amountParsingProxy,
|
||||
).call(value)
|
||||
: null;
|
||||
},
|
||||
addressTextFieldValidator: AddressValidator(
|
||||
type: widget.exchangeViewModel.depositCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
widget.exchangeViewModel.depositAddress = clipboard?.text ?? '';
|
||||
|
||||
final domain = widget.exchangeViewModel.depositAddress;
|
||||
widget.exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.depositCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = widget.exchangeViewModel.depositAddress;
|
||||
widget.exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.depositCurrency);
|
||||
},
|
||||
final domain = widget.exchangeViewModel.depositAddress;
|
||||
widget.exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.depositCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = widget.exchangeViewModel.depositAddress;
|
||||
widget.exchangeViewModel.depositAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.depositCurrency);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SwapLimitPopup(exchangeViewModel: widget.exchangeViewModel),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
height: 1,
|
||||
width: double.infinity,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
ModernButton.svg(
|
||||
size: 36,
|
||||
iconSize: 24,
|
||||
svgPath: "assets/new-ui/swap_amounts.svg",
|
||||
onPressed: widget.exchangeViewModel.reverseSwapDirection,
|
||||
),
|
||||
],
|
||||
SwapLimitPopup(exchangeViewModel: widget.exchangeViewModel),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
height: 1,
|
||||
width: double.infinity,
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
),
|
||||
ModernButton.svg(
|
||||
size: 36,
|
||||
iconSize: 24,
|
||||
svgPath: "assets/new-ui/swap_amounts.svg",
|
||||
onPressed: widget.exchangeViewModel.reverseSwapDirection,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => SwapAmountBox(
|
||||
isReceiverCard: true,
|
||||
walletSwitcherViewModel: widget.walletSwitcherViewModel,
|
||||
exchangeViewModel: widget.exchangeViewModel,
|
||||
onDispose: disposeBestRateSync,
|
||||
key: receiveKey,
|
||||
title: S.of(context).receive,
|
||||
initialCurrency: widget.exchangeViewModel.receiveCurrency,
|
||||
currencies: widget.exchangeViewModel.receiveCurrencies,
|
||||
onCurrencySelected: (currency) {
|
||||
if (currency is CryptoCurrency) {
|
||||
widget.exchangeViewModel
|
||||
.changeReceiveCurrency(currency: currency);
|
||||
}
|
||||
},
|
||||
currencyValueValidator: (value) {
|
||||
return widget.exchangeViewModel.isFixedRateMode
|
||||
? AmountValidator(
|
||||
isAutovalidate: true,
|
||||
currency: widget.exchangeViewModel.receiveCurrency,
|
||||
minValue: widget.exchangeViewModel.limits.min.toString(),
|
||||
maxValue: widget.exchangeViewModel.limits.max.toString(),
|
||||
amountParsingProxy:
|
||||
widget.exchangeViewModel.amountParsingProxy,
|
||||
).call(value)
|
||||
: null;
|
||||
},
|
||||
addressTextFieldValidator: AddressValidator(
|
||||
type: widget.exchangeViewModel.receiveCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
widget.exchangeViewModel.receiveAddress = clipboard?.text ?? '';
|
||||
Observer(
|
||||
builder: (_) => SwapAmountBox(
|
||||
isReceiverCard: true,
|
||||
walletSwitcherViewModel: widget.walletSwitcherViewModel,
|
||||
exchangeViewModel: widget.exchangeViewModel,
|
||||
onDispose: disposeBestRateSync,
|
||||
key: receiveKey,
|
||||
title: S.of(context).receive,
|
||||
initialCurrency: widget.exchangeViewModel.receiveCurrency,
|
||||
currencies: widget.exchangeViewModel.receiveCurrencies,
|
||||
onCurrencySelected: (currency) {
|
||||
if (currency is CryptoCurrency) {
|
||||
widget.exchangeViewModel
|
||||
.changeReceiveCurrency(currency: currency);
|
||||
}
|
||||
},
|
||||
currencyValueValidator: (value) {
|
||||
return widget.exchangeViewModel.isFixedRateMode
|
||||
? AmountValidator(
|
||||
isAutovalidate: true,
|
||||
currency: widget.exchangeViewModel.receiveCurrency,
|
||||
minValue: widget.exchangeViewModel.limits.min.toString(),
|
||||
maxValue: widget.exchangeViewModel.limits.max.toString(),
|
||||
amountParsingProxy:
|
||||
widget.exchangeViewModel.amountParsingProxy,
|
||||
).call(value)
|
||||
: null;
|
||||
},
|
||||
addressTextFieldValidator: AddressValidator(
|
||||
type: widget.exchangeViewModel.receiveCurrency),
|
||||
onPushPasteButton: (context) async {
|
||||
final clipboard = await Clipboard.getData('text/plain');
|
||||
widget.exchangeViewModel.receiveAddress = clipboard?.text ?? '';
|
||||
|
||||
final domain = widget.exchangeViewModel.receiveAddress;
|
||||
widget.exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = widget.exchangeViewModel.receiveAddress;
|
||||
widget.exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
final domain = widget.exchangeViewModel.receiveAddress;
|
||||
widget.exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
onPushAddressBookButton: (context) async {
|
||||
final domain = widget.exchangeViewModel.receiveAddress;
|
||||
widget.exchangeViewModel.receiveAddress =
|
||||
await fetchParsedAddress(context, domain,
|
||||
widget.exchangeViewModel.receiveCurrency);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Observer(
|
||||
|
||||
@@ -68,9 +68,9 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
if(tabs.length>1)
|
||||
return SliverMainAxisGroup(
|
||||
slivers: [
|
||||
// if(tabs.length>1)
|
||||
AssetsTopBar(
|
||||
dashboardViewModel: widget.dashboardViewModel,
|
||||
tabs: tabs.map((item) => item.title).toList(),
|
||||
|
||||
@@ -15,45 +15,47 @@ class AssetsSection extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 64.0),
|
||||
child: Observer(
|
||||
builder: (context) {
|
||||
final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
return Observer(builder: (context) {
|
||||
if (hasMweb) {
|
||||
return SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 64.0),
|
||||
child: Observer(
|
||||
builder: (context) {
|
||||
final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.zero,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
|
||||
itemBuilder: (context, index) {
|
||||
return Observer(builder: (context) {
|
||||
if (hasMweb) {
|
||||
return AssetTile(
|
||||
showSwap: dashboardViewModel.isEnabledSwapAction,
|
||||
balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
|
||||
showSecondary: index > 0 ? true : false,
|
||||
wallet: dashboardViewModel.wallet,
|
||||
chainIconPath: index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
|
||||
trailingText: index > 0 ? "MWEB" : null,
|
||||
modalMode: index > 0
|
||||
? AssetDetailsModalModes.ltcPrivate
|
||||
: AssetDetailsModalModes.ltcTransparent,
|
||||
title: index > 0 ? "Litecoin Private" : null,
|
||||
);
|
||||
}
|
||||
|
||||
final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
|
||||
return AssetTile(
|
||||
showSwap: dashboardViewModel.isEnabledSwapAction,
|
||||
balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
|
||||
showSecondary: index > 0 ? true : false,
|
||||
balance: balance,
|
||||
wallet: dashboardViewModel.wallet,
|
||||
chainIconPath: index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
|
||||
trailingText: index > 0 ? "MWEB" : null,
|
||||
modalMode: index > 0
|
||||
? AssetDetailsModalModes.ltcPrivate
|
||||
: AssetDetailsModalModes.ltcTransparent,
|
||||
title: index > 0 ? "Litecoin Private" : null,
|
||||
chainIconPath: _getChainIconPath(),
|
||||
);
|
||||
}
|
||||
|
||||
final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
|
||||
return AssetTile(
|
||||
showSwap: dashboardViewModel.isEnabledSwapAction,
|
||||
balance: balance,
|
||||
wallet: dashboardViewModel.wallet,
|
||||
chainIconPath: _getChainIconPath(),
|
||||
);
|
||||
});
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/line_tab_switcher.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -21,28 +23,37 @@ class AssetsTopBar extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasTokenSettingsButton = tabs[selectedTab] == S.of(context).assets && dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled;
|
||||
final settingsButtonText = _getSettingsButtonText();
|
||||
final hasTokenSettingsButton = settingsButtonText != null;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0, left: 12.0, right: 18.0),
|
||||
child: Row(
|
||||
return SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 12.0, bottom: 12.0, left: 12.0, right: 18.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if(tabs.length > 1)
|
||||
LineTabSwitcher(
|
||||
tabs: tabs,
|
||||
onTabChange: onTabChange,
|
||||
selectedTab: selectedTab,
|
||||
),
|
||||
)
|
||||
else SizedBox.shrink(),
|
||||
Opacity(
|
||||
opacity: hasTokenSettingsButton ? 1 : 0,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (hasTokenSettingsButton) {
|
||||
if (tabs[selectedTab] == S.of(context).assets) {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.homeSettings,
|
||||
arguments: dashboardViewModel.balanceViewModel,
|
||||
);
|
||||
} else if(tabs[selectedTab] == S.of(context).history) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (context) => FilterWidget(filterItems: dashboardViewModel.filterItems),
|
||||
);
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@@ -64,17 +75,28 @@ class AssetsTopBar extends StatelessWidget {
|
||||
colorFilter: ColorFilter.mode(
|
||||
Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
|
||||
Text(
|
||||
S.of(context).tokens,
|
||||
settingsButtonText??"",
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.primary),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String? _getSettingsButtonText() {
|
||||
if (tabs[selectedTab] == S.current.assets &&
|
||||
dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled) {
|
||||
return S.current.tokens;
|
||||
}
|
||||
|
||||
if (tabs[selectedTab] == S.current.history) {
|
||||
return S.current.filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,26 +27,29 @@ class HistorySection extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Observer(
|
||||
builder: (_) => (dashboardViewModel.items.isEmpty &&
|
||||
dashboardViewModel.status is! SyncingSyncStatus)
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
child: Text(S.of(context).transactions_will_appear_here,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant)))
|
||||
: ListView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: EdgeInsets.zero,
|
||||
shrinkWrap: true,
|
||||
itemCount: dashboardViewModel.items.length,
|
||||
itemBuilder: (context, index) => Observer(builder: (_) {
|
||||
final prevItem = index == 0 ? null : dashboardViewModel.items[index - 1];
|
||||
final item = dashboardViewModel.items[index];
|
||||
return SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
sliver: Observer(
|
||||
builder: (_) => (dashboardViewModel.items.isEmpty &&
|
||||
dashboardViewModel.status is! SyncingSyncStatus)
|
||||
? SliverPadding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: Center(
|
||||
child: Text(S.of(context).transactions_will_appear_here,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant)),
|
||||
),
|
||||
),
|
||||
)
|
||||
: SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
childCount: dashboardViewModel.items.length,
|
||||
(context, index) => Observer(builder: (_) {
|
||||
final prevItem = index == 0 ? null : dashboardViewModel.items[index - 1];
|
||||
final item = dashboardViewModel.items[index];
|
||||
final nextItem = index == dashboardViewModel.items.length - 1
|
||||
? null
|
||||
: dashboardViewModel.items[index + 1];
|
||||
@@ -163,6 +166,6 @@ class HistorySection extends StatelessWidget {
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ class HistoryTile extends StatelessWidget {
|
||||
return Stack(
|
||||
children: [
|
||||
CakeImageWidget(imageUrl:
|
||||
"assets/images/lightning-icon.svg",
|
||||
"assets/new-ui/lightning-icon.svg",
|
||||
width: 34,
|
||||
height: 34,
|
||||
),
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import 'package:cake_wallet/core/sync_status_title.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/coins_page/top_bar_widget/pulsing_dot.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||
|
||||
class SyncBar extends StatelessWidget {
|
||||
SyncBar({super.key, required this.dashboardViewModel, required this.isSyncHeavy});
|
||||
@@ -62,7 +64,13 @@ class SyncBar extends StatelessWidget {
|
||||
if (_showFullBar())
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.of(context, rootNavigator: true).pushNamed(Routes.connectionSync);
|
||||
CupertinoScaffold.showCupertinoModalBottomSheet(
|
||||
context: context,
|
||||
barrierColor: Colors.black.withAlpha(85),
|
||||
builder: (context) => FractionallySizedBox(
|
||||
child: Material(
|
||||
child: getIt.get<ManageNodesPage>(param1: false),
|
||||
)));
|
||||
},
|
||||
child: AnimatedSwitcher(
|
||||
duration: Duration(milliseconds: 100),
|
||||
@@ -162,7 +170,7 @@ class SyncBar extends StatelessWidget {
|
||||
children.add(CakeImageWidget(imageUrl:
|
||||
"assets/new-ui/mweb_sync.svg",
|
||||
colorFilter:
|
||||
ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
|
||||
ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
|
||||
));
|
||||
}
|
||||
if (dashboardViewModel.hasSilentPayments) {
|
||||
@@ -186,4 +194,4 @@ class SyncBar extends StatelessWidget {
|
||||
bool _showDot() {
|
||||
return !isSyncHeavy && progressStatuses.contains(dashboardViewModel.status.runtimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||
|
||||
void nothing(){}
|
||||
|
||||
class ModalPageWrapper extends StatelessWidget {
|
||||
ModalPageWrapper(
|
||||
{super.key,
|
||||
required this.content,
|
||||
required this.topBar,
|
||||
this.header,
|
||||
this.bottomContent,
|
||||
this.horizontalPadding = 18.0,
|
||||
this.verticalPadding = 72.0}) {
|
||||
}
|
||||
|
||||
final Widget content;
|
||||
final Widget? bottomContent;
|
||||
final ModalTopBar topBar;
|
||||
final ModalHeader? header;
|
||||
final double horizontalPadding;
|
||||
final double verticalPadding;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const gradientSize = 84;
|
||||
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
body: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
|
||||
child: CustomScrollView(
|
||||
controller: ModalScrollController.of(context),
|
||||
physics: ClampingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverToBoxAdapter(child: SizedBox(height: verticalPadding)),
|
||||
if (header != null) ...[
|
||||
SliverToBoxAdapter(child: header),
|
||||
SliverToBoxAdapter(child: SizedBox(height: 20)),
|
||||
],
|
||||
SliverSafeArea(sliver: SliverToBoxAdapter(child: content)),
|
||||
SliverToBoxAdapter(child: SizedBox(height: verticalPadding)),
|
||||
],
|
||||
)
|
||||
)),
|
||||
if (bottomContent != null)
|
||||
Positioned(
|
||||
bottom: 12,
|
||||
left: horizontalPadding,
|
||||
right: horizontalPadding,
|
||||
child: SafeArea(child: bottomContent!),
|
||||
),
|
||||
Container(
|
||||
height: (MediaQuery.of(context).padding.top + gradientSize),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.bottomCenter,
|
||||
end: Alignment.topCenter,
|
||||
colors: <Color>[
|
||||
Theme.of(context).colorScheme.surface.withAlpha(5),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(25),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(50),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(100),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(150),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(200),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(235),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(255),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(255),
|
||||
Theme.of(context).colorScheme.surface.withAlpha(255),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
topBar,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_v
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
import '../../../src/screens/receive/widgets/qr_image.dart';
|
||||
|
||||
@@ -22,40 +21,57 @@ class ReceiveQrCode extends StatelessWidget {
|
||||
final bool largeQrMode;
|
||||
final WalletAddressListViewModel addressListViewModel;
|
||||
|
||||
static const double largeQrModeBottomPadding = 70;
|
||||
static const double largeQrModeBottomPadding = 140;
|
||||
static const Duration animDuration = Duration(milliseconds: 500);
|
||||
final bool isLightMode = !(getIt.get<ThemeStore>().currentTheme.isDark);
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double targetY = largeQrMode ? 60 : 0;
|
||||
final double resolvedSize = MediaQuery.of(context).size.width * (largeQrMode ? 0.85 : 0.5);
|
||||
final double targetY = largeQrMode ? largeQrModeBottomPadding+50 : 0;
|
||||
final double resolvedSize = MediaQuery.of(context).size.width * 0.5;
|
||||
final double resolvedScale = largeQrMode ? 1.7 : 1;
|
||||
|
||||
return Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
duration: Duration(milliseconds: 300),
|
||||
opacity: largeQrMode ? 1 : 0,
|
||||
child: CakeImageWidget(imageUrl:
|
||||
isLightMode
|
||||
? "assets/new-ui/cakewallet-wordmark-light.svg"
|
||||
: "assets/new-ui/cakewallet-wordmark.svg",
|
||||
height: 45,
|
||||
)),
|
||||
AnimatedSlide(
|
||||
curve: Curves.easeOutCubic,
|
||||
duration: animDuration,
|
||||
offset: largeQrMode ? Offset(0, -1) : Offset.zero,
|
||||
child: AnimatedOpacity(
|
||||
duration: animDuration,
|
||||
opacity: largeQrMode ? 1 : 0,
|
||||
child: CakeImageWidget(imageUrl:
|
||||
isLightMode
|
||||
? "assets/new-ui/cakewallet-wordmark-light.svg"
|
||||
: "assets/new-ui/cakewallet-wordmark.svg",
|
||||
height: 45,
|
||||
)),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onTap,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: TweenAnimationBuilder<double>(
|
||||
tween: Tween<double>(begin: 0, end: targetY),
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeOut,
|
||||
builder: (context, value, child) {
|
||||
return Transform.translate(
|
||||
offset: Offset(0, value),
|
||||
child: Observer(
|
||||
builder: (_)=>Column(
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
tween: Tween<double>(begin: 0, end: targetY),
|
||||
duration: animDuration,
|
||||
curve: Curves.easeOutCubic,
|
||||
builder: (context, value, child) {
|
||||
return Transform.translate(
|
||||
offset: Offset(0, value),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Observer(
|
||||
builder: (_) => Column(
|
||||
children: [
|
||||
AnimatedScale(
|
||||
curve: Curves.easeOutCubic,
|
||||
alignment: Alignment.bottomCenter,
|
||||
scale: resolvedScale,
|
||||
duration: animDuration,
|
||||
child: AnimatedContainer(
|
||||
duration: animDuration,
|
||||
curve: Curves.easeOutCubic,
|
||||
width: resolvedSize,
|
||||
height: resolvedSize,
|
||||
@@ -71,49 +87,47 @@ class ReceiveQrCode extends StatelessWidget {
|
||||
: Colors.transparent),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => Observer(
|
||||
builder: (_) => QrImage(
|
||||
data: addressListViewModel.uri.toString(),
|
||||
embeddedImagePath:
|
||||
addressListViewModel.tokenCurrency != null
|
||||
? addressListViewModel.tokenCurrency == CryptoCurrency.btcln
|
||||
? addressListViewModel.qrImage
|
||||
: addressListViewModel.tokenCurrency!.iconPath
|
||||
: addressListViewModel.qrImage,
|
||||
size: constraints.maxWidth)))),
|
||||
child: Observer(
|
||||
builder: (_) => QrImage(
|
||||
data: addressListViewModel.uri.toString(),
|
||||
size: resolvedSize,
|
||||
embeddedImagePath:
|
||||
addressListViewModel.tokenCurrency != null
|
||||
? addressListViewModel.tokenCurrency ==
|
||||
CryptoCurrency.btcln
|
||||
? addressListViewModel.qrImage
|
||||
: addressListViewModel.tokenCurrency!.iconPath
|
||||
: addressListViewModel.qrImage,
|
||||
))),
|
||||
),
|
||||
),
|
||||
if (addressListViewModel.hasPayjoin)
|
||||
Opacity(
|
||||
opacity: largeQrMode ? 0 : 1,
|
||||
child: Container(
|
||||
width:resolvedSize,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.vertical(bottom: Radius.circular(16)),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
CakeImageWidget(imageUrl: "assets/new-ui/payjoin.svg"),
|
||||
Text(S.of(context).payjoin_enabled)
|
||||
],
|
||||
),
|
||||
))),
|
||||
AnimatedSize(
|
||||
duration: Duration(milliseconds: 300),
|
||||
// curve: Curves.easeOutCubic,
|
||||
child: SizedBox(height: largeQrMode ? largeQrModeBottomPadding : 0))
|
||||
],
|
||||
),
|
||||
),
|
||||
if (addressListViewModel.hasPayjoin)
|
||||
Opacity(
|
||||
opacity: largeQrMode ? 0 : 1,
|
||||
child: Container(
|
||||
width: resolvedSize,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(16)),
|
||||
color: Theme.of(context).colorScheme.surfaceContainer),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 4,
|
||||
children: [
|
||||
CakeImageWidget(imageUrl:"assets/new-ui/payjoin.svg"),
|
||||
Text(S.of(context).payjoin_enabled)
|
||||
],
|
||||
),
|
||||
))),
|
||||
AnimatedSize(
|
||||
duration: animDuration,
|
||||
curve: Curves.easeOutCubic,
|
||||
child: SizedBox(height: largeQrMode ? largeQrModeBottomPadding+40 : 0))
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -6,14 +6,14 @@ void nothing(){}
|
||||
class ModalTopBar extends StatelessWidget {
|
||||
ModalTopBar(
|
||||
{super.key,
|
||||
required this.title,
|
||||
required this.title,
|
||||
this.subtitle,
|
||||
this.onLeadingPressed=nothing,
|
||||
this.onTrailingPressed=nothing,
|
||||
this.leadingIcon,
|
||||
this.trailingIcon,
|
||||
this.leadingWidget,
|
||||
this.trailingWidget}) {
|
||||
this.onLeadingPressed=nothing,
|
||||
this.onTrailingPressed=nothing,
|
||||
this.leadingIcon,
|
||||
this.trailingIcon,
|
||||
this.leadingWidget,
|
||||
this.trailingWidget}) {
|
||||
if(leadingIcon != null && leadingWidget != null) {
|
||||
throw Exception("Cannot have both leadingIcon and leadingWidget");
|
||||
}
|
||||
@@ -38,10 +38,10 @@ class ModalTopBar extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(18),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
Positioned(
|
||||
top: 6,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -72,11 +72,11 @@ class ModalTopBar extends StatelessWidget {
|
||||
if (leadingIcon != null || leadingWidget != null)
|
||||
leadingIcon != null
|
||||
? ModernButton(
|
||||
key: ValueKey(leadingIcon.hashCode),
|
||||
size: buttonSize,
|
||||
onPressed: onLeadingPressed,
|
||||
icon: leadingIcon!,
|
||||
iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
|
||||
key: ValueKey(leadingIcon.hashCode),
|
||||
size: buttonSize,
|
||||
onPressed: onLeadingPressed,
|
||||
icon: leadingIcon!,
|
||||
iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
|
||||
: leadingWidget!
|
||||
else
|
||||
Container(width: buttonSize),
|
||||
@@ -85,10 +85,10 @@ class ModalTopBar extends StatelessWidget {
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: trailingIcon != null
|
||||
? ModernButton(
|
||||
key: ValueKey(trailingIcon.hashCode),
|
||||
size: buttonSize,
|
||||
onPressed: onTrailingPressed,
|
||||
icon: trailingIcon!,)
|
||||
key: ValueKey(trailingIcon.hashCode),
|
||||
size: buttonSize,
|
||||
onPressed: onTrailingPressed,
|
||||
icon: trailingIcon!,)
|
||||
: trailingWidget!,
|
||||
)
|
||||
else
|
||||
@@ -99,4 +99,4 @@ class ModalTopBar extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,8 @@ abstract class BasePage extends StatelessWidget {
|
||||
|
||||
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||
|
||||
bool get hideAppBar => false;
|
||||
|
||||
Widget Function(BuildContext, Widget)? get rootWrapper => null;
|
||||
|
||||
MaterialThemeBase get currentTheme => getIt.get<ThemeStore>().currentTheme;
|
||||
@@ -191,24 +193,21 @@ abstract class BasePage extends StatelessWidget {
|
||||
: null,
|
||||
// color: Colors.grey[200],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top:6.0),
|
||||
child: Scaffold(
|
||||
key: _scaffoldKey,
|
||||
backgroundColor: pageBackgroundColor(context),
|
||||
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
|
||||
extendBodyBehindAppBar: extendBodyBehindAppBar,
|
||||
endDrawer: endDrawer,
|
||||
appBar: appBar(context),
|
||||
body: SafeArea(
|
||||
left: false,
|
||||
right: false,
|
||||
top: false,
|
||||
bottom: Platform.isAndroid,
|
||||
child: body(context),
|
||||
),
|
||||
floatingActionButton: floatingActionButton(context),
|
||||
child: Scaffold(
|
||||
key: _scaffoldKey,
|
||||
backgroundColor: pageBackgroundColor(context),
|
||||
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
|
||||
extendBodyBehindAppBar: extendBodyBehindAppBar,
|
||||
endDrawer: endDrawer,
|
||||
appBar: hideAppBar ? null : appBar(context),
|
||||
body: SafeArea(
|
||||
left: false,
|
||||
right: false,
|
||||
top: false,
|
||||
bottom: Platform.isAndroid,
|
||||
child: body(context),
|
||||
),
|
||||
floatingActionButton: floatingActionButton(context),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -31,38 +31,40 @@ class _NFTListingPageState extends State<NFTListingPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
child: PrimaryButton(
|
||||
text: S.current.import,
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
textColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context,
|
||||
Routes.importNFTPage,
|
||||
arguments: widget.nftViewModel,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.nftViewModel.isLoading)
|
||||
Center(
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Theme.of(context).colorScheme.primary,
|
||||
return SliverToBoxAdapter(
|
||||
child: Observer(
|
||||
builder: (context) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
child: PrimaryButton(
|
||||
text: S.current.import,
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
textColor: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
onPressed: () => Navigator.pushNamed(
|
||||
context,
|
||||
Routes.importNFTPage,
|
||||
arguments: widget.nftViewModel,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
NFTListWidget(nftViewModel: widget.nftViewModel)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
if (widget.nftViewModel.isLoading)
|
||||
Center(
|
||||
child: CircularProgressIndicator(
|
||||
backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
NFTListWidget(nftViewModel: widget.nftViewModel)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:cake_wallet/entities/new_ui_entities/list_item/list_Item_checkbo
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_text_field.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -140,6 +141,7 @@ class NodeFormState extends State<NodeForm> {
|
||||
initialValue: vm.socksProxyAddress,
|
||||
validator: SocksProxyNodeAddressValidator(),
|
||||
),
|
||||
if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
|
||||
ListItemCheckbox(
|
||||
keyValue: vm.autoSwitchingUIKey,
|
||||
label: S.current.enable_for_auto_switching,
|
||||
|
||||
@@ -7,11 +7,12 @@ import 'package:flutter/material.dart';
|
||||
class NodeListRow extends StandardListRow {
|
||||
NodeListRow(
|
||||
{required String title,
|
||||
String? subtitle,
|
||||
required this.node,
|
||||
required void Function(BuildContext context) onTap,
|
||||
required bool isSelected,
|
||||
required this.isPow})
|
||||
: super(title: title, onTap: onTap, isSelected: isSelected);
|
||||
: super(title: title, onTap: onTap, isSelected: isSelected, subtitle: subtitle);
|
||||
|
||||
final Node node;
|
||||
final bool isPow;
|
||||
|
||||
@@ -227,262 +227,264 @@ class SendPage extends BasePage {
|
||||
!sendViewModel.balanceViewModel.isReversing,
|
||||
onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
|
||||
!sendViewModel.balanceViewModel.isReversing,
|
||||
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,
|
||||
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) {
|
||||
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) {
|
||||
int amount = 0;
|
||||
for (var item in sendViewModel.outputs) {
|
||||
amount += item.formattedCryptoAmount;
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
int amount = 0;
|
||||
for (var item in sendViewModel.outputs) {
|
||||
amount += item.formattedCryptoAmount;
|
||||
}
|
||||
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,
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -1,119 +1,219 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/wallet_connect_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/connection_sync_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ConnectionSyncPage extends BasePage {
|
||||
ConnectionSyncPage(this.dashboardViewModel);
|
||||
ConnectionSyncPage(this._connectionSyncViewModel);
|
||||
|
||||
@override
|
||||
String get title => S.current.connection_sync;
|
||||
bool get hideAppBar => true;
|
||||
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
final ConnectionSyncViewModel _connectionSyncViewModel;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: "",
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: () => Navigator.of(context).pop()),
|
||||
header: ModalHeader(
|
||||
iconPath: "assets/new-ui/settings_row_icons/connections.svg",
|
||||
message: S.of(context).connections_desc,
|
||||
title: S.of(context).connections),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.reconnect,
|
||||
handler: (context) => _presentReconnectAlert(context),
|
||||
),
|
||||
if (dashboardViewModel.hasRescan) ...[
|
||||
SettingsCellWithArrow(
|
||||
title: dashboardViewModel.hasSilentPayments
|
||||
? S.current.silent_payments_scanning
|
||||
: S.current.rescan,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),
|
||||
),
|
||||
],
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.manage_nodes,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes),
|
||||
),
|
||||
if (Platform.isAndroid && FeatureFlag.isBackgroundSyncEnabled) ...[
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.background_sync,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.backgroundSync),
|
||||
),
|
||||
],
|
||||
Observer(
|
||||
builder: (context) {
|
||||
if (!dashboardViewModel.hasPowNodes) return const SizedBox();
|
||||
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.setUsePolygonScan(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.setUsePolygonScan(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(
|
||||
alertTitle: S.of(context).warning,
|
||||
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));
|
||||
}) ??
|
||||
false;
|
||||
if (confirmation) {
|
||||
_connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.manage_pow_nodes,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.managePowNodes),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
_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;
|
||||
|
||||
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 (isWalletConnectCompatibleChain(dashboardViewModel.wallet.type) &&
|
||||
!dashboardViewModel.wallet.isHardwareWallet) ...[ // ToDo: Remove this line once WalletConnect is implemented
|
||||
WalletConnectTile(
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.walletConnectConnectionsListing),
|
||||
),
|
||||
],
|
||||
if (FeatureFlag.isInAppTorEnabled)
|
||||
Observer(builder: (context) {
|
||||
return SettingsSwitcherCell(
|
||||
leading: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 1),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.shade100,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
),
|
||||
child: Text(
|
||||
'Alpha',
|
||||
style: TextStyle(
|
||||
color: Colors.red.shade700,
|
||||
fontSize: 8,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
title: S.current.enable_builtin_tor,
|
||||
value: dashboardViewModel.builtinTor,
|
||||
onValueChange: (_, bool value) => dashboardViewModel.setBuiltinTor(value, context),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _presentReconnectAlert(BuildContext context) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).reconnection,
|
||||
alertContent: S.of(context).reconnect_alert_text,
|
||||
rightButtonText: S.of(context).ok,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () async {
|
||||
Navigator.of(context).pop();
|
||||
await dashboardViewModel.reconnect();
|
||||
},
|
||||
actionLeftButton: () => Navigator.of(context).pop());
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import 'package:cake_wallet/entities/bitcoin_amount_display_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_currency.dart';
|
||||
import 'package:cake_wallet/entities/language_service.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
|
||||
import 'package:cake_wallet/entities/sync_status_display_mode.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_theme_choice.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
@@ -19,7 +23,6 @@ import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||
|
||||
class DisplaySettingsPage extends StatelessWidget {
|
||||
DisplaySettingsPage(this._displaySettingsViewModel);
|
||||
@@ -29,172 +32,228 @@ class DisplaySettingsPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: Column(
|
||||
children: [
|
||||
ModalTopBar(title: S.of(context).display_settings,leadingIcon: Icon(Icons.arrow_back_ios_new),onLeadingPressed: () => Navigator.of(context).pop()),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
controller: ModalScrollController.of(context),
|
||||
physics: ClampingScrollPhysics(),
|
||||
child: Observer(builder: (_) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SettingsSwitcherCell(
|
||||
title: S.of(context).apps,
|
||||
value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
|
||||
onValueChange: (_, bool value) {
|
||||
_displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(value);
|
||||
},
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.of(context).show_address_book_popup,
|
||||
value: _displaySettingsViewModel.showAddressBookPopup,
|
||||
onValueChange: (_, bool value) {
|
||||
_displaySettingsViewModel.setShowAddressBookPopup(value);
|
||||
},
|
||||
),
|
||||
if (_displaySettingsViewModel.showZcashCardSetting)
|
||||
SettingsSwitcherCell(
|
||||
title: S.of(context).show_zcash_card,
|
||||
value: _displaySettingsViewModel.showZcashCard,
|
||||
onValueChange: (_, bool value) {
|
||||
_displaySettingsViewModel.setShowZcashCard(value);
|
||||
},
|
||||
),
|
||||
SettingsPickerCell<SyncStatusDisplayMode>(
|
||||
title: S.current.sync_status_display_mode,
|
||||
items: SyncStatusDisplayMode.values.toList(),
|
||||
selectedItem: _displaySettingsViewModel.syncStatusDisplayMode,
|
||||
onItemSelected: (SyncStatusDisplayMode mode) =>
|
||||
_displaySettingsViewModel.setSyncStatusDisplayMode(mode),
|
||||
displayItem: (SyncStatusDisplayMode mode) => mode.title,
|
||||
isGridView: false,
|
||||
),
|
||||
if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting)
|
||||
SettingsPickerCell<BitcoinAmountDisplayMode>(
|
||||
title: S.of(context).bitcoin_amount_display,
|
||||
items: BitcoinAmountDisplayMode.all,
|
||||
selectedItem: _displaySettingsViewModel.displayAmountsInSatoshi,
|
||||
onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi,
|
||||
displayItem: (mode) => mode.title,
|
||||
isGridView: false,
|
||||
),
|
||||
//if (!isHaven) it does not work correctly
|
||||
if (!_displaySettingsViewModel.disabledFiatApiMode)
|
||||
SettingsPickerCell<FiatCurrency>(
|
||||
title: S.of(context).settings_currency,
|
||||
searchHintText: S.of(context).search_currency,
|
||||
items: FiatCurrency.all,
|
||||
selectedItem: _displaySettingsViewModel.fiatCurrency,
|
||||
onItemSelected: (FiatCurrency currency) =>
|
||||
_displaySettingsViewModel.setFiatCurrency(currency),
|
||||
images: FiatCurrency.all
|
||||
.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png"))
|
||||
.toList(),
|
||||
isGridView: true,
|
||||
matchingCriteria: (FiatCurrency currency, String searchText) {
|
||||
return currency.title.toLowerCase().contains(searchText) ||
|
||||
currency.fullName.toLowerCase().contains(searchText);
|
||||
},
|
||||
),
|
||||
SettingsPickerCell<String>(
|
||||
title: S.of(context).settings_change_language,
|
||||
searchHintText: S.of(context).search_language,
|
||||
items: LanguageService.list.keys.toList(),
|
||||
displayItem: (dynamic code) {
|
||||
return LanguageService.list[code] ?? '';
|
||||
},
|
||||
selectedItem: _displaySettingsViewModel.languageCode,
|
||||
onItemSelected: _displaySettingsViewModel.onLanguageSelected,
|
||||
images: LanguageService.list.keys
|
||||
.map((e) => Image.asset(
|
||||
"assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
|
||||
.toList(),
|
||||
matchingCriteria: (String code, String searchText) {
|
||||
return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false;
|
||||
},
|
||||
),
|
||||
|
||||
if (FeatureFlag.customBackgroundEnabled)
|
||||
StandardListRow(
|
||||
title: "Custom background",
|
||||
isSelected: false,
|
||||
onTap: (_) => _pickImage(context),
|
||||
),
|
||||
|
||||
if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile) ...[
|
||||
SizedBox(height: 24),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 24),
|
||||
child: Text(
|
||||
S.current.appearance,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14,
|
||||
height: 22 / 14,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 20),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
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(12),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Semantics(
|
||||
label: S.of(context).color_theme,
|
||||
child: SettingsThemeChoicesCell(_displaySettingsViewModel),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: S.of(context).display,
|
||||
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(
|
||||
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.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();
|
||||
|
||||
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;
|
||||
|
||||
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: () async {
|
||||
final items = FiatCurrency.all;
|
||||
|
||||
final selectedAtIndex =
|
||||
items.indexOf(_displaySettingsViewModel.fiatCurrency);
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: items,
|
||||
selectedAtIndex: selectedAtIndex,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: (FiatCurrency currency) {
|
||||
_displaySettingsViewModel.setFiatCurrency(currency);
|
||||
},
|
||||
images: FiatCurrency.all
|
||||
.map((e) => Image.asset("assets/images/flags/${e.countryCode}.png"))
|
||||
.toList(),
|
||||
hintText: S.of(context).search_currency,
|
||||
isGridView: true,
|
||||
matchingCriteria: (FiatCurrency currency, String searchText) {
|
||||
return currency.title.toLowerCase().contains(searchText) ||
|
||||
currency.fullName.toLowerCase().contains(searchText);
|
||||
},
|
||||
isSeparated: false,
|
||||
|
||||
),
|
||||
);
|
||||
}),
|
||||
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 =
|
||||
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(
|
||||
"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),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to pick an image from the gallery
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/settings/connection_sync_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class DomainLookupsPage extends BasePage {
|
||||
DomainLookupsPage(this._privacySettingsViewModel);
|
||||
DomainLookupsPage(this._connectionsSyncViewModel);
|
||||
|
||||
@override
|
||||
String get title => S.current.domain_looks_up;
|
||||
|
||||
final PrivacySettingsViewModel _privacySettingsViewModel;
|
||||
final ConnectionSyncViewModel _connectionsSyncViewModel;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
@@ -23,36 +23,36 @@ class DomainLookupsPage extends BasePage {
|
||||
children: [
|
||||
SettingsSwitcherCell(
|
||||
title: 'Twitter',
|
||||
value: _privacySettingsViewModel.lookupTwitter,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsTwitter(value)),
|
||||
value: _connectionsSyncViewModel.lookupTwitter,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsTwitter(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'Mastodon',
|
||||
value: _privacySettingsViewModel.looksUpMastodon,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsMastodon(value)),
|
||||
value: _connectionsSyncViewModel.looksUpMastodon,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsMastodon(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'Yat service',
|
||||
value: _privacySettingsViewModel.looksUpYatService,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsYatService(value)),
|
||||
value: _connectionsSyncViewModel.looksUpYatService,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsYatService(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'Unstoppable Domains',
|
||||
value: _privacySettingsViewModel.looksUpUnstoppableDomains,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsUnstoppableDomains(value)),
|
||||
value: _connectionsSyncViewModel.looksUpUnstoppableDomains,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsUnstoppableDomains(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'OpenAlias',
|
||||
value: _privacySettingsViewModel.looksUpOpenAlias,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsOpenAlias(value)),
|
||||
value: _connectionsSyncViewModel.looksUpOpenAlias,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsOpenAlias(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'Ethereum Name Service',
|
||||
value: _privacySettingsViewModel.looksUpENS,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsENS(value)),
|
||||
value: _connectionsSyncViewModel.looksUpENS,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsENS(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: '.well-known',
|
||||
value: _privacySettingsViewModel.looksUpWellKnown,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsWellKnown(value)),
|
||||
value: _connectionsSyncViewModel.looksUpWellKnown,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsWellKnown(value)),
|
||||
SettingsSwitcherCell(
|
||||
title: 'Zano Aliases',
|
||||
value: _privacySettingsViewModel.lookupsZanoAlias,
|
||||
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsZanoAlias(value)),
|
||||
value: _connectionsSyncViewModel.lookupsZanoAlias,
|
||||
onValueChange: (_, bool value) => _connectionsSyncViewModel.setLookupsZanoAlias(value)),
|
||||
|
||||
//if (!isHaven) it does not work correctly
|
||||
],
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modern_button.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
|
||||
@@ -7,6 +11,7 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -14,30 +19,46 @@ import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
|
||||
|
||||
class ManageNodesPage extends BasePage {
|
||||
ManageNodesPage(this.isPow, {this.nodeListViewModel, this.powNodeListViewModel})
|
||||
ManageNodesPage(this.isPow, {this.nodeListViewModel, this.powNodeListViewModel, this.dashboardViewModel})
|
||||
: assert((isPow && powNodeListViewModel != null) || (!isPow && nodeListViewModel != null)),
|
||||
assert(powNodeListViewModel == null || nodeListViewModel == null);
|
||||
|
||||
final DashboardViewModel? dashboardViewModel;
|
||||
final NodeListViewModel? nodeListViewModel;
|
||||
final PowNodeListViewModel? powNodeListViewModel;
|
||||
final bool isPow;
|
||||
|
||||
@override
|
||||
bool get hideAppBar => true;
|
||||
|
||||
@override
|
||||
String get title => S.current.manage_nodes;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
return ModalPageWrapper(
|
||||
horizontalPadding: 0,
|
||||
topBar: ModalTopBar(
|
||||
title: S.of(context).manage_nodes,
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: () => Navigator.of(context).pop(),
|
||||
trailingWidget: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
if (dashboardViewModel?.hasRescan ?? true)
|
||||
ModernButton(
|
||||
size: 36,
|
||||
icon: Icon(Icons.history),
|
||||
onPressed: () => Navigator.of(context).pushNamed(Routes.rescan)),
|
||||
ModernButton(
|
||||
size: 36,
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () => Navigator.of(context).pushNamed(isPow ? Routes.newPowNode : Routes.newNode))
|
||||
],
|
||||
),
|
||||
),
|
||||
content: Column(
|
||||
children: [
|
||||
Semantics(
|
||||
button: true,
|
||||
child: NodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async => await Navigator.of(context).pushNamed(isPow ? Routes.newPowNode : Routes.newNode),
|
||||
),
|
||||
),
|
||||
if (FeatureFlag.isAutomaticNodeSwitchingEnabled)
|
||||
Observer(
|
||||
builder: (_) => SettingsSwitcherCell(
|
||||
@@ -60,32 +81,34 @@ class ManageNodesPage extends BasePage {
|
||||
builder: (BuildContext context) {
|
||||
int itemsCount =
|
||||
nodeListViewModel?.nodes.length ?? powNodeListViewModel!.nodes.length;
|
||||
return Flexible(
|
||||
child: SectionStandardList(
|
||||
scrollController: ModalScrollController.of(context),
|
||||
sectionCount: 1,
|
||||
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCounter: (int sectionIndex) => itemsCount,
|
||||
itemBuilder: (_, index) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final node =
|
||||
nodeListViewModel?.nodes[index] ?? powNodeListViewModel!.nodes[index];
|
||||
late bool isSelected;
|
||||
if (isPow) {
|
||||
isSelected = node.keyIndex == powNodeListViewModel!.currentNode.keyIndex;
|
||||
} else {
|
||||
isSelected = node.keyIndex == nodeListViewModel!.currentNode.keyIndex;
|
||||
}
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uriRaw,
|
||||
node: node,
|
||||
isSelected: isSelected,
|
||||
isPow: isPow,
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
return SectionStandardList(
|
||||
scrollController: ModalScrollController.of(context),
|
||||
sectionCount: 1,
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCounter: (int sectionIndex) => itemsCount,
|
||||
itemBuilder: (_, index) {
|
||||
return Observer(
|
||||
builder: (context) {
|
||||
final node =
|
||||
nodeListViewModel?.nodes[index] ?? powNodeListViewModel!.nodes[index];
|
||||
late bool isSelected;
|
||||
if (isPow) {
|
||||
isSelected = node.keyIndex == powNodeListViewModel!.currentNode.keyIndex;
|
||||
} else {
|
||||
isSelected = node.keyIndex == nodeListViewModel!.currentNode.keyIndex;
|
||||
}
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uriRaw,
|
||||
subtitle: node.label!,
|
||||
node: node,
|
||||
isSelected: isSelected,
|
||||
isPow: isPow,
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
@@ -110,11 +133,10 @@ class ManageNodesPage extends BasePage {
|
||||
);
|
||||
},
|
||||
);
|
||||
return nodeListRow;
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
return nodeListRow;
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -122,4 +144,21 @@ class ManageNodesPage extends BasePage {
|
||||
),
|
||||
);
|
||||
}
|
||||
Future<void> _presentReconnectAlert(BuildContext context) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).reconnection,
|
||||
alertContent: S.of(context).reconnect_alert_text,
|
||||
rightButtonText: S.of(context).ok,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
actionRightButton: () async {
|
||||
Navigator.of(context).pop();
|
||||
await dashboardViewModel!.reconnect();
|
||||
},
|
||||
actionLeftButton: () => Navigator.of(context).pop());
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,64 @@
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cake_wallet/core/node_address_validator.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_text_field.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
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';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class MwebNodePage extends BasePage {
|
||||
MwebNodePage(this.mwebSettingsViewModelBase)
|
||||
: _nodeUriController = TextEditingController(text: mwebSettingsViewModelBase.mwebNodeUri),
|
||||
super();
|
||||
class MwebNodePage extends StatefulWidget {
|
||||
const MwebNodePage(this.mwebSettingsViewModelBase, {super.key});
|
||||
|
||||
final MwebSettingsViewModelBase mwebSettingsViewModelBase;
|
||||
final TextEditingController _nodeUriController;
|
||||
|
||||
@override
|
||||
String get title => S.current.litecoin_mweb_node;
|
||||
State<MwebNodePage> createState() => _MwebNodePageState();
|
||||
}
|
||||
|
||||
class _MwebNodePageState extends State<MwebNodePage> {
|
||||
late final TextEditingController _nodeUriController =
|
||||
TextEditingController(text: widget.mwebSettingsViewModelBase.mwebNodeUri);
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: BaseTextFormField(controller: _nodeUriController),
|
||||
)
|
||||
],
|
||||
),
|
||||
void dispose() {
|
||||
_nodeUriController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ModalPageWrapper(
|
||||
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(),
|
||||
),
|
||||
]
|
||||
}),
|
||||
),
|
||||
Positioned(
|
||||
child: Observer(
|
||||
builder: (_) => LoadingPrimaryButton(
|
||||
onPressed: () => save(context),
|
||||
text: S.of(context).save,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
bottom: 24,
|
||||
left: 24,
|
||||
right: 24,
|
||||
)
|
||||
],
|
||||
bottomContent: LoadingPrimaryButton(
|
||||
onPressed: () => save(context),
|
||||
text: S.of(context).save,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void save(BuildContext context) {
|
||||
mwebSettingsViewModelBase.setMwebNodeUri(_nodeUriController.text);
|
||||
widget.mwebSettingsViewModelBase.setMwebNodeUri(_nodeUriController.text);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
|
||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/dev/moneroc_cache_debug.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/setting_priority_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_version_cell.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/share_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_core/db/sqlite.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class OtherSettingsPage extends BasePage {
|
||||
OtherSettingsPage(this._otherSettingsViewModel) {
|
||||
@@ -25,164 +28,206 @@ class OtherSettingsPage extends BasePage {
|
||||
}
|
||||
|
||||
@override
|
||||
String get title => S.current.other_settings;
|
||||
bool get hideAppBar => true;
|
||||
|
||||
final OtherSettingsViewModel _otherSettingsViewModel;
|
||||
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) => Observer(
|
||||
builder: (_) => Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
if (_otherSettingsViewModel.displayTransactionPriority)
|
||||
_otherSettingsViewModel.walletType == WalletType.bitcoin
|
||||
? SettingsPriorityPickerCell(
|
||||
title: S.current.settings_fee_priority,
|
||||
items: priorityForWalletType(_otherSettingsViewModel.walletType),
|
||||
displayItem: _otherSettingsViewModel.getDisplayBitcoinPriority,
|
||||
selectedItem: _otherSettingsViewModel.transactionPriority,
|
||||
customItemIndex: _otherSettingsViewModel.customPriorityItemIndex,
|
||||
onItemSelected: _otherSettingsViewModel.onDisplayBitcoinPrioritySelected,
|
||||
customValue: _otherSettingsViewModel.customBitcoinFeeRate,
|
||||
maxValue: _otherSettingsViewModel.maxCustomFeeRate?.toDouble(),
|
||||
)
|
||||
: SettingsPickerCell(
|
||||
title: S.current.settings_fee_priority,
|
||||
items: priorityForWalletType(_otherSettingsViewModel.walletType),
|
||||
displayItem: _otherSettingsViewModel.getDisplayPriority,
|
||||
selectedItem: _otherSettingsViewModel.transactionPriority,
|
||||
onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected,
|
||||
),
|
||||
if (_otherSettingsViewModel.changeRepresentativeEnabled)
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.change_rep,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.changeRep),
|
||||
),
|
||||
if (_otherSettingsViewModel.changeHardwareWalletTypeEnabled)
|
||||
SettingsCellWithArrow(
|
||||
title: "Hardware wallet manufacturer",
|
||||
handler: (context) => Navigator.of(context)
|
||||
.pushNamed(Routes.restoreWalletFromHardwareWallet, arguments: {
|
||||
"showUnavailable": false,
|
||||
"availableHardwareWalletTypes": [
|
||||
HardwareWalletType.cupcake,
|
||||
HardwareWalletType.coldcard,
|
||||
HardwareWalletType.seedsigner,
|
||||
],
|
||||
"onSelect": (BuildContext context, HardwareWalletType hwType) async {
|
||||
await _otherSettingsViewModel.onHardwareWalletTypeChanged(hwType);
|
||||
Navigator.pop(context);
|
||||
Widget body(BuildContext context) {
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: S.of(context).other,
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
// header: ModalHeader(
|
||||
// iconPath: "assets/new-ui/settings_row_icons/other.svg",
|
||||
// message: "Other settings",
|
||||
// title: S.of(context).other_settings),
|
||||
content: NewListSections(
|
||||
sections: {
|
||||
"": [
|
||||
if (_otherSettingsViewModel.displayTransactionPriority)
|
||||
_otherSettingsViewModel.walletType == WalletType.bitcoin
|
||||
? ListItemSelector(
|
||||
keyValue: "fee_priority",
|
||||
label: S.of(context).settings_fee_priority,
|
||||
options: [_otherSettingsViewModel.transactionPriority.title],
|
||||
onTap: () async {
|
||||
|
||||
final items = priorityForWalletType(_otherSettingsViewModel.walletType);
|
||||
|
||||
var selectedAtIndex = items.indexOf(_otherSettingsViewModel.transactionPriority);
|
||||
double sliderValue = _otherSettingsViewModel.customBitcoinFeeRate ?? 0.0;
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
builder: (BuildContext context, StateSetter setState) {
|
||||
return Picker(
|
||||
items: items,
|
||||
displayItem: (TransactionPriority item) => _otherSettingsViewModel.getDisplayBitcoinPriority(item, sliderValue.round()),
|
||||
selectedAtIndex: selectedAtIndex,
|
||||
customItemIndex: _otherSettingsViewModel.customPriorityItemIndex,
|
||||
maxValue: _otherSettingsViewModel.maxCustomFeeRate?.toDouble(),
|
||||
headerEnabled: false,
|
||||
closeOnItemSelected: false,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
sliderValue: sliderValue,
|
||||
onSliderChanged: (double newValue) =>
|
||||
setState(() => sliderValue = newValue),
|
||||
onItemSelected: (TransactionPriority priority) {
|
||||
setState(() => selectedAtIndex = items.indexOf(priority));
|
||||
_otherSettingsViewModel.onDisplayBitcoinPrioritySelected.call(priority, sliderValue);
|
||||
},
|
||||
}),
|
||||
),
|
||||
if (_otherSettingsViewModel.walletType == WalletType.bitcoin) ...[
|
||||
SettingsCellWithArrow(
|
||||
title: S.of(context).export_lightning_logs,
|
||||
handler: onExportLNLog,
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.of(context).export_payjoin_logs,
|
||||
handler: onExportPJLog,
|
||||
),
|
||||
],
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.settings_terms_and_conditions,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.readDisclaimer),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions &&
|
||||
_otherSettingsViewModel.walletType == WalletType.monero)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] monero background sync',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions &&
|
||||
[WalletType.monero, WalletType.wownero, WalletType.zano]
|
||||
.contains(_otherSettingsViewModel.walletType))
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] xmr call profiler',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devMoneroCallProfiler),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions &&
|
||||
[WalletType.monero].contains(_otherSettingsViewModel.walletType))
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] xmr wallet cache debug',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devMoneroWalletCacheDebug),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] shared preferences',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devSharedPreferences),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] secure storage preferences',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devSecurePreferences),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] background sync logs',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devBackgroundSyncLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] socket health logs',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.devSocketHealthLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] network requests logs',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.devNetworkRequests),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] exchange provider logs',
|
||||
handler: (context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] *QR tools',
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.devQRTools),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] exchange provider logs',
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs),
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions)
|
||||
SettingsCellWithArrow(
|
||||
title: '[dev] browse sqlite db',
|
||||
handler: (BuildContext context) async {
|
||||
final data = await dumpDb();
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db')),
|
||||
);
|
||||
}
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
_otherSettingsViewModel.onDisplayBitcoinPrioritySelected.call(items[selectedAtIndex], sliderValue);
|
||||
}
|
||||
)
|
||||
: ListItemSelector(
|
||||
keyValue: "fee_priority",
|
||||
label: S.of(context).settings_fee_priority,
|
||||
options: [_otherSettingsViewModel.transactionPriority.title],
|
||||
onTap: () async {
|
||||
final selectedAtIndex = priorityForWalletType(_otherSettingsViewModel.walletType).indexOf(_otherSettingsViewModel.transactionPriority,);
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: priorityForWalletType(_otherSettingsViewModel.walletType),
|
||||
displayItem: _otherSettingsViewModel.getDisplayPriority,
|
||||
selectedAtIndex: selectedAtIndex,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: (TransactionPriority item) => _otherSettingsViewModel.onDisplayBitcoinPrioritySelected.call(item, 0),
|
||||
isSeparated: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if(_otherSettingsViewModel.changeRepresentativeEnabled)
|
||||
ListItemRegularRow(
|
||||
keyValue: "change_rep",
|
||||
label: S.of(context).change_rep,
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.changeRep)
|
||||
),
|
||||
if (_otherSettingsViewModel.changeHardwareWalletTypeEnabled)
|
||||
ListItemRegularRow(
|
||||
keyValue: "hardware_wallet_manufacturer",
|
||||
label: "Hardware wallet manufacturer",
|
||||
onTap: () => Navigator.of(context)
|
||||
.pushNamed(Routes.restoreWalletFromHardwareWallet, arguments: {
|
||||
"showUnavailable": false,
|
||||
"availableHardwareWalletTypes": [
|
||||
HardwareWalletType.cupcake,
|
||||
HardwareWalletType.coldcard,
|
||||
HardwareWalletType.seedsigner,
|
||||
],
|
||||
"onSelect": (BuildContext context, HardwareWalletType hwType) async {
|
||||
await _otherSettingsViewModel.onHardwareWalletTypeChanged(hwType);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
}),
|
||||
),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_sign_and_verify",
|
||||
label: S.of(context).sign_verify_title,
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(Routes.signPage);
|
||||
}),
|
||||
],
|
||||
if(FeatureFlag.hasDevOptions)
|
||||
"dev": [
|
||||
if(_otherSettingsViewModel.walletType == WalletType.bitcoin) ...[
|
||||
ListItemRegularRow(
|
||||
keyValue: "export_lightning_logs",
|
||||
label: S.of(context).export_lightning_logs,
|
||||
onTap: () => onExportLNLog(context)
|
||||
),
|
||||
SettingsVersionCell(
|
||||
title: S.of(context).version(_otherSettingsViewModel.currentVersion),
|
||||
ListItemRegularRow(
|
||||
keyValue: "export_payjoin_logs",
|
||||
label: S.of(context).export_payjoin_logs,
|
||||
onTap: () => onExportPJLog(context)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (FeatureFlag.hasDevOptions &&
|
||||
_otherSettingsViewModel.walletType == WalletType.monero)
|
||||
ListItemRegularRow(
|
||||
keyValue: "[dev] monero background sync",
|
||||
label: "[dev] monero background sync",
|
||||
onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync)
|
||||
),
|
||||
if (FeatureFlag.hasDevOptions &&
|
||||
[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 (FeatureFlag.hasDevOptions &&
|
||||
[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')),
|
||||
);
|
||||
}
|
||||
),
|
||||
]
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
Future<void> onExportLNLog(BuildContext context) async {
|
||||
final file = await _otherSettingsViewModel.getLightningLog();
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_choices_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
@@ -18,195 +15,94 @@ class PrivacyPage extends BasePage {
|
||||
PrivacyPage(this._privacySettingsViewModel);
|
||||
|
||||
@override
|
||||
String get title => S.current.privacy_settings;
|
||||
bool get hideAppBar => true;
|
||||
|
||||
final PrivacySettingsViewModel _privacySettingsViewModel;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Observer(builder: (_) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<FiatApiMode>(
|
||||
title: S.current.fiat_api,
|
||||
items: FiatApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.fiatApiMode,
|
||||
onItemSelected: (FiatApiMode fiatApiMode) =>
|
||||
_privacySettingsViewModel.setFiatMode(fiatApiMode),
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: "",
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
header: ModalHeader(
|
||||
iconPath: "assets/new-ui/settings_row_icons/privacy.svg",
|
||||
message: S.of(context).privacy_desc,
|
||||
title: S.of(context).privacy),
|
||||
content: SingleChildScrollView(
|
||||
child: Container(
|
||||
child: Observer(builder: (_) {
|
||||
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);
|
||||
}),
|
||||
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",
|
||||
keyValue: "silent_payments",
|
||||
label: S.of(context).silent_payments,
|
||||
onTap: () =>
|
||||
Navigator.of(context).pushNamed(Routes.silentPaymentsSettings)),
|
||||
if (_privacySettingsViewModel.isLitecoin)
|
||||
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)),
|
||||
],
|
||||
}
|
||||
),
|
||||
),
|
||||
SettingsChoicesCell(
|
||||
ChoicesListItem<ExchangeApiMode>(
|
||||
title: S.current.swap,
|
||||
items: ExchangeApiMode.all,
|
||||
selectedItem: _privacySettingsViewModel.exchangeStatus,
|
||||
onItemSelected: (ExchangeApiMode mode) =>
|
||||
_privacySettingsViewModel.setExchangeApiMode(mode),
|
||||
),
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseLightning)
|
||||
SettingsSwitcherCell(
|
||||
title: S.of(context).enable_lightning,
|
||||
value: _privacySettingsViewModel.useLightning,
|
||||
onValueChange: (_, value) => _privacySettingsViewModel.setUseLightning(value),
|
||||
),
|
||||
if (_privacySettingsViewModel.canUsePayjoin)
|
||||
SettingsSwitcherCell(
|
||||
title: S.of(context).use_payjoin,
|
||||
value: _privacySettingsViewModel.usePayjoin,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUsePayjoin(value);
|
||||
},
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.settings_save_recipient_address,
|
||||
value: _privacySettingsViewModel.shouldSaveRecipientAddress,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setShouldSaveRecipientAddress(value);
|
||||
}),
|
||||
if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
|
||||
SettingsSwitcherCell(
|
||||
title: _privacySettingsViewModel.isMoneroWallet
|
||||
? S.current.auto_generate_subaddresses
|
||||
: S.current.auto_generate_addresses,
|
||||
value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setAutoGenerateSubaddresses(value);
|
||||
},
|
||||
),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.prevent_screenshots,
|
||||
value: _privacySettingsViewModel.isAppSecure,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
},
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableTradeOption,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableTradeOption(value);
|
||||
},
|
||||
),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_automatic_exchange_status_updates,
|
||||
value: _privacySettingsViewModel.disableAutomaticExchangeStatusUpdates,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableAutomaticExchangeStatusUpdates(value);
|
||||
},
|
||||
),
|
||||
// SettingsSwitcherCell(
|
||||
// title: S.current.disable_bulletin,
|
||||
// value: _privacySettingsViewModel.disableBulletin,
|
||||
// onValueChange: (BuildContext _, bool value) {
|
||||
// _privacySettingsViewModel.setDisableBulletin(value);
|
||||
// },
|
||||
// ),
|
||||
if (_privacySettingsViewModel.canUseBlinkProtection)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.use_blink_protection,
|
||||
value: _privacySettingsViewModel.useBlinkProtection,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseBlinkProtection(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseEtherscan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.etherscan_history,
|
||||
value: _privacySettingsViewModel.useEtherscan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseEtherscan(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUsePolygonScan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.polygonscan_history,
|
||||
value: _privacySettingsViewModel.usePolygonScan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUsePolygonScan(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseBaseScan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.basescan_history,
|
||||
value: _privacySettingsViewModel.useBaseScan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseBaseScan(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseArbiScan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.arbiscan_history,
|
||||
value: _privacySettingsViewModel.useArbiScan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseArbiScan(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseBscScan)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.bscscan_history,
|
||||
value: _privacySettingsViewModel.useBscScan,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseBscScan(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseTronGrid)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.trongrid_history,
|
||||
value: _privacySettingsViewModel.useTronGrid,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setUseTronGrid(value);
|
||||
},
|
||||
),
|
||||
if (_privacySettingsViewModel.canUseMempoolFeeAPI)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.enable_mempool_api,
|
||||
value: _privacySettingsViewModel.useMempoolFeeAPI,
|
||||
onValueChange: (BuildContext _, bool isEnabled) async {
|
||||
if (!isEnabled) {
|
||||
final bool confirmation = await showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).warning,
|
||||
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));
|
||||
}) ??
|
||||
false;
|
||||
if (confirmation) {
|
||||
_privacySettingsViewModel.setUseMempoolFeeAPI(isEnabled);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_privacySettingsViewModel.setUseMempoolFeeAPI(isEnabled);
|
||||
},
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.domain_looks_up,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.domainLookupsPage),
|
||||
),
|
||||
if(_privacySettingsViewModel.hasCoinControl)
|
||||
SettingsCellWithArrow(
|
||||
title: "Coin Control",
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.unspentCoinsList),
|
||||
),
|
||||
// SettingsCellWithArrow(
|
||||
// title: 'Trocador providers',
|
||||
// handler: (context) => Navigator.of(context).pushNamed(Routes.trocadorProvidersPage),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@ import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
|
||||
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
|
||||
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
|
||||
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
@@ -14,7 +17,6 @@ import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
|
||||
@@ -28,7 +30,10 @@ class SecurityBackupPage extends BasePage {
|
||||
final AuthService _authService;
|
||||
|
||||
@override
|
||||
String get title => S.current.security;
|
||||
bool get hideAppBar => true;
|
||||
|
||||
@override
|
||||
String get title => S.current.security_and_backup;
|
||||
|
||||
final SecuritySettingsViewModel _securitySettingsViewModel;
|
||||
|
||||
@@ -36,170 +41,160 @@ class SecurityBackupPage extends BasePage {
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18.0),
|
||||
child: Column(
|
||||
spacing: 16,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ModalHeader(
|
||||
iconPath: "assets/new-ui/settings_row_icons/security.svg",
|
||||
message: S.of(context).privacy_and_security_desc,
|
||||
title: S.of(context).security),
|
||||
Observer(
|
||||
builder: (_) => NewListSections(sections: {
|
||||
"": [
|
||||
if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
|
||||
ListItemToggle(
|
||||
keyValue: "security_backup_page_allow_biometrics_button_key",
|
||||
label: S.current.settings_allow_biometrical_authentication,
|
||||
value: _securitySettingsViewModel.allowBiometricalAuthentication,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
onAuthSuccess: (isAuthenticatedSuccessfully) async {
|
||||
if (isAuthenticatedSuccessfully) {
|
||||
if (await _securitySettingsViewModel.biometricAuthenticated()) {
|
||||
_securitySettingsViewModel.setAllowBiometricalAuthentication(
|
||||
isAuthenticatedSuccessfully);
|
||||
}
|
||||
} else {
|
||||
return ModalPageWrapper(
|
||||
topBar: ModalTopBar(
|
||||
title: "",
|
||||
leadingIcon: Icon(Icons.arrow_back_ios_new),
|
||||
onLeadingPressed: () => Navigator.of(context).pop()),
|
||||
header: ModalHeader(
|
||||
iconPath: "assets/new-ui/settings_row_icons/security.svg",
|
||||
message: S.of(context).privacy_and_security_desc,
|
||||
title: S.of(context).security),
|
||||
content: Column(
|
||||
spacing: 16,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Observer(
|
||||
builder: (_) => NewListSections(sections: {
|
||||
"": [
|
||||
if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
|
||||
ListItemToggle(
|
||||
keyValue: "security_backup_page_allow_biometrics_button_key",
|
||||
label: S.current.settings_allow_biometrical_authentication,
|
||||
value: _securitySettingsViewModel.allowBiometricalAuthentication,
|
||||
onChanged: (bool value) {
|
||||
if (value) {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
onAuthSuccess: (isAuthenticatedSuccessfully) async {
|
||||
if (isAuthenticatedSuccessfully) {
|
||||
if (await _securitySettingsViewModel.biometricAuthenticated()) {
|
||||
_securitySettingsViewModel.setAllowBiometricalAuthentication(
|
||||
isAuthenticatedSuccessfully);
|
||||
}
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
} else {
|
||||
_securitySettingsViewModel.setAllowBiometricalAuthentication(value);
|
||||
}
|
||||
}),
|
||||
if (FeatureFlag.duressPinEnabled)
|
||||
ListItemToggle(
|
||||
keyValue: "security_backup_page_duress_pin_button_key",
|
||||
label: "Duress PIN",
|
||||
value: _securitySettingsViewModel.enableDuressPin,
|
||||
onChanged: (bool value) {
|
||||
_authService
|
||||
.authenticateAction(context, route: Routes.securityBackupDuressPin,
|
||||
onAuthSuccess: (isAuthenticatedSuccessfully) async {
|
||||
if (isAuthenticatedSuccessfully) {
|
||||
if (!value) {
|
||||
_securitySettingsViewModel.setEnableDuressPin(value);
|
||||
_securitySettingsViewModel.clearDuressPin();
|
||||
return;
|
||||
} else {
|
||||
_securitySettingsViewModel.setAllowBiometricalAuthentication(
|
||||
isAuthenticatedSuccessfully);
|
||||
}
|
||||
final res = await _showDuressPinDescription(context);
|
||||
if (res) {
|
||||
final confirmation = await _showDuressPinConfirmation(context);
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
} else {
|
||||
_securitySettingsViewModel.setAllowBiometricalAuthentication(value);
|
||||
}
|
||||
}),
|
||||
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);
|
||||
}),
|
||||
if (FeatureFlag.duressPinEnabled)
|
||||
ListItemToggle(
|
||||
keyValue: "security_backup_page_duress_pin_button_key",
|
||||
label: "Duress PIN",
|
||||
value: _securitySettingsViewModel.enableDuressPin,
|
||||
onChanged: (bool value) {
|
||||
_authService
|
||||
.authenticateAction(context, route: Routes.securityBackupDuressPin,
|
||||
onAuthSuccess: (isAuthenticatedSuccessfully) async {
|
||||
if (isAuthenticatedSuccessfully) {
|
||||
if (!value) {
|
||||
_securitySettingsViewModel.setEnableDuressPin(value);
|
||||
_securitySettingsViewModel.clearDuressPin();
|
||||
return;
|
||||
}
|
||||
final res = await _showDuressPinDescription(context);
|
||||
if (res) {
|
||||
final confirmation = await _showDuressPinConfirmation(context);
|
||||
|
||||
if (confirmation) {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.setupDuressPin,
|
||||
arguments:
|
||||
(PinCodeState<PinCodeWidget> pinCtx, String _) async {
|
||||
pinCtx.close();
|
||||
_securitySettingsViewModel.setEnableDuressPin(true);
|
||||
},
|
||||
);
|
||||
}
|
||||
if (confirmation) {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.setupDuressPin,
|
||||
arguments:
|
||||
(PinCodeState<PinCodeWidget> pinCtx, String _) async {
|
||||
pinCtx.close();
|
||||
_securitySettingsViewModel.setEnableDuressPin(true);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings);
|
||||
}),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_require_pin_after_button_key",
|
||||
label: S.current.require_pin_after,
|
||||
trailingText: _securitySettingsViewModel.pinCodeRequiredDuration.toString(),
|
||||
onTap: () async {
|
||||
final items = PinCodeRequiredDuration.values;
|
||||
}
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings);
|
||||
}),
|
||||
ListItemSelector(
|
||||
keyValue: "security_backup_page_require_pin_after_button_key",
|
||||
label: S.current.require_pin_after,
|
||||
options: [_securitySettingsViewModel.pinCodeRequiredDuration.toString()],
|
||||
onTap: () async {
|
||||
final items = PinCodeRequiredDuration.values;
|
||||
|
||||
final selectedAtIndex =
|
||||
items.indexOf(_securitySettingsViewModel.pinCodeRequiredDuration);
|
||||
final selectedAtIndex =
|
||||
items.indexOf(_securitySettingsViewModel.pinCodeRequiredDuration);
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: items,
|
||||
selectedAtIndex: selectedAtIndex,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: (PinCodeRequiredDuration item) {
|
||||
_securitySettingsViewModel.setPinCodeRequiredDuration(item);
|
||||
},
|
||||
isSeparated: false,
|
||||
),
|
||||
);
|
||||
}),
|
||||
// if (!_isHardwareWallet)
|
||||
// ListItemRegularRow(
|
||||
// keyValue: "security_backup_page_show_keys_button_key",
|
||||
// label: S.current.show_keys,
|
||||
// onTap: () {
|
||||
// _authService.authenticateAction(
|
||||
// context,
|
||||
// route: Routes.showKeys,
|
||||
// conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
// .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
// );
|
||||
// }),
|
||||
// if (!SettingsStoreBase.walletPasswordDirectInput)
|
||||
// ListItemRegularRow(
|
||||
// keyValue: "security_backup_page_change_password_button_key",
|
||||
// label: S.current.create_backup,
|
||||
// onTap: () {
|
||||
// _authService.authenticateAction(
|
||||
// context,
|
||||
// route: Routes.backup,
|
||||
// conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
// .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
// );
|
||||
// }),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_change_pin_button_key",
|
||||
label: S.current.settings_change_pin,
|
||||
onTap: () {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
route: Routes.setupPin,
|
||||
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
|
||||
setupPinContext.close();
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (_) => Picker(
|
||||
items: items,
|
||||
selectedAtIndex: selectedAtIndex,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
onItemSelected: (PinCodeRequiredDuration item) {
|
||||
_securitySettingsViewModel.setPinCodeRequiredDuration(item);
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
}),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_sign_and_verify",
|
||||
label: S.current.sign_verify_title,
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(Routes.signPage);
|
||||
}),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_totp_2fa_button_key",
|
||||
label: _securitySettingsViewModel.useTotp2FA
|
||||
? S.current.modify_2fa
|
||||
: S.current.setup_2fa,
|
||||
onTap: () {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
route: _securitySettingsViewModel.useTotp2FA
|
||||
? Routes.modify2FAPage
|
||||
: Routes.setup2faInfoPage,
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
})
|
||||
]
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
isSeparated: false,
|
||||
),
|
||||
);
|
||||
}),
|
||||
// if (!_isHardwareWallet)
|
||||
// ListItemRegularRow(
|
||||
// keyValue: "security_backup_page_show_keys_button_key",
|
||||
// label: S.current.show_keys,
|
||||
// onTap: () {
|
||||
// _authService.authenticateAction(
|
||||
// context,
|
||||
// route: Routes.showKeys,
|
||||
// conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
// .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
// );
|
||||
// }),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_change_pin_button_key",
|
||||
label: S.current.settings_change_pin,
|
||||
onTap: () {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
route: Routes.setupPin,
|
||||
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
|
||||
setupPinContext.close();
|
||||
},
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
}),
|
||||
ListItemRegularRow(
|
||||
keyValue: "security_backup_page_totp_2fa_button_key",
|
||||
label: _securitySettingsViewModel.useTotp2FA
|
||||
? S.current.modify_2fa
|
||||
: S.current.setup_2fa,
|
||||
onTap: () {
|
||||
_authService.authenticateAction(
|
||||
context,
|
||||
route: _securitySettingsViewModel.useTotp2FA
|
||||
? Routes.modify2FAPage
|
||||
: Routes.setup2faInfoPage,
|
||||
conditionToDetermineIfToUse2FA: _securitySettingsViewModel
|
||||
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
);
|
||||
})
|
||||
]
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,9 +12,13 @@ class SettingsChoicesCell extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final items = choicesListItem.items;
|
||||
final selectedIndex = items.indexOf(choicesListItem.selectedItem);
|
||||
final itemCount = items.length;
|
||||
|
||||
return Container(
|
||||
color: useGenericColor ? Theme.of(context).colorScheme.surface : null,
|
||||
padding: padding ?? EdgeInsets.only(left: 24, right: 24, top: 16, bottom: 16),
|
||||
padding: padding ?? const EdgeInsets.only(left: 24, right: 24, top: 16, bottom: 16),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -33,46 +37,68 @@ class SettingsChoicesCell extends StatelessWidget {
|
||||
Center(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: useGenericColor
|
||||
? null
|
||||
: Border.all(
|
||||
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: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: choicesListItem.items.map((dynamic e) {
|
||||
final isSelected = choicesListItem.selectedItem == e;
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
choicesListItem.onItemSelected.call(e);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: isSelected ? Theme.of(context).colorScheme.primary : null,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
choicesListItem.displayItem.call(e),
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.onPrimary
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final itemWidth = constraints.maxWidth / itemCount;
|
||||
return Stack(
|
||||
children: [
|
||||
if (selectedIndex >= 0)
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 450),
|
||||
curve: Curves.easeInOut,
|
||||
left: selectedIndex * itemWidth,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: itemWidth,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: items.map((dynamic e) {
|
||||
final isSelected = choicesListItem.selectedItem == e;
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => choicesListItem.onItemSelected.call(e),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
color: Colors.transparent,
|
||||
child: Center(
|
||||
child: AnimatedDefaultTextStyle(
|
||||
duration: const Duration(milliseconds: 220),
|
||||
curve: Curves.easeInOut,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.onPrimary
|
||||
: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
fontWeight:
|
||||
isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
),
|
||||
child: Text(choicesListItem.displayItem.call(e)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -80,4 +106,4 @@ class SettingsChoicesCell extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ class SettingsSwitcherCell extends StandardListRow {
|
||||
Key? key,
|
||||
this.padding,
|
||||
this.switchBackgroundColor,
|
||||
this.height = 56,
|
||||
}) : super(title: title, isSelected: false, decoration: decoration, onTap: onTap, key: key);
|
||||
|
||||
final bool value;
|
||||
@@ -20,6 +21,7 @@ class SettingsSwitcherCell extends StandardListRow {
|
||||
final void Function(BuildContext context, bool value)? onValueChange;
|
||||
final Widget? leading;
|
||||
final EdgeInsets? padding;
|
||||
final double? height;
|
||||
|
||||
@override
|
||||
Widget buildTrailing(BuildContext context) => StandardSwitch(
|
||||
@@ -33,7 +35,7 @@ class SettingsSwitcherCell extends StandardListRow {
|
||||
final leading = buildLeading(context);
|
||||
final trailing = buildTrailing(context);
|
||||
return Container(
|
||||
height: 56,
|
||||
height: height,
|
||||
padding: padding ?? EdgeInsets.only(left: 12, right: 12),
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
|
||||
@@ -12,9 +12,9 @@ class SettingsThemeChoicesCell extends StatelessWidget {
|
||||
|
||||
final DisplaySettingsViewModel _displaySettingsViewModel;
|
||||
|
||||
final double cellHeight = 25;
|
||||
final double cellHeight = 12;
|
||||
final double cellWidth = 12;
|
||||
final double cellRadius = 8;
|
||||
final double cellRadius = 18;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -28,14 +28,17 @@ class SettingsThemeChoicesCell extends StatelessWidget {
|
||||
final previewHeight = _getResponsivePreviewHeight(screenHeight);
|
||||
final previewWidth = previewHeight * 0.6;
|
||||
|
||||
return Container(
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 350),
|
||||
curve: Curves.easeInOut,
|
||||
height: getHeight(context, currentTheme, currentTheme.hasAccentColors),
|
||||
padding: EdgeInsets.all(12),
|
||||
padding: EdgeInsets.all(14),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
SizedBox(
|
||||
height: previewHeight,
|
||||
child: ListView.builder(
|
||||
itemCount: availableThemes.length,
|
||||
scrollDirection: Axis.horizontal,
|
||||
@@ -50,16 +53,16 @@ class SettingsThemeChoicesCell extends StatelessWidget {
|
||||
onTap: () {
|
||||
_displaySettingsViewModel.onThemeSelected(theme);
|
||||
},
|
||||
child: Container(
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 350),
|
||||
curve: Curves.easeInOut,
|
||||
margin: EdgeInsets.only(right: 24),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(cellRadius),
|
||||
border: isSelected
|
||||
? Border.all(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(cellRadius),
|
||||
side: BorderSide(
|
||||
color: isSelected ? Theme.of(context).colorScheme.primary : Colors.transparent,
|
||||
strokeAlign: BorderSide.strokeAlignOutside)
|
||||
: null,
|
||||
),
|
||||
)),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(cellRadius),
|
||||
child: CakeImageWidget(
|
||||
@@ -75,56 +78,94 @@ class SettingsThemeChoicesCell extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
if (_displaySettingsViewModel.currentTheme.hasAccentColors) ...[
|
||||
SizedBox(height: cellHeight),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context).accent_color,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
Container(
|
||||
child: Row(
|
||||
children: availableAccentColors.map((accentColor) {
|
||||
final isSelected = _displaySettingsViewModel
|
||||
.isAccentColorSelected(accentColor.name.toLowerCase());
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_displaySettingsViewModel
|
||||
.onAccentColorSelected(accentColor.name.toLowerCase());
|
||||
},
|
||||
child: Container(
|
||||
width: 26,
|
||||
height: 26,
|
||||
margin: EdgeInsets.only(right: 11),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: isSelected
|
||||
? Border.all(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
width: 3)
|
||||
: null,
|
||||
color: accentColor.color,
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 350),
|
||||
switchInCurve: Curves.easeOut,
|
||||
switchOutCurve: Curves.easeIn,
|
||||
transitionBuilder: (child, animation) => FadeTransition(
|
||||
opacity: animation,
|
||||
child: SizeTransition(
|
||||
sizeFactor: animation,
|
||||
axisAlignment: -1,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
child: _displaySettingsViewModel.currentTheme.hasAccentColors
|
||||
? Column(
|
||||
key: const ValueKey('accent'),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 14),
|
||||
child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)
|
||||
),
|
||||
SizedBox(height: cellHeight),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
S.of(context).accent_color,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Row(
|
||||
spacing: 4,
|
||||
children: availableAccentColors.map((accentColor) {
|
||||
final isSelected = _displaySettingsViewModel
|
||||
.isAccentColorSelected(accentColor.name.toLowerCase());
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
_displaySettingsViewModel
|
||||
.onAccentColorSelected(accentColor.name.toLowerCase());
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
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))
|
||||
),
|
||||
),
|
||||
AnimatedScale(
|
||||
duration: Duration(milliseconds: 350),
|
||||
scale: isSelected ? 0.8 : 1,
|
||||
child: Container(
|
||||
width: 28,
|
||||
height: 28,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(99999999),
|
||||
color: accentColor.color),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: const SizedBox.shrink(key: ValueKey('no-accent')),
|
||||
),
|
||||
if (_displaySettingsViewModel.currentTheme is BlackTheme)
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.oled_mode,
|
||||
value: _displaySettingsViewModel.isBlackThemeOledEnabled,
|
||||
onValueChange: (_, bool value) {
|
||||
_displaySettingsViewModel.setBlackThemeOled(value);
|
||||
},
|
||||
padding: EdgeInsets.zero,
|
||||
switchBackgroundColor: currentTheme.colorScheme.secondaryContainer,
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 12, bottom: 4),
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -135,14 +176,14 @@ class SettingsThemeChoicesCell extends StatelessWidget {
|
||||
double getHeight(BuildContext context, MaterialThemeBase theme, bool hasAccentColors) {
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
|
||||
double baseHeight = (screenHeight * 0.25).clamp(150.0, screenHeight * 0.5);
|
||||
double baseHeight = (screenHeight * 0.253).clamp(150.0, screenHeight * 0.5);
|
||||
|
||||
if (hasAccentColors) {
|
||||
baseHeight += (screenHeight * 0.05).clamp(35.0, 60.0);
|
||||
baseHeight += (screenHeight * 0.60).clamp(35.0, 60.0);
|
||||
}
|
||||
|
||||
if (theme is BlackTheme) {
|
||||
baseHeight += (screenHeight * 0.08).clamp(48.0, 96.0);
|
||||
baseHeight += (screenHeight * 0.059).clamp(48.0, 96.0);
|
||||
}
|
||||
|
||||
return baseHeight;
|
||||
|
||||
@@ -6,20 +6,21 @@ class ListItemStyleWrapper extends StatelessWidget {
|
||||
required this.isFirstInSection,
|
||||
required this.isLastInSection,
|
||||
required this.builder,
|
||||
this.hasImage,
|
||||
this.onTap,
|
||||
this.height = 50,
|
||||
this.iconPath,
|
||||
});
|
||||
|
||||
final String? iconPath;
|
||||
final bool isFirstInSection;
|
||||
final bool isLastInSection;
|
||||
final bool ?hasImage;
|
||||
final double height;
|
||||
final VoidCallback? onTap;
|
||||
final Widget Function(BuildContext context, TextStyle textStyle, TextStyle labelStyle) builder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final textStyle = TextStyle(
|
||||
@@ -60,17 +61,17 @@ class ListItemStyleWrapper extends StatelessWidget {
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: builder(context, textStyle, labelStyle))))),
|
||||
if(hasImage == true && isLastInSection == false) Container(
|
||||
if(iconPath != null && isLastInSection == false) Container(
|
||||
color: theme.colorScheme.surfaceContainer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 48, right: 13),
|
||||
padding: const EdgeInsets.only(left: 50, right: 13),
|
||||
child: Container(height: 1, color: theme.colorScheme.outlineVariant),
|
||||
),
|
||||
)
|
||||
else if(!isLastInSection) Container(
|
||||
color: theme.colorScheme.surfaceContainer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 13),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Container(height: 1, color: theme.colorScheme.outlineVariant),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -37,6 +37,7 @@ class _ListItemCheckboxWidgetState extends State<ListItemCheckboxWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListItemStyleWrapper(
|
||||
iconPath: widget.iconPath,
|
||||
onTap: widget.onTap ?? () {
|
||||
widget.onChanged(!widget.value);
|
||||
},
|
||||
@@ -53,11 +54,11 @@ class _ListItemCheckboxWidgetState extends State<ListItemCheckboxWidget> {
|
||||
children: [
|
||||
if (widget.iconPath != null)
|
||||
widget.iconPath!.toLowerCase().endsWith("svg")
|
||||
? CakeImageWidget(imageUrl:widget.iconPath!, height: 24, width: 24)
|
||||
? CakeImageWidget(imageUrl:widget.iconPath!, height: 26, width: 26)
|
||||
: Image.asset(
|
||||
widget.iconPath!,
|
||||
width: 24,
|
||||
height: 24,
|
||||
width: 26,
|
||||
height: 26,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
|
||||
@@ -12,7 +12,6 @@ class ListItemRegularRowWidget extends StatelessWidget {
|
||||
this.trailingText,
|
||||
this.iconPath,
|
||||
this.onTap,
|
||||
this.hasImage,
|
||||
this.isFirstInSection = false,
|
||||
this.isLastInSection = false,
|
||||
this.showArrow = true,
|
||||
@@ -28,7 +27,6 @@ class ListItemRegularRowWidget extends StatelessWidget {
|
||||
final String? trailingText;
|
||||
final String? iconPath;
|
||||
final VoidCallback? onTap;
|
||||
final bool? hasImage;
|
||||
final bool isFirstInSection;
|
||||
final bool isLastInSection;
|
||||
final bool showArrow;
|
||||
@@ -46,7 +44,7 @@ class ListItemRegularRowWidget extends StatelessWidget {
|
||||
|
||||
return ListItemStyleWrapper(
|
||||
onTap: onTap,
|
||||
hasImage: iconPath != null ? true : false,
|
||||
iconPath: iconPath,
|
||||
isFirstInSection: isFirstInSection,
|
||||
isLastInSection: isLastInSection,
|
||||
height: subtitle != null ? 64 : 50,
|
||||
|
||||
@@ -33,25 +33,25 @@ class ListItemSelectorWidget extends StatelessWidget {
|
||||
isLastInSection: isLastInSection,
|
||||
builder: (context, textStyle, labelStyle) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(child: Text(label, style: textStyle)),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
options[selectedIndex],
|
||||
style: labelStyle,
|
||||
),
|
||||
CakeImageWidget(imageUrl:
|
||||
"assets/new-ui/chooser.svg",
|
||||
colorFilter:
|
||||
ColorFilter.mode(theme.colorScheme.onSurfaceVariant, BlendMode.srcIn),
|
||||
),
|
||||
SizedBox(width: 8)
|
||||
],
|
||||
),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(child: Text(label, style: textStyle)),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
options[selectedIndex],
|
||||
style: labelStyle,
|
||||
),
|
||||
CakeImageWidget(imageUrl:
|
||||
"assets/new-ui/chooser.svg",
|
||||
colorFilter:
|
||||
ColorFilter.mode(theme.colorScheme.onSurfaceVariant, BlendMode.srcIn),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,14 @@ class StandardListRow extends StatelessWidget {
|
||||
StandardListRow({
|
||||
required this.title,
|
||||
required this.isSelected,
|
||||
this.subtitle,
|
||||
this.onTap,
|
||||
this.decoration,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String? subtitle;
|
||||
final bool isSelected;
|
||||
final void Function(BuildContext context)? onTap;
|
||||
final Decoration? decoration;
|
||||
@@ -48,18 +50,52 @@ class StandardListRow extends StatelessWidget {
|
||||
Widget? buildLeading(BuildContext context) => null;
|
||||
|
||||
Widget buildCenter(BuildContext context, {required bool hasLeftOffset}) {
|
||||
|
||||
return Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
if (hasLeftOffset) SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: titleColor(context),
|
||||
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (subtitle != null && subtitle!.isNotEmpty)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
textAlign: TextAlign.left,
|
||||
subtitle!,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
color: titleColor(context),
|
||||
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (subtitle != null && subtitle!.isNotEmpty)
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
textAlign: TextAlign.left,
|
||||
title,
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
title,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: titleColor(context),
|
||||
fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
@@ -138,6 +174,7 @@ class SectionStandardList extends StatelessWidget {
|
||||
this.hasTopSeparator = false,
|
||||
this.scrollController,
|
||||
this.physics,
|
||||
this.shrinkWrap = false,
|
||||
}) : totalRows = [];
|
||||
|
||||
final int sectionCount;
|
||||
@@ -150,6 +187,7 @@ class SectionStandardList extends StatelessWidget {
|
||||
final EdgeInsets dividerPadding;
|
||||
final ScrollController? scrollController;
|
||||
final ScrollPhysics? physics;
|
||||
final bool shrinkWrap;
|
||||
|
||||
List<Widget> transform(
|
||||
bool hasTopSeparator,
|
||||
@@ -208,6 +246,7 @@ class SectionStandardList extends StatelessWidget {
|
||||
return ListView.separated(
|
||||
controller: scrollController,
|
||||
physics: physics,
|
||||
shrinkWrap: shrinkWrap,
|
||||
separatorBuilder: (_, index) {
|
||||
final row = totalRows[index];
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ abstract class DashboardViewModelBase with Store {
|
||||
} catch (_) {}
|
||||
}
|
||||
return length * confirmations;
|
||||
}, _transactionDisposerCallback);
|
||||
}, _transactionDisposerCallback, delay: 300);
|
||||
|
||||
if (hasSilentPayments) {
|
||||
silentPaymentsScanningActive = bitcoin!.getScanningActive(wallet);
|
||||
@@ -481,13 +481,23 @@ abstract class DashboardViewModelBase with Store {
|
||||
}
|
||||
// printV("Transaction disposer callback (relevantTxs: ${relevantTxs.length} current: ${transactions.length})");
|
||||
|
||||
transactions.clear();
|
||||
transactions.addAll(relevantTxs.map((tx) => TransactionListItem(
|
||||
transaction: tx,
|
||||
balanceViewModel: balanceViewModel,
|
||||
appStore: appStore,
|
||||
key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
|
||||
)));
|
||||
final newTransactions = relevantTxs
|
||||
.map((tx) => TransactionListItem(
|
||||
transaction: tx,
|
||||
balanceViewModel: balanceViewModel,
|
||||
appStore: appStore,
|
||||
key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
|
||||
))
|
||||
.where((item) => !transactions.contains(item));
|
||||
|
||||
transactions.addAll(newTransactions);
|
||||
// transactions.clear();
|
||||
// transactions.addAll(relevantTxs.map((tx) => TransactionListItem(
|
||||
// transaction: tx,
|
||||
// balanceViewModel: balanceViewModel,
|
||||
// appStore: appStore,
|
||||
// key: ValueKey('${wallet.type.name}_transaction_history_item_${tx.id}_key'),
|
||||
// )));
|
||||
} finally {
|
||||
_isTransactionDisposerCallbackRunning = false;
|
||||
}
|
||||
@@ -671,6 +681,10 @@ abstract class DashboardViewModelBase with Store {
|
||||
bool get hasLightning =>
|
||||
wallet.type == WalletType.bitcoin && wallet.isSoftwareWallet && bitcoin!.useLightning(wallet);
|
||||
|
||||
@computed
|
||||
bool get hasWalletConnect =>
|
||||
isWalletConnectCompatibleChain(wallet.type) && !wallet.isHardwareWallet;
|
||||
|
||||
@computed
|
||||
bool get isTestnet => wallet.type == WalletType.bitcoin && bitcoin!.isTestnet(wallet);
|
||||
|
||||
@@ -1248,7 +1262,7 @@ abstract class DashboardViewModelBase with Store {
|
||||
} catch (_) {}
|
||||
}
|
||||
return length * confirmations;
|
||||
}, _transactionDisposerCallback);
|
||||
}, _transactionDisposerCallback, delay: 300);
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@@ -289,4 +289,12 @@ class TransactionListItem extends ActionListItem with Keyable {
|
||||
|
||||
@override
|
||||
DateTime get date => transaction.date;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is TransactionListItem) {
|
||||
return other.transaction.txHash == transaction.txHash;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/evm/evm.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/utils/tor.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'connection_sync_view_model.g.dart';
|
||||
|
||||
class ConnectionSyncViewModel = ConnectionSyncViewModelBase with _$ConnectionSyncViewModel;
|
||||
|
||||
abstract class ConnectionSyncViewModelBase with Store {
|
||||
ConnectionSyncViewModelBase(this._settingsStore, this._wallet);
|
||||
|
||||
final SettingsStore _settingsStore;
|
||||
final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
|
||||
|
||||
@computed
|
||||
bool get lookupTwitter => _settingsStore.lookupsTwitter;
|
||||
|
||||
@computed
|
||||
bool get lookupsZanoAlias => _settingsStore.lookupsZanoAlias;
|
||||
|
||||
@computed
|
||||
bool get looksUpMastodon => _settingsStore.lookupsMastodon;
|
||||
|
||||
@computed
|
||||
bool get looksUpYatService => _settingsStore.lookupsYatService;
|
||||
|
||||
@computed
|
||||
bool get looksUpUnstoppableDomains => _settingsStore.lookupsUnstoppableDomains;
|
||||
|
||||
@computed
|
||||
bool get looksUpOpenAlias => _settingsStore.lookupsOpenAlias;
|
||||
|
||||
@computed
|
||||
bool get looksUpENS => _settingsStore.lookupsENS;
|
||||
|
||||
@computed
|
||||
bool get looksUpWellKnown => _settingsStore.lookupsWellKnown;
|
||||
|
||||
@computed
|
||||
ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus;
|
||||
|
||||
@computed
|
||||
FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode;
|
||||
|
||||
@computed
|
||||
bool get disableAutomaticExchangeStatusUpdates =>
|
||||
_settingsStore.disableAutomaticExchangeStatusUpdates;
|
||||
|
||||
@computed
|
||||
bool get builtinTor => _settingsStore.currentBuiltinTor;
|
||||
|
||||
|
||||
@computed
|
||||
bool get hasPowNodes => [WalletType.nano, WalletType.banano].contains(_wallet.type);
|
||||
|
||||
@computed
|
||||
bool get useMempoolFeeAPI => _settingsStore.useMempoolFeeAPI;
|
||||
|
||||
@computed
|
||||
bool get canUseMempoolFeeAPI => _wallet.type == WalletType.bitcoin;
|
||||
|
||||
@computed
|
||||
bool get useBlinkProtection => _settingsStore.useBlinkProtection;
|
||||
|
||||
bool get canUseBlinkProtection => canSupportBlinkProtection(_wallet.chainId);
|
||||
|
||||
@computed
|
||||
bool get useEtherscan => _settingsStore.useEtherscan;
|
||||
|
||||
@computed
|
||||
bool get usePolygonScan => _settingsStore.usePolygonScan;
|
||||
|
||||
@computed
|
||||
bool get useBaseScan => _settingsStore.useBaseScan;
|
||||
|
||||
@computed
|
||||
bool get useArbiScan => _settingsStore.useArbiScan;
|
||||
|
||||
@computed
|
||||
bool get useBscScan => _settingsStore.useBscScan;
|
||||
|
||||
@computed
|
||||
bool get useTronGrid => _settingsStore.useTronGrid;
|
||||
|
||||
@computed
|
||||
bool get canUseEtherscan => _wallet.chainId == 1;
|
||||
|
||||
@computed
|
||||
bool get canUsePolygonScan => _wallet.chainId == 137;
|
||||
|
||||
@computed
|
||||
bool get canUseBaseScan => _wallet.chainId == 8453;
|
||||
|
||||
@computed
|
||||
bool get canUseArbiScan => _wallet.chainId == 42161;
|
||||
|
||||
@computed
|
||||
bool get canUseBscScan => _wallet.chainId == 56;
|
||||
|
||||
@computed
|
||||
bool get canUseTronGrid => _wallet.type == WalletType.tron;
|
||||
|
||||
@action
|
||||
void setLookupsTwitter(bool value) => _settingsStore.lookupsTwitter = value;
|
||||
|
||||
@action
|
||||
void setLookupsZanoAlias(bool value) => _settingsStore.lookupsZanoAlias = value;
|
||||
|
||||
@action
|
||||
void setLookupsMastodon(bool value) => _settingsStore.lookupsMastodon = value;
|
||||
|
||||
@action
|
||||
void setLookupsENS(bool value) => _settingsStore.lookupsENS = value;
|
||||
|
||||
@action
|
||||
void setLookupsWellKnown(bool value) => _settingsStore.lookupsWellKnown = value;
|
||||
|
||||
@action
|
||||
void setLookupsYatService(bool value) => _settingsStore.lookupsYatService = value;
|
||||
|
||||
@action
|
||||
void setLookupsUnstoppableDomains(bool value) => _settingsStore.lookupsUnstoppableDomains = value;
|
||||
|
||||
@action
|
||||
void setLookupsOpenAlias(bool value) => _settingsStore.lookupsOpenAlias = value;
|
||||
|
||||
@action
|
||||
void setUseMempoolFeeAPI(bool value) => _settingsStore.useMempoolFeeAPI = value;
|
||||
|
||||
@action
|
||||
void setDisableAutomaticExchangeStatusUpdates(bool value) =>
|
||||
_settingsStore.disableAutomaticExchangeStatusUpdates = value;
|
||||
|
||||
@action
|
||||
void setFiatMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
|
||||
|
||||
@action
|
||||
void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value;
|
||||
|
||||
@action
|
||||
void setUseBlinkProtection(bool value) => _settingsStore.useBlinkProtection = value;
|
||||
|
||||
@action
|
||||
void setUseEtherscan(bool value) {
|
||||
_settingsStore.useEtherscan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUsePolygonScan(bool value) {
|
||||
_settingsStore.usePolygonScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseBaseScan(bool value) {
|
||||
_settingsStore.useBaseScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseTronGrid(bool value) {
|
||||
_settingsStore.useTronGrid = value;
|
||||
tron!.updateTronGridUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseArbiScan(bool value) {
|
||||
_settingsStore.useArbiScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseBscScan(bool value) {
|
||||
_settingsStore.useBscScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setBuiltinTor(bool value, BuildContext context) {
|
||||
if (value) {
|
||||
unawaited(
|
||||
showPopUp<bool>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithOneAction(
|
||||
alertTitle: S.of(context).tor_connection,
|
||||
alertContent: S.of(context).tor_experimental,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () => Navigator.of(context).pop(true),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
_settingsStore.currentBuiltinTor = value;
|
||||
if (value) {
|
||||
unawaited(ensureTorStarted(context: context).then((_) async {
|
||||
if (_settingsStore.currentBuiltinTor == false) return;
|
||||
int? chainId;
|
||||
if (isEVMCompatibleChain(_wallet.type)) {
|
||||
chainId = evm!.getSelectedChainId(_wallet);
|
||||
}
|
||||
await _wallet.connectToNode(
|
||||
node: _settingsStore.getCurrentNode(_wallet.type, chainId: chainId));
|
||||
}));
|
||||
} else {
|
||||
unawaited(ensureTorStopped(context: context).then((_) async {
|
||||
if (_settingsStore.currentBuiltinTor == true) return;
|
||||
int? chainId;
|
||||
if (isEVMCompatibleChain(_wallet.type)) {
|
||||
chainId = evm!.getSelectedChainId(_wallet);
|
||||
}
|
||||
await _wallet.connectToNode(
|
||||
node: _settingsStore.getCurrentNode(_wallet.type, chainId: chainId));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,9 @@ abstract class DisplaySettingsViewModelBase with Store {
|
||||
SettingsStore get _settingsStore => _appStore.settingsStore;
|
||||
final ThemeStore _themeStore;
|
||||
|
||||
@computed
|
||||
bool get disableTradeOption => _settingsStore.disableTradeOption;
|
||||
|
||||
@computed
|
||||
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
|
||||
|
||||
@@ -110,6 +113,9 @@ abstract class DisplaySettingsViewModelBase with Store {
|
||||
return [];
|
||||
}
|
||||
|
||||
@action
|
||||
void setDisableTradeOption(bool value) => _settingsStore.disableTradeOption = value;
|
||||
|
||||
@action
|
||||
void setBalanceDisplayMode(BalanceDisplayMode value) => _settingsStore.balanceDisplayMode = value;
|
||||
|
||||
@@ -246,18 +252,18 @@ abstract class DisplaySettingsViewModelBase with Store {
|
||||
String getImageForTheme(MaterialThemeBase theme) {
|
||||
switch (theme.title) {
|
||||
case 'Dark Theme':
|
||||
return 'assets/images/dark.svg';
|
||||
return 'assets/new-ui/dark.svg';
|
||||
case 'Light Theme':
|
||||
return 'assets/images/light.svg';
|
||||
return 'assets/new-ui/light.svg';
|
||||
case 'Black Theme (Cake Primary)':
|
||||
case 'Black Theme (BCH Green)':
|
||||
case 'Black Theme (Bitcoin Yellow)':
|
||||
case 'Black Theme (Monero Orange)':
|
||||
case 'Black Theme (Tron Red)':
|
||||
case 'Black Theme (Frosting Purple)':
|
||||
return 'assets/images/black_accent.svg';
|
||||
return 'assets/new-ui/black_accent.svg';
|
||||
default:
|
||||
return 'assets/images/dark.svg';
|
||||
return 'assets/new-ui/dark.svg';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/package_info.dart';
|
||||
@@ -57,6 +58,33 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@computed
|
||||
bool get isAutoGenerateSubaddressesEnabled =>
|
||||
_settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled;
|
||||
|
||||
@action
|
||||
void setAutoGenerateSubaddresses(bool value) {
|
||||
_wallet.isEnabledAutoGenerateSubaddress = value;
|
||||
_settingsStore.autoGenerateSubaddressStatus =
|
||||
value ? AutoGenerateSubaddressStatus.enabled : AutoGenerateSubaddressStatus.disabled;
|
||||
}
|
||||
|
||||
bool get isAutoGenerateSubaddressesVisible => [
|
||||
WalletType.monero,
|
||||
WalletType.wownero,
|
||||
WalletType.bitcoin,
|
||||
WalletType.litecoin,
|
||||
WalletType.bitcoinCash,
|
||||
WalletType.dogecoin,
|
||||
WalletType.decred
|
||||
].contains(_wallet.type);
|
||||
|
||||
@computed
|
||||
bool get isMoneroWallet => _wallet.type == WalletType.monero;
|
||||
|
||||
@computed
|
||||
bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress;
|
||||
|
||||
@computed
|
||||
bool get changeRepresentativeEnabled =>
|
||||
[WalletType.nano, WalletType.banano].contains(_wallet.type);
|
||||
@@ -127,6 +155,10 @@ abstract class OtherSettingsViewModelBase with Store {
|
||||
@computed
|
||||
double get customBitcoinFeeRate => _settingsStore.customBitcoinFeeRate.toDouble();
|
||||
|
||||
@action
|
||||
void setShouldSaveRecipientAddress(bool value) =>
|
||||
_settingsStore.shouldSaveRecipientAddress = value;
|
||||
|
||||
int? get customPriorityItemIndex {
|
||||
final priorities = priorityForWalletType(walletType);
|
||||
final customItem = priorities
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/evm/evm.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
@@ -12,7 +8,6 @@ import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
|
||||
part 'privacy_settings_view_model.g.dart';
|
||||
|
||||
@@ -25,7 +20,10 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
final WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> _wallet;
|
||||
|
||||
@computed
|
||||
ExchangeApiMode get exchangeStatus => _settingsStore.exchangeStatus;
|
||||
bool get isBitcoin => _wallet.type == WalletType.bitcoin;
|
||||
|
||||
@computed
|
||||
bool get isLitecoin => _wallet.type == WalletType.litecoin;
|
||||
|
||||
@computed
|
||||
bool get isAutoGenerateSubaddressesEnabled =>
|
||||
@@ -65,9 +63,6 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
@computed
|
||||
bool get shouldSaveRecipientAddress => _settingsStore.shouldSaveRecipientAddress;
|
||||
|
||||
@computed
|
||||
FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode;
|
||||
|
||||
@computed
|
||||
bool get isAppSecure => _settingsStore.isAppSecure;
|
||||
|
||||
@@ -81,32 +76,6 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
@computed
|
||||
bool get disableBulletin => _settingsStore.disableBulletin;
|
||||
|
||||
@computed
|
||||
bool get useEtherscan => _settingsStore.useEtherscan;
|
||||
|
||||
@computed
|
||||
bool get usePolygonScan => _settingsStore.usePolygonScan;
|
||||
|
||||
@computed
|
||||
bool get useBaseScan => _settingsStore.useBaseScan;
|
||||
|
||||
@computed
|
||||
bool get useArbiScan => _settingsStore.useArbiScan;
|
||||
|
||||
@computed
|
||||
bool get useBscScan => _settingsStore.useBscScan;
|
||||
|
||||
@computed
|
||||
bool get useTronGrid => _settingsStore.useTronGrid;
|
||||
|
||||
@computed
|
||||
bool get useMempoolFeeAPI => _settingsStore.useMempoolFeeAPI;
|
||||
|
||||
@computed
|
||||
bool get useBlinkProtection => _settingsStore.useBlinkProtection;
|
||||
|
||||
bool get canUseBlinkProtection => canSupportBlinkProtection(_wallet.chainId);
|
||||
|
||||
@computed
|
||||
bool get lookupTwitter => _settingsStore.lookupsTwitter;
|
||||
|
||||
@@ -135,36 +104,18 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
bool get usePayjoin => _settingsStore.usePayjoin;
|
||||
|
||||
@computed
|
||||
bool get useLightning => _wallet.type == WalletType.bitcoin && bitcoin!.useLightning(_wallet);
|
||||
|
||||
bool get canUseEtherscan => _wallet.chainId == 1;
|
||||
|
||||
bool get canUsePolygonScan => _wallet.chainId == 137;
|
||||
|
||||
bool get canUseBaseScan => _wallet.chainId == 8453;
|
||||
|
||||
bool get canUseArbiScan => _wallet.chainId == 42161;
|
||||
|
||||
bool get canUseBscScan => _wallet.chainId == 56;
|
||||
|
||||
bool get canUseTronGrid => _wallet.type == WalletType.tron;
|
||||
|
||||
bool get canUseMempoolFeeAPI => _wallet.type == WalletType.bitcoin;
|
||||
|
||||
bool get canUsePayjoin => _wallet.type == WalletType.bitcoin && DeviceInfo.instance.isMobile;
|
||||
|
||||
@computed
|
||||
bool get canUseLightning => _wallet.type == WalletType.bitcoin;
|
||||
|
||||
@computed
|
||||
bool get useLightning => _wallet.type == WalletType.bitcoin && bitcoin!.useLightning(_wallet);
|
||||
|
||||
@action
|
||||
void setShouldSaveRecipientAddress(bool value) =>
|
||||
_settingsStore.shouldSaveRecipientAddress = value;
|
||||
|
||||
@action
|
||||
void setExchangeApiMode(ExchangeApiMode value) => _settingsStore.exchangeStatus = value;
|
||||
|
||||
@action
|
||||
void setFiatMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
|
||||
|
||||
@action
|
||||
void setIsAppSecure(bool value) => _settingsStore.isAppSecure = value;
|
||||
|
||||
@@ -178,66 +129,6 @@ abstract class PrivacySettingsViewModelBase with Store {
|
||||
@action
|
||||
void setDisableBulletin(bool value) => _settingsStore.disableBulletin = value;
|
||||
|
||||
@action
|
||||
void setLookupsTwitter(bool value) => _settingsStore.lookupsTwitter = value;
|
||||
|
||||
@action
|
||||
void setLookupsZanoAlias(bool value) => _settingsStore.lookupsZanoAlias = value;
|
||||
|
||||
@action
|
||||
void setLookupsMastodon(bool value) => _settingsStore.lookupsMastodon = value;
|
||||
|
||||
@action
|
||||
void setLookupsENS(bool value) => _settingsStore.lookupsENS = value;
|
||||
|
||||
@action
|
||||
void setLookupsWellKnown(bool value) => _settingsStore.lookupsWellKnown = value;
|
||||
|
||||
@action
|
||||
void setLookupsYatService(bool value) => _settingsStore.lookupsYatService = value;
|
||||
|
||||
@action
|
||||
void setLookupsUnstoppableDomains(bool value) => _settingsStore.lookupsUnstoppableDomains = value;
|
||||
|
||||
@action
|
||||
void setLookupsOpenAlias(bool value) => _settingsStore.lookupsOpenAlias = value;
|
||||
|
||||
@action
|
||||
void setUseEtherscan(bool value) {
|
||||
_settingsStore.useEtherscan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUsePolygonScan(bool value) {
|
||||
_settingsStore.usePolygonScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseBaseScan(bool value) {
|
||||
_settingsStore.useBaseScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseTronGrid(bool value) {
|
||||
_settingsStore.useTronGrid = value;
|
||||
tron!.updateTronGridUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseArbiScan(bool value) {
|
||||
_settingsStore.useArbiScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseBscScan(bool value) {
|
||||
_settingsStore.useBscScan = value;
|
||||
evm!.updateScanProviderUsageState(_wallet, value);
|
||||
}
|
||||
|
||||
@action
|
||||
void setUseMempoolFeeAPI(bool value) => _settingsStore.useMempoolFeeAPI = value;
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ abstract class SecuritySettingsViewModelBase with Store {
|
||||
final SettingsStore _settingsStore;
|
||||
final AuthService _authService;
|
||||
|
||||
@computed
|
||||
bool get isAppSecure => _settingsStore.isAppSecure;
|
||||
|
||||
@computed
|
||||
bool get allowBiometricalAuthentication => _settingsStore.allowBiometricalAuthentication;
|
||||
|
||||
@@ -36,6 +39,9 @@ abstract class SecuritySettingsViewModelBase with Store {
|
||||
return await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated();
|
||||
}
|
||||
|
||||
@action
|
||||
void setIsAppSecure(bool value) => _settingsStore.isAppSecure = value;
|
||||
|
||||
@action
|
||||
void setAllowBiometricalAuthentication(bool value) =>
|
||||
_settingsStore.allowBiometricalAuthentication = value;
|
||||
|
||||
@@ -20,7 +20,11 @@ dependencies:
|
||||
ref: 69b3276b090fa6ac01b4483ca3adca93a8e615be
|
||||
http: ^1.1.0
|
||||
path_provider: ^2.0.11
|
||||
modal_bottom_sheet: ^3.0.0
|
||||
modal_bottom_sheet:
|
||||
git:
|
||||
url: https://github.com/cake-tech/modal_bottom_sheet
|
||||
ref: b1cca111c53d41b9f07123a8c67cfe06fb1b69bf
|
||||
path: modal_bottom_sheet
|
||||
mobx: ^2.1.4
|
||||
flutter_mobx: 2.0.6+5
|
||||
flutter_slidable: ^3.0.1
|
||||
|
||||
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
@@ -1,10 +1,3 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_14441_461975)">
|
||||
<path d="M8.51392 11.9985L5 8.48462L5.66456 7.82006L8.51392 10.6576L11.3633 7.82006L12.0278 8.48462L8.51392 11.9985ZM5.67404 4.16738L5 3.51245L8.51392 -0.00146484L12.0278 3.51245L11.3538 4.16738L8.51392 1.33947L5.67404 4.16738Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_14441_461975">
|
||||
<rect width="12" height="12" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<svg width="8" height="13" viewBox="0 0 8 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.76917 12.8717L0 9.1025L0.712833 8.38967L3.76917 11.4333L6.8255 8.38967L7.53833 9.1025L3.76917 12.8717ZM0.723 4.47167L0 3.76917L3.76917 0L7.53833 3.76917L6.81533 4.47167L3.76917 1.43833L0.723 4.47167Z" fill="#8C9FBB"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 551 B After Width: | Height: | Size: 331 B |
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
@@ -0,0 +1,47 @@
|
||||
<svg width="250" height="250" viewBox="0 0 250 250" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="#F7931A"/>
|
||||
<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint0_linear_14352_348907)"/>
|
||||
<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint1_linear_14352_348907)"/>
|
||||
<path d="M246.252 155.241C229.557 222.205 161.732 262.959 94.7596 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7758C20.451 27.8031 88.2752 -12.9547 155.228 3.74061C222.197 20.4359 262.947 88.2719 246.252 155.241Z" fill="url(#paint2_linear_14352_348907)"/>
|
||||
<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint3_linear_14352_348907)"/>
|
||||
<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint4_linear_14352_348907)"/>
|
||||
<path d="M3.76352 94.7757C20.4512 27.8033 88.2754 -12.9547 155.228 3.74058C222.197 20.4359 262.947 88.272 246.252 155.241L245.852 156.806C228.634 222.319 162.265 262.198 96.329 246.641L94.7597 246.26C27.8143 229.565 -12.9396 161.737 3.76352 94.7757ZM154.018 8.59214C89.7456 -7.43476 24.6351 31.6917 8.61509 95.9847V95.9866C-7.41942 160.268 31.7034 225.381 95.9686 241.408C160.262 257.44 225.373 218.317 241.4 154.032C257.428 89.7415 218.307 24.6193 154.018 8.59214Z" fill="url(#paint5_linear_14352_348907)"/>
|
||||
<path d="M59.8672 139.11L153.37 58.5384C157.444 55.9292 161.327 58.5384 158.841 63.0146L128.999 121.703H182.216C182.216 121.703 190.671 121.703 182.216 128.666L90.2058 209.734C83.7402 215.205 79.264 212.221 83.7402 203.766L112.587 146.57H59.8672C59.8672 146.57 51.4121 146.57 59.8672 139.11Z" fill="#F66E00"/>
|
||||
<path d="M59.8672 139.11L153.37 58.5384C157.444 55.9292 161.327 58.5384 158.841 63.0146L128.999 121.703H182.216C182.216 121.703 190.671 121.703 182.216 128.666L90.2058 209.734C83.7402 215.205 79.264 212.221 83.7402 203.766L112.587 146.57H59.8672C59.8672 146.57 51.4121 146.57 59.8672 139.11Z" fill="url(#paint6_linear_14352_348907)"/>
|
||||
<path d="M59.8672 129.11L153.37 48.5384C157.444 45.9292 161.327 48.5384 158.841 53.0146L128.999 111.703H182.216C182.216 111.703 190.671 111.703 182.216 118.666L90.2058 199.734C83.7402 205.205 79.264 202.221 83.7402 193.766L112.587 136.57H59.8672C59.8672 136.57 51.4122 136.57 59.8672 129.11Z" fill="url(#paint7_linear_14352_348907)"/>
|
||||
<path d="M153.37 48.5381C157.444 45.9293 161.327 48.5386 158.841 53.0146L128.999 111.703H182.216C182.216 111.703 190.671 111.703 182.216 118.666L90.206 199.734L89.9043 199.984C83.6025 205.11 79.3339 202.089 83.7402 193.766L112.587 136.57H59.8672L59.5205 136.556C58.0447 136.456 52.6656 135.667 59.4834 129.454L59.8672 129.11L153.37 48.5381ZM157.358 49.7138C157.097 49.5162 156.108 49.2016 154.55 50.1601L61.1728 130.625C59.1363 132.425 58.3889 133.553 58.1709 134.13C58.1586 134.162 58.1504 134.192 58.1425 134.217C58.3059 134.302 58.5992 134.409 59.0254 134.484C59.2691 134.527 59.4939 134.55 59.6562 134.561C59.7358 134.566 59.7973 134.568 59.8349 134.569C59.8537 134.57 59.8664 134.57 59.872 134.57H115.835L85.5263 194.667L85.5166 194.685L85.5078 194.702C84.4623 196.677 84.0261 198.177 83.9463 199.191C83.907 199.691 83.9586 200.015 84.0185 200.202C84.0743 200.376 84.1322 200.421 84.1367 200.425C84.1439 200.431 84.1966 200.473 84.3623 200.492C84.5453 200.513 84.8502 200.5 85.292 200.375C86.1886 200.12 87.4319 199.461 88.914 198.207L180.894 117.165L180.919 117.143L180.944 117.122C182.863 115.542 183.621 114.527 183.878 113.995C183.7 113.924 183.434 113.843 183.08 113.785C182.831 113.744 182.602 113.722 182.436 113.712C182.355 113.707 182.291 113.704 182.252 113.703H125.738L157.058 52.1084L157.074 52.0752L157.092 52.0429C157.573 51.1768 157.647 50.5775 157.616 50.2461C157.588 49.9474 157.477 49.8036 157.358 49.7138Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F7BC1A"/>
|
||||
<stop offset="1" stop-color="#FF7700"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F7BC1A"/>
|
||||
<stop offset="1" stop-color="#FF6A00"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_14352_348907" x1="125.006" y1="0" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.725084" stop-color="#C94701" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#C94701" stop-opacity="0.3"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFE091"/>
|
||||
<stop offset="1" stop-color="#FF9735"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.85" stop-color="#FFA54D" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#FFA54D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_14352_348907" x1="125.006" y1="0.000349739" x2="125.006" y2="250.003" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFF3DA"/>
|
||||
<stop offset="0.15" stop-color="#FFF3DA" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint6_linear_14352_348907" x1="121.042" y1="57.5" x2="121.042" y2="212.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F89A02"/>
|
||||
<stop offset="1" stop-color="#F56600"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_14352_348907" x1="121.042" y1="47.5" x2="121.042" y2="202.5" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#FEEABD"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -1,40 +1,35 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_16845_60754)">
|
||||
<g clip-path="url(#clip1_16845_60754)">
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint0_linear_16845_60754)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint1_linear_16845_60754)"/>
|
||||
<path d="M11.8691 3.35876C14.2163 3.35876 16.1192 5.26162 16.1192 7.60881V9.85891H17.4943C18.1155 9.85897 18.6191 10.3625 18.6191 10.9838V18.2337C18.6191 18.855 18.1155 19.3586 17.4943 19.3586H6.24403C5.62276 19.3586 5.11914 18.855 5.11914 18.2337V10.9838C5.11916 10.3625 5.62278 9.85897 6.24403 9.85891H7.61908V7.60881C7.6191 5.26165 9.52197 3.3588 11.8691 3.35876ZM11.8691 13.0787C11.049 13.0787 10.384 13.7436 10.384 14.5638C10.384 15.3839 11.049 16.0489 11.8691 16.0489C12.6893 16.0489 13.3543 15.3839 13.3543 14.5638C13.3543 13.7436 12.6893 13.0787 11.8691 13.0787ZM11.8691 5.35871C10.6265 5.35875 9.61938 6.36621 9.61936 7.60881V9.85891H14.1193V7.60881C14.1192 6.36619 13.1118 5.35871 11.8691 5.35871Z" fill="white"/>
|
||||
<path d="M11.8691 3.35876C14.2163 3.35876 16.1192 5.26162 16.1192 7.60881V9.85891H17.4943C18.1155 9.85897 18.6191 10.3625 18.6191 10.9838V18.2337C18.6191 18.855 18.1155 19.3586 17.4943 19.3586H6.24403C5.62276 19.3586 5.11914 18.855 5.11914 18.2337V10.9838C5.11916 10.3625 5.62278 9.85897 6.24403 9.85891H7.61908V7.60881C7.6191 5.26165 9.52197 3.3588 11.8691 3.35876ZM11.8691 13.0787C11.049 13.0787 10.384 13.7436 10.384 14.5638C10.384 15.3839 11.049 16.0489 11.8691 16.0489C12.6893 16.0489 13.3543 15.3839 13.3543 14.5638C13.3543 13.7436 12.6893 13.0787 11.8691 13.0787ZM11.8691 5.35871C10.6265 5.35875 9.61938 6.36621 9.61936 7.60881V9.85891H14.1193V7.60881C14.1192 6.36619 13.1118 5.35871 11.8691 5.35871Z" fill="url(#paint2_linear_16845_60754)"/>
|
||||
<path d="M11.8691 3.35876C14.2163 3.35876 16.1192 5.26162 16.1192 7.60881V9.85891H17.4943C18.1155 9.85897 18.6191 10.3625 18.6191 10.9838V18.2337C18.6191 18.855 18.1155 19.3586 17.4943 19.3586H6.24403C5.62276 19.3586 5.11914 18.855 5.11914 18.2337V10.9838C5.11916 10.3625 5.62278 9.85897 6.24403 9.85891H7.61908V7.60881C7.6191 5.26165 9.52197 3.3588 11.8691 3.35876ZM11.8691 13.0787C11.049 13.0787 10.384 13.7436 10.384 14.5638C10.384 15.3839 11.049 16.0489 11.8691 16.0489C12.6893 16.0489 13.3543 15.3839 13.3543 14.5638C13.3543 13.7436 12.6893 13.0787 11.8691 13.0787ZM11.8691 5.35871C10.6265 5.35875 9.61938 6.36621 9.61936 7.60881V9.85891H14.1193V7.60881C14.1192 6.36619 13.1118 5.35871 11.8691 5.35871Z" fill="url(#paint3_linear_16845_60754)"/>
|
||||
<path d="M11.8691 3.35876C14.2163 3.35876 16.1192 5.26162 16.1192 7.60881V9.85891H17.4943C18.1155 9.85897 18.6191 10.3625 18.6191 10.9838V18.2337C18.6191 18.855 18.1155 19.3586 17.4943 19.3586H6.24403C5.62276 19.3586 5.11914 18.855 5.11914 18.2337V10.9838C5.11916 10.3625 5.62278 9.85897 6.24403 9.85891H7.61908V7.60881C7.6191 5.26165 9.52197 3.3588 11.8691 3.35876ZM11.8691 13.0787C11.049 13.0787 10.384 13.7436 10.384 14.5638C10.384 15.3839 11.049 16.0489 11.8691 16.0489C12.6893 16.0489 13.3543 15.3839 13.3543 14.5638C13.3543 13.7436 12.6893 13.0787 11.8691 13.0787ZM11.8691 5.35871C10.6265 5.35875 9.61938 6.36621 9.61936 7.60881V9.85891H14.1193V7.60881C14.1192 6.36619 13.1118 5.35871 11.8691 5.35871Z" fill="url(#paint4_linear_16845_60754)"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_16845_60754" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8F8F8F"/>
|
||||
<stop offset="1" stop-color="#6D6D6D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_16845_60754" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F7931A"/>
|
||||
<stop offset="1" stop-color="#F67300"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_16845_60754" x1="11.8691" y1="3.35876" x2="11.8691" y2="19.3586" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4B8FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_16845_60754" x1="11.8691" y1="3.35876" x2="11.8691" y2="19.3586" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4CEFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_16845_60754" x1="11.8691" y1="3.35876" x2="11.8691" y2="19.3586" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#5F330B"/>
|
||||
<stop offset="1" stop-color="#462100"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_16845_60754">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_16845_60754">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#clip0_16529_391320)">
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint0_linear_16529_391320)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint1_linear_16529_391320)"/>
|
||||
<path d="M11.8711 3.3584C14.2183 3.3584 16.1211 5.26126 16.1212 7.60844V9.85854H17.4962C18.1175 9.8586 18.6211 10.3622 18.6211 10.9834V18.2334C18.6211 18.8547 18.1175 19.3582 17.4962 19.3583H6.24598C5.62471 19.3582 5.12109 18.8547 5.12109 18.2334V10.9834C5.12112 10.3622 5.62473 9.8586 6.24598 9.85854H7.62103V7.60844C7.62105 5.26128 9.52393 3.35844 11.8711 3.3584ZM11.8711 13.0783C11.051 13.0783 10.386 13.7433 10.386 14.5634C10.386 15.3835 11.051 16.0485 11.8711 16.0485C12.6912 16.0485 13.3562 15.3835 13.3562 14.5634C13.3562 13.7433 12.6912 13.0783 11.8711 13.0783ZM11.8711 5.35834C10.6285 5.35838 9.62133 6.36584 9.62131 7.60844V9.85854H14.1212V7.60844C14.1212 6.36582 13.1137 5.35834 11.8711 5.35834Z" fill="white"/>
|
||||
<path d="M11.8711 3.3584C14.2183 3.3584 16.1211 5.26126 16.1212 7.60844V9.85854H17.4962C18.1175 9.8586 18.6211 10.3622 18.6211 10.9834V18.2334C18.6211 18.8547 18.1175 19.3582 17.4962 19.3583H6.24598C5.62471 19.3582 5.12109 18.8547 5.12109 18.2334V10.9834C5.12112 10.3622 5.62473 9.8586 6.24598 9.85854H7.62103V7.60844C7.62105 5.26128 9.52393 3.35844 11.8711 3.3584ZM11.8711 13.0783C11.051 13.0783 10.386 13.7433 10.386 14.5634C10.386 15.3835 11.051 16.0485 11.8711 16.0485C12.6912 16.0485 13.3562 15.3835 13.3562 14.5634C13.3562 13.7433 12.6912 13.0783 11.8711 13.0783ZM11.8711 5.35834C10.6285 5.35838 9.62133 6.36584 9.62131 7.60844V9.85854H14.1212V7.60844C14.1212 6.36582 13.1137 5.35834 11.8711 5.35834Z" fill="url(#paint2_linear_16529_391320)"/>
|
||||
<path d="M11.8711 3.3584C14.2183 3.3584 16.1211 5.26126 16.1212 7.60844V9.85854H17.4962C18.1175 9.8586 18.6211 10.3622 18.6211 10.9834V18.2334C18.6211 18.8547 18.1175 19.3582 17.4962 19.3583H6.24598C5.62471 19.3582 5.12109 18.8547 5.12109 18.2334V10.9834C5.12112 10.3622 5.62473 9.8586 6.24598 9.85854H7.62103V7.60844C7.62105 5.26128 9.52393 3.35844 11.8711 3.3584ZM11.8711 13.0783C11.051 13.0783 10.386 13.7433 10.386 14.5634C10.386 15.3835 11.051 16.0485 11.8711 16.0485C12.6912 16.0485 13.3562 15.3835 13.3562 14.5634C13.3562 13.7433 12.6912 13.0783 11.8711 13.0783ZM11.8711 5.35834C10.6285 5.35838 9.62133 6.36584 9.62131 7.60844V9.85854H14.1212V7.60844C14.1212 6.36582 13.1137 5.35834 11.8711 5.35834Z" fill="url(#paint3_linear_16529_391320)"/>
|
||||
<path d="M11.8711 3.3584C14.2183 3.3584 16.1211 5.26126 16.1212 7.60844V9.85854H17.4962C18.1175 9.8586 18.6211 10.3622 18.6211 10.9834V18.2334C18.6211 18.8547 18.1175 19.3582 17.4962 19.3583H6.24598C5.62471 19.3582 5.12109 18.8547 5.12109 18.2334V10.9834C5.12112 10.3622 5.62473 9.8586 6.24598 9.85854H7.62103V7.60844C7.62105 5.26128 9.52393 3.35844 11.8711 3.3584ZM11.8711 13.0783C11.051 13.0783 10.386 13.7433 10.386 14.5634C10.386 15.3835 11.051 16.0485 11.8711 16.0485C12.6912 16.0485 13.3562 15.3835 13.3562 14.5634C13.3562 13.7433 12.6912 13.0783 11.8711 13.0783ZM11.8711 5.35834C10.6285 5.35838 9.62133 6.36584 9.62131 7.60844V9.85854H14.1212V7.60844C14.1212 6.36582 13.1137 5.35834 11.8711 5.35834Z" fill="url(#paint4_linear_16529_391320)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_16529_391320" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#8F8F8F"/>
|
||||
<stop offset="1" stop-color="#6D6D6D"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_16529_391320" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F7931A"/>
|
||||
<stop offset="1" stop-color="#F67300"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_16529_391320" x1="11.8711" y1="3.3584" x2="11.8711" y2="19.3583" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4B8FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_16529_391320" x1="11.8711" y1="3.3584" x2="11.8711" y2="19.3583" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4CEFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_16529_391320" x1="11.8711" y1="3.3584" x2="11.8711" y2="19.3583" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#5F330B"/>
|
||||
<stop offset="1" stop-color="#462100"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_16529_391320">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.2 KiB |
@@ -1,47 +1,42 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_16845_60955)">
|
||||
<g clip-path="url(#clip1_16845_60955)">
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="black"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint0_linear_16845_60955)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint1_linear_16845_60955)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint2_linear_16845_60955)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="#2C5CF6"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint3_linear_16845_60955)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint4_linear_16845_60955)"/>
|
||||
<path d="M12 20.8489C9.98136 20.2984 8.31007 19.1102 6.98613 17.2843C5.66204 15.4584 5 13.417 5 11.1602V5.79006L12 3.16949L19 5.79006V11.1602C19 13.417 18.338 15.4584 17.0139 17.2843C15.6899 19.1102 14.0186 20.2984 12 20.8489ZM12 19.3736C13.5089 18.9069 14.7689 17.9852 15.78 16.6086C16.7911 15.2319 17.3822 13.6958 17.5533 12.0002H12V4.6591L6.4 6.75023V11.5714C6.4 11.6862 6.41556 11.8291 6.44667 12.0002H12V19.3736Z" fill="#E3E3E3"/>
|
||||
<path d="M12 20.8489C9.98136 20.2984 8.31007 19.1102 6.98613 17.2843C5.66204 15.4584 5 13.417 5 11.1602V5.79006L12 3.16949L19 5.79006V11.1602C19 13.417 18.338 15.4584 17.0139 17.2843C15.6899 19.1102 14.0186 20.2984 12 20.8489ZM12 19.3736C13.5089 18.9069 14.7689 17.9852 15.78 16.6086C16.7911 15.2319 17.3822 13.6958 17.5533 12.0002H12V4.6591L6.4 6.75023V11.5714C6.4 11.6862 6.41556 11.8291 6.44667 12.0002H12V19.3736Z" fill="url(#paint5_linear_16845_60955)"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_16845_60955" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2C2C2C"/>
|
||||
<stop offset="1" stop-color="#191919"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_16845_60955" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#351C83"/>
|
||||
<stop offset="1" stop-color="#0C0033"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_16845_60955" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF6200"/>
|
||||
<stop offset="1" stop-color="#E20F0F"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_16845_60955" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2C5CF6"/>
|
||||
<stop offset="1" stop-color="#0F37FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_16845_60955" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3B96FF"/>
|
||||
<stop offset="1" stop-color="#0044F0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_16845_60955" x1="12" y1="3.16949" x2="12" y2="20.8489" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4CEFF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_16845_60955">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip1_16845_60955">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#clip0_16529_391334)">
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="black"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint0_linear_16529_391334)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint1_linear_16529_391334)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint2_linear_16529_391334)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="#2C5CF6"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint3_linear_16529_391334)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint4_linear_16529_391334)"/>
|
||||
<path d="M12 20.8494C9.98136 20.2988 8.31007 19.1106 6.98613 17.2847C5.66204 15.4588 5 13.4175 5 11.1607V5.79049L12 3.16992L19 5.79049V11.1607C19 13.4175 18.338 15.4588 17.0139 17.2847C15.6899 19.1106 14.0186 20.2988 12 20.8494ZM12 19.374C13.5089 18.9073 14.7689 17.9857 15.78 16.609C16.7911 15.2323 17.3822 13.6962 17.5533 12.0007H12V4.65952L6.4 6.75066V11.5718C6.4 11.6866 6.41556 11.8295 6.44667 12.0007H12V19.374Z" fill="#E3E3E3"/>
|
||||
<path d="M12 20.8494C9.98136 20.2988 8.31007 19.1106 6.98613 17.2847C5.66204 15.4588 5 13.4175 5 11.1607V5.79049L12 3.16992L19 5.79049V11.1607C19 13.4175 18.338 15.4588 17.0139 17.2847C15.6899 19.1106 14.0186 20.2988 12 20.8494ZM12 19.374C13.5089 18.9073 14.7689 17.9857 15.78 16.609C16.7911 15.2323 17.3822 13.6962 17.5533 12.0007H12V4.65952L6.4 6.75066V11.5718C6.4 11.6866 6.41556 11.8295 6.44667 12.0007H12V19.374Z" fill="url(#paint5_linear_16529_391334)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_16529_391334" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2C2C2C"/>
|
||||
<stop offset="1" stop-color="#191919"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_16529_391334" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#351C83"/>
|
||||
<stop offset="1" stop-color="#0C0033"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_16529_391334" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF6200"/>
|
||||
<stop offset="1" stop-color="#E20F0F"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_16529_391334" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2C5CF6"/>
|
||||
<stop offset="1" stop-color="#0F37FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_16529_391334" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3B96FF"/>
|
||||
<stop offset="1" stop-color="#0044F0"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint5_linear_16529_391334" x1="12" y1="3.16992" x2="12" y2="20.8494" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#A4CEFF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_16529_391334">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,29 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_17329_949648)">
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint0_linear_17329_949648)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint1_linear_17329_949648)"/>
|
||||
<path d="M0 8C0 5.19974 0 3.79961 0.544967 2.73005C1.02433 1.78924 1.78924 1.02433 2.73005 0.544967C3.79961 0 5.19974 0 8 0H16C18.8003 0 20.2004 0 21.27 0.544967C22.2108 1.02433 22.9757 1.78924 23.455 2.73005C24 3.79961 24 5.19974 24 8V16C24 18.8003 24 20.2004 23.455 21.27C22.9757 22.2108 22.2108 22.9757 21.27 23.455C20.2004 24 18.8003 24 16 24H8C5.19974 24 3.79961 24 2.73005 23.455C1.78924 22.9757 1.02433 22.2108 0.544967 21.27C0 20.2004 0 18.8003 0 16V8Z" fill="url(#paint2_linear_17329_949648)"/>
|
||||
<path d="M21.6004 12.2103L15.9535 17.8165L12.0004 13.8926L8.04727 17.8165L2.40039 12.2103L4.0931 10.5301L8.04727 14.454L12.0004 10.5301L15.9535 14.454L19.9077 10.5301L21.6004 12.2103ZM5.78997 8.85195C9.62131 5.04933 14.3815 5.04937 18.2129 8.85195L16.5181 10.5332C13.6046 7.64263 10.3981 7.64269 7.48477 10.5342L5.78997 8.85195Z" fill="url(#paint3_linear_17329_949648)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_17329_949648" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0082F8"/>
|
||||
<stop offset="1" stop-color="#0666FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_17329_949648" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#2B9AFF"/>
|
||||
<stop offset="1" stop-color="#0666FF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_17329_949648" x1="12" y1="0" x2="12" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3396FF"/>
|
||||
<stop offset="1" stop-color="#007CFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_17329_949648" x1="12.0004" y1="6" x2="12.0004" y2="17.8165" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#BFDEFF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_17329_949648">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -242,6 +242,7 @@
|
||||
"connected": "متصل",
|
||||
"connection_sync": "الاتصال والمزامنة",
|
||||
"connections": "الاتصالات",
|
||||
"connections_desc": "إدارة الاتصالات بالخدمات وواجهات برمجة التطبيقات التابعة لجهات خارجية.",
|
||||
"connectWalletPrompt": "قم بتوصيل محفظتك عبر WalletConnect لإجراء المعاملات",
|
||||
"contact": "جهة اتصال",
|
||||
"contact_list_contacts": "جهات الاتصال",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "تم حفظ الملف",
|
||||
"fill_code": "يرجى إدخال رمز التحقق المُرسل إلى بريدك الإلكتروني",
|
||||
"filter_by": "تصفية حسب",
|
||||
"filters": "المرشحات",
|
||||
"finding_provider": "جارٍ البحث عن مزوّد",
|
||||
"first_wallet_text": "محفظة رائعة لـ Monero وBitcoin وEthereum وLitecoin وHaven",
|
||||
"fixed_pair_not_supported": "هذا الزوج الثابت غير مدعوم مع خدمات المبادلة المحددة",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "الخصوصية",
|
||||
"privacy_and_security": "الخصوصية والأمان",
|
||||
"privacy_and_security_desc": "قم بتكوين إعدادات المصادقة والأمان وإعداد المصادقة الثنائية (2FA) في Cake.",
|
||||
"privacy_desc": "تغيير إعدادات الخصوصية وتبديل ميزات الخصوصية الخاصة.",
|
||||
"privacy_features": "ميزات الخصوصية",
|
||||
"privacy_policy": "سياسة الخصوصية",
|
||||
"privacy_settings": "إعدادات الخصوصية",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Свързан",
|
||||
"connection_sync": "Връзка и синхронизация",
|
||||
"connections": "Връзки",
|
||||
"connections_desc": "Управлявайте връзки към услуги и API на трети страни.",
|
||||
"connectWalletPrompt": "Свържете портфейла си с WalletConnect, за да извършвате транзакции",
|
||||
"contact": "Контакт",
|
||||
"contact_list_contacts": "Контакти",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Файлът е запазен",
|
||||
"fill_code": "Моля, въведете кода за потвърждение, изпратен на вашия имейл",
|
||||
"filter_by": "Филтриране по",
|
||||
"filters": "Филтри",
|
||||
"finding_provider": "Намиране на доставчик",
|
||||
"first_wallet_text": "Страхотен портфейл за Monero, Bitcoin, Ethereum, Litecoin и Haven",
|
||||
"fixed_pair_not_supported": "Тази фиксирана двойка не се поддържа от избраните услуги за обмен",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Поверителност",
|
||||
"privacy_and_security": "Поверителност и сигурност",
|
||||
"privacy_and_security_desc": "Конфигурирайте настройките за удостоверяване и сигурност и настройте Cake 2FA.",
|
||||
"privacy_desc": "Променете настройките за поверителност и превключете специални функции за поверителност.",
|
||||
"privacy_features": "Функции за поверителност",
|
||||
"privacy_policy": "Политика за поверителност",
|
||||
"privacy_settings": "Настройки за поверителност",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Připojeno",
|
||||
"connection_sync": "Připojení a synchronizace",
|
||||
"connections": "Připojení",
|
||||
"connections_desc": "Správa připojení ke službám a rozhraním API třetích stran.",
|
||||
"connectWalletPrompt": "Připojte svou peněženku přes WalletConnect a provádějte transakce",
|
||||
"contact": "Kontakt",
|
||||
"contact_list_contacts": "Kontakty",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Soubor uložen",
|
||||
"fill_code": "Zadejte prosím ověřovací kód, který vám byl zaslán na e-mail",
|
||||
"filter_by": "Filtrovat podle",
|
||||
"filters": "Filtry",
|
||||
"finding_provider": "Hledání poskytovatele",
|
||||
"first_wallet_text": "Skvělá peněženka pro Monero, Bitcoin, Ethereum, Litecoin a Haven",
|
||||
"fixed_pair_not_supported": "Tento pevný pár není podporován u vybraných swapovacích služeb",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Soukromí",
|
||||
"privacy_and_security": "Soukromí a zabezpečení",
|
||||
"privacy_and_security_desc": "Nakonfigurujte nastavení ověřování a zabezpečení a nastavte Cake 2FA.",
|
||||
"privacy_desc": "Změňte nastavení ochrany osobních údajů a přepínejte speciální funkce ochrany osobních údajů.",
|
||||
"privacy_features": "Funkce soukromí",
|
||||
"privacy_policy": "Zásady ochrany osobních údajů",
|
||||
"privacy_settings": "Nastavení soukromí",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Verbunden",
|
||||
"connection_sync": "Verbindung und Synchronisierung",
|
||||
"connections": "Verbindungen",
|
||||
"connections_desc": "Verwalten Sie Verbindungen zu Diensten und APIs von Drittanbietern.",
|
||||
"connectWalletPrompt": "Verbinden Sie Ihr Wallet mit WalletConnect, um Transaktionen durchzuführen",
|
||||
"contact": "Kontakt",
|
||||
"contact_list_contacts": "Kontakte",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Datei gespeichert",
|
||||
"fill_code": "Bitte geben Sie den Verifizierungscode ein, den Sie per E-Mail erhalten haben",
|
||||
"filter_by": "Filtern nach",
|
||||
"filters": "Filter",
|
||||
"finding_provider": "Anbieter wird gesucht",
|
||||
"first_wallet_text": "Eine großartige Wallet für Monero, Bitcoin, Ethereum, Litecoin und Haven",
|
||||
"fixed_pair_not_supported": "Dieses feste Paar wird von den ausgewählten Swap-Diensten nicht unterstützt",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Privatsphäre",
|
||||
"privacy_and_security": "Datenschutz & Sicherheit",
|
||||
"privacy_and_security_desc": "Konfigurieren Sie Authentifizierungs- und Sicherheitseinstellungen und richten Sie Cake 2FA ein.",
|
||||
"privacy_desc": "Ändern Sie die Datenschutzeinstellungen und schalten Sie spezielle Datenschutzfunktionen ein.",
|
||||
"privacy_features": "Datenschutzfunktionen",
|
||||
"privacy_policy": "Datenschutzerklärung",
|
||||
"privacy_settings": "Datenschutzeinstellungen",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Connected",
|
||||
"connection_sync": "Connection and sync",
|
||||
"connections": "Connections",
|
||||
"connections_desc": "Manage connections to services and third party APIs.",
|
||||
"connectWalletPrompt": "Connect your wallet with WalletConnect to make transactions",
|
||||
"contact": "Contact",
|
||||
"contact_list_contacts": "Contacts",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "File saved",
|
||||
"fill_code": "Please fill in the verification code provided to your email",
|
||||
"filter_by": "Filter by",
|
||||
"filters": "Filters",
|
||||
"finding_provider": "Finding provider",
|
||||
"first_wallet_text": "Awesome wallet for Monero, Bitcoin, Ethereum, Litecoin, and Haven",
|
||||
"fixed_pair_not_supported": "This fixed pair is not supported with the selected swap services",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Privacy",
|
||||
"privacy_and_security": "Privacy & Security",
|
||||
"privacy_and_security_desc": "Configure authentication and security settings and setup Cake 2FA.",
|
||||
"privacy_desc": "Change privacy settings and toggle special privacy features.",
|
||||
"privacy_features": "Privacy features",
|
||||
"privacy_policy": "Privacy Policy",
|
||||
"privacy_settings": "Privacy settings",
|
||||
@@ -1365,4 +1368,4 @@
|
||||
"zcash_card_missing_funds": "Missing funds?",
|
||||
"zcash_card_scan": "Scan",
|
||||
"zcash_card_warning": "Do not close the app until the procedure completes, if you do so this process will need to restart from scratch."
|
||||
}
|
||||
}
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Conectado",
|
||||
"connection_sync": "Conexión y sincronización",
|
||||
"connections": "Conexiones",
|
||||
"connections_desc": "Administrar conexiones a servicios y API de terceros.",
|
||||
"connectWalletPrompt": "Conecta tu billetera con WalletConnect para realizar transacciones",
|
||||
"contact": "Contacto",
|
||||
"contact_list_contacts": "Contactos",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Archivo guardado",
|
||||
"fill_code": "Por favor, introduce el código de verificación enviado a tu correo electrónico",
|
||||
"filter_by": "Filtrar por",
|
||||
"filters": "Filtros",
|
||||
"finding_provider": "Buscando proveedor",
|
||||
"first_wallet_text": "Billetera increíble para Monero, Bitcoin, Ethereum, Litecoin y Haven",
|
||||
"fixed_pair_not_supported": "Este par fijo no es compatible con los servicios de swap seleccionados",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Privacidad",
|
||||
"privacy_and_security": "Privacidad y seguridad",
|
||||
"privacy_and_security_desc": "Configure los ajustes de autenticación y seguridad y configure Cake 2FA.",
|
||||
"privacy_desc": "Cambie la configuración de privacidad y alterne funciones de privacidad especiales.",
|
||||
"privacy_features": "Funciones de privacidad",
|
||||
"privacy_policy": "Política de privacidad",
|
||||
"privacy_settings": "Configuración de privacidad",
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
"connected": "متصل",
|
||||
"connection_sync": "اتصال و همگامسازی",
|
||||
"connections": "اتصالات",
|
||||
"connections_desc": "اتصالات به سرویس ها و API های شخص ثالث را مدیریت کنید.",
|
||||
"connectWalletPrompt": "برای انجام تراکنشها، کیف پول خود را از طریق WalletConnect متصل کنید",
|
||||
"contact": "مخاطب",
|
||||
"contact_list_contacts": "مخاطبین",
|
||||
@@ -473,6 +474,7 @@
|
||||
"file_saved": "فایل ذخیره شد",
|
||||
"fill_code": "لطفاً کد تأیید ارسالشده به ایمیل خود را وارد کنید",
|
||||
"filter_by": "فیلتر بر اساس",
|
||||
"filters": "فیلترها",
|
||||
"finding_provider": "در حال یافتن ارائهدهنده",
|
||||
"first_wallet_text": "کیف پول فوقالعاده برای مونرو، بیتکوین، اتریوم، لایتکوین و هیون",
|
||||
"fixed_pair_not_supported": "این جفتارز ثابت توسط سرویسهای سواپ انتخابشده پشتیبانی نمیشود",
|
||||
@@ -754,6 +756,7 @@
|
||||
"privacy": "حریم خصوصی",
|
||||
"privacy_and_security": "حریم خصوصی و امنیت",
|
||||
"privacy_and_security_desc": "تنظیمات احراز هویت و امنیت را پیکربندی کنید و Cake 2FA را راهاندازی کنید.",
|
||||
"privacy_desc": "تنظیمات حریم خصوصی را تغییر دهید و ویژگی های حریم خصوصی را تغییر دهید.",
|
||||
"privacy_features": "ویژگیهای حریم خصوصی",
|
||||
"privacy_policy": "سیاست حفظ حریم خصوصی",
|
||||
"privacy_settings": "تنظیمات حریم خصوصی",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Connecté",
|
||||
"connection_sync": "Connexion et synchronisation",
|
||||
"connections": "Connexions",
|
||||
"connections_desc": "Gérez les connexions aux services et aux API tierces.",
|
||||
"connectWalletPrompt": "Connectez votre portefeuille avec WalletConnect pour effectuer des transactions",
|
||||
"contact": "Contact",
|
||||
"contact_list_contacts": "Contacts",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Fichier enregistré",
|
||||
"fill_code": "Veuillez saisir le code de vérification envoyé à votre adresse e-mail.",
|
||||
"filter_by": "Filtrer par",
|
||||
"filters": "Filtres",
|
||||
"finding_provider": "Recherche d’un fournisseur",
|
||||
"first_wallet_text": "Portefeuille génial pour Monero, Bitcoin, Ethereum, Litecoin et Haven",
|
||||
"fixed_pair_not_supported": "Cette paire fixe n'est pas prise en charge par les services d'échange sélectionnés",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Confidentialité",
|
||||
"privacy_and_security": "Confidentialité et sécurité",
|
||||
"privacy_and_security_desc": "Configurez les paramètres d'authentification et de sécurité, et configurez Cake 2FA.",
|
||||
"privacy_desc": "Modifiez les paramètres de confidentialité et activez les fonctionnalités de confidentialité spéciales.",
|
||||
"privacy_features": "Fonctionnalités de confidentialité",
|
||||
"privacy_policy": "Politique de confidentialité",
|
||||
"privacy_settings": "Paramètres de confidentialité",
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
"connect_your_hardware_wallet_ios": "Embojoaju nde billetera hardware Bluetooth ndive",
|
||||
"connection_sync": "Joaju ha ñembojuehe",
|
||||
"connections": "Jeikeha",
|
||||
"connections_desc": "Emohenda joaju umi servicio ha API mbohapýha rehegua.",
|
||||
"connectWalletPrompt": "Embojoaju nde billetera WalletConnect ndive hag̃ua rejapo transacción",
|
||||
"contact": "Contacto",
|
||||
"contact_list_contacts": "Ñe'ẽngára",
|
||||
@@ -371,6 +372,7 @@
|
||||
"field_required": "Ko kora tekotevẽva",
|
||||
"fill_code": "Ikatúpiko emyenyhẽ pe ayvu ñemi jehechaukaha oñemondóva nde korreópe.",
|
||||
"filter_by": "Mboguaha rupi",
|
||||
"filters": "Filtro-kuéra rehegua",
|
||||
"finding_provider": "Ojejuhu hag̃ua proveedor",
|
||||
"first_wallet_text": "Viru ñongatuha iporãiterei Monero, Bitcoin, Ethereum, Litecoin ha Haven-pe guarã.",
|
||||
"fixed_pair_not_supported": "Ko mokõi par fijo ndojehepyme’ẽi umi swap rembiapo ojeiporavo va’ekuépe.",
|
||||
@@ -588,6 +590,7 @@
|
||||
"privacy": "Ñemigua",
|
||||
"privacy_and_security": "Privasida ha Tekorosã",
|
||||
"privacy_and_security_desc": "Emohenda ñemboheko hag̃ua jehechajey hag̃ua hag̃ua hag̃ua hag̃ua seguridad ha emboheko Cake 2FA.",
|
||||
"privacy_desc": "Emoambue ñemigua ñemboheko ha embohasa ñemigua mba’ekuaarã especial.",
|
||||
"privacy_features": "Tembiapoite ñemigua",
|
||||
"privacy_policy": "Purureko ñemi rehegua",
|
||||
"privacy_settings": "Ñemohenda ñemigua",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "An haɗa",
|
||||
"connection_sync": "Haɗi da aiki tare",
|
||||
"connections": "Haɗe-haɗe",
|
||||
"connections_desc": "Sarrafa haɗin kai zuwa ayyuka da APIs na ɓangare na uku.",
|
||||
"connectWalletPrompt": "Haɗa walat ɗinka da WalletConnect don yin ma'amaloli",
|
||||
"contact": "Tuntuɓa",
|
||||
"contact_list_contacts": "Lambobin sadarwa",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "An ajiye fayil",
|
||||
"fill_code": "Da fatan za a shigar da lambar tabbatarwa da aka aiko zuwa imel ɗin ku",
|
||||
"filter_by": "Tace ta",
|
||||
"filters": "Tace",
|
||||
"finding_provider": "Ana neman mai ba da sabis",
|
||||
"first_wallet_text": "Kyakkyawan walat don Monero, Bitcoin, Ethereum, Litecoin, da Haven",
|
||||
"fixed_pair_not_supported": "Ba a tallafa wa wannan tsayayyen nau'i ba tare da sabis ɗin musayar da aka zaɓa ba",
|
||||
@@ -757,6 +759,7 @@
|
||||
"privacy": "Sirri",
|
||||
"privacy_and_security": "Sirri & Tsaro",
|
||||
"privacy_and_security_desc": "Saita tabbatarwa da saitunan tsaro, sannan ka saita Cake 2FA.",
|
||||
"privacy_desc": "Canja saitunan keɓantawa kuma kunna fasalolin keɓantawa na musamman.",
|
||||
"privacy_features": "Siffofin keɓantawa",
|
||||
"privacy_policy": "Manufar Sirri",
|
||||
"privacy_settings": "Saitunan keɓantawa",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "कनेक्टेड",
|
||||
"connection_sync": "कनेक्शन और सिंक",
|
||||
"connections": "कनेक्शन",
|
||||
"connections_desc": "सेवाओं और तृतीय पक्ष एपीआई से कनेक्शन प्रबंधित करें।",
|
||||
"connectWalletPrompt": "लेन-देन करने के लिए अपने वॉलेट को WalletConnect से कनेक्ट करें",
|
||||
"contact": "संपर्क",
|
||||
"contact_list_contacts": "संपर्क",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "फ़ाइल सहेजी गई",
|
||||
"fill_code": "कृपया अपने ईमेल पर भेजा गया सत्यापन कोड दर्ज करें",
|
||||
"filter_by": "इसके अनुसार फ़िल्टर करें",
|
||||
"filters": "फिल्टर",
|
||||
"finding_provider": "प्रदाता खोजा जा रहा है",
|
||||
"first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin और Haven के लिए शानदार वॉलेट",
|
||||
"fixed_pair_not_supported": "यह निश्चित जोड़ी चयनित स्वैप सेवाओं के साथ समर्थित नहीं है",
|
||||
@@ -725,8 +727,8 @@
|
||||
"payjoin_unavailable_sheet_title": "Payjoin उपलब्ध क्यों नहीं है?",
|
||||
"payment_id": "भुगतान आईडी: ",
|
||||
"payment_made_easy": "भुगतान करना आसान",
|
||||
"payment_was_received": "आपका भुगतान प्राप्त हो गया।",
|
||||
"Payment_was_received": "आपका भुगतान प्राप्त हो गया था।",
|
||||
"payment_was_received": "आपका भुगतान प्राप्त हो गया।",
|
||||
"payments": "भुगतान",
|
||||
"pending": " (लंबित)",
|
||||
"percentageOf": "${amount} का",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "गोपनीयता",
|
||||
"privacy_and_security": "निजता और सुरक्षा",
|
||||
"privacy_and_security_desc": "प्रमाणीकरण और सुरक्षा सेटिंग्स कॉन्फ़िगर करें और Cake 2FA सेट अप करें।",
|
||||
"privacy_desc": "गोपनीयता सेटिंग्स बदलें और विशेष गोपनीयता सुविधाओं को टॉगल करें।",
|
||||
"privacy_features": "गोपनीयता सुविधाएँ",
|
||||
"privacy_policy": "गोपनीयता नीति",
|
||||
"privacy_settings": "गोपनीयता सेटिंग्स",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Povezano",
|
||||
"connection_sync": "Povezivanje i sinkronizacija",
|
||||
"connections": "Veze",
|
||||
"connections_desc": "Upravljajte vezama s uslugama i API-jima trećih strana.",
|
||||
"connectWalletPrompt": "Povežite svoj novčanik s WalletConnectom za izvršavanje transakcija",
|
||||
"contact": "Kontakt",
|
||||
"contact_list_contacts": "Kontakti",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Datoteka je spremljena",
|
||||
"fill_code": "Molimo unesite verifikacijski kod koji ste primili na svoju e-poštu",
|
||||
"filter_by": "Filtriraj po",
|
||||
"filters": "Filteri",
|
||||
"finding_provider": "Traženje pružatelja",
|
||||
"first_wallet_text": "Odličan novčanik za Monero, Bitcoin, Ethereum, Litecoin i Haven",
|
||||
"fixed_pair_not_supported": "Ovaj fiksni par nije podržan s odabranim uslugama zamjene",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Privatnost",
|
||||
"privacy_and_security": "Privatnost i sigurnost",
|
||||
"privacy_and_security_desc": "Konfigurirajte postavke provjere autentičnosti i sigurnosti te postavite Cake 2FA.",
|
||||
"privacy_desc": "Promijenite postavke privatnosti i uključite/isključite posebne značajke privatnosti.",
|
||||
"privacy_features": "Značajke privatnosti",
|
||||
"privacy_policy": "Pravila privatnosti",
|
||||
"privacy_settings": "Postavke privatnosti",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Միացված",
|
||||
"connection_sync": "Կապ և համաժամեցում",
|
||||
"connections": "Միացումներ",
|
||||
"connections_desc": "Կառավարեք կապերը ծառայությունների և երրորդ կողմի API-ների հետ:",
|
||||
"connectWalletPrompt": "Միացրեք ձեր դրամապանակը WalletConnect-ի միջոցով՝ գործարքներ կատարելու համար",
|
||||
"contact": "Կոնտակտ",
|
||||
"contact_list_contacts": "Կոնտակտներ",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Ֆայլը պահպանվել է",
|
||||
"fill_code": "Խնդրում ենք մուտքագրել ձեր էլեկտրոնային փոստին ուղարկված հաստատման կոդը",
|
||||
"filter_by": "Զտել ըստ",
|
||||
"filters": "Զտիչներ",
|
||||
"finding_provider": "Մատակարարի որոնում",
|
||||
"first_wallet_text": "Հիանալի դրամապանակ Monero, Bitcoin, Ethereum, Litecoin և Haven-ի համար",
|
||||
"fixed_pair_not_supported": "Այս ֆիքսված զույգը չի աջակցվում ընտրված փոխանակման ծառայությունների կողմից",
|
||||
@@ -754,6 +756,7 @@
|
||||
"privacy": "Գաղտնիություն",
|
||||
"privacy_and_security": "Գաղտնիություն և անվտանգություն",
|
||||
"privacy_and_security_desc": "Կազմաձևեք նույնականացման և անվտանգության կարգավորումները և կարգավորեք Cake 2FA-ն։",
|
||||
"privacy_desc": "Փոխեք գաղտնիության կարգավորումները և միացրեք գաղտնիության հատուկ գործառույթները:",
|
||||
"privacy_features": "Գաղտնիության գործառույթներ",
|
||||
"privacy_policy": "Գաղտնիության քաղաքականություն",
|
||||
"privacy_settings": "Գաղտնիության կարգավորումներ",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Terhubung",
|
||||
"connection_sync": "Koneksi dan sinkronisasi",
|
||||
"connections": "Koneksi",
|
||||
"connections_desc": "Kelola koneksi ke layanan dan API pihak ketiga.",
|
||||
"connectWalletPrompt": "Hubungkan dompet Anda dengan WalletConnect untuk melakukan transaksi",
|
||||
"contact": "Kontak",
|
||||
"contact_list_contacts": "Kontak",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "File tersimpan",
|
||||
"fill_code": "Silakan isi kode verifikasi yang dikirim ke email Anda",
|
||||
"filter_by": "Filter berdasarkan",
|
||||
"filters": "Filter",
|
||||
"finding_provider": "Mencari penyedia",
|
||||
"first_wallet_text": "Dompet yang keren untuk Monero, Bitcoin, Ethereum, Litecoin, dan Haven",
|
||||
"fixed_pair_not_supported": "Pasangan tetap ini tidak didukung oleh layanan swap yang dipilih",
|
||||
@@ -757,6 +759,7 @@
|
||||
"privacy": "Privasi",
|
||||
"privacy_and_security": "Privasi & Keamanan",
|
||||
"privacy_and_security_desc": "Konfigurasikan pengaturan autentikasi dan keamanan serta siapkan Cake 2FA.",
|
||||
"privacy_desc": "Ubah pengaturan privasi dan aktifkan fitur privasi khusus.",
|
||||
"privacy_features": "Fitur privasi",
|
||||
"privacy_policy": "Kebijakan Privasi",
|
||||
"privacy_settings": "Pengaturan Privasi",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Connesso",
|
||||
"connection_sync": "Connessione e sincronizzazione",
|
||||
"connections": "Connessioni",
|
||||
"connections_desc": "Gestisci le connessioni a servizi e API di terze parti.",
|
||||
"connectWalletPrompt": "Collega il tuo wallet con WalletConnect per effettuare transazioni",
|
||||
"contact": "Contatto",
|
||||
"contact_list_contacts": "Contatti",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "File salvato",
|
||||
"fill_code": "Inserisci il codice di verifica inviato al tuo indirizzo email",
|
||||
"filter_by": "Filtra per",
|
||||
"filters": "Filtri",
|
||||
"finding_provider": "Ricerca del fornitore",
|
||||
"first_wallet_text": "Portafoglio fantastico per Monero, Bitcoin, Ethereum, Litecoin e Haven",
|
||||
"fixed_pair_not_supported": "Questa coppia fissa non è supportata dai servizi di swap selezionati",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Privacy",
|
||||
"privacy_and_security": "Privacy e sicurezza",
|
||||
"privacy_and_security_desc": "Configura le impostazioni di autenticazione e sicurezza e imposta Cake 2FA.",
|
||||
"privacy_desc": "Modifica le impostazioni sulla privacy e attiva le funzionalità speciali sulla privacy.",
|
||||
"privacy_features": "Funzionalità per la privacy",
|
||||
"privacy_policy": "Informativa sulla privacy",
|
||||
"privacy_settings": "Impostazioni sulla privacy",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "接続済み",
|
||||
"connection_sync": "接続と同期",
|
||||
"connections": "接続",
|
||||
"connections_desc": "サービスおよびサードパーティ API への接続を管理します。",
|
||||
"connectWalletPrompt": "WalletConnect でウォレットを接続して取引を行う",
|
||||
"contact": "連絡先",
|
||||
"contact_list_contacts": "連絡先",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "ファイルを保存しました",
|
||||
"fill_code": "メールに記載されている認証コードを入力してください",
|
||||
"filter_by": "絞り込み",
|
||||
"filters": "フィルター",
|
||||
"finding_provider": "プロバイダーを検索中",
|
||||
"first_wallet_text": "Monero、Bitcoin、Ethereum、Litecoin、Havenに対応した素晴らしいウォレット",
|
||||
"fixed_pair_not_supported": "この固定ペアは、選択したスワップサービスではサポートされていません",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "プライバシー",
|
||||
"privacy_and_security": "プライバシーとセキュリティ",
|
||||
"privacy_and_security_desc": "認証とセキュリティの設定を構成し、Cake 2FA をセットアップします。",
|
||||
"privacy_desc": "プライバシー設定を変更し、特別なプライバシー機能を切り替えます。",
|
||||
"privacy_features": "プライバシー機能",
|
||||
"privacy_policy": "プライバシーポリシー",
|
||||
"privacy_settings": "プライバシー設定",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "연결됨",
|
||||
"connection_sync": "연결 및 동기화",
|
||||
"connections": "연결",
|
||||
"connections_desc": "서비스 및 타사 API에 대한 연결을 관리합니다.",
|
||||
"connectWalletPrompt": "거래를 하려면 WalletConnect로 지갑을 연결하세요",
|
||||
"contact": "연락처",
|
||||
"contact_list_contacts": "연락처",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "파일이 저장되었습니다",
|
||||
"fill_code": "이메일로 받은 인증 코드를 입력하세요",
|
||||
"filter_by": "필터 기준:",
|
||||
"filters": "필터",
|
||||
"finding_provider": "제공자 찾는 중",
|
||||
"first_wallet_text": "모네로, 비트코인, 이더리움, 라이트코인, 헤이븐을 위한 멋진 지갑",
|
||||
"fixed_pair_not_supported": "이 고정 페어는 선택한 스왑 서비스에서 지원되지 않습니다",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "개인정보 보호",
|
||||
"privacy_and_security": "개인정보 보호 및 보안",
|
||||
"privacy_and_security_desc": "인증 및 보안 설정을 구성하고 Cake 2FA를 설정합니다.",
|
||||
"privacy_desc": "개인정보 보호 설정을 변경하고 특별 개인정보 보호 기능을 전환하세요.",
|
||||
"privacy_features": "개인정보 보호 기능",
|
||||
"privacy_policy": "개인정보처리방침",
|
||||
"privacy_settings": "개인정보 보호 설정",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "ချိတ်ဆက်ပြီး",
|
||||
"connection_sync": "ချိတ်ဆက်မှုနှင့် ထပ်တူညီစေခြင်း",
|
||||
"connections": "ချိတ်ဆက်မှုများ",
|
||||
"connections_desc": "ဝန်ဆောင်မှုများနှင့် ပြင်ပကုမ္ပဏီ API များသို့ ချိတ်ဆက်မှုများကို စီမံပါ။",
|
||||
"connectWalletPrompt": "ငွေလွှဲပြောင်းမှုများ ပြုလုပ်ရန် WalletConnect ဖြင့် သင့်ပိုက်ဆံအိတ်ကို ချိတ်ဆက်ပါ",
|
||||
"contact": "ဆက်သွယ်ရန်",
|
||||
"contact_list_contacts": "အဆက်အသွယ်များ",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "ဖိုင်ကို သိမ်းဆည်းပြီးပါပြီ",
|
||||
"fill_code": "သင့်အီးမေးလ်သို့ ပို့ထားသော အတည်ပြုကုဒ်ကို ဖြည့်ပါ။",
|
||||
"filter_by": "အလိုက် စစ်ထုတ်ရန်",
|
||||
"filters": "စစ်ထုတ်မှုများ",
|
||||
"finding_provider": "ပံ့ပိုးသူကို ရှာဖွေနေသည်",
|
||||
"first_wallet_text": "Monero၊ Bitcoin၊ Ethereum၊ Litecoin နှင့် Haven အတွက် အလွန်ကောင်းမွန်သော Wallet",
|
||||
"fixed_pair_not_supported": "ဤပုံသေစုံတွဲကို ရွေးချယ်ထားသော swap ဝန်ဆောင်မှုများဖြင့် မထောက်ပံ့ပါ",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "ကိုယ်ရေးလုံခြုံမှု",
|
||||
"privacy_and_security": "ကိုယ်ရေးကိုယ်တာနှင့် လုံခြုံရေး",
|
||||
"privacy_and_security_desc": "အထောက်အထားစိစစ်ခြင်းနှင့် လုံခြုံရေးဆက်တင်များကို ပြင်ဆင်သတ်မှတ်ပြီး Cake 2FA ကို စနစ်ထည့်သွင်းပါ။",
|
||||
"privacy_desc": "ကိုယ်ရေးကိုယ်တာဆက်တင်များကိုပြောင်းလဲပြီး အထူးကိုယ်ရေးကိုယ်တာအင်္ဂါရပ်များကို ပြောင်းပါ။",
|
||||
"privacy_features": "ကိုယ်ရေးလုံခြုံရေး အင်္ဂါရပ်များ",
|
||||
"privacy_policy": "ကိုယ်ရေးအချက်အလက်မူဝါဒ",
|
||||
"privacy_settings": "ကိုယ်ရေးကိုယ်တာ ဆက်တင်များ",
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
"connected": "Verbonden",
|
||||
"connection_sync": "Verbinding en synchronisatie",
|
||||
"connections": "Verbindingen",
|
||||
"connections_desc": "Beheer verbindingen met services en API's van derden.",
|
||||
"connectWalletPrompt": "Verbind je wallet met WalletConnect om transacties uit te voeren",
|
||||
"contact": "Contact",
|
||||
"contact_list_contacts": "Contacten",
|
||||
@@ -473,6 +474,7 @@
|
||||
"file_saved": "Bestand opgeslagen",
|
||||
"fill_code": "Vul de verificatiecode in die je in je e-mail hebt ontvangen",
|
||||
"filter_by": "Filteren op",
|
||||
"filters": "Filters",
|
||||
"finding_provider": "Aanbieder zoeken",
|
||||
"first_wallet_text": "Geweldige wallet voor Monero, Bitcoin, Ethereum, Litecoin en Haven",
|
||||
"fixed_pair_not_supported": "Dit vaste paar wordt niet ondersteund met de geselecteerde swap-services",
|
||||
@@ -752,6 +754,7 @@
|
||||
"privacy": "Privacy",
|
||||
"privacy_and_security": "Privacy en beveiliging",
|
||||
"privacy_and_security_desc": "Configureer de authenticatie- en beveiligingsinstellingen en stel Cake 2FA in.",
|
||||
"privacy_desc": "Wijzig privacy-instellingen en schakel speciale privacyfuncties in.",
|
||||
"privacy_features": "Privacyfuncties",
|
||||
"privacy_policy": "Privacybeleid",
|
||||
"privacy_settings": "Privacy-instellingen",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Połączono",
|
||||
"connection_sync": "Połączenie i synchronizacja",
|
||||
"connections": "Połączenia",
|
||||
"connections_desc": "Zarządzaj połączeniami z usługami i interfejsami API stron trzecich.",
|
||||
"connectWalletPrompt": "Połącz swój portfel z WalletConnect, aby wykonywać transakcje",
|
||||
"contact": "Kontakt",
|
||||
"contact_list_contacts": "Kontakty",
|
||||
@@ -474,6 +475,7 @@
|
||||
"file_saved": "Plik zapisany",
|
||||
"fill_code": "Proszę wprowadzić kod weryfikacyjny wysłany na Twój adres e‑mail",
|
||||
"filter_by": "Filtruj według",
|
||||
"filters": "Filtry",
|
||||
"finding_provider": "Wyszukiwanie dostawcy",
|
||||
"first_wallet_text": "Świetny portfel dla Monero, Bitcoin, Ethereum, Litecoin i Haven",
|
||||
"fixed_pair_not_supported": "Ta stała para nie jest obsługiwana przez wybrane usługi swap.",
|
||||
@@ -754,6 +756,7 @@
|
||||
"privacy": "Prywatność",
|
||||
"privacy_and_security": "Prywatność i bezpieczeństwo",
|
||||
"privacy_and_security_desc": "Skonfiguruj ustawienia uwierzytelniania i zabezpieczeń oraz skonfiguruj Cake 2FA.",
|
||||
"privacy_desc": "Zmień ustawienia prywatności i przełącz specjalne funkcje prywatności.",
|
||||
"privacy_features": "Funkcje prywatności",
|
||||
"privacy_policy": "Polityka prywatności",
|
||||
"privacy_settings": "Ustawienia prywatności",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Conectado",
|
||||
"connection_sync": "Conexão e sincronização",
|
||||
"connections": "Conexões",
|
||||
"connections_desc": "Gerencie conexões com serviços e APIs de terceiros.",
|
||||
"connectWalletPrompt": "Conecte sua carteira ao WalletConnect para realizar transações",
|
||||
"contact": "Contato",
|
||||
"contact_list_contacts": "Contatos",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Arquivo salvo",
|
||||
"fill_code": "Por favor, preencha o código de verificação enviado para o seu e-mail",
|
||||
"filter_by": "Filtrar por",
|
||||
"filters": "Filtros",
|
||||
"finding_provider": "Procurando provedor",
|
||||
"first_wallet_text": "Carteira incrível para Monero, Bitcoin, Ethereum, Litecoin e Haven",
|
||||
"fixed_pair_not_supported": "Este par fixo não é compatível com os serviços de swap selecionados",
|
||||
@@ -757,6 +759,7 @@
|
||||
"privacy": "Privacidade",
|
||||
"privacy_and_security": "Privacidade e Segurança",
|
||||
"privacy_and_security_desc": "Configure as definições de autenticação e segurança e configure o Cake 2FA.",
|
||||
"privacy_desc": "Altere as configurações de privacidade e ative recursos especiais de privacidade.",
|
||||
"privacy_features": "Recursos de privacidade",
|
||||
"privacy_policy": "Política de Privacidade",
|
||||
"privacy_settings": "Configurações de privacidade",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Подключено",
|
||||
"connection_sync": "Подключение и синхронизация",
|
||||
"connections": "Подключения",
|
||||
"connections_desc": "Управляйте подключениями к сервисам и сторонним API.",
|
||||
"connectWalletPrompt": "Подключите свой кошелек к WalletConnect, чтобы совершать транзакции",
|
||||
"contact": "Контакт",
|
||||
"contact_list_contacts": "Контакты",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Файл сохранён",
|
||||
"fill_code": "Пожалуйста, введите код подтверждения, отправленный на вашу электронную почту",
|
||||
"filter_by": "Фильтровать по",
|
||||
"filters": "Фильтры",
|
||||
"finding_provider": "Поиск провайдера",
|
||||
"first_wallet_text": "Отличный кошелёк для Monero, Bitcoin, Ethereum, Litecoin и Haven",
|
||||
"fixed_pair_not_supported": "Эта фиксированная пара не поддерживается выбранными сервисами обмена",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Конфиденциальность",
|
||||
"privacy_and_security": "Конфиденциальность и безопасность",
|
||||
"privacy_and_security_desc": "Настройте параметры аутентификации и безопасности, а также настройте Cake 2FA.",
|
||||
"privacy_desc": "Измените настройки конфиденциальности и включите специальные функции конфиденциальности.",
|
||||
"privacy_features": "Функции конфиденциальности",
|
||||
"privacy_policy": "Политика конфиденциальности",
|
||||
"privacy_settings": "Настройки конфиденциальности",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "เชื่อมต่อแล้ว",
|
||||
"connection_sync": "การเชื่อมต่อและซิงค์",
|
||||
"connections": "การเชื่อมต่อ",
|
||||
"connections_desc": "จัดการการเชื่อมต่อกับบริการและ API ของบุคคลที่สาม",
|
||||
"connectWalletPrompt": "เชื่อมต่อกระเป๋าเงินของคุณกับ WalletConnect เพื่อทำธุรกรรม",
|
||||
"contact": "ผู้ติดต่อ",
|
||||
"contact_list_contacts": "รายชื่อผู้ติดต่อ",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "บันทึกไฟล์แล้ว",
|
||||
"fill_code": "โปรดกรอกรหัสยืนยันที่ส่งไปยังอีเมลของคุณ",
|
||||
"filter_by": "กรองตาม",
|
||||
"filters": "ตัวกรอง",
|
||||
"finding_provider": "กำลังค้นหาผู้ให้บริการ",
|
||||
"first_wallet_text": "กระเป๋าเงินที่ยอดเยี่ยมสำหรับ Monero, Bitcoin, Ethereum, Litecoin และ Haven",
|
||||
"fixed_pair_not_supported": "คู่แบบคงที่นี้ไม่รองรับกับบริการสวอปที่เลือก",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "ความเป็นส่วนตัว",
|
||||
"privacy_and_security": "ความเป็นส่วนตัวและความปลอดภัย",
|
||||
"privacy_and_security_desc": "กำหนดค่าการยืนยันตัวตนและการตั้งค่าความปลอดภัย และตั้งค่า Cake 2FA",
|
||||
"privacy_desc": "เปลี่ยนการตั้งค่าความเป็นส่วนตัวและสลับคุณสมบัติความเป็นส่วนตัวพิเศษ",
|
||||
"privacy_features": "ฟีเจอร์ความเป็นส่วนตัว",
|
||||
"privacy_policy": "นโยบายความเป็นส่วนตัว",
|
||||
"privacy_settings": "การตั้งค่าความเป็นส่วนตัว",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Nakakonekta",
|
||||
"connection_sync": "Koneksyon at pag-sync",
|
||||
"connections": "Mga koneksyon",
|
||||
"connections_desc": "Pamahalaan ang mga koneksyon sa mga serbisyo at mga third party na API.",
|
||||
"connectWalletPrompt": "Ikonekta ang iyong wallet sa WalletConnect para makapag-transact",
|
||||
"contact": "Kontak",
|
||||
"contact_list_contacts": "Mga Contact",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Na-save ang file",
|
||||
"fill_code": "Mangyaring ilagay ang verification code na ipinadala sa iyong email",
|
||||
"filter_by": "I-filter ayon sa",
|
||||
"filters": "Mga filter",
|
||||
"finding_provider": "Naghahanap ng provider",
|
||||
"first_wallet_text": "Napakahusay na wallet para sa Monero, Bitcoin, Ethereum, Litecoin, at Haven",
|
||||
"fixed_pair_not_supported": "Hindi sinusuportahan ang nakapirming pares na ito sa mga napiling serbisyo ng swap",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Pagkapribado",
|
||||
"privacy_and_security": "Pagkapribado at Seguridad",
|
||||
"privacy_and_security_desc": "I-configure ang mga setting ng pagpapatotoo at seguridad at i-set up ang Cake 2FA.",
|
||||
"privacy_desc": "Baguhin ang mga setting ng privacy at i-toggle ang mga espesyal na feature sa privacy.",
|
||||
"privacy_features": "Mga tampok sa privacy",
|
||||
"privacy_policy": "Patakaran sa Privacy",
|
||||
"privacy_settings": "Mga setting sa privacy",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Bağlı",
|
||||
"connection_sync": "Bağlantı ve senkronizasyon",
|
||||
"connections": "Bağlantılar",
|
||||
"connections_desc": "Hizmetlere ve üçüncü taraf API'lere olan bağlantıları yönetin.",
|
||||
"connectWalletPrompt": "İşlem yapmak için cüzdanınızı WalletConnect ile bağlayın",
|
||||
"contact": "Kişi",
|
||||
"contact_list_contacts": "Kişiler",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Dosya kaydedildi",
|
||||
"fill_code": "Lütfen e-postanıza gönderilen doğrulama kodunu girin",
|
||||
"filter_by": "Filtrele:",
|
||||
"filters": "Filtreler",
|
||||
"finding_provider": "Sağlayıcı aranıyor",
|
||||
"first_wallet_text": "Monero, Bitcoin, Ethereum, Litecoin ve Haven için harika bir cüzdan",
|
||||
"fixed_pair_not_supported": "Bu sabit parite, seçilen takas hizmetleriyle desteklenmiyor",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Gizlilik",
|
||||
"privacy_and_security": "Gizlilik ve Güvenlik",
|
||||
"privacy_and_security_desc": "Kimlik doğrulama ve güvenlik ayarlarını yapılandırın ve Cake 2FA'yı ayarlayın.",
|
||||
"privacy_desc": "Gizlilik ayarlarını değiştirin ve özel gizlilik özelliklerini değiştirin.",
|
||||
"privacy_features": "Gizlilik özellikleri",
|
||||
"privacy_policy": "Gizlilik Politikası",
|
||||
"privacy_settings": "Gizlilik ayarları",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Підключено",
|
||||
"connection_sync": "Підключення та синхронізація",
|
||||
"connections": "Підключення",
|
||||
"connections_desc": "Керуйте підключеннями до служб і сторонніх API.",
|
||||
"connectWalletPrompt": "Підключіть свій гаманець через WalletConnect, щоб здійснювати транзакції",
|
||||
"contact": "Контакт",
|
||||
"contact_list_contacts": "Контакти",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "Файл збережено",
|
||||
"fill_code": "Будь ласка, введіть код підтвердження, надісланий на вашу електронну адресу",
|
||||
"filter_by": "Фільтрувати за",
|
||||
"filters": "Фільтри",
|
||||
"finding_provider": "Пошук провайдера",
|
||||
"first_wallet_text": "Чудовий гаманець для Monero, Bitcoin, Ethereum, Litecoin та Haven",
|
||||
"fixed_pair_not_supported": "Ця фіксована пара не підтримується вибраними сервісами обміну",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "Конфіденційність",
|
||||
"privacy_and_security": "Конфіденційність і безпека",
|
||||
"privacy_and_security_desc": "Налаштуйте параметри автентифікації та безпеки й налаштуйте Cake 2FA.",
|
||||
"privacy_desc": "Змініть налаштування конфіденційності та ввімкніть спеціальні функції конфіденційності.",
|
||||
"privacy_features": "Функції приватності",
|
||||
"privacy_policy": "Політика конфіденційності",
|
||||
"privacy_settings": "Налаштування конфіденційності",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "منسلک",
|
||||
"connection_sync": "کنکشن اور ہم آہنگی",
|
||||
"connections": "کنکشنز",
|
||||
"connections_desc": "سروسز اور تھرڈ پارٹی APIs کے کنکشنز کا نظم کریں۔",
|
||||
"connectWalletPrompt": "لین دین کرنے کے لیے WalletConnect کے ذریعے اپنا والیٹ کنیکٹ کریں",
|
||||
"contact": "رابطہ",
|
||||
"contact_list_contacts": "رابطے",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "فائل محفوظ ہو گئی",
|
||||
"fill_code": "براہ کرم اپنے ای میل پر موصول ہونے والا تصدیقی کوڈ درج کریں۔",
|
||||
"filter_by": "کے مطابق فلٹر کریں",
|
||||
"filters": "فلٹرز",
|
||||
"finding_provider": "فراہم کنندہ تلاش کیا جا رہا ہے",
|
||||
"first_wallet_text": "Monero، Bitcoin، Ethereum، Litecoin اور Haven کے لیے بہترین والیٹ",
|
||||
"fixed_pair_not_supported": "منتخب کردہ سواپ سروسز کے ساتھ یہ فکسڈ جوڑی سپورٹ نہیں کی جاتی",
|
||||
@@ -757,6 +759,7 @@
|
||||
"privacy": "رازداری",
|
||||
"privacy_and_security": "رازداری اور سیکیورٹی",
|
||||
"privacy_and_security_desc": "تصدیق اور سیکیورٹی کی ترتیبات کو کنفیگر کریں اور Cake 2FA سیٹ اپ کریں۔",
|
||||
"privacy_desc": "رازداری کی ترتیبات کو تبدیل کریں اور خصوصی رازداری کی خصوصیات کو ٹوگل کریں۔",
|
||||
"privacy_features": "رازداری کی خصوصیات",
|
||||
"privacy_policy": "رازداری کی پالیسی",
|
||||
"privacy_settings": "پرائیویسی کی ترتیبات",
|
||||
|
||||
@@ -241,6 +241,7 @@
|
||||
"connected": "Đã kết nối",
|
||||
"connection_sync": "Kết nối và đồng bộ",
|
||||
"connections": "Kết nối",
|
||||
"connections_desc": "Quản lý kết nối với các dịch vụ và API của bên thứ ba.",
|
||||
"connectWalletPrompt": "Kết nối ví của bạn với WalletConnect để thực hiện các giao dịch",
|
||||
"contact": "Liên hệ",
|
||||
"contact_list_contacts": "Liên hệ",
|
||||
@@ -474,6 +475,7 @@
|
||||
"file_saved": "Đã lưu tệp",
|
||||
"fill_code": "Vui lòng nhập mã xác minh được gửi đến email của bạn",
|
||||
"filter_by": "Lọc theo",
|
||||
"filters": "Bộ lọc",
|
||||
"finding_provider": "Đang tìm nhà cung cấp",
|
||||
"first_wallet_text": "Ví tuyệt vời cho Monero, Bitcoin, Ethereum, Litecoin và Haven",
|
||||
"fixed_pair_not_supported": "Cặp tỷ giá cố định này không được hỗ trợ với các dịch vụ hoán đổi đã chọn",
|
||||
@@ -753,6 +755,7 @@
|
||||
"privacy": "Quyền riêng tư",
|
||||
"privacy_and_security": "Quyền riêng tư & Bảo mật",
|
||||
"privacy_and_security_desc": "Định cấu hình cài đặt xác thực và bảo mật, đồng thời thiết lập Cake 2FA.",
|
||||
"privacy_desc": "Thay đổi cài đặt quyền riêng tư và chuyển đổi các tính năng bảo mật đặc biệt.",
|
||||
"privacy_features": "Tính năng quyền riêng tư",
|
||||
"privacy_policy": "Chính sách bảo mật",
|
||||
"privacy_settings": "Cài đặt quyền riêng tư",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "Ti sopọ",
|
||||
"connection_sync": "Ìsopọ̀ àti ìbámu",
|
||||
"connections": "Awọn asopọ",
|
||||
"connections_desc": "Ṣakoso awọn asopọ si awọn iṣẹ ati awọn API ẹnikẹta.",
|
||||
"connectWalletPrompt": "So apamọwọ rẹ pọ̀ mọ́ WalletConnect láti ṣe àwọn ìdúnàdúrà",
|
||||
"contact": "Olùbáṣepọ̀",
|
||||
"contact_list_contacts": "Àwọn olùbásọ̀rọ̀",
|
||||
@@ -476,6 +477,7 @@
|
||||
"file_saved": "Faili ti fipamọ",
|
||||
"fill_code": "Jọ̀wọ́ tẹ kóòdù ìmúdájú tí a rán sí ímeèlì rẹ.",
|
||||
"filter_by": "Ṣàlẹ̀mọ́ nípa",
|
||||
"filters": "Ajọ",
|
||||
"finding_provider": "N wa olupese",
|
||||
"first_wallet_text": "Àpamọ́wọ́ tó dára gan-an fún Monero, Bitcoin, Ethereum, Litecoin, àti Haven",
|
||||
"fixed_pair_not_supported": "Akọsopọ paṣipaarọ ti o wa titi yii ko ni atilẹyin pẹlu awọn iṣẹ swap ti o yan",
|
||||
@@ -756,6 +758,7 @@
|
||||
"privacy": "Àṣírí",
|
||||
"privacy_and_security": "Ìpamọ́ & Ààbò",
|
||||
"privacy_and_security_desc": "Ṣètò ìfàṣẹsí àti àwọn àtúnṣe aabo, kí o sì ṣètò Cake 2FA.",
|
||||
"privacy_desc": "Yi eto ipamọ pada ki o yi awọn ẹya aṣiri pataki pada.",
|
||||
"privacy_features": "Awọn ẹya ìpamọ́",
|
||||
"privacy_policy": "Ilana Aṣírí",
|
||||
"privacy_settings": "Àwọn ààtò ìpamọ́",
|
||||
|
||||
@@ -242,6 +242,7 @@
|
||||
"connected": "已连接",
|
||||
"connection_sync": "连接与同步",
|
||||
"connections": "连接",
|
||||
"connections_desc": "管理与服务和第三方 API 的连接。",
|
||||
"connectWalletPrompt": "通过 WalletConnect 连接您的钱包以进行交易",
|
||||
"contact": "联系人",
|
||||
"contact_list_contacts": "联系人",
|
||||
@@ -475,6 +476,7 @@
|
||||
"file_saved": "文件已保存",
|
||||
"fill_code": "请填写发送至您邮箱的验证码",
|
||||
"filter_by": "筛选条件",
|
||||
"filters": "过滤器",
|
||||
"finding_provider": "正在查找服务提供商",
|
||||
"first_wallet_text": "适用于门罗币、比特币、以太坊、莱特币和 Haven 的超棒钱包",
|
||||
"fixed_pair_not_supported": "所选的兑换服务不支持该固定交易对",
|
||||
@@ -755,6 +757,7 @@
|
||||
"privacy": "隐私",
|
||||
"privacy_and_security": "隐私与安全",
|
||||
"privacy_and_security_desc": "配置身份验证与安全设置,并设置 Cake 2FA。",
|
||||
"privacy_desc": "更改隐私设置并切换特殊隐私功能。",
|
||||
"privacy_features": "隐私功能",
|
||||
"privacy_policy": "隐私政策",
|
||||
"privacy_settings": "隐私设置",
|
||||
|
||||