CWA-215 | added cryptocurrency icons to address book; applied new design to contact page; added suffixIcon parameter to base text form field; fixed seed widget

This commit is contained in:
Oleksandr Sobol 2020-05-20 20:28:01 +03:00
parent 3f1bb416d4
commit 3a8bae74e4
16 changed files with 243 additions and 241 deletions

BIN
assets/images/ada.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/images/bch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/images/bnb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/images/dash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/images/eos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
assets/images/eth.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/images/nano.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/images/trx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
assets/images/usdt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
assets/images/xlm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
assets/images/xrp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -216,43 +216,43 @@ class AddressBookPage extends BasePage {
image = Image.asset('assets/images/monero.png', height: 24, width: 24); image = Image.asset('assets/images/monero.png', height: 24, width: 24);
break; break;
case CryptoCurrency.ada: case CryptoCurrency.ada:
image = null; image = Image.asset('assets/images/ada.png', height: 24, width: 24);
break; break;
case CryptoCurrency.bch: case CryptoCurrency.bch:
image = null; image = Image.asset('assets/images/bch.png', height: 24, width: 24);
break; break;
case CryptoCurrency.bnb: case CryptoCurrency.bnb:
image = null; image = Image.asset('assets/images/bnb.png', height: 24, width: 24);
break; break;
case CryptoCurrency.btc: case CryptoCurrency.btc:
image = Image.asset('assets/images/bitcoin.png', height: 24, width: 24); image = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
break; break;
case CryptoCurrency.dash: case CryptoCurrency.dash:
image = null; image = Image.asset('assets/images/dash.png', height: 24, width: 24);
break; break;
case CryptoCurrency.eos: case CryptoCurrency.eos:
image = null; image = Image.asset('assets/images/eos.png', height: 24, width: 24);
break; break;
case CryptoCurrency.eth: case CryptoCurrency.eth:
image = null; image = Image.asset('assets/images/eth.png', height: 24, width: 24);
break; break;
case CryptoCurrency.ltc: case CryptoCurrency.ltc:
image = Image.asset('assets/images/litecoin.png', height: 24, width: 24); image = Image.asset('assets/images/litecoin.png', height: 24, width: 24);
break; break;
case CryptoCurrency.nano: case CryptoCurrency.nano:
image = null; image = Image.asset('assets/images/nano.png', height: 24, width: 24);
break; break;
case CryptoCurrency.trx: case CryptoCurrency.trx:
image = null; image = Image.asset('assets/images/trx.png', height: 24, width: 24);
break; break;
case CryptoCurrency.usdt: case CryptoCurrency.usdt:
image = null; image = Image.asset('assets/images/usdt.png', height: 24, width: 24);
break; break;
case CryptoCurrency.xlm: case CryptoCurrency.xlm:
image = null; image = Image.asset('assets/images/xlm.png', height: 24, width: 24);
break; break;
case CryptoCurrency.xrp: case CryptoCurrency.xrp:
image = null; image = Image.asset('assets/images/xrp.png', height: 24, width: 24);
break; break;
default: default:
image = null; image = null;

View file

@ -1,5 +1,6 @@
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/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/domain/common/crypto_currency.dart'; import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
@ -10,6 +11,9 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/address_text_field.dart'; import 'package:cake_wallet/src/widgets/address_text_field.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/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
class ContactPage extends BasePage { class ContactPage extends BasePage {
ContactPage({this.contact}); ContactPage({this.contact});
@ -19,6 +23,9 @@ class ContactPage extends BasePage {
@override @override
String get title => S.current.contact; String get title => S.current.contact;
@override
Color get backgroundColor => PaletteDark.historyPanel;
@override @override
Widget body(BuildContext context) => ContactForm(contact); Widget body(BuildContext context) => ContactForm(contact);
} }
@ -37,22 +44,31 @@ class ContactFormState extends State<ContactForm> {
final _contactNameController = TextEditingController(); final _contactNameController = TextEditingController();
final _currencyTypeController = TextEditingController(); final _currencyTypeController = TextEditingController();
final _addressController = TextEditingController(); final _addressController = TextEditingController();
final currencies = CryptoCurrency.all;
final downArrow = Image.asset(
'assets/images/arrow_bottom_purple_icon.png',
color: PaletteDark.walletCardText,
height: 8);
CryptoCurrency _selectectCrypto = CryptoCurrency.xmr; CryptoCurrency _selectectCrypto;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.contact == null) { if (widget.contact != null) {
_currencyTypeController.text = _selectectCrypto.toString();
} else {
_selectectCrypto = widget.contact.type; _selectectCrypto = widget.contact.type;
_contactNameController.text = widget.contact.name; _contactNameController.text = widget.contact.name;
_currencyTypeController.text = _selectectCrypto.toString(); _currencyTypeController.text = _selectectCrypto.toString();
_addressController.text = widget.contact.address; _addressController.text = widget.contact.address;
WidgetsBinding.instance.addPostFrameCallback(afterLayout);
} }
} }
void afterLayout(dynamic _) {
final addressBookStore = Provider.of<AddressBookStore>(context);
addressBookStore.setDisabledStatus(false);
}
@override @override
void dispose() { void dispose() {
_contactNameController.dispose(); _contactNameController.dispose();
@ -61,113 +77,67 @@ class ContactFormState extends State<ContactForm> {
super.dispose(); super.dispose();
} }
Future<void> _setCurrencyType(BuildContext context) async { void onHandleControllers(AddressBookStore addressBookStore) {
var currencyType = CryptoCurrency.all[0].toString(); if (_contactNameController.text.isNotEmpty &&
var selectedCurrency = CryptoCurrency.all[0]; _addressController.text.isNotEmpty &&
_currencyTypeController.text.isNotEmpty) {
await showDialog<void>( addressBookStore.setDisabledStatus(false);
context: context, } else {
builder: (BuildContext context) { addressBookStore.setDisabledStatus(true);
return AlertDialog( }
title: Text(S.of(context).please_select),
backgroundColor: Theme.of(context).backgroundColor,
content: Container(
height: 150.0,
child: CupertinoPicker(
backgroundColor: Theme.of(context).backgroundColor,
itemExtent: 45.0,
onSelectedItemChanged: (int index) {
selectedCurrency = CryptoCurrency.all[index];
currencyType = CryptoCurrency.all[index].toString();
},
children:
List.generate(CryptoCurrency.all.length, (int index) {
return Center(
child: Text(
CryptoCurrency.all[index].toString(),
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme
.caption
.color),
),
);
})),
),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(S.of(context).cancel)),
FlatButton(
onPressed: () {
_selectectCrypto = selectedCurrency;
_currencyTypeController.text = currencyType;
Navigator.of(context).pop();
},
child: Text(S.of(context).ok))
],
);
});
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final addressBookStore = Provider.of<AddressBookStore>(context); final addressBookStore = Provider.of<AddressBookStore>(context);
return ScrollableWithBottomSection( _contactNameController.addListener(() {onHandleControllers(addressBookStore);});
_currencyTypeController.addListener(() {onHandleControllers(addressBookStore);});
_addressController.addListener(() {onHandleControllers(addressBookStore);});
return Container(
color: PaletteDark.historyPanel,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.all(24),
content: Form( content: Form(
key: _formKey, key: _formKey,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
TextFormField( BaseTextFormField(
style: TextStyle(
fontSize: 14.0,
color: Theme.of(context).primaryTextTheme.headline.color),
decoration: InputDecoration(
hintStyle: TextStyle(color: Theme.of(context).hintColor),
hintText: S.of(context).contact_name,
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor, width: 1.0))),
controller: _contactNameController, controller: _contactNameController,
hintText: S.of(context).contact_name,
borderColor: PaletteDark.walletCardSubAddressField,
validator: (value) { validator: (value) {
addressBookStore.validateContactName(value); addressBookStore.validateContactName(value);
return addressBookStore.errorMessage; return addressBookStore.errorMessage;
}, }
), ),
SizedBox(height: 14.0), Padding(
Container( padding: EdgeInsets.only(top: 20),
child: Container(
child: InkWell( child: InkWell(
onTap: () => _setCurrencyType(context), onTap: () => _presentPicker(context),
child: IgnorePointer( child: IgnorePointer(
child: TextFormField( child: BaseTextFormField(
style: TextStyle(
fontSize: 14.0,
color: Theme.of(context)
.primaryTextTheme
.headline
.color),
decoration: InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.cakeGreen, width: 2.0)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0))),
controller: _currencyTypeController, controller: _currencyTypeController,
hintText: S.of(context).settings_currency,
borderColor: PaletteDark.walletCardSubAddressField,
suffixIcon: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
downArrow
],
),
)
), ),
), ),
), ),
), ),
SizedBox(height: 14.0), Padding(
AddressTextField( padding: EdgeInsets.only(top: 20),
child: AddressTextField(
controller: _addressController, controller: _addressController,
options: [AddressTextFieldOption.qrCode], options: [AddressTextFieldOption.qrCode],
validator: (value) { validator: (value) {
@ -175,32 +145,37 @@ class ContactFormState extends State<ContactForm> {
cryptoCurrency: _selectectCrypto); cryptoCurrency: _selectectCrypto);
return addressBookStore.errorMessage; return addressBookStore.errorMessage;
}, },
),
) )
], ],
), ),
), ),
bottomSectionPadding: EdgeInsets.only(
left: 24,
right: 24,
bottom: 24
),
bottomSection: Row( bottomSection: Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: PrimaryButton( child: PrimaryButton(
onPressed: () { onPressed: () {
setState(() { setState(() {
_selectectCrypto = CryptoCurrency.xmr; _selectectCrypto = null;
_contactNameController.text = ''; _contactNameController.text = '';
_currencyTypeController.text = _currencyTypeController.text = '';
_selectectCrypto.toString();
_addressController.text = ''; _addressController.text = '';
}); });
}, },
text: S.of(context).reset, text: S.of(context).reset,
color: color: Colors.red,
Theme.of(context).accentTextTheme.button.backgroundColor, textColor: Colors.white
textColor: ),
Theme.of(context).primaryTextTheme.button.color),
), ),
SizedBox(width: 20), SizedBox(width: 20),
Expanded( Expanded(
child: PrimaryButton( child: Observer(
builder: (_) => PrimaryButton(
onPressed: () async { onPressed: () async {
if (!_formKey.currentState.validate()) { if (!_formKey.currentState.validate()) {
return; return;
@ -228,31 +203,38 @@ class ContactFormState extends State<ContactForm> {
await showDialog<void>( await showDialog<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertWithOneAction(
title: Text( alertTitle: S.current.contact,
e.toString(), alertContent: e.toString(),
textAlign: TextAlign.center, buttonText: S.of(context).ok,
), buttonAction: () => Navigator.of(context).pop()
actions: <Widget>[
FlatButton(
onPressed: () =>
Navigator.of(context).pop(),
child: Text(S.of(context).ok))
],
); );
}); });
} }
}, },
text: S.of(context).save, text: S.of(context).save,
color: Theme.of(context) color: Colors.green,
.primaryTextTheme textColor: Colors.white,
.button isDisabled: addressBookStore.isDisabledStatus,
.backgroundColor, )
textColor: Theme.of(context) )
.primaryTextTheme )
.button
.color))
], ],
)); )),
);
}
void _presentPicker(BuildContext context) {
showDialog<void>(
builder: (_) => CurrencyPicker(
selectedAtIndex: currencies.indexOf(_selectectCrypto),
items: currencies,
title: S.of(context).please_select,
onItemSelected: (CryptoCurrency item) {
_selectectCrypto = item;
_currencyTypeController.text = _selectectCrypto.toString();
}
),
context: context);
} }
} }

View file

@ -12,11 +12,15 @@ class AddressBookStore = AddressBookStoreBase with _$AddressBookStore;
abstract class AddressBookStoreBase with Store { abstract class AddressBookStoreBase with Store {
AddressBookStoreBase({@required this.contacts}) { AddressBookStoreBase({@required this.contacts}) {
updateContactList(); updateContactList();
isDisabledStatus = true;
} }
@observable @observable
List<Contact> contactList; List<Contact> contactList;
@observable
bool isDisabledStatus;
@observable @observable
bool isValid; bool isValid;
@ -37,6 +41,11 @@ abstract class AddressBookStoreBase with Store {
@action @action
Future delete({Contact contact}) async => await contact.delete(); Future delete({Contact contact}) async => await contact.delete();
@action
void setDisabledStatus(bool isDisabled) {
isDisabledStatus = isDisabled;
}
void validateContactName(String value) { void validateContactName(String value) {
const pattern = '''^[^`,'"]{1,32}\$'''; const pattern = '''^[^`,'"]{1,32}\$''';
final regExp = RegExp(pattern); final regExp = RegExp(pattern);

View file

@ -17,6 +17,7 @@ class BaseTextFormField extends StatelessWidget {
this.borderColor = PaletteDark.menuList, this.borderColor = PaletteDark.menuList,
this.prefix, this.prefix,
this.suffix, this.suffix,
this.suffixIcon,
this.enabled = true, this.enabled = true,
this.validator this.validator
}); });
@ -34,6 +35,7 @@ class BaseTextFormField extends StatelessWidget {
final Color borderColor; final Color borderColor;
final Widget prefix; final Widget prefix;
final Widget suffix; final Widget suffix;
final Widget suffixIcon;
final bool enabled; final bool enabled;
final FormFieldValidator<String> validator; final FormFieldValidator<String> validator;
@ -55,6 +57,7 @@ class BaseTextFormField extends StatelessWidget {
decoration: InputDecoration( decoration: InputDecoration(
prefix: prefix, prefix: prefix,
suffix: suffix, suffix: suffix,
suffixIcon: suffixIcon,
hintStyle: TextStyle( hintStyle: TextStyle(
color: hintColor, color: hintColor,
fontSize: 16 fontSize: 16

View file

@ -13,7 +13,6 @@ import 'package:cake_wallet/src/domain/monero/mnemonics/russian.dart';
import 'package:cake_wallet/src/domain/monero/mnemonics/spanish.dart'; import 'package:cake_wallet/src/domain/monero/mnemonics/spanish.dart';
import 'package:cake_wallet/src/domain/common/mnemotic_item.dart'; import 'package:cake_wallet/src/domain/common/mnemotic_item.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/top_panel.dart';
class SeedWidget extends StatefulWidget { class SeedWidget extends StatefulWidget {
SeedWidget({Key key, this.onMnemoticChange, this.onFinish, this.seedLanguage}) : super(key: key) { SeedWidget({Key key, this.onMnemoticChange, this.onFinish, this.seedLanguage}) : super(key: key) {
@ -237,9 +236,18 @@ class SeedWidgetState extends State<SeedWidget> {
Flexible( Flexible(
fit: FlexFit.tight, fit: FlexFit.tight,
flex: 1, flex: 1,
child: TopPanel( child: Container(
color: PaletteDark.menuList, width: double.infinity,
widget: SingleChildScrollView( height: double.infinity,
padding: EdgeInsets.all(24),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)
),
color: PaletteDark.menuList
),
child: SingleChildScrollView(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -281,8 +289,8 @@ class SeedWidgetState extends State<SeedWidget> {
) )
], ],
), ),
) ),
) ),
), ),
Flexible( Flexible(
fit: FlexFit.tight, fit: FlexFit.tight,