Merge pull request #56 from cake-tech/CWA-202-update-node-list-screen

CWA-202 | applied new design to nodes_list_page and new_node_page; cr…
This commit is contained in:
Oleksandr Sobol 2020-05-07 14:00:01 +03:00 committed by GitHub
commit 68ac339540
29 changed files with 549 additions and 539 deletions

View file

@ -24,6 +24,7 @@ class S implements WidgetsLocalizations {
String get account => "Account"; String get account => "Account";
String get accounts => "Accounts"; String get accounts => "Accounts";
String get add => "Add"; String get add => "Add";
String get add_new_node => "Add new node";
String get add_new_word => "Add new word"; String get add_new_word => "Add new word";
String get address_book => "Address Book"; String get address_book => "Address Book";
String get address_book_menu => "Address book"; String get address_book_menu => "Address book";
@ -519,6 +520,8 @@ class $de extends S {
@override @override
String get remove => "Löschen"; String get remove => "Löschen";
@override @override
String get add_new_node => "Neuen Knoten hinzufügen";
@override
String get yesterday => "Gestern"; String get yesterday => "Gestern";
@override @override
String get expired => "Abgelaufen"; String get expired => "Abgelaufen";
@ -1101,6 +1104,8 @@ class $hi extends S {
@override @override
String get remove => "हटाना"; String get remove => "हटाना";
@override @override
String get add_new_node => "नया नोड जोड़ें";
@override
String get yesterday => "बिता कल"; String get yesterday => "बिता कल";
@override @override
String get expired => "समय सीमा समाप्त"; String get expired => "समय सीमा समाप्त";
@ -1683,6 +1688,8 @@ class $ru extends S {
@override @override
String get remove => "Удалить"; String get remove => "Удалить";
@override @override
String get add_new_node => "Добавить новую ноду";
@override
String get yesterday => "Вчера"; String get yesterday => "Вчера";
@override @override
String get expired => "Истекает"; String get expired => "Истекает";
@ -2265,6 +2272,8 @@ class $ko extends S {
@override @override
String get remove => "없애다"; String get remove => "없애다";
@override @override
String get add_new_node => "새 노드 추가";
@override
String get yesterday => "어제"; String get yesterday => "어제";
@override @override
String get expired => "만료"; String get expired => "만료";
@ -2847,6 +2856,8 @@ class $pt extends S {
@override @override
String get remove => "Remover"; String get remove => "Remover";
@override @override
String get add_new_node => "Adicionar novo nó";
@override
String get yesterday => "Ontem"; String get yesterday => "Ontem";
@override @override
String get expired => "Expirada"; String get expired => "Expirada";
@ -3429,6 +3440,8 @@ class $uk extends S {
@override @override
String get remove => "Видалити"; String get remove => "Видалити";
@override @override
String get add_new_node => "Додати новий вузол";
@override
String get yesterday => "Вчора"; String get yesterday => "Вчора";
@override @override
String get expired => "Закінчується"; String get expired => "Закінчується";
@ -4011,6 +4024,8 @@ class $ja extends S {
@override @override
String get remove => "削除する"; String get remove => "削除する";
@override @override
String get add_new_node => "新しいノードを追加";
@override
String get yesterday => "昨日"; String get yesterday => "昨日";
@override @override
String get expired => "期限切れ"; String get expired => "期限切れ";
@ -4597,6 +4612,8 @@ class $pl extends S {
@override @override
String get remove => "Usunąć"; String get remove => "Usunąć";
@override @override
String get add_new_node => "Dodaj nowy węzeł";
@override
String get yesterday => "Wczoraj"; String get yesterday => "Wczoraj";
@override @override
String get expired => "Przedawniony"; String get expired => "Przedawniony";
@ -5179,6 +5196,8 @@ class $es extends S {
@override @override
String get remove => "Retirar"; String get remove => "Retirar";
@override @override
String get add_new_node => "Agregar nuevo nodo";
@override
String get yesterday => "Ayer"; String get yesterday => "Ayer";
@override @override
String get expired => "Muerto"; String get expired => "Muerto";
@ -5761,6 +5780,8 @@ class $nl extends S {
@override @override
String get remove => "Verwijderen"; String get remove => "Verwijderen";
@override @override
String get add_new_node => "Voeg een nieuw knooppunt toe";
@override
String get yesterday => "Gisteren"; String get yesterday => "Gisteren";
@override @override
String get expired => "Verlopen"; String get expired => "Verlopen";
@ -6343,6 +6364,8 @@ class $zh extends S {
@override @override
String get remove => "去掉"; String get remove => "去掉";
@override @override
String get add_new_node => "添加新節點";
@override
String get yesterday => "昨天"; String get yesterday => "昨天";
@override @override
String get expired => "已过期"; String get expired => "已过期";

View file

@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/stores/wallet/wallet_store.dart'; import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart'; import 'package:cake_wallet/src/screens/auth/auth_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/reconnect_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
class WalletMenu { class WalletMenu {
WalletMenu(this.context); WalletMenu(this.context);
@ -40,7 +40,7 @@ class WalletMenu {
Navigator.of(context).pushNamed(Routes.walletList); Navigator.of(context).pushNamed(Routes.walletList);
break; break;
case 2: case 2:
// FIXME: apply Nodes Navigator.of(context).pushNamed(Routes.nodeList);
break; break;
case 3: case 3:
Navigator.of(context).pushNamed(Routes.auth, Navigator.of(context).pushNamed(Routes.auth,
@ -75,16 +75,16 @@ class WalletMenu {
await showDialog<void>( await showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return ReconnectAlertDialog( return AlertWithTwoActions(
reconnectTitleText: S.of(context).reconnection, alertTitle: S.of(context).reconnection,
reconnectContentText: S.of(context).reconnect_alert_text, alertContent: S.of(context).reconnect_alert_text,
reconnectLeftActionButtonText: S.of(context).ok, leftButtonText: S.of(context).ok,
reconnectRightActionButtonText: S.of(context).cancel, rightButtonText: S.of(context).cancel,
reconnectActionLeft: () { actionLeftButton: () {
walletStore.reconnect(); walletStore.reconnect();
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
reconnectActionRight: () => Navigator.of(context).pop() actionRightButton: () => Navigator.of(context).pop()
); );
}); });
} }

View file

@ -1,34 +0,0 @@
import 'dart:ui';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
import 'package:flutter/cupertino.dart';
class ReconnectAlertDialog extends BaseAlertDialog {
ReconnectAlertDialog({
@required this.reconnectTitleText,
@required this.reconnectContentText,
@required this.reconnectLeftActionButtonText,
@required this.reconnectRightActionButtonText,
@required this.reconnectActionLeft,
@required this.reconnectActionRight
});
final String reconnectTitleText;
final String reconnectContentText;
final String reconnectLeftActionButtonText;
final String reconnectRightActionButtonText;
final VoidCallback reconnectActionLeft;
final VoidCallback reconnectActionRight;
@override
String get titleText => reconnectTitleText;
@override
String get contentText => reconnectContentText;
@override
String get leftActionButtonText => reconnectLeftActionButtonText;
@override
String get rightActionButtonText => reconnectRightActionButtonText;
@override
VoidCallback get actionLeft => reconnectActionLeft;
@override
VoidCallback get actionRight => reconnectActionRight;
}

View file

@ -16,7 +16,7 @@ import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart'; import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/wallet_creation_dialog.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class NewWalletPage extends BasePage { class NewWalletPage extends BasePage {
NewWalletPage( NewWalletPage(
@ -90,11 +90,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (_) { builder: (_) {
return WalletCreationDialog( return AlertWithOneAction(
dialogTitle: S.current.new_wallet, alertTitle: S.current.new_wallet,
dialogContent: state.error, alertContent: state.error,
dialogButtonText: S.of(context).ok, buttonText: S.of(context).ok,
dialogButtonAction: () => Navigator.of(context).pop() buttonAction: () => Navigator.of(context).pop()
); );
}); });
}); });

View file

@ -1,56 +0,0 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
class WalletCreationDialog extends BaseAlertDialog {
WalletCreationDialog({
@required this.dialogTitle,
@required this.dialogContent,
@required this.dialogButtonText,
@required this.dialogButtonAction,
});
final String dialogTitle;
final String dialogContent;
final String dialogButtonText;
final VoidCallback dialogButtonAction;
@override
String get titleText => dialogTitle;
@override
String get contentText => dialogContent;
@override
Widget actionButtons(BuildContext context) {
return Container(
width: 300,
height: 52,
padding: EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)
),
color: Colors.white
),
child: ButtonTheme(
minWidth: double.infinity,
child: FlatButton(
onPressed: dialogButtonAction,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
child: Text(
dialogButtonText,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.blue,
decoration: TextDecoration.none,
),
)),
),
);
}
}

View file

@ -1,16 +1,21 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/stores/node_list/node_list_store.dart'; import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
class NewNodePage extends BasePage { class NewNodePage extends BasePage {
@override @override
String get title => S.current.node_new; String get title => S.current.node_new;
@override
Color get backgroundColor => PaletteDark.historyPanel;
@override @override
Widget body(BuildContext context) => NewNodePageForm(); Widget body(BuildContext context) => NewNodePageForm();
} }
@ -36,36 +41,53 @@ class NewNodeFormState extends State<NewNodePageForm> {
super.dispose(); super.dispose();
} }
void onHandleControllers(NodeListStore nodeListStore) {
if (_nodeAddressController.text.isNotEmpty &&
_nodePortController.text.isNotEmpty) {
nodeListStore.setDisabledState(false);
} else {
nodeListStore.setDisabledState(true);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final nodeList = Provider.of<NodeListStore>(context); final nodeList = Provider.of<NodeListStore>(context);
return Form( _nodeAddressController.addListener(() {onHandleControllers(nodeList);});
_nodePortController.addListener(() {onHandleControllers(nodeList);});
return Container(
color: PaletteDark.historyPanel,
padding: EdgeInsets.only(left: 24, right: 24),
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24.0),
content: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.only(left: 38.0, right: 38.0, top: 0),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Row( Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: TextFormField( child: TextFormField(
style: TextStyle(fontSize: 14.0), style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: hintStyle:
TextStyle(color: Palette.wildDarkBlue), TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).node_address, hintText: S.of(context).node_address,
focusedBorder: UnderlineInputBorder( focusedBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)), color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder( enabledBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Theme.of(context).focusColor, color: PaletteDark.menuList,
width: 1.0))), width: 1.0))),
controller: _nodeAddressController, controller: _nodeAddressController,
validator: (value) { validator: (value) {
@ -81,19 +103,26 @@ class NewNodeFormState extends State<NewNodePageForm> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: TextFormField( child: TextFormField(
style: TextStyle(fontSize: 14.0), style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
keyboardType: TextInputType.numberWithOptions( keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: false), signed: false, decimal: false),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: hintStyle:
TextStyle(color: Palette.wildDarkBlue), TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).node_port, hintText: S.of(context).node_port,
focusedBorder: UnderlineInputBorder( focusedBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)), color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder( enabledBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Theme.of(context).focusColor, color: PaletteDark.menuList,
width: 1.0))), width: 1.0))),
controller: _nodePortController, controller: _nodePortController,
validator: (value) { validator: (value) {
@ -109,17 +138,24 @@ class NewNodeFormState extends State<NewNodePageForm> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: TextFormField( child: TextFormField(
style: TextStyle(fontSize: 14.0), style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: hintStyle:
TextStyle(color: Palette.wildDarkBlue), TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).login, hintText: S.of(context).login,
focusedBorder: UnderlineInputBorder( focusedBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)), color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder( enabledBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Theme.of(context).focusColor, color: PaletteDark.menuList,
width: 1.0))), width: 1.0))),
controller: _loginController, controller: _loginController,
validator: (value) => null, validator: (value) => null,
@ -132,17 +168,24 @@ class NewNodeFormState extends State<NewNodePageForm> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: TextFormField( child: TextFormField(
style: TextStyle(fontSize: 14.0), style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration( decoration: InputDecoration(
hintStyle: hintStyle:
TextStyle(color: Palette.wildDarkBlue), TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).password, hintText: S.of(context).password,
focusedBorder: UnderlineInputBorder( focusedBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)), color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder( enabledBorder: UnderlineInputBorder(
borderSide: BorderSide( borderSide: BorderSide(
color: Theme.of(context).focusColor, color: PaletteDark.menuList,
width: 1.0))), width: 1.0))),
controller: _passwordController, controller: _passwordController,
validator: (value) => null, validator: (value) => null,
@ -151,12 +194,11 @@ class NewNodeFormState extends State<NewNodePageForm> {
], ],
) )
], ],
)
), ),
), bottomSectionPadding: EdgeInsets.only(bottom: 24),
)), bottomSection: Observer(
Container( builder: (_) => Row(
padding: EdgeInsets.only(bottom: 20.0, left: 20.0, right: 20.0),
child: Row(
children: <Widget>[ children: <Widget>[
Flexible( Flexible(
child: Container( child: Container(
@ -169,14 +211,8 @@ class NewNodeFormState extends State<NewNodePageForm> {
_passwordController.text = ''; _passwordController.text = '';
}, },
text: S.of(context).reset, text: S.of(context).reset,
color: Theme.of(context) color: Colors.red,
.accentTextTheme textColor: Colors.white),
.button
.backgroundColor,
textColor: Theme.of(context)
.primaryTextTheme
.button
.color),
)), )),
Flexible( Flexible(
child: Container( child: Container(
@ -196,20 +232,15 @@ class NewNodeFormState extends State<NewNodePageForm> {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
text: S.of(context).save, text: S.of(context).save,
color: Theme.of(context) color: Colors.green,
.primaryTextTheme textColor: Colors.white,
.button isDisabled: nodeList.disabledState,
.backgroundColor,
textColor: Theme.of(context)
.primaryTextTheme
.button
.color,
), ),
)), )),
], ],
)
), ),
) )
], );
));
} }
} }

View file

@ -5,10 +5,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/nodes/node_indicator.dart'; import 'package:cake_wallet/src/screens/nodes/widgets/node_indicator.dart';
import 'package:cake_wallet/src/stores/node_list/node_list_store.dart'; import 'package:cake_wallet/src/stores/node_list/node_list_store.dart';
import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
class NodeListPage extends BasePage { class NodeListPage extends BasePage {
NodeListPage(); NodeListPage();
@ -16,76 +18,50 @@ class NodeListPage extends BasePage {
@override @override
String get title => S.current.nodes; String get title => S.current.nodes;
@override
Color get backgroundColor => PaletteDark.historyPanel;
@override @override
Widget trailing(context) { Widget trailing(context) {
final nodeList = Provider.of<NodeListStore>(context); final nodeList = Provider.of<NodeListStore>(context);
final settings = Provider.of<SettingsStore>(context); final settings = Provider.of<SettingsStore>(context);
return Row( return Container(
mainAxisSize: MainAxisSize.min, height: 32,
children: <Widget>[ width: 72,
ButtonTheme( decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(16)),
color: PaletteDark.menuList
),
child: ButtonTheme(
minWidth: double.minPositive, minWidth: double.minPositive,
child: FlatButton( child: FlatButton(
onPressed: () async { onPressed: () async {
await showDialog<void>( await showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertWithTwoActions(
title: Text( alertTitle: S.of(context).node_reset_settings_title,
S.of(context).node_reset_settings_title, alertContent: S.of(context).nodes_list_reset_to_default_message,
textAlign: TextAlign.center, leftButtonText: S.of(context).reset,
), rightButtonText: S.of(context).cancel,
content: Text( actionLeftButton: () async {
S.of(context).nodes_list_reset_to_default_message, Navigator.of(context).pop();
textAlign: TextAlign.center,
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(S.of(context).cancel)),
FlatButton(
onPressed: () async {
Navigator.pop(context);
await nodeList.reset(); await nodeList.reset();
await settings.setCurrentNodeToDefault(); await settings.setCurrentNodeToDefault();
}, },
child: Text(S.of(context).reset)) actionRightButton: () => Navigator.of(context).pop()
],
); );
}); });
}, },
child: Text( child: Text(
S.of(context).reset, S.of(context).reset,
textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16.0, fontSize: 10.0,
color: Theme.of(context).primaryTextTheme.subtitle.color), color: Colors.blue),
)), )),
), ),
Container(
width: 28.0,
height: 28.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).selectedRowColor),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Icon(Icons.add, color: Palette.violet, size: 22.0),
ButtonTheme(
minWidth: 28.0,
height: 28.0,
child: FlatButton(
shape: CircleBorder(),
onPressed: () async =>
await Navigator.of(context).pushNamed(Routes.newNode),
child: Offstage()),
)
],
)),
],
); );
} }
@ -104,38 +80,59 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
final nodeList = Provider.of<NodeListStore>(context); final nodeList = Provider.of<NodeListStore>(context);
final settings = Provider.of<SettingsStore>(context); final settings = Provider.of<SettingsStore>(context);
final currentColor = Theme.of(context).selectedRowColor; final trashImage = Image.asset('assets/images/trash.png', height: 32, width: 32, color: Colors.white);
final notCurrentColor = Theme.of(context).backgroundColor;
final currentColor = PaletteDark.menuHeader;
final notCurrentColor = PaletteDark.menuList;
final currentTextColor = Colors.blue;
final notCurrentTextColor = Colors.white;
return Container( return Container(
padding: EdgeInsets.only(bottom: 20.0), height: double.infinity,
color: PaletteDark.historyPanel,
padding: EdgeInsets.only(top: 12),
child: Column( child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[ children: <Widget>[
Expanded(child: Observer(builder: (context) { NodeListRow(
return ListView.separated( title: S.of(context).add_new_node,
separatorBuilder: (_, __) => Divider( trailing: Icon(Icons.add, color: Colors.white, size: 24.0),
color: Theme.of(context).dividerTheme.color, height: 1), color: PaletteDark.menuList,
textColor: Colors.white,
onTap: () async =>
await Navigator.of(context).pushNamed(Routes.newNode),
isDrawTop: true,
isDrawBottom: true),
Expanded(
child: Padding(
padding: EdgeInsets.only(top: 32),
child: Observer(
builder: (_) => ListView.separated(
separatorBuilder: (_, __) => Container(
height: 1,
padding: EdgeInsets.only(left: 24),
color: PaletteDark.menuList,
child: Container(
height: 1,
color: PaletteDark.walletCardTopEndSync,
),
),
itemCount: nodeList.nodes.length, itemCount: nodeList.nodes.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
final node = nodeList.nodes[index]; final node = nodeList.nodes[index];
return Observer(builder: (_) { final isDrawTop = index == 0 ? true : false;
final isDrawBottom = index == nodeList.nodes.length - 1 ? true : false;
return Observer(
builder: (_) {
final isCurrent = settings.node == null final isCurrent = settings.node == null
? false ? false
: node.key == settings.node.key; : node.key == settings.node.key;
final content = Container( final content = NodeListRow(
color: isCurrent ? currentColor : notCurrentColor, title: node.uri,
child: ListTile(
title: Text(
node.uri,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.primaryTextTheme
.title
.color),
),
trailing: FutureBuilder( trailing: FutureBuilder(
future: nodeList.isNodeOnline(node), future: nodeList.isNodeOnline(node),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -149,36 +146,31 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
return NodeIndicator(); return NodeIndicator();
} }
}), }),
color: isCurrent ? currentColor : notCurrentColor,
textColor: isCurrent ? currentTextColor : notCurrentTextColor,
onTap: () async { onTap: () async {
if (!isCurrent) { if (!isCurrent) {
await showDialog<void>( await showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertWithTwoActions(
content: Text( alertTitle: S.current.nodes,
S alertContent: S.of(context)
.of(context)
.change_current_node(node.uri), .change_current_node(node.uri),
textAlign: TextAlign.center, leftButtonText: S.of(context).change,
), rightButtonText: S.of(context).cancel,
actions: <Widget>[ actionLeftButton: () async {
FlatButton(
onPressed: () =>
Navigator.pop(context),
child: Text(S.of(context).cancel)),
FlatButton(
onPressed: () async {
Navigator.of(context).pop(); Navigator.of(context).pop();
await settings.setCurrentNode( await settings.setCurrentNode(
node: node); node: node);
}, },
child: Text(S.of(context).change)), actionRightButton: () => Navigator.of(context).pop()
],
); );
}); });
} }
}, },
)); isDrawTop: isDrawTop,
isDrawBottom: isDrawBottom);
return isCurrent return isCurrent
? content ? content
@ -188,25 +180,15 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
return await showDialog( return await showDialog(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertWithTwoActions(
title: Text( alertTitle: S.of(context).remove_node,
S.of(context).remove_node, alertContent: S.of(context).remove_node_message,
textAlign: TextAlign.center, leftButtonText: S.of(context).remove,
), rightButtonText: S.of(context).cancel,
content: Text( actionLeftButton: () =>
S.of(context).remove_node_message,
textAlign: TextAlign.center,
),
actions: <Widget>[
FlatButton(
onPressed: () =>
Navigator.pop(context, false),
child: Text(S.of(context).cancel)),
FlatButton(
onPressed: () =>
Navigator.pop(context, true), Navigator.pop(context, true),
child: Text(S.of(context).remove)), actionRightButton: () =>
], Navigator.pop(context, false)
); );
}); });
}, },
@ -214,17 +196,12 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
await nodeList.remove(node: node), await nodeList.remove(node: node),
direction: DismissDirection.endToStart, direction: DismissDirection.endToStart,
background: Container( background: Container(
padding: EdgeInsets.only(right: 10.0), padding: EdgeInsets.only(right: 10.0, top: 2),
alignment: AlignmentDirectional.centerEnd, alignment: AlignmentDirectional.centerEnd,
color: Palette.red, color: Palette.red,
child: Column( child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
const Icon( trashImage,
CupertinoIcons.delete,
color: Colors.white,
),
Text( Text(
S.of(context).delete, S.of(context).delete,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
@ -232,9 +209,12 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
], ],
)), )),
child: content); child: content);
}); },
}); );
})) })
),
)
)
], ],
), ),
); );

View file

@ -9,8 +9,8 @@ class NodeIndicator extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
width: 10.0, width: 8.0,
height: 10.0, height: 8.0,
decoration: BoxDecoration(shape: BoxShape.circle, color: color), decoration: BoxDecoration(shape: BoxShape.circle, color: color),
); );
} }

View file

@ -0,0 +1,63 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
class NodeListRow extends StatelessWidget {
NodeListRow({
@required this.title,
@required this.trailing,
@required this.color,
@required this.textColor,
@required this.onTap,
@required this.isDrawTop,
@required this.isDrawBottom});
final String title;
final Widget trailing;
final Color color;
final Color textColor;
final VoidCallback onTap;
final bool isDrawTop;
final bool isDrawBottom;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
isDrawTop
? Container(
width: double.infinity,
height: 1,
color: PaletteDark.walletCardTopEndSync,
)
: Offstage(),
Container(
width: double.infinity,
height: 56,
color: color,
child: ListTile(
contentPadding: EdgeInsets.only(
left: 24,
right: 24,
),
title: Text(
title,
style: TextStyle(
fontSize: 14,
color: textColor
),
textAlign: TextAlign.left),
trailing: trailing,
onTap: onTap,
)
),
isDrawBottom
? Container(
width: double.infinity,
height: 1,
color: PaletteDark.walletCardTopEndSync,
)
: Offstage(),
],
);
}
}

View file

@ -16,7 +16,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart'; import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
import 'package:cake_wallet/src/screens/restore/widgets/restore_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class RestoreWalletFromKeysPage extends BasePage { class RestoreWalletFromKeysPage extends BasePage {
RestoreWalletFromKeysPage( RestoreWalletFromKeysPage(
@ -91,11 +91,11 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return RestoreAlertDialog( return AlertWithOneAction(
restoreTitle: S.current.restore_title_from_keys, alertTitle: S.current.restore_title_from_keys,
restoreContent: state.error, alertContent: state.error,
restoreButtonText: S.of(context).ok, buttonText: S.of(context).ok,
restoreButtonAction: () => Navigator.of(context).pop(), buttonAction: () => Navigator.of(context).pop()
); );
}); });
}); });

View file

@ -11,7 +11,7 @@ import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/restore/widgets/restore_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class RestoreWalletFromSeedDetailsPage extends BasePage { class RestoreWalletFromSeedDetailsPage extends BasePage {
@override @override
@ -64,11 +64,11 @@ class _RestoreFromSeedDetailsFormState
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return RestoreAlertDialog( return AlertWithOneAction(
restoreTitle: S.current.restore_wallet_restore_description, alertTitle: S.current.restore_title_from_seed,
restoreContent: state.error, alertContent: state.error,
restoreButtonText: S.of(context).ok, buttonText: S.of(context).ok,
restoreButtonAction: () => Navigator.of(context).pop(), buttonAction: () => Navigator.of(context).pop()
); );
}); });
}); });

View file

@ -8,7 +8,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/stores/settings/settings_store.dart'; import 'package:cake_wallet/src/stores/settings/settings_store.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/palette.dart'; import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/setup_pin_code/widgets/pin_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class SetupPinCodePage extends BasePage { class SetupPinCodePage extends BasePage {
SetupPinCodePage({this.onPinCodeSetup}); SetupPinCodePage({this.onPinCodeSetup});
@ -64,27 +64,28 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return PinAlertDialog( return AlertWithOneAction(
pinTitleText: S.current.setup_pin, alertTitle: S.current.setup_pin,
pinContentText: S.of(context).setup_successful, alertContent: S.of(context).setup_successful,
pinActionButtonText: S.of(context).ok, buttonText: S.of(context).ok,
pinBarrierDismissible: false, buttonAction: () {
pinAction: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
widget.onPinCodeSetup(context, pin); widget.onPinCodeSetup(context, pin);
reset(); reset();
}); },
alertBarrierDismissible: false,
);
}); });
} else { } else {
showDialog<void>( showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return PinAlertDialog( return AlertWithOneAction(
pinTitleText: S.current.setup_pin, alertTitle: S.current.setup_pin,
pinContentText: S.of(context).pin_is_incorrect, alertContent: S.of(context).pin_is_incorrect,
pinActionButtonText: S.of(context).ok, buttonText: S.of(context).ok,
pinBarrierDismissible: true, buttonAction: () => Navigator.of(context).pop()
pinAction: () => Navigator.of(context).pop()); );
}); });
reset(); reset();

View file

@ -1,60 +0,0 @@
import 'dart:ui';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class PinAlertDialog extends BaseAlertDialog {
PinAlertDialog({
@required this.pinTitleText,
@required this.pinContentText,
@required this.pinActionButtonText,
@required this.pinAction,
@required this.pinBarrierDismissible
});
final String pinTitleText;
final String pinContentText;
final String pinActionButtonText;
final VoidCallback pinAction;
final bool pinBarrierDismissible;
@override
String get titleText => pinTitleText;
@override
String get contentText => pinContentText;
@override
bool get barrierDismissible => pinBarrierDismissible;
@override
Widget actionButtons(BuildContext context) {
return Container(
width: 300,
height: 52,
padding: EdgeInsets.only(left: 12, right: 12),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)
),
color: Colors.white
),
child: ButtonTheme(
minWidth: double.infinity,
child: FlatButton(
onPressed: pinAction,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
child: Text(
pinActionButtonText,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: Colors.blue,
decoration: TextDecoration.none,
),
)),
),
);
}
}

View file

@ -12,6 +12,7 @@ class NodeListStore = NodeListBase with _$NodeListStore;
abstract class NodeListBase with Store { abstract class NodeListBase with Store {
NodeListBase({this.nodesSource}) { NodeListBase({this.nodesSource}) {
nodes = ObservableList<Node>(); nodes = ObservableList<Node>();
disabledState = true;
_onNodesChangeSubscription = nodesSource.watch().listen((e) => update()); _onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
update(); update();
} }
@ -25,6 +26,9 @@ abstract class NodeListBase with Store {
@observable @observable
String errorMessage; String errorMessage;
@observable
bool disabledState;
Box<Node> nodesSource; Box<Node> nodesSource;
StreamSubscription<BoxEvent> _onNodesChangeSubscription; StreamSubscription<BoxEvent> _onNodesChangeSubscription;
@ -61,6 +65,11 @@ abstract class NodeListBase with Store {
@action @action
Future reset() async => await resetToDefault(nodesSource); Future reset() async => await resetToDefault(nodesSource);
@action
void setDisabledState(bool isDisable) {
disabledState = isDisable;
}
Future<bool> isNodeOnline(Node node) async { Future<bool> isNodeOnline(Node node) async {
try { try {
return await node.requestNode(node.uri, return await node.requestNode(node.uri,

View file

@ -1,24 +1,29 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart'; import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
class RestoreAlertDialog extends BaseAlertDialog { class AlertWithOneAction extends BaseAlertDialog {
RestoreAlertDialog({ AlertWithOneAction({
@required this.restoreTitle, @required this.alertTitle,
@required this.restoreContent, @required this.alertContent,
@required this.restoreButtonText, @required this.buttonText,
@required this.restoreButtonAction, @required this.buttonAction,
this.alertBarrierDismissible = true
}); });
final String restoreTitle; final String alertTitle;
final String restoreContent; final String alertContent;
final String restoreButtonText; final String buttonText;
final VoidCallback restoreButtonAction; final VoidCallback buttonAction;
final bool alertBarrierDismissible;
@override @override
String get titleText => restoreTitle; String get titleText => alertTitle;
@override @override
String get contentText => restoreContent; String get contentText => alertContent;
@override
bool get barrierDismissible => alertBarrierDismissible;
@override @override
Widget actionButtons(BuildContext context) { Widget actionButtons(BuildContext context) {
@ -36,11 +41,11 @@ class RestoreAlertDialog extends BaseAlertDialog {
child: ButtonTheme( child: ButtonTheme(
minWidth: double.infinity, minWidth: double.infinity,
child: FlatButton( child: FlatButton(
onPressed: restoreButtonAction, onPressed: buttonAction,
highlightColor: Colors.transparent, highlightColor: Colors.transparent,
splashColor: Colors.transparent, splashColor: Colors.transparent,
child: Text( child: Text(
restoreButtonText, buttonText,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
@ -52,5 +57,4 @@ class RestoreAlertDialog extends BaseAlertDialog {
), ),
); );
} }
} }

View file

@ -0,0 +1,38 @@
import 'dart:ui';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
import 'package:flutter/cupertino.dart';
class AlertWithTwoActions extends BaseAlertDialog {
AlertWithTwoActions({
@required this.alertTitle,
@required this.alertContent,
@required this.leftButtonText,
@required this.rightButtonText,
@required this.actionLeftButton,
@required this.actionRightButton,
this.alertBarrierDismissible = true
});
final String alertTitle;
final String alertContent;
final String leftButtonText;
final String rightButtonText;
final VoidCallback actionLeftButton;
final VoidCallback actionRightButton;
final bool alertBarrierDismissible;
@override
String get titleText => alertTitle;
@override
String get contentText => alertContent;
@override
String get leftActionButtonText => leftButtonText;
@override
String get rightActionButtonText => rightButtonText;
@override
VoidCallback get actionLeft => actionLeftButton;
@override
VoidCallback get actionRight => actionRightButton;
@override
bool get barrierDismissible => alertBarrierDismissible;
}

View file

@ -134,7 +134,6 @@ class BaseAlertDialog extends StatelessWidget {
color: PaletteDark.menuHeader color: PaletteDark.menuHeader
), ),
child: Column( child: Column(
//mainAxisSize: MainAxisSize.max,
children: <Widget>[ children: <Widget>[
Container( Container(
width: 300, width: 300,

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Möchten Sie den ausgewählten Knoten wirklich entfernen?", "remove_node_message" : "Möchten Sie den ausgewählten Knoten wirklich entfernen?",
"remove" : "Löschen", "remove" : "Löschen",
"delete" : "Löschen", "delete" : "Löschen",
"add_new_node" : "Neuen Knoten hinzufügen",
"use" : "Wechseln zu ", "use" : "Wechseln zu ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Are you sure that you want to remove selected node?", "remove_node_message" : "Are you sure that you want to remove selected node?",
"remove" : "Remove", "remove" : "Remove",
"delete" : "Delete", "delete" : "Delete",
"add_new_node" : "Add new node",
"use" : "Switch to ", "use" : "Switch to ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "¿Está seguro de que desea eliminar el nodo seleccionado?", "remove_node_message" : "¿Está seguro de que desea eliminar el nodo seleccionado?",
"remove" : "Retirar", "remove" : "Retirar",
"delete" : "Borrar", "delete" : "Borrar",
"add_new_node" : "Agregar nuevo nodo",
"use" : "Cambiar a ", "use" : "Cambiar a ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?", "remove_node_message" : "क्या आप वाकई चयनित नोड को निकालना चाहते हैं?",
"remove" : "हटाना", "remove" : "हटाना",
"delete" : "हटाएं", "delete" : "हटाएं",
"add_new_node" : "नया नोड जोड़ें",
"use" : "पर स्विच ", "use" : "पर स्विच ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "選択したノードを削除してもよろしいですか?", "remove_node_message" : "選択したノードを削除してもよろしいですか?",
"remove" : "削除する", "remove" : "削除する",
"delete" : "削除する", "delete" : "削除する",
"add_new_node" : "新しいノードを追加",
"use" : "切り替える ", "use" : "切り替える ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "선택한 노드를 제거 하시겠습니까?", "remove_node_message" : "선택한 노드를 제거 하시겠습니까?",
"remove" : "없애다", "remove" : "없애다",
"delete" : "지우다", "delete" : "지우다",
"add_new_node" : "새 노드 추가",
"use" : "로 전환 ", "use" : "로 전환 ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?", "remove_node_message" : "Weet u zeker dat u het geselecteerde knooppunt wilt verwijderen?",
"remove" : "Verwijderen", "remove" : "Verwijderen",
"delete" : "Delete", "delete" : "Delete",
"add_new_node" : "Voeg een nieuw knooppunt toe",
"use" : "Overschakelen naar ", "use" : "Overschakelen naar ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Czy na pewno chcesz usunąć wybrany węzeł?", "remove_node_message" : "Czy na pewno chcesz usunąć wybrany węzeł?",
"remove" : "Usunąć", "remove" : "Usunąć",
"delete" : "Kasować", "delete" : "Kasować",
"add_new_node" : "Dodaj nowy węzeł",
"use" : "Przełącz na ", "use" : "Przełącz na ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Você realmente deseja remover o nó selecionado?", "remove_node_message" : "Você realmente deseja remover o nó selecionado?",
"remove" : "Remover", "remove" : "Remover",
"delete" : "Excluir", "delete" : "Excluir",
"add_new_node" : "Adicionar novo nó",
"use" : "Trocar para PIN de ", "use" : "Trocar para PIN de ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Вы уверены, что хотите удалить текущую ноду?", "remove_node_message" : "Вы уверены, что хотите удалить текущую ноду?",
"remove" : "Удалить", "remove" : "Удалить",
"delete" : "Удалить", "delete" : "Удалить",
"add_new_node" : "Добавить новую ноду",
"use" : "Переключиться на ", "use" : "Переключиться на ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "Ви впевнені, що хочете видалити поточний вузол?", "remove_node_message" : "Ви впевнені, що хочете видалити поточний вузол?",
"remove" : "Видалити", "remove" : "Видалити",
"delete" : "Видалити", "delete" : "Видалити",
"add_new_node" : "Додати новий вузол",
"use" : "Переключитися на ", "use" : "Переключитися на ",

View file

@ -124,6 +124,7 @@
"remove_node_message" : "您确定要删除所选节点吗?", "remove_node_message" : "您确定要删除所选节点吗?",
"remove" : "去掉", "remove" : "去掉",
"delete" : "删除", "delete" : "删除",
"add_new_node" : "添加新節點",
"use" : "切換到 ", "use" : "切換到 ",