CWA-202 | applied new design to nodes_list_page and new_node_page; created node_list_row widget, alert_with_one_action and alert_with_two_action; deleted reconnect_alert_dialog, wallet_creation_dialog, restore_alert_dialog and pin_alert_dialog

Oleksandr Sobol committed May 4, 2020 at 23:12 UTC 8f54e539187be05fc42a43b2ef09c603b226d207
29 files changed +545 -535
lib/generated/i18n.dart
+23
@@ -24,6 +24,7 @@ class S implements WidgetsLocalizations {
24 String get account => "Account";
25 String get accounts => "Accounts";
26 String get add => "Add";
27 + String get add_new_node => "Add new node";
28 String get add_new_word => "Add new word";
29 String get address_book => "Address Book";
30 String get address_book_menu => "Address book";
@@ -519,6 +520,8 @@ class $de extends S {
520 @override
521 String get remove => "Löschen";
522 @override
523 + String get add_new_node => "Neuen Knoten hinzufügen";
524 + @override
525 String get yesterday => "Gestern";
526 @override
527 String get expired => "Abgelaufen";
@@ -1101,6 +1104,8 @@ class $hi extends S {
1104 @override
1105 String get remove => "हटाना";
1106 @override
1107 + String get add_new_node => "नया नोड जोड़ें";
1108 + @override
1109 String get yesterday => "बिता कल";
1110 @override
1111 String get expired => "समय सीमा समाप्त";
@@ -1683,6 +1688,8 @@ class $ru extends S {
1688 @override
1689 String get remove => "Удалить";
1690 @override
1691 + String get add_new_node => "Добавить новую ноду";
1692 + @override
1693 String get yesterday => "Вчера";
1694 @override
1695 String get expired => "Истекает";
@@ -2265,6 +2272,8 @@ class $ko extends S {
2272 @override
2273 String get remove => "없애다";
2274 @override
2275 + String get add_new_node => "새 노드 추가";
2276 + @override
2277 String get yesterday => "어제";
2278 @override
2279 String get expired => "만료";
@@ -2847,6 +2856,8 @@ class $pt extends S {
2856 @override
2857 String get remove => "Remover";
2858 @override
2859 + String get add_new_node => "Adicionar novo nó";
2860 + @override
2861 String get yesterday => "Ontem";
2862 @override
2863 String get expired => "Expirada";
@@ -3429,6 +3440,8 @@ class $uk extends S {
3440 @override
3441 String get remove => "Видалити";
3442 @override
3443 + String get add_new_node => "Додати новий вузол";
3444 + @override
3445 String get yesterday => "Вчора";
3446 @override
3447 String get expired => "Закінчується";
@@ -4011,6 +4024,8 @@ class $ja extends S {
4024 @override
4025 String get remove => "削除する";
4026 @override
4027 + String get add_new_node => "新しいノードを追加";
4028 + @override
4029 String get yesterday => "昨日";
4030 @override
4031 String get expired => "期限切れ";
@@ -4597,6 +4612,8 @@ class $pl extends S {
4612 @override
4613 String get remove => "Usunąć";
4614 @override
4615 + String get add_new_node => "Dodaj nowy węzeł";
4616 + @override
4617 String get yesterday => "Wczoraj";
4618 @override
4619 String get expired => "Przedawniony";
@@ -5179,6 +5196,8 @@ class $es extends S {
5196 @override
5197 String get remove => "Retirar";
5198 @override
5199 + String get add_new_node => "Agregar nuevo nodo";
5200 + @override
5201 String get yesterday => "Ayer";
5202 @override
5203 String get expired => "Muerto";
@@ -5761,6 +5780,8 @@ class $nl extends S {
5780 @override
5781 String get remove => "Verwijderen";
5782 @override
5783 + String get add_new_node => "Voeg een nieuw knooppunt toe";
5784 + @override
5785 String get yesterday => "Gisteren";
5786 @override
5787 String get expired => "Verlopen";
@@ -6343,6 +6364,8 @@ class $zh extends S {
6364 @override
6365 String get remove => "去掉";
6366 @override
6367 + String get add_new_node => "添加新節點";
6368 + @override
6369 String get yesterday => "昨天";
6370 @override
6371 String get expired => "已过期";
lib/src/screens/dashboard/wallet_menu.dart
+12 -12
@@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
4 import 'package:cake_wallet/generated/i18n.dart';
5 import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
6 import 'package:cake_wallet/src/screens/auth/auth_page.dart';
7 -import 'package:cake_wallet/src/screens/dashboard/widgets/reconnect_alert_dialog.dart';
7 +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
8
9 class WalletMenu {
10 WalletMenu(this.context);
@@ -40,7 +40,7 @@ class WalletMenu {
40 Navigator.of(context).pushNamed(Routes.walletList);
41 break;
42 case 2:
43 - // FIXME: apply Nodes
43 + Navigator.of(context).pushNamed(Routes.nodeList);
44 break;
45 case 3:
46 Navigator.of(context).pushNamed(Routes.auth,
@@ -75,16 +75,16 @@ class WalletMenu {
75 await showDialog<void>(
76 context: context,
77 builder: (BuildContext context) {
78 - return ReconnectAlertDialog(
79 - reconnectTitleText: S.of(context).reconnection,
80 - reconnectContentText: S.of(context).reconnect_alert_text,
81 - reconnectLeftActionButtonText: S.of(context).ok,
82 - reconnectRightActionButtonText: S.of(context).cancel,
83 - reconnectActionLeft: () {
84 - walletStore.reconnect();
85 - Navigator.of(context).pop();
86 - },
87 - reconnectActionRight: () => Navigator.of(context).pop()
78 + return AlertWithTwoActions(
79 + alertTitle: S.of(context).reconnection,
80 + alertContent: S.of(context).reconnect_alert_text,
81 + leftButtonText: S.of(context).ok,
82 + rightButtonText: S.of(context).cancel,
83 + actionLeftButton: () {
84 + walletStore.reconnect();
85 + Navigator.of(context).pop();
86 + },
87 + actionRightButton: () => Navigator.of(context).pop()
88 );
89 });
90 }
lib/src/screens/dashboard/widgets/reconnect_alert_dialog.dart deleted
-34
@@ -1,34 +0,0 @@
1 -import 'dart:ui';
2 -import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
3 -import 'package:flutter/cupertino.dart';
4 -
5 -class ReconnectAlertDialog extends BaseAlertDialog {
6 - ReconnectAlertDialog({
7 - @required this.reconnectTitleText,
8 - @required this.reconnectContentText,
9 - @required this.reconnectLeftActionButtonText,
10 - @required this.reconnectRightActionButtonText,
11 - @required this.reconnectActionLeft,
12 - @required this.reconnectActionRight
13 - });
14 -
15 - final String reconnectTitleText;
16 - final String reconnectContentText;
17 - final String reconnectLeftActionButtonText;
18 - final String reconnectRightActionButtonText;
19 - final VoidCallback reconnectActionLeft;
20 - final VoidCallback reconnectActionRight;
21 -
22 - @override
23 - String get titleText => reconnectTitleText;
24 - @override
25 - String get contentText => reconnectContentText;
26 - @override
27 - String get leftActionButtonText => reconnectLeftActionButtonText;
28 - @override
29 - String get rightActionButtonText => reconnectRightActionButtonText;
30 - @override
31 - VoidCallback get actionLeft => reconnectActionLeft;
32 - @override
33 - VoidCallback get actionRight => reconnectActionRight;
34 -}
\ No newline at end of file
lib/src/screens/new_wallet/new_wallet_page.dart
+6 -6
@@ -16,7 +16,7 @@ import 'package:cake_wallet/palette.dart';
16 import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
17 import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
18 import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
19 -import 'package:cake_wallet/src/screens/new_wallet/widgets/wallet_creation_dialog.dart';
19 +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
20
21 class NewWalletPage extends BasePage {
22 NewWalletPage(
@@ -90,11 +90,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
90 showDialog<void>(
91 context: context,
92 builder: (_) {
93 - return WalletCreationDialog(
94 - dialogTitle: S.current.new_wallet,
95 - dialogContent: state.error,
96 - dialogButtonText: S.of(context).ok,
97 - dialogButtonAction: () => Navigator.of(context).pop()
93 + return AlertWithOneAction(
94 + alertTitle: S.current.new_wallet,
95 + alertContent: state.error,
96 + buttonText: S.of(context).ok,
97 + buttonAction: () => Navigator.of(context).pop()
98 );
99 });
100 });
lib/src/screens/new_wallet/widgets/wallet_creation_dialog.dart deleted
-56
@@ -1,56 +0,0 @@
1 -import 'package:flutter/material.dart';
2 -import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
3 -
4 -class WalletCreationDialog extends BaseAlertDialog {
5 - WalletCreationDialog({
6 - @required this.dialogTitle,
7 - @required this.dialogContent,
8 - @required this.dialogButtonText,
9 - @required this.dialogButtonAction,
10 - });
11 -
12 - final String dialogTitle;
13 - final String dialogContent;
14 - final String dialogButtonText;
15 - final VoidCallback dialogButtonAction;
16 -
17 - @override
18 - String get titleText => dialogTitle;
19 -
20 - @override
21 - String get contentText => dialogContent;
22 -
23 - @override
24 - Widget actionButtons(BuildContext context) {
25 - return Container(
26 - width: 300,
27 - height: 52,
28 - padding: EdgeInsets.only(left: 12, right: 12),
29 - decoration: BoxDecoration(
30 - borderRadius: BorderRadius.only(
31 - bottomLeft: Radius.circular(24),
32 - bottomRight: Radius.circular(24)
33 - ),
34 - color: Colors.white
35 - ),
36 - child: ButtonTheme(
37 - minWidth: double.infinity,
38 - child: FlatButton(
39 - onPressed: dialogButtonAction,
40 - highlightColor: Colors.transparent,
41 - splashColor: Colors.transparent,
42 - child: Text(
43 - dialogButtonText,
44 - textAlign: TextAlign.center,
45 - style: TextStyle(
46 - fontSize: 15,
47 - fontWeight: FontWeight.w600,
48 - color: Colors.blue,
49 - decoration: TextDecoration.none,
50 - ),
51 - )),
52 - ),
53 - );
54 - }
55 -
56 -}
\ No newline at end of file
lib/src/screens/nodes/new_node_page.dart
+166 -135
@@ -1,16 +1,21 @@
1 import 'package:flutter/material.dart';
2 import 'package:flutter/cupertino.dart';
3 +import 'package:flutter_mobx/flutter_mobx.dart';
4 import 'package:provider/provider.dart';
5 import 'package:cake_wallet/palette.dart';
6 import 'package:cake_wallet/generated/i18n.dart';
7 import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
8 import 'package:cake_wallet/src/widgets/primary_button.dart';
9 import 'package:cake_wallet/src/screens/base_page.dart';
10 +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
11
12 class NewNodePage extends BasePage {
13 @override
14 String get title => S.current.node_new;
15
16 + @override
17 + Color get backgroundColor => PaletteDark.historyPanel;
18 +
19 @override
20 Widget body(BuildContext context) => NewNodePageForm();
21 }
@@ -36,130 +41,167 @@ class NewNodeFormState extends State<NewNodePageForm> {
41 super.dispose();
42 }
43
44 + void onHandleControllers(NodeListStore nodeListStore) {
45 + if (_nodeAddressController.text.isNotEmpty &&
46 + _nodePortController.text.isNotEmpty) {
47 + nodeListStore.setDisabledState(false);
48 + } else {
49 + nodeListStore.setDisabledState(true);
50 + }
51 + }
52 +
53 @override
54 Widget build(BuildContext context) {
55 final nodeList = Provider.of<NodeListStore>(context);
56
43 - return Form(
44 - key: _formKey,
45 - child: Column(
46 - children: <Widget>[
47 - Expanded(
48 - child: Container(
49 - padding: EdgeInsets.only(left: 38.0, right: 38.0, top: 0),
50 - child: Center(
51 - child: Column(
52 - mainAxisSize: MainAxisSize.min,
53 - children: <Widget>[
54 - Row(
55 - children: <Widget>[
56 - Expanded(
57 - child: TextFormField(
58 - style: TextStyle(fontSize: 14.0),
59 - decoration: InputDecoration(
60 - hintStyle:
61 - TextStyle(color: Palette.wildDarkBlue),
62 - hintText: S.of(context).node_address,
63 - focusedBorder: UnderlineInputBorder(
64 - borderSide: BorderSide(
65 - color: Palette.cakeGreen, width: 2.0)),
66 - enabledBorder: UnderlineInputBorder(
67 - borderSide: BorderSide(
68 - color: Theme.of(context).focusColor,
69 - width: 1.0))),
70 - controller: _nodeAddressController,
71 - validator: (value) {
72 - nodeList.validateNodeAddress(value);
73 - return nodeList.errorMessage;
74 - },
57 + _nodeAddressController.addListener(() {onHandleControllers(nodeList);});
58 + _nodePortController.addListener(() {onHandleControllers(nodeList);});
59 +
60 + return Container(
61 + color: PaletteDark.historyPanel,
62 + padding: EdgeInsets.only(left: 24, right: 24),
63 + child: ScrollableWithBottomSection(
64 + contentPadding: EdgeInsets.only(bottom: 24.0),
65 + content: Form(
66 + key: _formKey,
67 + child: Column(
68 + children: <Widget>[
69 + Row(
70 + children: <Widget>[
71 + Expanded(
72 + child: TextFormField(
73 + style: TextStyle(
74 + fontSize: 16.0,
75 + color: Colors.white
76 + ),
77 + decoration: InputDecoration(
78 + hintStyle:
79 + TextStyle(
80 + color: PaletteDark.walletCardText,
81 + fontSize: 16
82 ),
76 - )
77 - ],
83 + hintText: S.of(context).node_address,
84 + focusedBorder: UnderlineInputBorder(
85 + borderSide: BorderSide(
86 + color: PaletteDark.menuList,
87 + width: 1.0)),
88 + enabledBorder: UnderlineInputBorder(
89 + borderSide: BorderSide(
90 + color: PaletteDark.menuList,
91 + width: 1.0))),
92 + controller: _nodeAddressController,
93 + validator: (value) {
94 + nodeList.validateNodeAddress(value);
95 + return nodeList.errorMessage;
96 + },
97 ),
79 - SizedBox(height: 10.0),
80 - Row(
81 - children: <Widget>[
82 - Expanded(
83 - child: TextFormField(
84 - style: TextStyle(fontSize: 14.0),
85 - keyboardType: TextInputType.numberWithOptions(
86 - signed: false, decimal: false),
87 - decoration: InputDecoration(
88 - hintStyle:
89 - TextStyle(color: Palette.wildDarkBlue),
90 - hintText: S.of(context).node_port,
91 - focusedBorder: UnderlineInputBorder(
92 - borderSide: BorderSide(
93 - color: Palette.cakeGreen, width: 2.0)),
94 - enabledBorder: UnderlineInputBorder(
95 - borderSide: BorderSide(
96 - color: Theme.of(context).focusColor,
97 - width: 1.0))),
98 - controller: _nodePortController,
99 - validator: (value) {
100 - nodeList.validateNodePort(value);
101 - return nodeList.errorMessage;
102 - },
98 + )
99 + ],
100 + ),
101 + SizedBox(height: 10.0),
102 + Row(
103 + children: <Widget>[
104 + Expanded(
105 + child: TextFormField(
106 + style: TextStyle(
107 + fontSize: 16.0,
108 + color: Colors.white
109 + ),
110 + keyboardType: TextInputType.numberWithOptions(
111 + signed: false, decimal: false),
112 + decoration: InputDecoration(
113 + hintStyle:
114 + TextStyle(
115 + color: PaletteDark.walletCardText,
116 + fontSize: 16
117 ),
104 - )
105 - ],
118 + hintText: S.of(context).node_port,
119 + focusedBorder: UnderlineInputBorder(
120 + borderSide: BorderSide(
121 + color: PaletteDark.menuList,
122 + width: 1.0)),
123 + enabledBorder: UnderlineInputBorder(
124 + borderSide: BorderSide(
125 + color: PaletteDark.menuList,
126 + width: 1.0))),
127 + controller: _nodePortController,
128 + validator: (value) {
129 + nodeList.validateNodePort(value);
130 + return nodeList.errorMessage;
131 + },
132 ),
107 - SizedBox(height: 10.0),
108 - Row(
109 - children: <Widget>[
110 - Expanded(
111 - child: TextFormField(
112 - style: TextStyle(fontSize: 14.0),
113 - decoration: InputDecoration(
114 - hintStyle:
115 - TextStyle(color: Palette.wildDarkBlue),
116 - hintText: S.of(context).login,
117 - focusedBorder: UnderlineInputBorder(
118 - borderSide: BorderSide(
119 - color: Palette.cakeGreen, width: 2.0)),
120 - enabledBorder: UnderlineInputBorder(
121 - borderSide: BorderSide(
122 - color: Theme.of(context).focusColor,
123 - width: 1.0))),
124 - controller: _loginController,
125 - validator: (value) => null,
133 + )
134 + ],
135 + ),
136 + SizedBox(height: 10.0),
137 + Row(
138 + children: <Widget>[
139 + Expanded(
140 + child: TextFormField(
141 + style: TextStyle(
142 + fontSize: 16.0,
143 + color: Colors.white
144 + ),
145 + decoration: InputDecoration(
146 + hintStyle:
147 + TextStyle(
148 + color: PaletteDark.walletCardText,
149 + fontSize: 16
150 ),
127 - )
128 - ],
151 + hintText: S.of(context).login,
152 + focusedBorder: UnderlineInputBorder(
153 + borderSide: BorderSide(
154 + color: PaletteDark.menuList,
155 + width: 1.0)),
156 + enabledBorder: UnderlineInputBorder(
157 + borderSide: BorderSide(
158 + color: PaletteDark.menuList,
159 + width: 1.0))),
160 + controller: _loginController,
161 + validator: (value) => null,
162 ),
130 - SizedBox(height: 10.0),
131 - Row(
132 - children: <Widget>[
133 - Expanded(
134 - child: TextFormField(
135 - style: TextStyle(fontSize: 14.0),
136 - decoration: InputDecoration(
137 - hintStyle:
138 - TextStyle(color: Palette.wildDarkBlue),
139 - hintText: S.of(context).password,
140 - focusedBorder: UnderlineInputBorder(
141 - borderSide: BorderSide(
142 - color: Palette.cakeGreen, width: 2.0)),
143 - enabledBorder: UnderlineInputBorder(
144 - borderSide: BorderSide(
145 - color: Theme.of(context).focusColor,
146 - width: 1.0))),
147 - controller: _passwordController,
148 - validator: (value) => null,
149 - ),
150 - )
151 - ],
152 - )
153 - ],
154 - ),
163 + )
164 + ],
165 ),
156 - )),
157 - Container(
158 - padding: EdgeInsets.only(bottom: 20.0, left: 20.0, right: 20.0),
159 - child: Row(
166 + SizedBox(height: 10.0),
167 + Row(
168 children: <Widget>[
161 - Flexible(
162 - child: Container(
169 + Expanded(
170 + child: TextFormField(
171 + style: TextStyle(
172 + fontSize: 16.0,
173 + color: Colors.white
174 + ),
175 + decoration: InputDecoration(
176 + hintStyle:
177 + TextStyle(
178 + color: PaletteDark.walletCardText,
179 + fontSize: 16
180 + ),
181 + hintText: S.of(context).password,
182 + focusedBorder: UnderlineInputBorder(
183 + borderSide: BorderSide(
184 + color: PaletteDark.menuList,
185 + width: 1.0)),
186 + enabledBorder: UnderlineInputBorder(
187 + borderSide: BorderSide(
188 + color: PaletteDark.menuList,
189 + width: 1.0))),
190 + controller: _passwordController,
191 + validator: (value) => null,
192 + ),
193 + )
194 + ],
195 + )
196 + ],
197 + )
198 + ),
199 + bottomSectionPadding: EdgeInsets.only(bottom: 24),
200 + bottomSection: Observer(
201 + builder: (_) => Row(
202 + children: <Widget>[
203 + Flexible(
204 + child: Container(
205 padding: EdgeInsets.only(right: 8.0),
206 child: PrimaryButton(
207 onPressed: () {
@@ -169,17 +211,11 @@ class NewNodeFormState extends State<NewNodePageForm> {
211 _passwordController.text = '';
212 },
213 text: S.of(context).reset,
172 - color: Theme.of(context)
173 - .accentTextTheme
174 - .button
175 - .backgroundColor,
176 - textColor: Theme.of(context)
177 - .primaryTextTheme
178 - .button
179 - .color),
214 + color: Colors.red,
215 + textColor: Colors.white),
216 )),
181 - Flexible(
182 - child: Container(
217 + Flexible(
218 + child: Container(
219 padding: EdgeInsets.only(left: 8.0),
220 child: PrimaryButton(
221 onPressed: () async {
@@ -196,20 +232,15 @@ class NewNodeFormState extends State<NewNodePageForm> {
232 Navigator.of(context).pop();
233 },
234 text: S.of(context).save,
199 - color: Theme.of(context)
200 - .primaryTextTheme
201 - .button
202 - .backgroundColor,
203 - textColor: Theme.of(context)
204 - .primaryTextTheme
205 - .button
206 - .color,
235 + color: Colors.green,
236 + textColor: Colors.white,
237 + isDisabled: nodeList.disabledState,
238 ),
239 )),
209 - ],
210 - ),
211 - )
212 - ],
213 - ));
240 + ],
241 + )
242 + ),
243 + )
244 + );
245 }
246 }
lib/src/screens/nodes/nodes_list_page.dart
+168 -188
@@ -5,10 +5,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
5 import 'package:cake_wallet/routes.dart';
6 import 'package:cake_wallet/palette.dart';
7 import 'package:cake_wallet/generated/i18n.dart';
8 -import 'package:cake_wallet/src/screens/nodes/node_indicator.dart';
8 +import 'package:cake_wallet/src/screens/nodes/widgets/node_indicator.dart';
9 import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
10 import 'package:cake_wallet/src/stores/settings/settings_store.dart';
11 import 'package:cake_wallet/src/screens/base_page.dart';
12 +import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
13 +import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
14
15 class NodeListPage extends BasePage {
16 NodeListPage();
@@ -16,76 +18,50 @@ class NodeListPage extends BasePage {
18 @override
19 String get title => S.current.nodes;
20
21 + @override
22 + Color get backgroundColor => PaletteDark.historyPanel;
23 +
24 @override
25 Widget trailing(context) {
26 final nodeList = Provider.of<NodeListStore>(context);
27 final settings = Provider.of<SettingsStore>(context);
28
24 - return Row(
25 - mainAxisSize: MainAxisSize.min,
26 - children: <Widget>[
27 - ButtonTheme(
28 - minWidth: double.minPositive,
29 - child: FlatButton(
30 - onPressed: () async {
31 - await showDialog<void>(
32 - context: context,
33 - builder: (BuildContext context) {
34 - return AlertDialog(
35 - title: Text(
36 - S.of(context).node_reset_settings_title,
37 - textAlign: TextAlign.center,
38 - ),
39 - content: Text(
40 - S.of(context).nodes_list_reset_to_default_message,
41 - textAlign: TextAlign.center,
42 - ),
43 - actions: <Widget>[
44 - FlatButton(
45 - onPressed: () {
46 - Navigator.pop(context);
47 - },
48 - child: Text(S.of(context).cancel)),
49 - FlatButton(
50 - onPressed: () async {
51 - Navigator.pop(context);
52 - await nodeList.reset();
53 - await settings.setCurrentNodeToDefault();
54 - },
55 - child: Text(S.of(context).reset))
56 - ],
57 - );
58 - });
59 - },
60 - child: Text(
61 - S.of(context).reset,
62 - style: TextStyle(
63 - fontSize: 16.0,
64 - color: Theme.of(context).primaryTextTheme.subtitle.color),
65 - )),
66 - ),
67 - Container(
68 - width: 28.0,
69 - height: 28.0,
70 - decoration: BoxDecoration(
71 - shape: BoxShape.circle,
72 - color: Theme.of(context).selectedRowColor),
73 - child: Stack(
74 - alignment: Alignment.center,
75 - children: <Widget>[
76 - Icon(Icons.add, color: Palette.violet, size: 22.0),
77 - ButtonTheme(
78 - minWidth: 28.0,
79 - height: 28.0,
80 - child: FlatButton(
81 - shape: CircleBorder(),
82 - onPressed: () async =>
83 - await Navigator.of(context).pushNamed(Routes.newNode),
84 - child: Offstage()),
85 - )
86 - ],
29 + return Container(
30 + height: 32,
31 + width: 72,
32 + decoration: BoxDecoration(
33 + borderRadius: BorderRadius.all(Radius.circular(16)),
34 + color: PaletteDark.menuList
35 + ),
36 + child: ButtonTheme(
37 + minWidth: double.minPositive,
38 + child: FlatButton(
39 + onPressed: () async {
40 + await showDialog<void>(
41 + context: context,
42 + builder: (BuildContext context) {
43 + return AlertWithTwoActions(
44 + alertTitle: S.of(context).node_reset_settings_title,
45 + alertContent: S.of(context).nodes_list_reset_to_default_message,
46 + leftButtonText: S.of(context).reset,
47 + rightButtonText: S.of(context).cancel,
48 + actionLeftButton: () async {
49 + Navigator.of(context).pop();
50 + await nodeList.reset();
51 + await settings.setCurrentNodeToDefault();
52 + },
53 + actionRightButton: () => Navigator.of(context).pop()
54 + );
55 + });
56 + },
57 + child: Text(
58 + S.of(context).reset,
59 + textAlign: TextAlign.center,
60 + style: TextStyle(
61 + fontSize: 10.0,
62 + color: Colors.blue),
63 )),
88 - ],
64 + ),
65 );
66 }
67
@@ -104,137 +80,141 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
80 final nodeList = Provider.of<NodeListStore>(context);
81 final settings = Provider.of<SettingsStore>(context);
82
107 - final currentColor = Theme.of(context).selectedRowColor;
108 - final notCurrentColor = Theme.of(context).backgroundColor;
83 + final trashImage = Image.asset('assets/images/trash.png', height: 32, width: 32, color: Colors.white);
84 +
85 + final currentColor = PaletteDark.menuHeader;
86 + final notCurrentColor = PaletteDark.menuList;
87 +
88 + final currentTextColor = Colors.blue;
89 + final notCurrentTextColor = Colors.white;
90
91 return Container(
111 - padding: EdgeInsets.only(bottom: 20.0),
92 + height: double.infinity,
93 + color: PaletteDark.historyPanel,
94 + padding: EdgeInsets.only(top: 12),
95 child: Column(
96 + mainAxisSize: MainAxisSize.max,
97 children: <Widget>[
114 - Expanded(child: Observer(builder: (context) {
115 - return ListView.separated(
116 - separatorBuilder: (_, __) => Divider(
117 - color: Theme.of(context).dividerTheme.color, height: 1),
118 - itemCount: nodeList.nodes.length,
119 - itemBuilder: (BuildContext context, int index) {
120 - final node = nodeList.nodes[index];
121 -
122 - return Observer(builder: (_) {
123 - final isCurrent = settings.node == null
124 - ? false
125 - : node.key == settings.node.key;
126 -
127 - final content = Container(
128 - color: isCurrent ? currentColor : notCurrentColor,
129 - child: ListTile(
130 - title: Text(
131 - node.uri,
132 - style: TextStyle(
133 - fontSize: 16.0,
134 - color: Theme.of(context)
135 - .primaryTextTheme
136 - .title
137 - .color),
138 - ),
139 - trailing: FutureBuilder(
140 - future: nodeList.isNodeOnline(node),
141 - builder: (context, snapshot) {
142 - switch (snapshot.connectionState) {
143 - case ConnectionState.done:
144 - return NodeIndicator(
145 - color: snapshot.data as bool
146 - ? Palette.green
147 - : Palette.red);
148 - default:
149 - return NodeIndicator();
150 - }
151 - }),
152 - onTap: () async {
153 - if (!isCurrent) {
154 - await showDialog<void>(
155 - context: context,
156 - builder: (BuildContext context) {
157 - return AlertDialog(
158 - content: Text(
159 - S
160 - .of(context)
161 - .change_current_node(node.uri),
162 - textAlign: TextAlign.center,
163 - ),
164 - actions: <Widget>[
165 - FlatButton(
166 - onPressed: () =>
167 - Navigator.pop(context),
168 - child: Text(S.of(context).cancel)),
169 - FlatButton(
170 - onPressed: () async {
98 + NodeListRow(
99 + title: S.of(context).add_new_node,
100 + trailing: Icon(Icons.add, color: Colors.white, size: 24.0),
101 + color: PaletteDark.menuList,
102 + textColor: Colors.white,
103 + onTap: () async =>
104 + await Navigator.of(context).pushNamed(Routes.newNode),
105 + isDrawTop: true,
106 + isDrawBottom: true),
107 + Expanded(
108 + child: Padding(
109 + padding: EdgeInsets.only(top: 32),
110 + child: Observer(
111 + builder: (_) => ListView.separated(
112 + separatorBuilder: (_, __) => Container(
113 + height: 1,
114 + padding: EdgeInsets.only(left: 24),
115 + color: PaletteDark.menuList,
116 + child: Container(
117 + height: 1,
118 + color: PaletteDark.walletCardTopEndSync,
119 + ),
120 + ),
121 + itemCount: nodeList.nodes.length,
122 + itemBuilder: (BuildContext context, int index) {
123 + final node = nodeList.nodes[index];
124 +
125 + final isDrawTop = index == 0 ? true : false;
126 + final isDrawBottom = index == nodeList.nodes.length - 1 ? true : false;
127 +
128 + return Observer(
129 + builder: (_) {
130 + final isCurrent = settings.node == null
131 + ? false
132 + : node.key == settings.node.key;
133 +
134 + final content = NodeListRow(
135 + title: node.uri,
136 + trailing: FutureBuilder(
137 + future: nodeList.isNodeOnline(node),
138 + builder: (context, snapshot) {
139 + switch (snapshot.connectionState) {
140 + case ConnectionState.done:
141 + return NodeIndicator(
142 + color: snapshot.data as bool
143 + ? Palette.green
144 + : Palette.red);
145 + default:
146 + return NodeIndicator();
147 + }
148 + }),
149 + color: isCurrent ? currentColor : notCurrentColor,
150 + textColor: isCurrent ? currentTextColor : notCurrentTextColor,
151 + onTap: () async {
152 + if (!isCurrent) {
153 + await showDialog<void>(
154 + context: context,
155 + builder: (BuildContext context) {
156 + return AlertWithTwoActions(
157 + alertTitle: S.current.nodes,
158 + alertContent: S.of(context)
159 + .change_current_node(node.uri),
160 + leftButtonText: S.of(context).change,
161 + rightButtonText: S.of(context).cancel,
162 + actionLeftButton: () async {
163 Navigator.of(context).pop();
164 await settings.setCurrentNode(
165 node: node);
166 },
175 - child: Text(S.of(context).change)),
176 - ],
177 - );
178 - });
179 - }
180 - },
181 - ));
182 -
183 - return isCurrent
184 - ? content
185 - : Dismissible(
186 - key: Key('${node.key}'),
187 - confirmDismiss: (direction) async {
188 - return await showDialog(
189 - context: context,
190 - builder: (BuildContext context) {
191 - return AlertDialog(
192 - title: Text(
193 - S.of(context).remove_node,
194 - textAlign: TextAlign.center,
195 - ),
196 - content: Text(
197 - S.of(context).remove_node_message,
198 - textAlign: TextAlign.center,
199 - ),
200 - actions: <Widget>[
201 - FlatButton(
202 - onPressed: () =>
203 - Navigator.pop(context, false),
204 - child: Text(S.of(context).cancel)),
205 - FlatButton(
206 - onPressed: () =>
207 - Navigator.pop(context, true),
208 - child: Text(S.of(context).remove)),
209 - ],
210 - );
211 - });
212 - },
213 - onDismissed: (direction) async =>
214 - await nodeList.remove(node: node),
215 - direction: DismissDirection.endToStart,
216 - background: Container(
217 - padding: EdgeInsets.only(right: 10.0),
218 - alignment: AlignmentDirectional.centerEnd,
219 - color: Palette.red,
220 - child: Column(
221 - mainAxisAlignment:
222 - MainAxisAlignment.spaceBetween,
223 - children: <Widget>[
224 - const Icon(
225 - CupertinoIcons.delete,
226 - color: Colors.white,
227 - ),
228 - Text(
229 - S.of(context).delete,
230 - style: TextStyle(color: Colors.white),
231 - )
232 - ],
233 - )),
234 - child: content);
235 - });
236 - });
237 - }))
167 + actionRightButton: () => Navigator.of(context).pop()
168 + );
169 + });
170 + }
171 + },
172 + isDrawTop: isDrawTop,
173 + isDrawBottom: isDrawBottom);
174 +
175 + return isCurrent
176 + ? content
177 + : Dismissible(
178 + key: Key('${node.key}'),
179 + confirmDismiss: (direction) async {
180 + return await showDialog(
181 + context: context,
182 + builder: (BuildContext context) {
183 + return AlertWithTwoActions(
184 + alertTitle: S.of(context).remove_node,
185 + alertContent: S.of(context).remove_node_message,
186 + leftButtonText: S.of(context).remove,
187 + rightButtonText: S.of(context).cancel,
188 + actionLeftButton: () =>
189 + Navigator.pop(context, true),
190 + actionRightButton: () =>
191 + Navigator.pop(context, false)
192 + );
193 + });
194 + },
195 + onDismissed: (direction) async =>
196 + await nodeList.remove(node: node),
197 + direction: DismissDirection.endToStart,
198 + background: Container(
199 + padding: EdgeInsets.only(right: 10.0, top: 2),
200 + alignment: AlignmentDirectional.centerEnd,
201 + color: Palette.red,
202 + child: Column(
203 + children: <Widget>[
204 + trashImage,
205 + Text(
206 + S.of(context).delete,
207 + style: TextStyle(color: Colors.white),
208 + )
209 + ],
210 + )),
211 + child: content);
212 + },
213 + );
214 + })
215 + ),
216 + )
217 + )
218 ],
219 ),
220 );
lib/src/screens/nodes/widgets/node_indicator.dart renamed
+2 -2
@@ -9,8 +9,8 @@ class NodeIndicator extends StatelessWidget {
9 @override
10 Widget build(BuildContext context) {
11 return Container(
12 - width: 10.0,
13 - height: 10.0,
12 + width: 8.0,
13 + height: 8.0,
14 decoration: BoxDecoration(shape: BoxShape.circle, color: color),
15 );
16 }
lib/src/screens/nodes/widgets/node_list_row.dart new
+63
@@ -0,0 +1,63 @@
1 +import 'package:flutter/material.dart';
2 +import 'package:cake_wallet/palette.dart';
3 +
4 +class NodeListRow extends StatelessWidget {
5 + NodeListRow({
6 + @required this.title,
7 + @required this.trailing,
8 + @required this.color,
9 + @required this.textColor,
10 + @required this.onTap,
11 + @required this.isDrawTop,
12 + @required this.isDrawBottom});
13 +
14 + final String title;
15 + final Widget trailing;
16 + final Color color;
17 + final Color textColor;
18 + final VoidCallback onTap;
19 + final bool isDrawTop;
20 + final bool isDrawBottom;
21 +
22 + @override
23 + Widget build(BuildContext context) {
24 + return Column(
25 + children: <Widget>[
26 + isDrawTop
27 + ? Container(
28 + width: double.infinity,
29 + height: 1,
30 + color: PaletteDark.walletCardTopEndSync,
31 + )
32 + : Offstage(),
33 + Container(
34 + width: double.infinity,
35 + height: 56,
36 + color: color,
37 + child: ListTile(
38 + contentPadding: EdgeInsets.only(
39 + left: 24,
40 + right: 24,
41 + ),
42 + title: Text(
43 + title,
44 + style: TextStyle(
45 + fontSize: 14,
46 + color: textColor
47 + ),
48 + textAlign: TextAlign.left),
49 + trailing: trailing,
50 + onTap: onTap,
51 + )
52 + ),
53 + isDrawBottom
54 + ? Container(
55 + width: double.infinity,
56 + height: 1,
57 + color: PaletteDark.walletCardTopEndSync,
58 + )
59 + : Offstage(),
60 + ],
61 + );
62 + }
63 +}
lib/src/screens/restore/restore_wallet_from_keys_page.dart
+6 -6
@@ -16,7 +16,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
16 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
17 import 'package:cake_wallet/palette.dart';
18 import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
19 -import 'package:cake_wallet/src/screens/restore/widgets/restore_alert_dialog.dart';
19 +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
20
21 class RestoreWalletFromKeysPage extends BasePage {
22 RestoreWalletFromKeysPage(
@@ -91,11 +91,11 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
91 showDialog<void>(
92 context: context,
93 builder: (BuildContext context) {
94 - return RestoreAlertDialog(
95 - restoreTitle: S.current.restore_title_from_keys,
96 - restoreContent: state.error,
97 - restoreButtonText: S.of(context).ok,
98 - restoreButtonAction: () => Navigator.of(context).pop(),
94 + return AlertWithOneAction(
95 + alertTitle: S.current.restore_title_from_keys,
96 + alertContent: state.error,
97 + buttonText: S.of(context).ok,
98 + buttonAction: () => Navigator.of(context).pop()
99 );
100 });
101 });
lib/src/screens/restore/restore_wallet_from_seed_details.dart
+6 -6
@@ -11,7 +11,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
11 import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
12 import 'package:cake_wallet/src/widgets/primary_button.dart';
13 import 'package:cake_wallet/palette.dart';
14 -import 'package:cake_wallet/src/screens/restore/widgets/restore_alert_dialog.dart';
14 +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
15
16 class RestoreWalletFromSeedDetailsPage extends BasePage {
17 @override
@@ -64,11 +64,11 @@ class _RestoreFromSeedDetailsFormState
64 showDialog<void>(
65 context: context,
66 builder: (BuildContext context) {
67 - return RestoreAlertDialog(
68 - restoreTitle: S.current.restore_wallet_restore_description,
69 - restoreContent: state.error,
70 - restoreButtonText: S.of(context).ok,
71 - restoreButtonAction: () => Navigator.of(context).pop(),
67 + return AlertWithOneAction(
68 + alertTitle: S.current.restore_title_from_seed,
69 + alertContent: state.error,
70 + buttonText: S.of(context).ok,
71 + buttonAction: () => Navigator.of(context).pop()
72 );
73 });
74 });
lib/src/screens/setup_pin_code/setup_pin_code.dart
+15 -14
@@ -8,7 +8,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
8 import 'package:cake_wallet/src/stores/settings/settings_store.dart';
9 import 'package:cake_wallet/generated/i18n.dart';
10 import 'package:cake_wallet/palette.dart';
11 -import 'package:cake_wallet/src/screens/setup_pin_code/widgets/pin_alert_dialog.dart';
11 +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
12
13 class SetupPinCodePage extends BasePage {
14 SetupPinCodePage({this.onPinCodeSetup});
@@ -64,27 +64,28 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
64 showDialog<void>(
65 context: context,
66 builder: (BuildContext context) {
67 - return PinAlertDialog(
68 - pinTitleText: S.current.setup_pin,
69 - pinContentText: S.of(context).setup_successful,
70 - pinActionButtonText: S.of(context).ok,
71 - pinBarrierDismissible: false,
72 - pinAction: () {
67 + return AlertWithOneAction(
68 + alertTitle: S.current.setup_pin,
69 + alertContent: S.of(context).setup_successful,
70 + buttonText: S.of(context).ok,
71 + buttonAction: () {
72 Navigator.of(context).pop();
73 widget.onPinCodeSetup(context, pin);
74 reset();
76 - });
75 + },
76 + alertBarrierDismissible: false,
77 + );
78 });
79 } else {
80 showDialog<void>(
81 context: context,
82 builder: (BuildContext context) {
82 - return PinAlertDialog(
83 - pinTitleText: S.current.setup_pin,
84 - pinContentText: S.of(context).pin_is_incorrect,
85 - pinActionButtonText: S.of(context).ok,
86 - pinBarrierDismissible: true,
87 - pinAction: () => Navigator.of(context).pop());
83 + return AlertWithOneAction(
84 + alertTitle: S.current.setup_pin,
85 + alertContent: S.of(context).pin_is_incorrect,
86 + buttonText: S.of(context).ok,
87 + buttonAction: () => Navigator.of(context).pop()
88 + );
89 });
90
91 reset();
lib/src/screens/setup_pin_code/widgets/pin_alert_dialog.dart deleted
-60
@@ -1,60 +0,0 @@
1 -import 'dart:ui';
2 -import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
3 -import 'package:flutter/cupertino.dart';
4 -import 'package:flutter/material.dart';
5 -
6 -class PinAlertDialog extends BaseAlertDialog {
7 - PinAlertDialog({
8 - @required this.pinTitleText,
9 - @required this.pinContentText,
10 - @required this.pinActionButtonText,
11 - @required this.pinAction,
12 - @required this.pinBarrierDismissible
13 - });
14 -
15 - final String pinTitleText;
16 - final String pinContentText;
17 - final String pinActionButtonText;
18 - final VoidCallback pinAction;
19 - final bool pinBarrierDismissible;
20 -
21 - @override
22 - String get titleText => pinTitleText;
23 - @override
24 - String get contentText => pinContentText;
25 - @override
26 - bool get barrierDismissible => pinBarrierDismissible;
27 -
28 - @override
29 - Widget actionButtons(BuildContext context) {
30 - return Container(
31 - width: 300,
32 - height: 52,
33 - padding: EdgeInsets.only(left: 12, right: 12),
34 - decoration: BoxDecoration(
35 - borderRadius: BorderRadius.only(
36 - bottomLeft: Radius.circular(24),
37 - bottomRight: Radius.circular(24)
38 - ),
39 - color: Colors.white
40 - ),
41 - child: ButtonTheme(
42 - minWidth: double.infinity,
43 - child: FlatButton(
44 - onPressed: pinAction,
45 - highlightColor: Colors.transparent,
46 - splashColor: Colors.transparent,
47 - child: Text(
48 - pinActionButtonText,
49 - textAlign: TextAlign.center,
50 - style: TextStyle(
51 - fontSize: 15,
52 - fontWeight: FontWeight.w600,
53 - color: Colors.blue,
54 - decoration: TextDecoration.none,
55 - ),
56 - )),
57 - ),
58 - );
59 - }
60 -}
\ No newline at end of file
lib/src/stores/node_list/node_list_store.dart
+9
@@ -12,6 +12,7 @@ class NodeListStore = NodeListBase with _$NodeListStore;
12 abstract class NodeListBase with Store {
13 NodeListBase({this.nodesSource}) {
14 nodes = ObservableList<Node>();
15 + disabledState = true;
16 _onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
17 update();
18 }
@@ -25,6 +26,9 @@ abstract class NodeListBase with Store {
26 @observable
27 String errorMessage;
28
29 + @observable
30 + bool disabledState;
31 +
32 Box<Node> nodesSource;
33
34 StreamSubscription<BoxEvent> _onNodesChangeSubscription;
@@ -61,6 +65,11 @@ abstract class NodeListBase with Store {
65 @action
66 Future reset() async => await resetToDefault(nodesSource);
67
68 + @action
69 + void setDisabledState(bool isDisable) {
70 + disabledState = isDisable;
71 + }
72 +
73 Future<bool> isNodeOnline(Node node) async {
74 try {
75 return await node.requestNode(node.uri,
lib/src/widgets/alert_with_one_action.dart renamed
+19 -15
@@ -1,24 +1,29 @@
1 import 'package:flutter/material.dart';
2 import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
3
4 -class RestoreAlertDialog extends BaseAlertDialog {
5 - RestoreAlertDialog({
6 - @required this.restoreTitle,
7 - @required this.restoreContent,
8 - @required this.restoreButtonText,
9 - @required this.restoreButtonAction,
4 +class AlertWithOneAction extends BaseAlertDialog {
5 + AlertWithOneAction({
6 + @required this.alertTitle,
7 + @required this.alertContent,
8 + @required this.buttonText,
9 + @required this.buttonAction,
10 + this.alertBarrierDismissible = true
11 });
12
12 - final String restoreTitle;
13 - final String restoreContent;
14 - final String restoreButtonText;
15 - final VoidCallback restoreButtonAction;
13 + final String alertTitle;
14 + final String alertContent;
15 + final String buttonText;
16 + final VoidCallback buttonAction;
17 + final bool alertBarrierDismissible;
18
19 @override
18 - String get titleText => restoreTitle;
20 + String get titleText => alertTitle;
21
22 @override
21 - String get contentText => restoreContent;
23 + String get contentText => alertContent;
24 +
25 + @override
26 + bool get barrierDismissible => alertBarrierDismissible;
27
28 @override
29 Widget actionButtons(BuildContext context) {
@@ -36,11 +41,11 @@ class RestoreAlertDialog extends BaseAlertDialog {
41 child: ButtonTheme(
42 minWidth: double.infinity,
43 child: FlatButton(
39 - onPressed: restoreButtonAction,
44 + onPressed: buttonAction,
45 highlightColor: Colors.transparent,
46 splashColor: Colors.transparent,
47 child: Text(
43 - restoreButtonText,
48 + buttonText,
49 textAlign: TextAlign.center,
50 style: TextStyle(
51 fontSize: 15,
@@ -52,5 +57,4 @@ class RestoreAlertDialog extends BaseAlertDialog {
57 ),
58 );
59 }
55 -
60 }
\ No newline at end of file
lib/src/widgets/alert_with_two_actions.dart new
+38
@@ -0,0 +1,38 @@
1 +import 'dart:ui';
2 +import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
3 +import 'package:flutter/cupertino.dart';
4 +
5 +class AlertWithTwoActions extends BaseAlertDialog {
6 + AlertWithTwoActions({
7 + @required this.alertTitle,
8 + @required this.alertContent,
9 + @required this.leftButtonText,
10 + @required this.rightButtonText,
11 + @required this.actionLeftButton,
12 + @required this.actionRightButton,
13 + this.alertBarrierDismissible = true
14 + });
15 +
16 + final String alertTitle;
17 + final String alertContent;
18 + final String leftButtonText;
19 + final String rightButtonText;
20 + final VoidCallback actionLeftButton;
21 + final VoidCallback actionRightButton;
22 + final bool alertBarrierDismissible;
23 +
24 + @override
25 + String get titleText => alertTitle;
26 + @override
27 + String get contentText => alertContent;
28 + @override
29 + String get leftActionButtonText => leftButtonText;
30 + @override
31 + String get rightActionButtonText => rightButtonText;
32 + @override
33 + VoidCallback get actionLeft => actionLeftButton;
34 + @override
35 + VoidCallback get actionRight => actionRightButton;
36 + @override
37 + bool get barrierDismissible => alertBarrierDismissible;
38 +}
\ No newline at end of file
lib/src/widgets/base_alert_dialog.dart
-1
@@ -134,7 +134,6 @@ class BaseAlertDialog extends StatelessWidget {
134 color: PaletteDark.menuHeader
135 ),
136 child: Column(
137 - //mainAxisSize: MainAxisSize.max,
137 children: <Widget>[
138 Container(
139 width: 300,
res/values/strings_de.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Möchten Sie den ausgewählten Knoten wirklich entfernen?",
125 "remove" : "Löschen",
126 "delete" : "Löschen",
127 + "add_new_node" : "Neuen Knoten hinzufügen",
128
129
130 "use" : "Wechseln zu ",
res/values/strings_en.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Are you sure that you want to remove selected node?",
125 "remove" : "Remove",
126 "delete" : "Delete",
127 + "add_new_node" : "Add new node",
128
129
130 "use" : "Switch to ",
res/values/strings_es.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "¿Está seguro de que desea eliminar el nodo seleccionado?",
125 "remove" : "Retirar",
126 "delete" : "Borrar",
127 + "add_new_node" : "Agregar nuevo nodo",
128
129
130 "use" : "Cambiar a ",
res/values/strings_hi.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?",
125 "remove" : "हटाना",
126 "delete" : "हटाएं",
127 + "add_new_node" : "नया नोड जोड़ें",
128
129
130 "use" : "पर स्विच ",
res/values/strings_ja.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "選択したノードを削除してもよろしいですか?",
125 "remove" : "削除する",
126 "delete" : "削除する",
127 + "add_new_node" : "新しいノードを追加",
128
129
130 "use" : "切り替える ",
res/values/strings_ko.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "선택한 노드를 제거 하시겠습니까?",
125 "remove" : "없애다",
126 "delete" : "지우다",
127 + "add_new_node" : "새 노드 추가",
128
129
130 "use" : "로 전환 ",
res/values/strings_nl.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?",
125 "remove" : "Verwijderen",
126 "delete" : "Delete",
127 + "add_new_node" : "Voeg een nieuw knooppunt toe",
128
129
130 "use" : "Overschakelen naar ",
res/values/strings_pl.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Czy na pewno chcesz usunąć wybrany węzeł?",
125 "remove" : "Usunąć",
126 "delete" : "Kasować",
127 + "add_new_node" : "Dodaj nowy węzeł",
128
129
130 "use" : "Przełącz na ",
res/values/strings_pt.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Você realmente deseja remover o nó selecionado?",
125 "remove" : "Remover",
126 "delete" : "Excluir",
127 + "add_new_node" : "Adicionar novo nó",
128
129
130 "use" : "Trocar para PIN de ",
res/values/strings_ru.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Вы уверены, что хотите удалить текущую ноду?",
125 "remove" : "Удалить",
126 "delete" : "Удалить",
127 + "add_new_node" : "Добавить новую ноду",
128
129
130 "use" : "Переключиться на ",
res/values/strings_uk.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "Ви впевнені, що хочете видалити поточний вузол?",
125 "remove" : "Видалити",
126 "delete" : "Видалити",
127 + "add_new_node" : "Додати новий вузол",
128
129
130 "use" : "Переключитися на ",
res/values/strings_zh.arb
+1
@@ -124,6 +124,7 @@
124 "remove_node_message" : "您确定要删除所选节点吗?",
125 "remove" : "去掉",
126 "delete" : "删除",
127 + "add_new_node" : "添加新節點",
128
129
130 "use" : "切換到 ",