refactor desktop settings sidebar

This commit is contained in:
Godwin Asuquo 2023-01-28 12:43:44 +02:00
parent 20ae8d530f
commit 75f33a433e
24 changed files with 423 additions and 194 deletions

View file

@ -522,6 +522,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
return CupertinoPageRoute<void>(
builder: (_) => DesktopSettingsPage());
case Routes.empty_no_route:
return MaterialPageRoute<void>(
builder: (_) => SizedBox.shrink());
default:
return MaterialPageRoute<void>(
builder: (_) => Scaffold(

View file

@ -37,6 +37,7 @@ class Routes {
static const restoreWalletFromSeedDetails = '/restore_from_seed_details';
static const exchange = '/exchange';
static const desktop_settings_page = '/desktop_settings_page';
static const empty_no_route = '/empty_no_route';
static const unlock = '/auth_not_closable';
static const rescan = '/rescan';
static const faq = '/faq';

View file

@ -21,9 +21,11 @@ class _SideMenuItemState extends State<SideMenuItem> {
late int currentPage = SideMenuGlobal.controller.currentPage;
void _handleChange(int page) {
setState(() {
currentPage = page;
});
if (mounted) {
setState(() {
currentPage = page;
});
}
}
@override

View file

@ -1,74 +1,57 @@
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/dashboard/wallet_menu_item.dart';
import 'package:cake_wallet/src/widgets/setting_actions.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
// FIXME: terrible design
class WalletMenu {
WalletMenu(this.context, this.reconnect, this.hasRescan) : items = [] {
items.addAll([
WalletMenuItem(
title: S.current.connection_sync,
image: Image.asset('assets/images/nodes_menu.png',
height: 16, width: 16),
handler: () => Navigator.of(context).pushNamed(Routes.connectionSync),
),
WalletMenuItem(
title: S.current.wallets,
image: Image.asset('assets/images/wallet_menu.png',
height: 16, width: 16),
handler: () => Navigator.of(context).pushNamed(Routes.walletList),
),
WalletMenuItem(
title: S.current.address_book_menu,
image: Image.asset('assets/images/open_book_menu.png',
height: 16, width: 16),
handler: () => Navigator.of(context).pushNamed(Routes.addressBook),
),
WalletMenuItem(
title: S.current.security_and_backup,
image:
Image.asset('assets/images/key_menu.png', height: 16, width: 16),
handler: () {
Navigator.of(context).pushNamed(Routes.securityBackupPage);
}),
WalletMenuItem(
title: S.current.privacy_settings,
image:
Image.asset('assets/images/privacy_menu.png', height: 16, width: 16),
handler: () {
Navigator.of(context).pushNamed(Routes.privacyPage);
}),
WalletMenuItem(
title: S.current.display_settings,
image: Image.asset('assets/images/eye_menu.png',
height: 16, width: 16),
handler: () => Navigator.of(context).pushNamed(Routes.displaySettingsPage),
),
WalletMenuItem(
title: S.current.other_settings,
image: Image.asset('assets/images/settings_menu.png',
height: 16, width: 16),
handler: () => Navigator.of(context).pushNamed(Routes.otherSettingsPage),
),
WalletMenuItem(
title: S.current.settings_support,
image: Image.asset('assets/images/question_mark.png',
height: 16, width: 16, color: Palette.darkBlue),
handler: () => Navigator.of(context).pushNamed(Routes.support),
),
]);
}
WalletMenu._();
final List<WalletMenuItem> items;
final BuildContext context;
final Future<void> Function() reconnect;
final bool hasRescan;
static List<WalletMenuItem> items = [
WalletMenuItem(
title: SettingActions.connectionSettingAction.name,
image: SettingActions.connectionSettingAction.image,
handler: (BuildContext context) => SettingActions.connectionSettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.walletSettingAction.name,
image: SettingActions.walletSettingAction.image,
handler: (BuildContext context) => SettingActions.walletSettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.addressBookSettingAction.name,
image: SettingActions.addressBookSettingAction.image,
handler: (BuildContext context) => SettingActions.addressBookSettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.securityBackupSettingAction.name,
image: SettingActions.securityBackupSettingAction.image,
handler: (BuildContext context) => SettingActions.securityBackupSettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.privacySettingAction.name,
image: SettingActions.privacySettingAction.image,
handler: (BuildContext context) => SettingActions.privacySettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.displaySettingAction.name,
image: SettingActions.displaySettingAction.image,
handler: (BuildContext context) => SettingActions.displaySettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.otherSettingAction.name,
image: SettingActions.otherSettingAction.image,
handler: (BuildContext context) => SettingActions.otherSettingAction.onTap(context),
),
WalletMenuItem(
title: SettingActions.supportSettingAction.name,
image: SettingActions.supportSettingAction.image,
handler: (BuildContext context) => SettingActions.supportSettingAction.onTap(context),
),
];
void action(int index) {
static void action(int index, BuildContext context) {
final item = items[index];
item.handler();
item.handler(context);
}
}

View file

@ -4,9 +4,10 @@ class WalletMenuItem {
WalletMenuItem({
required this.title,
required this.image,
required this.handler});
required this.handler,
});
final String title;
final Image image;
final void Function() handler;
final String image;
final void Function(BuildContext) handler;
}

View file

@ -1,10 +1,9 @@
import 'dart:ui';
import 'package:cake_wallet/src/widgets/setting_action_button.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
// FIXME: terrible design.
@ -20,17 +19,17 @@ class MenuWidget extends StatefulWidget {
class MenuWidgetState extends State<MenuWidget> {
MenuWidgetState()
: this.menuWidth = 0,
this.screenWidth = 0,
this.screenHeight = 0,
this.headerHeight = 120,
this.tileHeight = 60,
this.fromTopEdge = 50,
this.fromBottomEdge = 25,
this.moneroIcon = Image.asset('assets/images/monero_menu.png'),
this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'),
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
this.havenIcon = Image.asset('assets/images/haven_menu.png');
: this.menuWidth = 0,
this.screenWidth = 0,
this.screenHeight = 0,
this.headerHeight = 10,
this.tileHeight = 60,
this.fromTopEdge = 50,
this.fromBottomEdge = 25,
this.moneroIcon = Image.asset('assets/images/monero_menu.png'),
this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'),
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
this.havenIcon = Image.asset('assets/images/haven_menu.png');
final largeScreen = 731;
@ -82,16 +81,12 @@ class MenuWidgetState extends State<MenuWidget> {
@override
Widget build(BuildContext context) {
final walletMenu = WalletMenu(
context,
() async => widget.dashboardViewModel.reconnect(),
widget.dashboardViewModel.hasRescan);
final itemCount = walletMenu.items.length;
final itemCount = WalletMenu.items.length;
moneroIcon = Image.asset('assets/images/monero_menu.png',
color: Theme.of(context).accentTextTheme!.overline!.decorationColor!);
color: Theme.of(context).accentTextTheme.overline!.decorationColor!);
bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png',
color: Theme.of(context).accentTextTheme!.overline!.decorationColor!);
color: Theme.of(context).accentTextTheme.overline!.decorationColor!);
litecoinIcon = Image.asset('assets/images/litecoin_menu.png');
havenIcon = Image.asset('assets/images/haven_menu.png');
@ -105,17 +100,15 @@ class MenuWidgetState extends State<MenuWidget> {
height: 60,
width: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2)),
color: PaletteDark.gray),
borderRadius: BorderRadius.all(Radius.circular(2)), color: PaletteDark.gray),
)),
SizedBox(width: 12),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
bottomLeft: Radius.circular(24)),
topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
child: Container(
color: Theme.of(context).textTheme!.bodyText1!.decorationColor!,
color: Theme.of(context).textTheme.bodyText1!.decorationColor!,
child: ListView.separated(
padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) {
@ -123,25 +116,13 @@ class MenuWidgetState extends State<MenuWidget> {
return Container(
height: headerHeight,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context)
.accentTextTheme!
.headline4!
.color!,
Theme.of(context)
.accentTextTheme!
.headline4!
.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
gradient: LinearGradient(colors: [
Theme.of(context).accentTextTheme.headline4!.color!,
Theme.of(context).accentTextTheme.headline4!.decorationColor!,
], begin: Alignment.topLeft, end: Alignment.bottomRight),
),
padding: EdgeInsets.only(
left: 24,
top: fromTopEdge,
right: 24,
bottom: fromBottomEdge),
left: 24, top: fromTopEdge, right: 24, bottom: fromBottomEdge),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
@ -150,13 +131,10 @@ class MenuWidgetState extends State<MenuWidget> {
SingleChildScrollView(
child: Container(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
widget.dashboardViewModel.subname !=
null
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: widget.dashboardViewModel.subname.isNotEmpty
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.center,
children: <Widget>[
Text(
widget.dashboardViewModel.name,
@ -165,19 +143,16 @@ class MenuWidgetState extends State<MenuWidget> {
fontSize: 16,
fontWeight: FontWeight.bold),
),
if (widget.dashboardViewModel.subname !=
null)
if (widget.dashboardViewModel.subname.isNotEmpty)
Observer(
builder: (_) => Text(
widget.dashboardViewModel
.subname,
widget.dashboardViewModel.subname,
style: TextStyle(
color: Theme.of(context)
.accentTextTheme!
.accentTextTheme
.overline!
.decorationColor!,
fontWeight:
FontWeight.w500,
fontWeight: FontWeight.w500,
fontSize: 12),
))
],
@ -190,58 +165,26 @@ class MenuWidgetState extends State<MenuWidget> {
index--;
final item = walletMenu.items[index];
final item = WalletMenu.items[index];
final title = item.title;
final image = item.image ?? Offstage();
final image = item.image;
final isLastTile = index == itemCount - 1;
return GestureDetector(
onTap: () {
Navigator.of(context).pop();
walletMenu.action(index);
},
child: Container(
color: Theme.of(context)
.textTheme!
.bodyText1!
.decorationColor!,
height: isLastTile ? headerHeight : tileHeight,
padding: isLastTile
? EdgeInsets.only(
left: 24,
right: 24,
top: fromBottomEdge,
//bottom: fromTopEdge
)
: EdgeInsets.only(left: 24, right: 24),
alignment: isLastTile ? Alignment.topLeft : null,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
image,
SizedBox(width: 16),
Expanded(
child: Text(
title,
style: TextStyle(
color: Theme.of(context)
.textTheme!
.headline3!
.color!,
fontSize: 16,
fontWeight: FontWeight.bold),
))
],
),
));
return SettingActionButton(
isLastTile: isLastTile,
headerHeight: headerHeight,
tileHeight: tileHeight,
selectionActive: false,
fromBottomEdge: fromBottomEdge,
fromTopEdge: fromTopEdge,
onTap: () => WalletMenu.action(index, context),
image: image,
title: title,
);
},
separatorBuilder: (_, index) => Container(
height: 1,
color: Theme.of(context)
.primaryTextTheme!
.caption!
.decorationColor!,
color: Theme.of(context).primaryTextTheme.caption!.decorationColor!,
),
itemCount: itemCount + 1),
)))

View file

@ -1,14 +1,113 @@
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu_controller.dart';
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
import 'package:cake_wallet/src/widgets/setting_action_button.dart';
import 'package:cake_wallet/typography.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/router.dart' as Router;
class DesktopSettingsPage extends StatelessWidget {
final _settingsNavigatorKey = GlobalKey<NavigatorState>();
class DesktopSettingsPage extends StatefulWidget {
const DesktopSettingsPage({super.key});
@override
State<DesktopSettingsPage> createState() => _DesktopSettingsPageState();
}
class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
int itemCount = 0;
SideMenuController sideMenu = SideMenuController();
int currentPage = 0;
bool isTapped = false;
initState() {
super.initState();
itemCount = WalletMenu.items.length;
sideMenu.addListener((index) {
setState(() {
isTapped = true;
currentPage = index;
});
});
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Center(
child: Text('Desktop settings page'),
return Scaffold(
body: Container(
child: Row(
children: [
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Settings',
style: textXLarge(),
),
SizedBox(height: 64),
Flexible(
child: ListView.separated(
padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) {
final item = WalletMenu.items[index];
final title = item.title;
final image = item.image;
final isLastTile = index == itemCount;
return SettingActionButton(
isLastTile: isLastTile,
selectionActive: isTapped,
isSelected: currentPage == index,
isArrowVisible: true,
onTap: () {
final settingContext =
_settingsNavigatorKey.currentState?.context ?? context;
sideMenu.changePage(index);
WalletMenu.action(index, settingContext);
},
image: image,
title: title,
);
},
separatorBuilder: (_, index) => Container(
height: 1,
color: Theme.of(context).primaryTextTheme.caption!.decorationColor!,
),
itemCount: itemCount,
),
),
],
),
),
),
Expanded(
flex: 2,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 100),
Flexible(
child: Navigator(
key: _settingsNavigatorKey,
initialRoute: Routes.empty_no_route,
onGenerateRoute: (settings) => Router.createRoute(settings),
onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) {
return [
navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
];
},
),
),
],
),
)
],
),
),
);
}

View file

@ -0,0 +1,83 @@
import 'package:cake_wallet/palette.dart';
import 'package:flutter/material.dart';
class SettingActionButton extends StatelessWidget {
final bool isLastTile;
final bool isSelected;
final bool isArrowVisible;
final bool selectionActive;
final VoidCallback onTap;
final String image;
final String title;
final double fromBottomEdge;
final double fromTopEdge;
final double headerHeight;
final double tileHeight;
const SettingActionButton({
super.key,
this.isLastTile = false,
this.isSelected = false,
this.selectionActive = true,
this.isArrowVisible = false,
required this.onTap,
required this.image,
required this.title,
this.headerHeight = 120,
this.tileHeight = 60,
this.fromTopEdge = 50,
this.fromBottomEdge = 25,
});
@override
Widget build(BuildContext context) {
Color? color = isSelected
? Theme.of(context).textTheme.headline3!.color
: selectionActive
? Palette.darkBlue
: Theme.of(context).textTheme.headline3!.color;
return GestureDetector(
onTap: onTap,
child: Container(
height: isLastTile ? headerHeight : tileHeight,
padding: isLastTile
? EdgeInsets.only(
left: 24,
right: 24,
top: fromBottomEdge,
//bottom: fromTopEdge
)
: EdgeInsets.only(left: 24, right: 24),
alignment: isLastTile ? Alignment.topLeft : null,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.asset(
image,
height: 16,
width: 16,
color: Palette.darkBlue,
),
SizedBox(width: 16),
Expanded(
child: Text(
title,
style: TextStyle(
color: color,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
if (isArrowVisible)
Icon(
Icons.arrow_forward_ios,
color: color,
size: 16,
)
],
),
),
);
}
}

View file

@ -0,0 +1,98 @@
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:flutter/material.dart';
class SettingActions {
final String name;
final String image;
final void Function(BuildContext) onTap;
SettingActions._({
required this.name,
required this.image,
required this.onTap,
});
static List<SettingActions> all = [
connectionSettingAction,
walletSettingAction,
addressBookSettingAction,
securityBackupSettingAction,
privacySettingAction,
displaySettingAction,
otherSettingAction,
supportSettingAction,
];
static SettingActions connectionSettingAction = SettingActions._(
name: S.current.connection_sync,
image: 'assets/images/nodes_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.connectionSync);
},
);
static SettingActions walletSettingAction = SettingActions._(
name: S.current.wallets,
image: 'assets/images/wallet_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.walletList);
},
);
static SettingActions addressBookSettingAction = SettingActions._(
name: S.current.address_book_menu,
image: 'assets/images/open_book_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.addressBook);
},
);
static SettingActions securityBackupSettingAction = SettingActions._(
name: S.current.security_and_backup,
image: 'assets/images/key_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.securityBackupPage);
},
);
static SettingActions privacySettingAction = SettingActions._(
name: S.current.privacy,
image: 'assets/images/privacy_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.privacyPage);
},
);
static SettingActions displaySettingAction = SettingActions._(
name: S.current.display_settings,
image: 'assets/images/eye_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.displaySettingsPage);
},
);
static SettingActions otherSettingAction = SettingActions._(
name: S.current.other_settings,
image: 'assets/images/settings_menu.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.otherSettingsPage);
},
);
static SettingActions supportSettingAction = SettingActions._(
name: S.current.settings_support,
image: 'assets/images/question_mark.png',
onTap: (BuildContext context) {
Navigator.pop(context);
Navigator.of(context).pushNamed(Routes.support);
},
);
}

View file

@ -673,5 +673,6 @@
"disabled": "Deaktiviert",
"enabled": "Ermöglicht",
"tor_only": "Nur Tor",
"unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein"
"unmatched_currencies": "Die Währung Ihres aktuellen Wallets stimmt nicht mit der des gescannten QR überein",
"settings": "Einstellungen"
}

View file

@ -673,5 +673,6 @@
"disabled": "Disabled",
"enabled": "Enabled",
"tor_only": "Tor only",
"unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR"
"unmatched_currencies": "Your current wallet's currency does not match that of the scanned QR",
"settings": "Settings"
}

View file

@ -673,5 +673,6 @@
"disabled": "Desactivado",
"enabled": "Activado",
"tor_only": "solo Tor",
"unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado"
"unmatched_currencies": "La moneda de su billetera actual no coincide con la del QR escaneado",
"settings": "Configuraciones"
}

View file

@ -671,5 +671,6 @@
"disabled": "Handicapé",
"enabled": "Activé",
"tor_only": "Tor uniquement",
"unmatched_currencies": "La devise de votre portefeuille actuel ne correspond pas à celle du QR scanné"
"unmatched_currencies": "La devise de votre portefeuille actuel ne correspond pas à celle du QR scanné",
"settings": "Paramètres"
}

View file

@ -672,5 +672,6 @@
"disabled": "अक्षम",
"enabled": "सक्रिय",
"tor_only": "Tor केवल",
"unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती"
"unmatched_currencies": "आपके वर्तमान वॉलेट की मुद्रा स्कैन किए गए क्यूआर से मेल नहीं खाती",
"settings": "सेटिंग्स"
}

View file

@ -673,5 +673,6 @@
"disabled": "Onemogućeno",
"enabled": "Omogućeno",
"tor_only": "Samo Tor",
"unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u"
"unmatched_currencies": "Valuta vašeg trenutnog novčanika ne odgovara onoj na skeniranom QR-u",
"settings": "Postavke"
}

View file

@ -673,5 +673,6 @@
"disabled": "Disabilitato",
"enabled": "Abilitato",
"tor_only": "Solo Tor",
"unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato"
"unmatched_currencies": "La valuta del tuo portafoglio attuale non corrisponde a quella del QR scansionato",
"settings": "Impostazioni"
}

View file

@ -673,5 +673,6 @@
"disabled": "無効",
"enabled": "有効",
"tor_only": "Torのみ",
"unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません"
"unmatched_currencies": "現在のウォレットの通貨がスキャンされたQRの通貨と一致しません",
"settings": "設定"
}

View file

@ -673,5 +673,6 @@
"disabled": "장애가 있는",
"enabled": "사용",
"tor_only": "Tor 뿐",
"unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다."
"unmatched_currencies": "현재 지갑의 통화가 스캔한 QR의 통화와 일치하지 않습니다.",
"settings": "설정"
}

View file

@ -673,5 +673,6 @@
"disabled": "Gehandicapt",
"enabled": "Ingeschakeld",
"tor_only": "Alleen Tor",
"unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR"
"unmatched_currencies": "De valuta van uw huidige portemonnee komt niet overeen met die van de gescande QR",
"settings": "Instellingen"
}

View file

@ -673,5 +673,6 @@
"disabled": "Wyłączone",
"enabled": "Włączony",
"tor_only": "Tylko Tor",
"unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR"
"unmatched_currencies": "Waluta Twojego obecnego portfela nie odpowiada walucie zeskanowanego kodu QR",
"settings": "Ustawienia"
}

View file

@ -672,5 +672,6 @@
"disabled": "Desabilitado",
"enabled": "Habilitado",
"tor_only": "Tor apenas",
"unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado"
"unmatched_currencies": "A moeda da sua carteira atual não corresponde à do QR digitalizado",
"settings": "Configurações"
}

View file

@ -673,5 +673,6 @@
"disabled": "Отключено",
"enabled": "Включено",
"tor_only": "Только Tor",
"unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода."
"unmatched_currencies": "Валюта вашего текущего кошелька не соответствует валюте отсканированного QR-кода.",
"settings": "Настройки"
}

View file

@ -672,5 +672,6 @@
"disabled": "Вимкнено",
"enabled": "Увімкнено",
"tor_only": "Тільки Tor",
"unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду"
"unmatched_currencies": "Валюта вашого гаманця не збігається з валютою сканованого QR-коду",
"settings": "Налаштування"
}

View file

@ -671,5 +671,6 @@
"disabled": "禁用",
"enabled": "启用",
"tor_only": "仅限 Tor",
"unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配"
"unmatched_currencies": "您当前钱包的货币与扫描的 QR 的货币不匹配",
"settings": "设置"
}