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 accounts => "Accounts";
String get add => "Add";
String get add_new_node => "Add new node";
String get add_new_word => "Add new word";
String get address_book => "Address Book";
String get address_book_menu => "Address book";
@ -519,6 +520,8 @@ class $de extends S {
@override
String get remove => "Löschen";
@override
String get add_new_node => "Neuen Knoten hinzufügen";
@override
String get yesterday => "Gestern";
@override
String get expired => "Abgelaufen";
@ -1101,6 +1104,8 @@ class $hi extends S {
@override
String get remove => "हटाना";
@override
String get add_new_node => "नया नोड जोड़ें";
@override
String get yesterday => "बिता कल";
@override
String get expired => "समय सीमा समाप्त";
@ -1683,6 +1688,8 @@ class $ru extends S {
@override
String get remove => "Удалить";
@override
String get add_new_node => "Добавить новую ноду";
@override
String get yesterday => "Вчера";
@override
String get expired => "Истекает";
@ -2265,6 +2272,8 @@ class $ko extends S {
@override
String get remove => "없애다";
@override
String get add_new_node => "새 노드 추가";
@override
String get yesterday => "어제";
@override
String get expired => "만료";
@ -2847,6 +2856,8 @@ class $pt extends S {
@override
String get remove => "Remover";
@override
String get add_new_node => "Adicionar novo nó";
@override
String get yesterday => "Ontem";
@override
String get expired => "Expirada";
@ -3429,6 +3440,8 @@ class $uk extends S {
@override
String get remove => "Видалити";
@override
String get add_new_node => "Додати новий вузол";
@override
String get yesterday => "Вчора";
@override
String get expired => "Закінчується";
@ -4011,6 +4024,8 @@ class $ja extends S {
@override
String get remove => "削除する";
@override
String get add_new_node => "新しいノードを追加";
@override
String get yesterday => "昨日";
@override
String get expired => "期限切れ";
@ -4597,6 +4612,8 @@ class $pl extends S {
@override
String get remove => "Usunąć";
@override
String get add_new_node => "Dodaj nowy węzeł";
@override
String get yesterday => "Wczoraj";
@override
String get expired => "Przedawniony";
@ -5179,6 +5196,8 @@ class $es extends S {
@override
String get remove => "Retirar";
@override
String get add_new_node => "Agregar nuevo nodo";
@override
String get yesterday => "Ayer";
@override
String get expired => "Muerto";
@ -5761,6 +5780,8 @@ class $nl extends S {
@override
String get remove => "Verwijderen";
@override
String get add_new_node => "Voeg een nieuw knooppunt toe";
@override
String get yesterday => "Gisteren";
@override
String get expired => "Verlopen";
@ -6343,6 +6364,8 @@ class $zh extends S {
@override
String get remove => "去掉";
@override
String get add_new_node => "添加新節點";
@override
String get yesterday => "昨天";
@override
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/src/stores/wallet/wallet_store.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 {
WalletMenu(this.context);
@ -40,7 +40,7 @@ class WalletMenu {
Navigator.of(context).pushNamed(Routes.walletList);
break;
case 2:
// FIXME: apply Nodes
Navigator.of(context).pushNamed(Routes.nodeList);
break;
case 3:
Navigator.of(context).pushNamed(Routes.auth,
@ -75,16 +75,16 @@ class WalletMenu {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return ReconnectAlertDialog(
reconnectTitleText: S.of(context).reconnection,
reconnectContentText: S.of(context).reconnect_alert_text,
reconnectLeftActionButtonText: S.of(context).ok,
reconnectRightActionButtonText: S.of(context).cancel,
reconnectActionLeft: () {
walletStore.reconnect();
Navigator.of(context).pop();
},
reconnectActionRight: () => Navigator.of(context).pop()
return AlertWithTwoActions(
alertTitle: S.of(context).reconnection,
alertContent: S.of(context).reconnect_alert_text,
leftButtonText: S.of(context).ok,
rightButtonText: S.of(context).cancel,
actionLeftButton: () {
walletStore.reconnect();
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/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/new_wallet/widgets/wallet_creation_dialog.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class NewWalletPage extends BasePage {
NewWalletPage(
@ -90,11 +90,11 @@ class _WalletNameFormState extends State<WalletNameForm> {
showDialog<void>(
context: context,
builder: (_) {
return WalletCreationDialog(
dialogTitle: S.current.new_wallet,
dialogContent: state.error,
dialogButtonText: S.of(context).ok,
dialogButtonAction: () => Navigator.of(context).pop()
return AlertWithOneAction(
alertTitle: S.current.new_wallet,
alertContent: state.error,
buttonText: S.of(context).ok,
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/cupertino.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:provider/provider.dart';
import 'package:cake_wallet/palette.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/widgets/primary_button.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 {
@override
String get title => S.current.node_new;
@override
Color get backgroundColor => PaletteDark.historyPanel;
@override
Widget body(BuildContext context) => NewNodePageForm();
}
@ -36,130 +41,167 @@ class NewNodeFormState extends State<NewNodePageForm> {
super.dispose();
}
void onHandleControllers(NodeListStore nodeListStore) {
if (_nodeAddressController.text.isNotEmpty &&
_nodePortController.text.isNotEmpty) {
nodeListStore.setDisabledState(false);
} else {
nodeListStore.setDisabledState(true);
}
}
@override
Widget build(BuildContext context) {
final nodeList = Provider.of<NodeListStore>(context);
return Form(
key: _formKey,
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>[
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(fontSize: 14.0),
decoration: InputDecoration(
hintStyle:
TextStyle(color: Palette.wildDarkBlue),
hintText: S.of(context).node_address,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0))),
controller: _nodeAddressController,
validator: (value) {
nodeList.validateNodeAddress(value);
return nodeList.errorMessage;
},
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(fontSize: 14.0),
keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: false),
decoration: InputDecoration(
hintStyle:
TextStyle(color: Palette.wildDarkBlue),
hintText: S.of(context).node_port,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0))),
controller: _nodePortController,
validator: (value) {
nodeList.validateNodePort(value);
return nodeList.errorMessage;
},
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(fontSize: 14.0),
decoration: InputDecoration(
hintStyle:
TextStyle(color: Palette.wildDarkBlue),
hintText: S.of(context).login,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0))),
controller: _loginController,
validator: (value) => null,
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(fontSize: 14.0),
decoration: InputDecoration(
hintStyle:
TextStyle(color: Palette.wildDarkBlue),
hintText: S.of(context).password,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0))),
controller: _passwordController,
validator: (value) => null,
),
)
],
)
],
),
),
)),
Container(
padding: EdgeInsets.only(bottom: 20.0, left: 20.0, right: 20.0),
child: Row(
_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,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Flexible(
child: Container(
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration(
hintStyle:
TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).node_address,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0))),
controller: _nodeAddressController,
validator: (value) {
nodeList.validateNodeAddress(value);
return nodeList.errorMessage;
},
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
keyboardType: TextInputType.numberWithOptions(
signed: false, decimal: false),
decoration: InputDecoration(
hintStyle:
TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).node_port,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0))),
controller: _nodePortController,
validator: (value) {
nodeList.validateNodePort(value);
return nodeList.errorMessage;
},
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration(
hintStyle:
TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).login,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0))),
controller: _loginController,
validator: (value) => null,
),
)
],
),
SizedBox(height: 10.0),
Row(
children: <Widget>[
Expanded(
child: TextFormField(
style: TextStyle(
fontSize: 16.0,
color: Colors.white
),
decoration: InputDecoration(
hintStyle:
TextStyle(
color: PaletteDark.walletCardText,
fontSize: 16
),
hintText: S.of(context).password,
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: PaletteDark.menuList,
width: 1.0))),
controller: _passwordController,
validator: (value) => null,
),
)
],
)
],
)
),
bottomSectionPadding: EdgeInsets.only(bottom: 24),
bottomSection: Observer(
builder: (_) => Row(
children: <Widget>[
Flexible(
child: Container(
padding: EdgeInsets.only(right: 8.0),
child: PrimaryButton(
onPressed: () {
@ -169,17 +211,11 @@ class NewNodeFormState extends State<NewNodePageForm> {
_passwordController.text = '';
},
text: S.of(context).reset,
color: Theme.of(context)
.accentTextTheme
.button
.backgroundColor,
textColor: Theme.of(context)
.primaryTextTheme
.button
.color),
color: Colors.red,
textColor: Colors.white),
)),
Flexible(
child: Container(
Flexible(
child: Container(
padding: EdgeInsets.only(left: 8.0),
child: PrimaryButton(
onPressed: () async {
@ -196,20 +232,15 @@ class NewNodeFormState extends State<NewNodePageForm> {
Navigator.of(context).pop();
},
text: S.of(context).save,
color: Theme.of(context)
.primaryTextTheme
.button
.backgroundColor,
textColor: Theme.of(context)
.primaryTextTheme
.button
.color,
color: Colors.green,
textColor: Colors.white,
isDisabled: nodeList.disabledState,
),
)),
],
),
)
],
));
],
)
),
)
);
}
}

View file

@ -5,10 +5,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/palette.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/settings/settings_store.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 {
NodeListPage();
@ -16,76 +18,50 @@ class NodeListPage extends BasePage {
@override
String get title => S.current.nodes;
@override
Color get backgroundColor => PaletteDark.historyPanel;
@override
Widget trailing(context) {
final nodeList = Provider.of<NodeListStore>(context);
final settings = Provider.of<SettingsStore>(context);
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ButtonTheme(
minWidth: double.minPositive,
child: FlatButton(
onPressed: () async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
S.of(context).node_reset_settings_title,
textAlign: TextAlign.center,
),
content: Text(
S.of(context).nodes_list_reset_to_default_message,
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 settings.setCurrentNodeToDefault();
},
child: Text(S.of(context).reset))
],
);
});
},
child: Text(
S.of(context).reset,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context).primaryTextTheme.subtitle.color),
)),
),
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()),
)
],
return Container(
height: 32,
width: 72,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(16)),
color: PaletteDark.menuList
),
child: ButtonTheme(
minWidth: double.minPositive,
child: FlatButton(
onPressed: () async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).node_reset_settings_title,
alertContent: S.of(context).nodes_list_reset_to_default_message,
leftButtonText: S.of(context).reset,
rightButtonText: S.of(context).cancel,
actionLeftButton: () async {
Navigator.of(context).pop();
await nodeList.reset();
await settings.setCurrentNodeToDefault();
},
actionRightButton: () => Navigator.of(context).pop()
);
});
},
child: Text(
S.of(context).reset,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 10.0,
color: Colors.blue),
)),
],
),
);
}
@ -104,137 +80,141 @@ class NodeListPageBodyState extends State<NodeListPageBody> {
final nodeList = Provider.of<NodeListStore>(context);
final settings = Provider.of<SettingsStore>(context);
final currentColor = Theme.of(context).selectedRowColor;
final notCurrentColor = Theme.of(context).backgroundColor;
final trashImage = Image.asset('assets/images/trash.png', height: 32, width: 32, color: Colors.white);
final currentColor = PaletteDark.menuHeader;
final notCurrentColor = PaletteDark.menuList;
final currentTextColor = Colors.blue;
final notCurrentTextColor = Colors.white;
return Container(
padding: EdgeInsets.only(bottom: 20.0),
height: double.infinity,
color: PaletteDark.historyPanel,
padding: EdgeInsets.only(top: 12),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(child: Observer(builder: (context) {
return ListView.separated(
separatorBuilder: (_, __) => Divider(
color: Theme.of(context).dividerTheme.color, height: 1),
itemCount: nodeList.nodes.length,
itemBuilder: (BuildContext context, int index) {
final node = nodeList.nodes[index];
NodeListRow(
title: S.of(context).add_new_node,
trailing: Icon(Icons.add, color: Colors.white, size: 24.0),
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,
itemBuilder: (BuildContext context, int index) {
final node = nodeList.nodes[index];
return Observer(builder: (_) {
final isCurrent = settings.node == null
? false
: node.key == settings.node.key;
final isDrawTop = index == 0 ? true : false;
final isDrawBottom = index == nodeList.nodes.length - 1 ? true : false;
final content = Container(
color: isCurrent ? currentColor : notCurrentColor,
child: ListTile(
title: Text(
node.uri,
style: TextStyle(
fontSize: 16.0,
color: Theme.of(context)
.primaryTextTheme
.title
.color),
),
trailing: FutureBuilder(
future: nodeList.isNodeOnline(node),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return NodeIndicator(
color: snapshot.data as bool
? Palette.green
: Palette.red);
default:
return NodeIndicator();
}
}),
onTap: () async {
if (!isCurrent) {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Text(
S
.of(context)
.change_current_node(node.uri),
textAlign: TextAlign.center,
),
actions: <Widget>[
FlatButton(
onPressed: () =>
Navigator.pop(context),
child: Text(S.of(context).cancel)),
FlatButton(
onPressed: () async {
return Observer(
builder: (_) {
final isCurrent = settings.node == null
? false
: node.key == settings.node.key;
final content = NodeListRow(
title: node.uri,
trailing: FutureBuilder(
future: nodeList.isNodeOnline(node),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
return NodeIndicator(
color: snapshot.data as bool
? Palette.green
: Palette.red);
default:
return NodeIndicator();
}
}),
color: isCurrent ? currentColor : notCurrentColor,
textColor: isCurrent ? currentTextColor : notCurrentTextColor,
onTap: () async {
if (!isCurrent) {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.current.nodes,
alertContent: S.of(context)
.change_current_node(node.uri),
leftButtonText: S.of(context).change,
rightButtonText: S.of(context).cancel,
actionLeftButton: () async {
Navigator.of(context).pop();
await settings.setCurrentNode(
node: node);
},
child: Text(S.of(context).change)),
],
);
});
}
},
));
actionRightButton: () => Navigator.of(context).pop()
);
});
}
},
isDrawTop: isDrawTop,
isDrawBottom: isDrawBottom);
return isCurrent
? content
: Dismissible(
key: Key('${node.key}'),
confirmDismiss: (direction) async {
return await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
S.of(context).remove_node,
textAlign: TextAlign.center,
),
content: Text(
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),
child: Text(S.of(context).remove)),
],
);
});
},
onDismissed: (direction) async =>
await nodeList.remove(node: node),
direction: DismissDirection.endToStart,
background: Container(
padding: EdgeInsets.only(right: 10.0),
alignment: AlignmentDirectional.centerEnd,
color: Palette.red,
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
const Icon(
CupertinoIcons.delete,
color: Colors.white,
),
Text(
S.of(context).delete,
style: TextStyle(color: Colors.white),
)
],
)),
child: content);
});
});
}))
return isCurrent
? content
: Dismissible(
key: Key('${node.key}'),
confirmDismiss: (direction) async {
return await showDialog(
context: context,
builder: (BuildContext context) {
return AlertWithTwoActions(
alertTitle: S.of(context).remove_node,
alertContent: S.of(context).remove_node_message,
leftButtonText: S.of(context).remove,
rightButtonText: S.of(context).cancel,
actionLeftButton: () =>
Navigator.pop(context, true),
actionRightButton: () =>
Navigator.pop(context, false)
);
});
},
onDismissed: (direction) async =>
await nodeList.remove(node: node),
direction: DismissDirection.endToStart,
background: Container(
padding: EdgeInsets.only(right: 10.0, top: 2),
alignment: AlignmentDirectional.centerEnd,
color: Palette.red,
child: Column(
children: <Widget>[
trashImage,
Text(
S.of(context).delete,
style: TextStyle(color: Colors.white),
)
],
)),
child: content);
},
);
})
),
)
)
],
),
);

View file

@ -9,8 +9,8 @@ class NodeIndicator extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 10.0,
height: 10.0,
width: 8.0,
height: 8.0,
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/palette.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 {
RestoreWalletFromKeysPage(
@ -91,11 +91,11 @@ class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return RestoreAlertDialog(
restoreTitle: S.current.restore_title_from_keys,
restoreContent: state.error,
restoreButtonText: S.of(context).ok,
restoreButtonAction: () => Navigator.of(context).pop(),
return AlertWithOneAction(
alertTitle: S.current.restore_title_from_keys,
alertContent: state.error,
buttonText: S.of(context).ok,
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/primary_button.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 {
@override
@ -64,11 +64,11 @@ class _RestoreFromSeedDetailsFormState
showDialog<void>(
context: context,
builder: (BuildContext context) {
return RestoreAlertDialog(
restoreTitle: S.current.restore_wallet_restore_description,
restoreContent: state.error,
restoreButtonText: S.of(context).ok,
restoreButtonAction: () => Navigator.of(context).pop(),
return AlertWithOneAction(
alertTitle: S.current.restore_title_from_seed,
alertContent: state.error,
buttonText: S.of(context).ok,
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/generated/i18n.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 {
SetupPinCodePage({this.onPinCodeSetup});
@ -64,27 +64,28 @@ class _SetupPinCodeFormState<WidgetType extends SetupPinCodeForm>
showDialog<void>(
context: context,
builder: (BuildContext context) {
return PinAlertDialog(
pinTitleText: S.current.setup_pin,
pinContentText: S.of(context).setup_successful,
pinActionButtonText: S.of(context).ok,
pinBarrierDismissible: false,
pinAction: () {
return AlertWithOneAction(
alertTitle: S.current.setup_pin,
alertContent: S.of(context).setup_successful,
buttonText: S.of(context).ok,
buttonAction: () {
Navigator.of(context).pop();
widget.onPinCodeSetup(context, pin);
reset();
});
},
alertBarrierDismissible: false,
);
});
} else {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return PinAlertDialog(
pinTitleText: S.current.setup_pin,
pinContentText: S.of(context).pin_is_incorrect,
pinActionButtonText: S.of(context).ok,
pinBarrierDismissible: true,
pinAction: () => Navigator.of(context).pop());
return AlertWithOneAction(
alertTitle: S.current.setup_pin,
alertContent: S.of(context).pin_is_incorrect,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop()
);
});
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 {
NodeListBase({this.nodesSource}) {
nodes = ObservableList<Node>();
disabledState = true;
_onNodesChangeSubscription = nodesSource.watch().listen((e) => update());
update();
}
@ -25,6 +26,9 @@ abstract class NodeListBase with Store {
@observable
String errorMessage;
@observable
bool disabledState;
Box<Node> nodesSource;
StreamSubscription<BoxEvent> _onNodesChangeSubscription;
@ -61,6 +65,11 @@ abstract class NodeListBase with Store {
@action
Future reset() async => await resetToDefault(nodesSource);
@action
void setDisabledState(bool isDisable) {
disabledState = isDisable;
}
Future<bool> isNodeOnline(Node node) async {
try {
return await node.requestNode(node.uri,

View file

@ -1,24 +1,29 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/base_alert_dialog.dart';
class RestoreAlertDialog extends BaseAlertDialog {
RestoreAlertDialog({
@required this.restoreTitle,
@required this.restoreContent,
@required this.restoreButtonText,
@required this.restoreButtonAction,
class AlertWithOneAction extends BaseAlertDialog {
AlertWithOneAction({
@required this.alertTitle,
@required this.alertContent,
@required this.buttonText,
@required this.buttonAction,
this.alertBarrierDismissible = true
});
final String restoreTitle;
final String restoreContent;
final String restoreButtonText;
final VoidCallback restoreButtonAction;
final String alertTitle;
final String alertContent;
final String buttonText;
final VoidCallback buttonAction;
final bool alertBarrierDismissible;
@override
String get titleText => restoreTitle;
String get titleText => alertTitle;
@override
String get contentText => restoreContent;
String get contentText => alertContent;
@override
bool get barrierDismissible => alertBarrierDismissible;
@override
Widget actionButtons(BuildContext context) {
@ -36,11 +41,11 @@ class RestoreAlertDialog extends BaseAlertDialog {
child: ButtonTheme(
minWidth: double.infinity,
child: FlatButton(
onPressed: restoreButtonAction,
onPressed: buttonAction,
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
child: Text(
restoreButtonText,
buttonText,
textAlign: TextAlign.center,
style: TextStyle(
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
),
child: Column(
//mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
width: 300,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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