Merge branch 'dev' into CAKE-20-update-exchange-and-send-screens

# Conflicts:
#	lib/di.dart
#	lib/palette.dart
#	lib/src/screens/base_page.dart
#	lib/src/screens/dashboard/dashboard_page.dart
#	lib/src/screens/receive/receive_page.dart
This commit is contained in:
Oleksandr Sobol
2020-07-31 19:17:10 +03:00
41 changed files with 645 additions and 297 deletions
+13 -3
View File
@@ -9,13 +9,18 @@ import 'package:cake_wallet/palette.dart';
import 'package:dots_indicator/dots_indicator.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/action_button.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/address_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
class DashboardPage extends BasePage {
DashboardPage({@required this.walletViewModel});
DashboardPage({
@required this.walletViewModel,
@required this.addressListViewModel,
});
@override
Color get backgroundLightColor => PaletteDark.backgroundColor;
@@ -23,6 +28,9 @@ class DashboardPage extends BasePage {
@override
Color get backgroundDarkColor => PaletteDark.backgroundColor;
@override
bool get resizeToAvoidBottomPadding => false;
@override
Widget get endDrawer => MenuWidget(
name: walletViewModel.name,
@@ -53,13 +61,14 @@ class DashboardPage extends BasePage {
}
final DashboardViewModel walletViewModel;
final WalletAddressListViewModel addressListViewModel;
final sendImage = Image.asset('assets/images/upload.png',
height: 22.24, width: 24, color: Colors.white);
final exchangeImage = Image.asset('assets/images/transfer.png',
height: 24.27, width: 22.25, color: Colors.white);
final receiveImage = Image.asset('assets/images/download.png',
height: 22.24, width: 24, color: Colors.white);
final controller = PageController(initialPage: 0);
final controller = PageController(initialPage: 1);
var pages = <Widget>[];
bool _isEffectsInstalled = false;
@@ -146,11 +155,12 @@ class DashboardPage extends BasePage {
return;
}
pages.add(AddressPage(addressListViewModel: addressListViewModel));
pages.add(BalancePage(dashboardViewModel: walletViewModel));
pages.add(TransactionsPage(dashboardViewModel: walletViewModel));
controller.addListener(() {
walletViewModel.currentPage = controller.page;
walletViewModel.pageViewStore.setCurrentPage(controller.page);
});
reaction((_) => walletViewModel.currentPage, (double currentPage) {
@@ -0,0 +1,59 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
class AddressPage extends StatelessWidget {
AddressPage({@required this.addressListViewModel});
final WalletAddressListViewModel addressListViewModel;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
child: Column(
children: <Widget>[
Expanded(
child: Center(
child: QRWidget(addressListViewModel: addressListViewModel),
)
),
GestureDetector(
onTap: () => Navigator.of(context).pushNamed(Routes.receive),
child: Container(
height: 50,
padding: EdgeInsets.only(left: 24, right: 12),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(25)),
color: PaletteDark.nightBlue
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
S.of(context).addresses,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.white
),
),
Icon(
Icons.arrow_forward_ios,
size: 14,
color: Colors.white,
)
],
),
),
)
],
),
);
}
}
@@ -8,6 +8,7 @@ import 'package:cake_wallet/view_model/monero_account_list/monero_account_edit_o
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/palette.dart';
class MoneroAccountEditOrCreatePage extends BasePage {
MoneroAccountEditOrCreatePage({@required this.moneroAccountCreationViewModel})
@@ -23,6 +24,12 @@ class MoneroAccountEditOrCreatePage extends BasePage {
@override
String get title => S.current.account;
@override
Color get backgroundLightColor => PaletteDark.backgroundColor;
@override
Color get backgroundDarkColor => PaletteDark.backgroundColor;
final GlobalKey<FormState> _formKey;
final TextEditingController _textController;
@@ -31,7 +38,6 @@ class MoneroAccountEditOrCreatePage extends BasePage {
Form(
key: _formKey,
child: Container(
color: Theme.of(context).backgroundColor,
padding: EdgeInsets.all(24.0),
child: Column(
children: <Widget>[
@@ -39,6 +45,7 @@ class MoneroAccountEditOrCreatePage extends BasePage {
child: Center(
child: BaseTextFormField(
controller: _textController,
textColor: Colors.white,
hintText: S.of(context).account,
validator: MoneroLabelValidator(),
))),
@@ -7,133 +7,157 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/view_model/monero_account_list/monero_account_list_view_model.dart';
import 'package:cake_wallet/src/screens/monero_accounts/widgets/account_tile.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart';
import 'package:cake_wallet/src/widgets/cake_scrollbar.dart';
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
class MoneroAccountListPage extends StatefulWidget {
MoneroAccountListPage({@required this.accountListViewModel});
class MoneroAccountListPage extends StatelessWidget {
MoneroAccountListPage({@required this.accountListViewModel}) {
backgroundHeight = 194;
thumbHeight = 72;
isAlwaysShowScrollThumb = false;
controller = ScrollController();
controller.addListener(() {
final scrollOffsetFromTop = controller.hasClients
? (controller.offset / controller.position.maxScrollExtent * (backgroundHeight - thumbHeight))
: 0.0;
accountListViewModel.setScrollOffsetFromTop(scrollOffsetFromTop);
});
}
final MoneroAccountListViewModel accountListViewModel;
final closeIcon = Image.asset('assets/images/close.png');
@override
MoneroAccountListPageForm createState() =>
MoneroAccountListPageForm(accountListViewModel);
}
class MoneroAccountListPageForm extends State<MoneroAccountListPage> {
MoneroAccountListPageForm(this.accountListViewModel);
final MoneroAccountListViewModel accountListViewModel;
ScrollController controller;
double backgroundHeight;
double thumbHeight;
bool isAlwaysShowScrollThumb;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Colors.transparent,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
child: Container(
decoration: BoxDecoration(
color: PaletteDark.darkNightBlue.withOpacity(0.75)),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 24, right: 24),
child: Text(
S.of(context).choose_account,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
color: Colors.white),
),
return AlertBackground(
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 24, right: 24),
child: Text(
S.of(context).choose_account,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
color: Colors.white
),
Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
child: GestureDetector(
onTap: () => null,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(14)),
child: Container(
height: 296,
color: Theme.of(context)
.accentTextTheme
.title
.backgroundColor,
child: Column(
children: <Widget>[
Expanded(child: Observer(builder: (_) {
final accounts =
widget.accountListViewModel.accounts;
),
),
Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
child: GestureDetector(
onTap: () => null,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(14)),
child: Container(
height: 296,
color: PaletteDark.deepPurpleBlue,
child: Column(
children: <Widget>[
Expanded(
child: Observer(
builder: (_) {
final accounts = accountListViewModel.accounts;
isAlwaysShowScrollThumb = accounts == null
? false
: accounts.length > 3;
return ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Theme.of(context).dividerColor,
height: 1),
itemCount: accounts.length ?? 0,
itemBuilder: (context, index) {
final account = accounts[index];
return AccountTile(
isCurrent: account.isSelected,
accountName: account.label,
onTap: () {
if (account.isSelected) {
return;
}
widget.accountListViewModel
.select(account);
Navigator.of(context).pop();
});
},
);
})),
GestureDetector(
onTap: () async => await Navigator.of(context)
.pushNamed(Routes.accountCreation),
child: Container(
height: 62,
color: Colors.white,
padding: EdgeInsets.only(left: 24, right: 24),
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
return Stack(
alignment: Alignment.center,
children: <Widget>[
Icon(
Icons.add,
color: PaletteDark.darkNightBlue,
),
Padding(
padding: EdgeInsets.only(left: 5),
child: Text(
S.of(context).create_new_account,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: PaletteDark.darkNightBlue,
decoration: TextDecoration.none,
),
ListView.separated(
controller: controller,
separatorBuilder: (context, index) =>
Container(
height: 1,
color: PaletteDark.dividerColor,
),
itemCount: accounts.length ?? 0,
itemBuilder: (context, index) {
final account = accounts[index];
return AccountTile(
isCurrent: account.isSelected,
accountName: account.label,
onTap: () {
if (account.isSelected) {
return;
}
accountListViewModel
.select(account);
Navigator.of(context).pop();
});
},
),
isAlwaysShowScrollThumb
? CakeScrollbar(
backgroundHeight: backgroundHeight,
thumbHeight: thumbHeight,
fromTop: accountListViewModel
.scrollOffsetFromTop
)
: Offstage(),
],
),
),
),
);
}
)
],
),
),
GestureDetector(
onTap: () async => await Navigator.of(context)
.pushNamed(Routes.accountCreation),
child: Container(
height: 62,
color: Colors.white,
padding: EdgeInsets.only(left: 24, right: 24),
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
Icons.add,
color: PaletteDark.darkNightBlue,
),
Padding(
padding: EdgeInsets.only(left: 5),
child: Text(
S.of(context).create_new_account,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: PaletteDark.darkNightBlue,
decoration: TextDecoration.none,
),
),
)
],
),
),
),
)
],
),
),
)
],
),
),
),
),
)
],
),
),
AlertCloseButton(image: closeIcon)
],
),
);
}
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
class AccountTile extends StatelessWidget {
AccountTile({
@@ -13,8 +14,8 @@ class AccountTile extends StatelessWidget {
@override
Widget build(BuildContext context) {
final color = isCurrent ? Theme.of(context).accentTextTheme.subtitle.decorationColor : Colors.transparent;
final textColor = isCurrent ? Colors.blue : Theme.of(context).primaryTextTheme.title.color;
final color = isCurrent ? PaletteDark.lightOceanBlue : Colors.transparent;
final textColor = isCurrent ? Colors.blue : Colors.white;
return GestureDetector(
onTap: onTap,
+43 -159
View File
@@ -1,199 +1,72 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart';
import 'package:cake_wallet/src/screens/receive/widgets/header_tile.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/core/amount_validator.dart';
import 'package:cake_wallet/src/screens/receive/widgets/address_cell.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
import 'package:cake_wallet/palette.dart';
class ReceivePage extends BasePage {
ReceivePage({this.addressListViewModel})
: amountController = TextEditingController(),
_formKey = GlobalKey<FormState>() {
amountController.addListener(() => addressListViewModel.amount =
_formKey.currentState.validate() ? amountController.text : '');
}
ReceivePage({this.addressListViewModel});
final WalletAddressListViewModel addressListViewModel;
final TextEditingController amountController;
final GlobalKey<FormState> _formKey;
@override
Color get backgroundLightColor => Colors.transparent;
String get title => S.current.receive;
@override
Color get backgroundDarkColor => Colors.transparent;
Color get backgroundLightColor => PaletteDark.backgroundColor;
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context).primaryColor
], begin: Alignment.topLeft, end: Alignment.bottomRight)),
child: scaffold);
@override
Widget middle(BuildContext context) => Text(
S.of(context).receive,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryTextTheme.title.color),
);
Color get backgroundDarkColor => PaletteDark.backgroundColor;
@override
Widget trailing(BuildContext context) {
final shareImage = Image.asset('assets/images/share.png',
color: Theme.of(context).primaryTextTheme.title.color);
color: Colors.white);
return SizedBox(
height: 20.0,
width: 14.0,
width: 20.0,
child: ButtonTheme(
minWidth: double.minPositive,
child: FlatButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.all(0),
onPressed: () => Share.text(S.current.share_address,
addressListViewModel.address.address, 'text/plain'),
child: shareImage),
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.all(0),
onPressed: () => Share.text(S.current.share_address,
addressListViewModel.address.address, 'text/plain'),
child: shareImage),
),
);
}
@override
Widget body(BuildContext context) {
final copyImage = Image.asset('assets/images/copy_content.png',
color: Theme.of(context).primaryTextTheme.title.color);
return SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(height: 25),
Row(children: <Widget>[
Spacer(flex: 4),
Observer(
builder: (_) => Flexible(
flex: 6,
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: QrImage(
data: addressListViewModel.uri.toString(),
backgroundColor: Colors.transparent,
foregroundColor: Theme.of(context)
.primaryTextTheme
.display4
.color,
))))),
Spacer(flex: 4)
]),
Padding(
padding: EdgeInsets.fromLTRB(24, 40, 24, 0),
child: Row(
children: <Widget>[
Expanded(
child: Form(
key: _formKey,
child: BaseTextFormField(
controller: amountController,
keyboardType:
TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
BlacklistingTextInputFormatter(
RegExp('[\\-|\\ |\\,]'))
],
textAlign: TextAlign.center,
hintText: S.of(context).receive_amount,
borderColor: Theme.of(context)
.primaryTextTheme
.headline5
.color
.withOpacity(0.4),
validator: AmountValidator(isAutovalidate: true),
autovalidate: true,
placeholderTextStyle: TextStyle(
color: Theme.of(context)
.primaryTextTheme
.headline5
.color,
fontSize: 20,
fontWeight: FontWeight.w600))))
],
padding: EdgeInsets.fromLTRB(24, 80, 24, 40),
child: QRWidget(
addressListViewModel: addressListViewModel,
isAmountFieldShow: true,
),
),
Padding(
padding: EdgeInsets.only(left: 24, right: 24, bottom: 40, top: 40),
child: Builder(
builder: (context) => Observer(
builder: (context) => GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(
text: addressListViewModel.address.address));
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(
S.of(context).copied_to_clipboard,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
duration: Duration(milliseconds: 500),
));
},
child: Container(
height: 48,
padding: EdgeInsets.only(left: 24, right: 24),
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(24)),
color: Theme.of(context)
.primaryTextTheme
.overline
.color),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Text(
addressListViewModel.address.address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme
.title
.color),
),
),
Padding(
padding: EdgeInsets.only(left: 12),
child: copyImage,
)
],
),
),
))),
),
Observer(
builder: (_) => ListView.separated(
separatorBuilder: (context, _) =>
Divider(height: 1, color: Theme.of(context).dividerColor),
Container(height: 1, color: PaletteDark.dividerColor),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: addressListViewModel.items.length,
@@ -210,8 +83,7 @@ class ReceivePage extends BasePage {
icon: Icon(
Icons.arrow_forward_ios,
size: 14,
color:
Theme.of(context).primaryTextTheme.title.color,
color: Colors.white,
));
}
@@ -223,28 +95,40 @@ class ReceivePage extends BasePage {
icon: Icon(
Icons.add,
size: 20,
color:
Theme.of(context).primaryTextTheme.title.color,
color: Colors.white,
));
}
if (item is WalletAddressListItem) {
cell = Observer(
builder: (_) => AddressCell.fromItem(item,
isCurrent: item.address ==
addressListViewModel.address.address,
onTap: (_) => addressListViewModel.address = item,
onEdit: () => Navigator.of(context).pushNamed(
Routes.newSubaddress,
arguments: item)));
builder: (_) {
final isCurrent = item.address ==
addressListViewModel.address.address;
final backgroundColor = isCurrent
? PaletteDark.lightOceanBlue
: PaletteDark.nightBlue;
final textColor = isCurrent
? Colors.blue
: Colors.white;
return AddressCell.fromItem(item,
isCurrent: isCurrent,
backgroundColor: backgroundColor,
textColor: textColor,
onTap: (_) => addressListViewModel.address = item,
onEdit: () => Navigator.of(context).pushNamed(
Routes.newSubaddress,
arguments: item));
}
);
}
return index != 0
? cell
: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24)),
topLeft: Radius.circular(30),
topRight: Radius.circular(30)),
child: cell,
);
})),
@@ -6,12 +6,16 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_i
class AddressCell extends StatelessWidget {
factory AddressCell.fromItem(WalletAddressListItem item,
{@required bool isCurrent,
@required Color backgroundColor,
@required Color textColor,
Function(String) onTap,
Function() onEdit}) =>
AddressCell(
address: item.address,
name: item.name,
isCurrent: isCurrent,
backgroundColor: backgroundColor,
textColor: textColor,
onTap: onTap,
onEdit: onEdit);
@@ -19,12 +23,16 @@ class AddressCell extends StatelessWidget {
{@required this.address,
@required this.name,
@required this.isCurrent,
@required this.backgroundColor,
@required this.textColor,
this.onTap,
this.onEdit});
final String address;
final String name;
final bool isCurrent;
final Color backgroundColor;
final Color textColor;
final Function(String) onTap;
final Function() onEdit;
@@ -32,23 +40,19 @@ class AddressCell extends StatelessWidget {
@override
Widget build(BuildContext context) {
const currentTextColor = Colors.blue; // FIXME: Why it's defined here ?
final currentColor =
Theme.of(context).accentTextTheme.subtitle.decorationColor;
final notCurrentColor = Theme.of(context).backgroundColor;
final notCurrentTextColor =
Theme.of(context).primaryTextTheme.caption.color;
final Widget cell = InkWell(
onTap: () => onTap(address),
child: Container(
color: isCurrent ? currentColor : notCurrentColor,
color: backgroundColor,
padding: EdgeInsets.only(left: 24, right: 24, top: 28, bottom: 28),
child: Text(
name ?? address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: name?.isNotEmpty ?? false ? 18 : 10,
fontSize: 18,
fontWeight: FontWeight.w600,
color: isCurrent ? currentTextColor : notCurrentTextColor,
color: textColor,
),
),
));
@@ -62,7 +66,7 @@ class AddressCell extends StatelessWidget {
secondaryActions: <Widget>[
IconSlideAction(
caption: S.of(context).edit,
color: Theme.of(context).primaryTextTheme.overline.color,
color: Colors.blue,
icon: Icons.edit,
onTap: () => onEdit?.call())
]);
@@ -23,7 +23,7 @@ class HeaderTile extends StatelessWidget {
top: 24,
bottom: 24
),
color: Theme.of(context).backgroundColor,
color: PaletteDark.nightBlue,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -33,7 +33,7 @@ class HeaderTile extends StatelessWidget {
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.title.color
color: Colors.white
),
),
Container(
@@ -41,7 +41,7 @@ class HeaderTile extends StatelessWidget {
width: 32,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).primaryTextTheme.overline.color
color: PaletteDark.distantNightBlue
),
child: icon,
)
@@ -0,0 +1,137 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/core/amount_validator.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
import 'package:cake_wallet/palette.dart';
class QRWidget extends StatelessWidget {
QRWidget({
@required this.addressListViewModel,
this.isAmountFieldShow = false
}) : amountController = TextEditingController(),
_formKey = GlobalKey<FormState>() {
amountController.addListener(() => addressListViewModel.amount =
_formKey.currentState.validate() ? amountController.text : '');
}
final WalletAddressListViewModel addressListViewModel;
final bool isAmountFieldShow;
final TextEditingController amountController;
final GlobalKey<FormState> _formKey;
@override
Widget build(BuildContext context) {
final copyImage = Image.asset('assets/images/copy_address.png',
color: PaletteDark.lightBlueGrey);
final addressTopOffset = isAmountFieldShow ? 60.0 : 40.0;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(children: <Widget>[
Spacer(flex: 3),
Observer(
builder: (_) => Flexible(
flex: 5,
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: QrImage(
data: addressListViewModel.uri.toString(),
backgroundColor: Colors.transparent,
foregroundColor: PaletteDark.lightBlueGrey,
))))),
Spacer(flex: 3)
]),
Padding(
padding: EdgeInsets.only(top: 20),
child: Text(
S.of(context).scan_qr_code,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: PaletteDark.cyanBlue
),
),
),
isAmountFieldShow
? Padding(
padding: EdgeInsets.only(top: 40),
child: Row(
children: <Widget>[
Expanded(
child: Form(
key: _formKey,
child: BaseTextFormField(
controller: amountController,
keyboardType:
TextInputType.numberWithOptions(decimal: true),
inputFormatters: [
BlacklistingTextInputFormatter(
RegExp('[\\-|\\ |\\,]'))
],
textAlign: TextAlign.center,
hintText: S.of(context).receive_amount,
textColor: Colors.white,
borderColor: PaletteDark.darkGrey,
validator: AmountValidator(
type: addressListViewModel.type
),
autovalidate: true,
placeholderTextStyle: TextStyle(
color: PaletteDark.cyanBlue,
fontSize: 18,
fontWeight: FontWeight.w500))))
],
),
)
: Offstage(),
Padding(
padding: EdgeInsets.only(top: addressTopOffset),
child: Builder(
builder: (context) => Observer(
builder: (context) => GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(
text: addressListViewModel.address.address));
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(
S.of(context).copied_to_clipboard,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
duration: Duration(milliseconds: 500),
));
},
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Text(
addressListViewModel.address.address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.white),
),
),
Padding(
padding: EdgeInsets.only(left: 12),
child: copyImage,
)
],
),
))),
)
],
);
}
}
@@ -8,6 +8,7 @@ import 'package:cake_wallet/core/address_label_validator.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/palette.dart';
class AddressEditOrCreatePage extends BasePage {
AddressEditOrCreatePage({@required this.addressEditOrCreateViewModel})
@@ -28,6 +29,12 @@ class AddressEditOrCreatePage extends BasePage {
@override
String get title => S.current.new_subaddress_title;
@override
Color get backgroundLightColor => PaletteDark.backgroundColor;
@override
Color get backgroundDarkColor => PaletteDark.backgroundColor;
@override
Widget body(BuildContext context) {
reaction((_) => addressEditOrCreateViewModel.state,
@@ -48,6 +55,7 @@ class AddressEditOrCreatePage extends BasePage {
child: Center(
child: BaseTextFormField(
controller: _labelController,
textColor: Colors.white,
hintText: S.of(context).new_subaddress_label_name,
validator: AddressLabelValidator()))),
Observer(
+26
View File
@@ -0,0 +1,26 @@
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
class AlertBackground extends StatelessWidget {
AlertBackground({@required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
return Container(
height: double.infinity,
width: double.infinity,
color: Colors.transparent,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
child: Container(
decoration: BoxDecoration(color: PaletteDark.darkNightBlue.withOpacity(0.75)),
child: child,
),
),
);
}
}
+28
View File
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
class AlertCloseButton extends StatelessWidget {
AlertCloseButton({@required this.image});
final Image image;
@override
Widget build(BuildContext context) {
return Positioned(
bottom: 24,
child: GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
height: 42,
width: 42,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle
),
child: Center(
child: image,
),
),
)
);
}
}
+45
View File
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
class CakeScrollbar extends StatelessWidget {
CakeScrollbar({
@required this.backgroundHeight,
@required this.thumbHeight,
@required this.fromTop
});
final double backgroundHeight;
final double thumbHeight;
final double fromTop;
@override
Widget build(BuildContext context) {
return Positioned(
right: 6,
child: Container(
height: backgroundHeight,
width: 6,
decoration: BoxDecoration(
color: PaletteDark.violetBlue,
borderRadius: BorderRadius.all(Radius.circular(3))
),
child: Stack(
children: <Widget>[
AnimatedPositioned(
duration: Duration(milliseconds: 0),
top: fromTop,
child: Container(
height: thumbHeight,
width: 6.0,
decoration: BoxDecoration(
color: PaletteDark.wildBlueGrey,
borderRadius: BorderRadius.all(Radius.circular(3))
),
),
)
],
),
)
);
}
}