CAKE-27 | applied light theme to send and send template pages; made status bar is transparent; reworked menu widget and base send widget; applied switch between light and dark themes

Oleksandr Sobol committed Aug 20, 2020 at 20:43 UTC 731f12cd63b62f5f52a07dbb675b4c1facaf0f0c
13 files changed +578 -467
lib/di.dart
+7
@@ -27,7 +27,9 @@ import 'package:cake_wallet/src/screens/receive/receive_page.dart';
27 import 'package:cake_wallet/src/screens/send/send_page.dart';
28 import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart';
29 import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
30 +import 'package:cake_wallet/store/theme_changer_store.dart';
31 import 'package:cake_wallet/store/wallet_list_store.dart';
32 +import 'package:cake_wallet/theme_changer.dart';
33 import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
34 import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart';
35 import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
@@ -318,3 +320,8 @@ Future setup(
320 getIt.registerFactory(() =>
321 ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
322 }
323 +
324 +void setupThemeChangerStore(ThemeChanger themeChanger) {
325 + getIt.registerSingleton<ThemeChangerStore>(
326 + ThemeChangerStore(themeChanger: themeChanger));
327 +}
lib/main.dart
+17 -5
@@ -1,4 +1,5 @@
1 import 'package:cake_wallet/reactions/bootstrap.dart';
2 +import 'package:cake_wallet/store/app_store.dart';
3 import 'package:cake_wallet/store/authentication_store.dart';
4 import 'package:cake_wallet/core/auth_service.dart';
5 import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
@@ -52,6 +53,8 @@ import 'package:cake_wallet/generated/i18n.dart';
53 import 'package:cake_wallet/src/domain/common/language.dart';
54 import 'package:cake_wallet/src/stores/seed_language/seed_language_store.dart';
55
56 +bool isThemeChangerRegistered = false;
57 +
58 void main() async {
59 WidgetsFlutterBinding.ensureInitialized();
60
@@ -197,7 +200,8 @@ class CakeWalletApp extends StatelessWidget {
200
201 @override
202 Widget build(BuildContext context) {
200 - final settingsStore = Provider.of<SettingsStore>(context);
203 + //final settingsStore = Provider.of<SettingsStore>(context);
204 + final settingsStore = getIt.get<AppStore>().settingsStore;
205
206 return ChangeNotifierProvider<ThemeChanger>(
207 create: (_) => ThemeChanger(
@@ -228,12 +232,20 @@ class MaterialAppWithTheme extends StatelessWidget {
232 final transactionDescriptions =
233 Provider.of<Box<TransactionDescription>>(context);
234
231 - final statusBarColor =
232 - settingsStore.isDarkTheme ? Colors.black : Colors.white;
235 + if (!isThemeChangerRegistered) {
236 + setupThemeChangerStore(theme);
237 + isThemeChangerRegistered = true;
238 + }
239 +
240 + /*final statusBarColor =
241 + settingsStore.isDarkTheme ? Colors.black : Colors.white;*/
242 + final _settingsStore = getIt.get<AppStore>().settingsStore;
243 +
244 + final statusBarColor = Colors.transparent;
245 final statusBarBrightness =
234 - settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
246 + _settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
247 final statusBarIconBrightness =
236 - settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
248 + _settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
249
250 SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
251 statusBarColor: statusBarColor,
lib/palette.dart
+1
@@ -29,6 +29,7 @@ class Palette {
29 static const Color gray = Color.fromRGBO(112, 147, 186, 1.0);
30 static const Color wildPeriwinkle = Color.fromRGBO(219, 227, 243, 1.0);
31 static const Color darkGray = Color.fromRGBO(122, 147, 186, 1.0);
32 + static const Color shadowWhite = Color.fromRGBO(242, 245, 255, 1.0);
33
34 // FIXME: Rename.
35 static const Color eee = Color.fromRGBO(236, 239, 245, 1.0);
lib/src/screens/dashboard/widgets/menu_widget.dart
+80 -87
@@ -3,6 +3,7 @@ import 'package:cake_wallet/palette.dart';
3 import 'package:flutter/material.dart';
4 import 'package:cake_wallet/src/domain/common/wallet_type.dart';
5 import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
6 +import 'package:flutter/rendering.dart';
7
8 class MenuWidget extends StatefulWidget {
9 MenuWidget({this.type, this.name, this.subname});
@@ -23,7 +24,6 @@ class MenuWidgetState extends State<MenuWidget> {
24 double menuWidth;
25 double screenWidth;
26 double screenHeight;
26 - double opacity;
27
28 double headerHeight;
29 double tileHeight;
@@ -35,11 +35,10 @@ class MenuWidgetState extends State<MenuWidget> {
35 menuWidth = 0;
36 screenWidth = 0;
37 screenHeight = 0;
38 - opacity = 0;
38
39 headerHeight = 125;
40 tileHeight = 75;
42 - fromTopEdge = 50;
41 + fromTopEdge = 30;
42 fromBottomEdge = 21;
43
44 super.initState();
@@ -52,7 +51,6 @@ class MenuWidgetState extends State<MenuWidget> {
51
52 setState(() {
53 menuWidth = screenWidth;
55 - opacity = 1;
54
55 if (screenHeight > largeScreen) {
56 final scale = screenHeight / largeScreen;
@@ -69,41 +67,43 @@ class MenuWidgetState extends State<MenuWidget> {
67 final walletMenu = WalletMenu(context);
68 final itemCount = walletMenu.items.length;
69
72 - return SafeArea(
73 - child: Row(
74 - mainAxisSize: MainAxisSize.max,
75 - crossAxisAlignment: CrossAxisAlignment.center,
76 - children: <Widget>[
77 - Padding(
70 + return Row(
71 + mainAxisSize: MainAxisSize.max,
72 + crossAxisAlignment: CrossAxisAlignment.center,
73 + children: <Widget>[
74 + Padding(
75 padding: EdgeInsets.only(left: 24),
76 child: Container(
77 height: 60,
78 width: 4,
79 decoration: BoxDecoration(
83 - borderRadius: BorderRadius.all(Radius.circular(2)),
84 - color: PaletteDark.gray),
80 + borderRadius: BorderRadius.all(Radius.circular(2)),
81 + color: PaletteDark.gray),
82 )),
86 - SizedBox(width: 12),
87 - Expanded(
88 - child: ClipRRect(
89 - borderRadius: BorderRadius.only(
83 + SizedBox(width: 12),
84 + Expanded(
85 + child: ClipRRect(
86 + borderRadius: BorderRadius.only(
87 topLeft: Radius.circular(24),
88 bottomLeft: Radius.circular(24)),
92 - child: Container(
93 - width: menuWidth,
94 - height: double.infinity,
95 - color: Theme.of(context).textTheme.body2.decorationColor,
96 - child: SingleChildScrollView(
97 - child: Column(
98 - children: <Widget>[
99 - Container(
89 + child: Container(
90 + width: menuWidth,
91 + height: double.infinity,
92 + color: Theme.of(context).textTheme.body2.color,
93 + alignment: Alignment.topCenter,
94 + child: ListView.separated(
95 + itemBuilder: (_, index) {
96 +
97 + if (index == 0) {
98 + return Container(
99 height: headerHeight,
100 color: Theme.of(context).textTheme.body2.color,
101 padding: EdgeInsets.only(
102 left: 24,
103 top: fromTopEdge,
104 right: 24,
106 - bottom: fromBottomEdge),
105 + bottom: fromBottomEdge
106 + ),
107 child: Row(
108 mainAxisAlignment: MainAxisAlignment.start,
109 children: <Widget>[
@@ -141,70 +141,63 @@ class MenuWidgetState extends State<MenuWidget> {
141 ))
142 ],
143 ),
144 - ),
145 - Container(
146 - height: 1,
147 - color: Theme.of(context).primaryTextTheme.caption.decorationColor,
148 - ),
149 - ListView.separated(
150 - shrinkWrap: true,
151 - physics: NeverScrollableScrollPhysics(),
152 - itemBuilder: (_, index) {
153 -
154 - final item = walletMenu.items[index];
155 - final image = walletMenu.images[index] ?? Offstage();
156 - final isLastTile = index == itemCount - 1;
157 -
158 - return GestureDetector(
159 - onTap: () {
160 - Navigator.of(context).pop();
161 - walletMenu.action(index);
162 - },
163 - child: Container(
164 - height: isLastTile
165 - ? headerHeight
166 - : tileHeight,
167 - padding: isLastTile
168 - ? EdgeInsets.only(
169 - left: 24,
170 - right: 24,
171 - top: fromBottomEdge,
172 - bottom: fromTopEdge)
173 - : EdgeInsets.only(left: 24, right: 24),
174 - alignment: isLastTile ? Alignment.topLeft : null,
175 - child: Row(
176 - mainAxisAlignment: MainAxisAlignment.start,
177 - crossAxisAlignment: CrossAxisAlignment.center,
178 - children: <Widget>[
179 - image,
180 - SizedBox(width: 16),
181 - Expanded(
182 - child: Text(
183 - item,
184 - style: TextStyle(
185 - color: Theme.of(context).textTheme
186 - .display2.color,
187 - fontSize: 16,
188 - fontWeight: FontWeight.bold),
189 - ))
190 - ],
191 - ),
192 - )
193 - );
194 - },
195 - separatorBuilder: (_, index) => Container(
196 - height: 1,
197 - color: Theme.of(context).primaryTextTheme.caption.decorationColor,
144 + );
145 + }
146 +
147 + index--;
148 +
149 + final item = walletMenu.items[index];
150 + final image = walletMenu.images[index] ?? Offstage();
151 + final isLastTile = index == itemCount - 1;
152 +
153 + return GestureDetector(
154 + onTap: () {
155 + Navigator.of(context).pop();
156 + walletMenu.action(index);
157 + },
158 + child: Container(
159 + color: Theme.of(context).textTheme.body2.decorationColor,
160 + height: isLastTile
161 + ? headerHeight
162 + : tileHeight,
163 + padding: isLastTile
164 + ? EdgeInsets.only(
165 + left: 24,
166 + right: 24,
167 + top: fromBottomEdge,
168 + //bottom: fromTopEdge
169 + )
170 + : EdgeInsets.only(left: 24, right: 24),
171 + alignment: isLastTile ? Alignment.topLeft : null,
172 + child: Row(
173 + mainAxisAlignment: MainAxisAlignment.start,
174 + crossAxisAlignment: CrossAxisAlignment.center,
175 + children: <Widget>[
176 + image,
177 + SizedBox(width: 16),
178 + Expanded(
179 + child: Text(
180 + item,
181 + style: TextStyle(
182 + color: Theme.of(context).textTheme
183 + .display2.color,
184 + fontSize: 16,
185 + fontWeight: FontWeight.bold),
186 + ))
187 + ],
188 ),
199 - itemCount: itemCount)
200 - ],
189 + )
190 + );
191 + },
192 + separatorBuilder: (_, index) => Container(
193 + height: 1,
194 + color: Theme.of(context).primaryTextTheme.caption.decorationColor,
195 ),
202 - ),
203 - ),
204 - )
205 - )
206 - ],
207 - )
196 + itemCount: itemCount + 1),
197 + ),
198 + )
199 + )
200 + ],
201 );
202 }
203
lib/src/screens/send/send_page.dart
+21 -4
@@ -1,7 +1,6 @@
1 import 'package:cake_wallet/view_model/send_view_model.dart';
2 import 'package:flutter/cupertino.dart';
3 import 'package:flutter/material.dart';
4 -import 'package:cake_wallet/palette.dart';
4 import 'package:cake_wallet/src/screens/base_page.dart';
5 import 'package:cake_wallet/src/screens/send/widgets/base_send_widget.dart';
6
@@ -14,15 +13,33 @@ class SendPage extends BasePage {
13 String get title => sendViewModel.pageTitle;
14
15 @override
17 - Color get backgroundLightColor => PaletteDark.nightBlue;
16 + Color get titleColor => Colors.white;
17
18 @override
20 - Color get backgroundDarkColor => PaletteDark.nightBlue;
19 + Color get backgroundLightColor => Colors.transparent;
20 +
21 + @override
22 + Color get backgroundDarkColor => Colors.transparent;
23
24 @override
25 bool get resizeToAvoidBottomPadding => false;
26
27 @override
28 Widget body(BuildContext context) =>
27 - BaseSendWidget(sendViewModel: sendViewModel);
29 + BaseSendWidget(
30 + sendViewModel: sendViewModel,
31 + leading: leading(context),
32 + middle: middle(context),
33 + );
34 +
35 + @override
36 + Widget build(BuildContext context) {
37 + return Scaffold(
38 + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
39 + body: Container(
40 + color: Theme.of(context).backgroundColor,
41 + child: body(context)
42 + )
43 + );
44 + }
45 }
lib/src/screens/send/send_template_page.dart
+22 -4
@@ -1,6 +1,5 @@
1 import 'package:flutter/cupertino.dart';
2 import 'package:flutter/material.dart';
3 -import 'package:cake_wallet/palette.dart';
3 import 'package:cake_wallet/src/screens/base_page.dart';
4 import 'package:cake_wallet/generated/i18n.dart';
5 import 'package:cake_wallet/view_model/send_view_model.dart';
@@ -15,15 +14,34 @@ class SendTemplatePage extends BasePage {
14 String get title => S.current.exchange_new_template;
15
16 @override
18 - Color get backgroundLightColor => PaletteDark.nightBlue;
17 + Color get titleColor => Colors.white;
18
19 @override
21 - Color get backgroundDarkColor => PaletteDark.nightBlue;
20 + Color get backgroundLightColor => Colors.transparent;
21 +
22 + @override
23 + Color get backgroundDarkColor => Colors.transparent;
24
25 @override
26 bool get resizeToAvoidBottomPadding => false;
27
28 @override
29 Widget body(BuildContext context) =>
28 - BaseSendWidget(sendViewModel: sendViewModel, isTemplate: true);
30 + BaseSendWidget(
31 + sendViewModel: sendViewModel,
32 + leading: leading(context),
33 + middle: middle(context),
34 + isTemplate: true
35 + );
36 +
37 + @override
38 + Widget build(BuildContext context) {
39 + return Scaffold(
40 + resizeToAvoidBottomPadding: resizeToAvoidBottomPadding,
41 + body: Container(
42 + color: Theme.of(context).backgroundColor,
43 + child: body(context)
44 + )
45 + );
46 + }
47 }
\ No newline at end of file
lib/src/screens/send/widgets/base_send_widget.dart
+355 -336
@@ -22,11 +22,15 @@ import 'package:cake_wallet/routes.dart';
22 class BaseSendWidget extends StatelessWidget {
23 BaseSendWidget({
24 @required this.sendViewModel,
25 + @required this.leading,
26 + @required this.middle,
27 this.isTemplate = false
28 });
29
30 final SendViewModel sendViewModel;
31 final bool isTemplate;
32 + final Widget leading;
33 + final Widget middle;
34
35 final _addressController = TextEditingController();
36 final _cryptoAmountController = TextEditingController();
@@ -42,371 +46,386 @@ class BaseSendWidget extends StatelessWidget {
46
47 _setEffects(context);
48
45 - return Container(
46 - color: PaletteDark.backgroundColor,
47 - child: ScrollableWithBottomSection(
48 - contentPadding: EdgeInsets.only(bottom: 24),
49 - content: Column(
50 - children: <Widget>[
51 - TopPanel(
52 - color: PaletteDark.nightBlue,
53 - edgeInsets: EdgeInsets.fromLTRB(24, 24, 24, 32),
54 - widget: Form(
55 - key: _formKey,
56 - child: Column(children: <Widget>[
57 - isTemplate
58 - ? BaseTextFormField(
59 - controller: _nameController,
60 - hintText: S.of(context).send_name,
61 - borderColor: PaletteDark.lightVioletBlue,
62 - textStyle: TextStyle(
63 - fontSize: 14,
64 - fontWeight: FontWeight.w500,
65 - color: Colors.white
66 - ),
67 - placeholderTextStyle: TextStyle(
68 - color: PaletteDark.darkCyanBlue,
69 - fontWeight: FontWeight.w500,
70 - fontSize: 14),
71 - validator: sendViewModel.templateValidator,
72 - )
73 - : Offstage(),
74 - Padding(
75 - padding: EdgeInsets.only(top: isTemplate ? 20 : 0),
76 - child: AddressTextField(
77 - controller: _addressController,
78 - placeholder: S.of(context).send_address(
79 - sendViewModel.cryptoCurrencyTitle),
80 - focusNode: _focusNode,
81 - onURIScanned: (uri) {
82 - var address = '';
83 - var amount = '';
84 -
85 - if (uri != null) {
86 - address = uri.path;
87 - amount = uri.queryParameters['tx_amount'];
88 - } else {
89 - address = uri.toString();
90 - }
91 -
92 - _addressController.text = address;
93 - _cryptoAmountController.text = amount;
94 - },
95 - options: [
96 - AddressTextFieldOption.paste,
97 - AddressTextFieldOption.qrCode,
98 - AddressTextFieldOption.addressBook
99 - ],
100 - buttonColor: PaletteDark.buttonNightBlue,
101 - borderColor: PaletteDark.lightVioletBlue,
102 - textStyle: TextStyle(
103 - fontSize: 14,
104 - fontWeight: FontWeight.w500,
105 - color: Colors.white
106 - ),
107 - hintStyle: TextStyle(
108 - fontSize: 14,
109 - fontWeight: FontWeight.w500,
110 - color: PaletteDark.darkCyanBlue
111 - ),
112 - validator: sendViewModel.addressValidator,
113 - ),
114 - ),
115 - Observer(
116 - builder: (_) {
117 - return Padding(
118 - padding: const EdgeInsets.only(top: 20),
119 - child: BaseTextFormField(
120 - controller: _cryptoAmountController,
121 - keyboardType: TextInputType.numberWithOptions(
122 - signed: false, decimal: true),
123 - inputFormatters: [
124 - BlacklistingTextInputFormatter(
125 - RegExp('[\\-|\\ |\\,]'))
126 - ],
127 - prefixIcon: Padding(
128 - padding: EdgeInsets.only(top: 9),
129 - child: Text(sendViewModel.currency.title + ':',
130 - style: TextStyle(
131 - fontSize: 16,
132 - fontWeight: FontWeight.w600,
133 - color: Colors.white,
134 - )),
135 - ),
136 - suffixIcon: isTemplate
137 - ? Offstage()
138 - : Padding(
139 - padding: EdgeInsets.only(bottom: 2),
140 - child: Row(
141 - mainAxisSize: MainAxisSize.min,
142 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
143 - children: <Widget>[
144 - Container(
145 - width: MediaQuery.of(context).size.width/2,
146 - alignment: Alignment.centerLeft,
147 - child: Text(
148 - ' / ' + sendViewModel.balance,
149 - maxLines: 1,
150 - overflow: TextOverflow.ellipsis,
151 - style: TextStyle(
152 - fontSize: 14,
153 - color: PaletteDark.darkCyanBlue
154 - )
155 - ),
156 - ),
157 - Container(
158 - height: 34,
159 - width: 34,
160 - margin: EdgeInsets.only(left: 12, bottom: 8),
161 - decoration: BoxDecoration(
162 - color: PaletteDark.buttonNightBlue,
163 - borderRadius: BorderRadius.all(Radius.circular(6))
164 - ),
165 - child: InkWell(
166 - onTap: () => sendViewModel.setSendAll(),
167 - child: Center(
168 - child: Text(S.of(context).all,
169 - textAlign: TextAlign.center,
170 - style: TextStyle(
171 - fontSize: 12,
172 - fontWeight: FontWeight.bold,
173 - color: PaletteDark.lightBlueGrey
174 - )
175 - ),
176 - ),
177 - ),
178 - )
179 - ],
180 - ),
181 - ),
182 - hintText: '0.0000',
183 - borderColor: PaletteDark.lightVioletBlue,
184 - textStyle: TextStyle(
185 - fontSize: 14,
186 - fontWeight: FontWeight.w500,
187 - color: Colors.white
188 - ),
189 - placeholderTextStyle: TextStyle(
190 - color: PaletteDark.darkCyanBlue,
191 - fontWeight: FontWeight.w500,
192 - fontSize: 14),
193 - validator: sendViewModel.amountValidator
194 - )
195 - );
196 - }
197 - ),
198 - Padding(
199 - padding: const EdgeInsets.only(top: 20),
200 - child: BaseTextFormField(
201 - controller: _fiatAmountController,
202 - keyboardType: TextInputType.numberWithOptions(
203 - signed: false, decimal: true),
204 - inputFormatters: [
205 - BlacklistingTextInputFormatter(
206 - RegExp('[\\-|\\ |\\,]'))
207 - ],
208 - prefixIcon: Padding(
209 - padding: EdgeInsets.only(top: 9),
210 - child: Text(
211 - sendViewModel.fiat.title + ':',
212 - style: TextStyle(
213 - fontSize: 16,
214 - fontWeight: FontWeight.w600,
215 - color: Colors.white,
216 - )),
217 - ),
218 - hintText: '0.00',
219 - borderColor: PaletteDark.lightVioletBlue,
49 + return ScrollableWithBottomSection(
50 + contentPadding: EdgeInsets.only(bottom: 24),
51 + content: Column(
52 + children: <Widget>[
53 + TopPanel(
54 + edgeInsets: EdgeInsets.all(0),
55 + gradient: LinearGradient(colors: [
56 + Theme.of(context).primaryTextTheme.subhead.color,
57 + Theme.of(context).primaryTextTheme.subhead.decorationColor,
58 + ],
59 + begin: Alignment.topLeft,
60 + end: Alignment.bottomRight),
61 + widget: Form(
62 + key: _formKey,
63 + child: Column(children: <Widget>[
64 + CupertinoNavigationBar(
65 + leading: leading,
66 + middle: middle,
67 + backgroundColor: Colors.transparent,
68 + border: null,
69 + ),
70 + Padding(
71 + padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
72 + child: Column(
73 + children: <Widget>[
74 + isTemplate
75 + ? BaseTextFormField(
76 + controller: _nameController,
77 + hintText: S.of(context).send_name,
78 + borderColor: Theme.of(context).primaryTextTheme.headline.color,
79 textStyle: TextStyle(
80 fontSize: 14,
81 fontWeight: FontWeight.w500,
82 color: Colors.white
83 ),
84 placeholderTextStyle: TextStyle(
226 - color: PaletteDark.darkCyanBlue,
85 + color: Theme.of(context).primaryTextTheme.headline.decorationColor,
86 fontWeight: FontWeight.w500,
87 fontSize: 14),
88 + validator: sendViewModel.templateValidator,
89 )
230 - ),
231 - isTemplate
232 - ? Offstage()
233 - : Padding(
234 - padding: const EdgeInsets.only(top: 24),
235 - child: Row(
236 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
237 - children: <Widget>[
238 - Text(S.of(context).send_estimated_fee,
239 - style: TextStyle(
240 - fontSize: 12,
90 + : Offstage(),
91 + Padding(
92 + padding: EdgeInsets.only(top: isTemplate ? 20 : 0),
93 + child: AddressTextField(
94 + controller: _addressController,
95 + placeholder: S.of(context).send_address(
96 + sendViewModel.cryptoCurrencyTitle),
97 + focusNode: _focusNode,
98 + onURIScanned: (uri) {
99 + var address = '';
100 + var amount = '';
101 +
102 + if (uri != null) {
103 + address = uri.path;
104 + amount = uri.queryParameters['tx_amount'];
105 + } else {
106 + address = uri.toString();
107 + }
108 +
109 + _addressController.text = address;
110 + _cryptoAmountController.text = amount;
111 + },
112 + options: [
113 + AddressTextFieldOption.paste,
114 + AddressTextFieldOption.qrCode,
115 + AddressTextFieldOption.addressBook
116 + ],
117 + buttonColor: Theme.of(context).primaryTextTheme.display1.color,
118 + borderColor: Theme.of(context).primaryTextTheme.headline.color,
119 + textStyle: TextStyle(
120 + fontSize: 14,
121 fontWeight: FontWeight.w500,
242 - color: Colors.white,
243 - )),
244 - Text(
245 - sendViewModel.estimatedFee.toString() + ' '
246 - + sendViewModel.currency.title,
247 - style: TextStyle(
248 - fontSize: 12,
249 - fontWeight: FontWeight.w600,
250 - color: Colors.white,
251 - ))
252 - ],
253 - ),
254 - )
255 - ]),
256 - ),
122 + color: Colors.white
123 + ),
124 + hintStyle: TextStyle(
125 + fontSize: 14,
126 + fontWeight: FontWeight.w500,
127 + color: Theme.of(context).primaryTextTheme.headline.decorationColor
128 + ),
129 + validator: sendViewModel.addressValidator,
130 + ),
131 + ),
132 + Observer(
133 + builder: (_) {
134 + return Padding(
135 + padding: const EdgeInsets.only(top: 20),
136 + child: BaseTextFormField(
137 + controller: _cryptoAmountController,
138 + keyboardType: TextInputType.numberWithOptions(
139 + signed: false, decimal: true),
140 + inputFormatters: [
141 + BlacklistingTextInputFormatter(
142 + RegExp('[\\-|\\ |\\,]'))
143 + ],
144 + prefixIcon: Padding(
145 + padding: EdgeInsets.only(top: 9),
146 + child: Text(sendViewModel.currency.title + ':',
147 + style: TextStyle(
148 + fontSize: 16,
149 + fontWeight: FontWeight.w600,
150 + color: Colors.white,
151 + )),
152 + ),
153 + suffixIcon: isTemplate
154 + ? Offstage()
155 + : Padding(
156 + padding: EdgeInsets.only(bottom: 2),
157 + child: Row(
158 + mainAxisSize: MainAxisSize.min,
159 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
160 + children: <Widget>[
161 + Container(
162 + width: MediaQuery.of(context).size.width/2,
163 + alignment: Alignment.centerLeft,
164 + child: Text(
165 + ' / ' + sendViewModel.balance,
166 + maxLines: 1,
167 + overflow: TextOverflow.ellipsis,
168 + style: TextStyle(
169 + fontSize: 14,
170 + color: Theme.of(context).primaryTextTheme.headline.decorationColor
171 + )
172 + ),
173 + ),
174 + Container(
175 + height: 34,
176 + width: 34,
177 + margin: EdgeInsets.only(left: 12, bottom: 8),
178 + decoration: BoxDecoration(
179 + color: Theme.of(context).primaryTextTheme.display1.color,
180 + borderRadius: BorderRadius.all(Radius.circular(6))
181 + ),
182 + child: InkWell(
183 + onTap: () => sendViewModel.setSendAll(),
184 + child: Center(
185 + child: Text(S.of(context).all,
186 + textAlign: TextAlign.center,
187 + style: TextStyle(
188 + fontSize: 12,
189 + fontWeight: FontWeight.bold,
190 + color: Theme.of(context).primaryTextTheme.display1.decorationColor
191 + )
192 + ),
193 + ),
194 + ),
195 + )
196 + ],
197 + ),
198 + ),
199 + hintText: '0.0000',
200 + borderColor: Theme.of(context).primaryTextTheme.headline.color,
201 + textStyle: TextStyle(
202 + fontSize: 14,
203 + fontWeight: FontWeight.w500,
204 + color: Colors.white
205 + ),
206 + placeholderTextStyle: TextStyle(
207 + color: Theme.of(context).primaryTextTheme.headline.decorationColor,
208 + fontWeight: FontWeight.w500,
209 + fontSize: 14),
210 + validator: sendViewModel.amountValidator
211 + )
212 + );
213 + }
214 + ),
215 + Padding(
216 + padding: const EdgeInsets.only(top: 20),
217 + child: BaseTextFormField(
218 + controller: _fiatAmountController,
219 + keyboardType: TextInputType.numberWithOptions(
220 + signed: false, decimal: true),
221 + inputFormatters: [
222 + BlacklistingTextInputFormatter(
223 + RegExp('[\\-|\\ |\\,]'))
224 + ],
225 + prefixIcon: Padding(
226 + padding: EdgeInsets.only(top: 9),
227 + child: Text(
228 + sendViewModel.fiat.title + ':',
229 + style: TextStyle(
230 + fontSize: 16,
231 + fontWeight: FontWeight.w600,
232 + color: Colors.white,
233 + )),
234 + ),
235 + hintText: '0.00',
236 + borderColor: Theme.of(context).primaryTextTheme.headline.color,
237 + textStyle: TextStyle(
238 + fontSize: 14,
239 + fontWeight: FontWeight.w500,
240 + color: Colors.white
241 + ),
242 + placeholderTextStyle: TextStyle(
243 + color: Theme.of(context).primaryTextTheme.headline.decorationColor,
244 + fontWeight: FontWeight.w500,
245 + fontSize: 14),
246 + )
247 + ),
248 + isTemplate
249 + ? Offstage()
250 + : Padding(
251 + padding: const EdgeInsets.only(top: 24),
252 + child: Row(
253 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
254 + children: <Widget>[
255 + Text(S.of(context).send_estimated_fee,
256 + style: TextStyle(
257 + fontSize: 12,
258 + fontWeight: FontWeight.w500,
259 + color: Theme.of(context).primaryTextTheme.display2.color,
260 + )),
261 + Text(
262 + sendViewModel.estimatedFee.toString() + ' '
263 + + sendViewModel.currency.title,
264 + style: TextStyle(
265 + fontSize: 12,
266 + fontWeight: FontWeight.w600,
267 + color: Theme.of(context).primaryTextTheme.display2.color,
268 + ))
269 + ],
270 + ),
271 + )
272 + ],
273 + ),
274 + )
275 + ]),
276 ),
258 - isTemplate
259 - ? Offstage()
260 - : Padding(
261 - padding: EdgeInsets.only(
262 - top: 30,
263 - left: 24,
264 - bottom: 24
265 - ),
277 + ),
278 + isTemplate
279 + ? Offstage()
280 + : Padding(
281 + padding: EdgeInsets.only(
282 + top: 30,
283 + left: 24,
284 + bottom: 24
285 + ),
286 + child: Row(
287 + mainAxisAlignment: MainAxisAlignment.start,
288 + children: <Widget>[
289 + Text(
290 + S.of(context).send_templates,
291 + style: TextStyle(
292 + fontSize: 18,
293 + fontWeight: FontWeight.w600,
294 + color: Theme.of(context).primaryTextTheme.title.color
295 + ),
296 + )
297 + ],
298 + ),
299 + ),
300 + isTemplate
301 + ? Offstage()
302 + : Container(
303 + height: 40,
304 + width: double.infinity,
305 + padding: EdgeInsets.only(left: 24),
306 + child: SingleChildScrollView(
307 + scrollDirection: Axis.horizontal,
308 child: Row(
267 - mainAxisAlignment: MainAxisAlignment.start,
309 children: <Widget>[
269 - Text(
270 - S.of(context).send_templates,
271 - style: TextStyle(
272 - fontSize: 18,
273 - fontWeight: FontWeight.w600,
274 - color: PaletteDark.darkCyanBlue
275 - ),
276 - )
277 - ],
278 - ),
279 - ),
280 - isTemplate
281 - ? Offstage()
282 - : Container(
283 - height: 40,
284 - width: double.infinity,
285 - padding: EdgeInsets.only(left: 24),
286 - child: SingleChildScrollView(
287 - scrollDirection: Axis.horizontal,
288 - child: Row(
289 - children: <Widget>[
290 - GestureDetector(
291 - onTap: () => Navigator.of(context)
292 - .pushNamed(Routes.sendTemplate),
293 - child: Container(
294 - padding: EdgeInsets.only(left: 1, right: 10),
295 - child: DottedBorder(
296 - borderType: BorderType.RRect,
297 - dashPattern: [6, 4],
298 - color: PaletteDark.darkCyanBlue,
299 - strokeWidth: 2,
300 - radius: Radius.circular(20),
301 - child: Container(
302 - height: 34,
303 - width: 75,
304 - padding: EdgeInsets.only(left: 10, right: 10),
305 - alignment: Alignment.center,
306 - decoration: BoxDecoration(
307 - borderRadius: BorderRadius.all(Radius.circular(20)),
308 - color: Colors.transparent,
309 - ),
310 - child: Text(
311 - S.of(context).send_new,
312 - style: TextStyle(
313 - fontSize: 14,
314 - fontWeight: FontWeight.w600,
315 - color: PaletteDark.darkCyanBlue
316 - ),
310 + GestureDetector(
311 + onTap: () => Navigator.of(context)
312 + .pushNamed(Routes.sendTemplate),
313 + child: Container(
314 + padding: EdgeInsets.only(left: 1, right: 10),
315 + child: DottedBorder(
316 + borderType: BorderType.RRect,
317 + dashPattern: [6, 4],
318 + color: Theme.of(context).primaryTextTheme.display2.decorationColor,
319 + strokeWidth: 2,
320 + radius: Radius.circular(20),
321 + child: Container(
322 + height: 34,
323 + width: 75,
324 + padding: EdgeInsets.only(left: 10, right: 10),
325 + alignment: Alignment.center,
326 + decoration: BoxDecoration(
327 + borderRadius: BorderRadius.all(Radius.circular(20)),
328 + color: Colors.transparent,
329 + ),
330 + child: Text(
331 + S.of(context).send_new,
332 + style: TextStyle(
333 + fontSize: 14,
334 + fontWeight: FontWeight.w600,
335 + color: Theme.of(context).primaryTextTheme.display3.color
336 ),
318 - )
319 - ),
337 + ),
338 + )
339 ),
340 ),
322 - Observer(
323 - builder: (_) {
324 - final templates = sendViewModel.templates;
325 - final itemCount = templates.length;
341 + ),
342 + Observer(
343 + builder: (_) {
344 + final templates = sendViewModel.templates;
345 + final itemCount = templates.length;
346
327 - return ListView.builder(
328 - scrollDirection: Axis.horizontal,
329 - shrinkWrap: true,
330 - physics: NeverScrollableScrollPhysics(),
331 - itemCount: itemCount,
332 - itemBuilder: (context, index) {
333 - final template = templates[index];
347 + return ListView.builder(
348 + scrollDirection: Axis.horizontal,
349 + shrinkWrap: true,
350 + physics: NeverScrollableScrollPhysics(),
351 + itemCount: itemCount,
352 + itemBuilder: (context, index) {
353 + final template = templates[index];
354
335 - return TemplateTile(
336 - key: UniqueKey(),
337 - to: template.name,
338 - amount: template.amount,
339 - from: template.cryptoCurrency,
340 - onTap: () {
341 - _addressController.text = template.address;
342 - _cryptoAmountController.text = template.amount;
343 - getOpenaliasRecord(context);
344 - },
345 - onRemove: () {
346 - showDialog<void>(
355 + return TemplateTile(
356 + key: UniqueKey(),
357 + to: template.name,
358 + amount: template.amount,
359 + from: template.cryptoCurrency,
360 + onTap: () {
361 + _addressController.text = template.address;
362 + _cryptoAmountController.text = template.amount;
363 + getOpenaliasRecord(context);
364 + },
365 + onRemove: () {
366 + showDialog<void>(
367 context: context,
368 builder: (dialogContext) {
369 return AlertWithTwoActions(
350 - alertTitle: S.of(context).template,
351 - alertContent: S.of(context).confirm_delete_template,
352 - leftButtonText: S.of(context).delete,
353 - rightButtonText: S.of(context).cancel,
354 - actionLeftButton: () {
355 - Navigator.of(dialogContext).pop();
356 - sendViewModel.sendTemplateStore.remove(template: template);
357 - sendViewModel.sendTemplateStore.update();
358 - },
359 - actionRightButton: () => Navigator.of(dialogContext).pop()
370 + alertTitle: S.of(context).template,
371 + alertContent: S.of(context).confirm_delete_template,
372 + leftButtonText: S.of(context).delete,
373 + rightButtonText: S.of(context).cancel,
374 + actionLeftButton: () {
375 + Navigator.of(dialogContext).pop();
376 + sendViewModel.sendTemplateStore.remove(template: template);
377 + sendViewModel.sendTemplateStore.update();
378 + },
379 + actionRightButton: () => Navigator.of(dialogContext).pop()
380 );
381 }
362 - );
363 - },
364 - );
365 - }
366 - );
382 + );
383 + },
384 + );
385 + }
386 + );
387 }
368 - )
369 - ],
370 - ),
388 + )
389 + ],
390 ),
372 - )
373 - ],
374 - ),
375 - bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
376 - bottomSection: isTemplate
377 - ? PrimaryButton(
391 + ),
392 + )
393 + ],
394 + ),
395 + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
396 + bottomSection: isTemplate
397 + ? PrimaryButton(
398 + onPressed: () {
399 + if (_formKey.currentState.validate()) {
400 + sendViewModel.sendTemplateStore.addTemplate(
401 + name: _nameController.text,
402 + address: _addressController.text,
403 + cryptoCurrency: sendViewModel.currency.title,
404 + amount: _cryptoAmountController.text
405 + );
406 + sendViewModel.sendTemplateStore.update();
407 + Navigator.of(context).pop();
408 + }
409 + },
410 + text: S.of(context).save,
411 + color: Colors.green,
412 + textColor: Colors.white)
413 + : Observer(builder: (_) {
414 + return LoadingPrimaryButton(
415 onPressed: () {
416 if (_formKey.currentState.validate()) {
380 - sendViewModel.sendTemplateStore.addTemplate(
381 - name: _nameController.text,
382 - address: _addressController.text,
383 - cryptoCurrency: sendViewModel.currency.title,
384 - amount: _cryptoAmountController.text
385 - );
386 - sendViewModel.sendTemplateStore.update();
387 - Navigator.of(context).pop();
417 + print('SENT!!!');
418 }
419 },
390 - text: S.of(context).save,
391 - color: Colors.green,
392 - textColor: Colors.white)
393 - : Observer(builder: (_) {
394 - return LoadingPrimaryButton(
395 - onPressed: () {
396 - if (_formKey.currentState.validate()) {
397 - print('SENT!!!');
398 - }
399 - },
400 - text: S.of(context).send,
401 - color: Colors.blue,
402 - textColor: Colors.white,
403 - isLoading: sendViewModel.state is TransactionIsCreating ||
404 - sendViewModel.state is TransactionCommitting,
405 - isDisabled:
406 - false // FIXME !(syncStore.status is SyncedSyncStatus),
407 - );
408 - }),
409 - ),
420 + text: S.of(context).send,
421 + color: Palette.blueCraiola,
422 + textColor: Colors.white,
423 + isLoading: sendViewModel.state is TransactionIsCreating ||
424 + sendViewModel.state is TransactionCommitting,
425 + isDisabled:
426 + false // FIXME !(syncStore.status is SyncedSyncStatus),
427 + );
428 + }),
429 );
430 }
431
lib/src/widgets/address_text_field.dart
+12 -4
@@ -112,7 +112,9 @@ class AddressTextField extends StatelessWidget {
112 borderRadius:
113 BorderRadius.all(Radius.circular(6))),
114 child: Image.asset(
115 - 'assets/images/duplicate.png')),
115 + 'assets/images/duplicate.png',
116 + color: Theme.of(context).primaryTextTheme.display1.decorationColor,
117 + )),
118 )),
119 ],
120 if (this.options.contains(AddressTextFieldOption.qrCode)) ...[
@@ -128,7 +130,9 @@ class AddressTextField extends StatelessWidget {
130 color: buttonColor ?? Theme.of(context).accentTextTheme.title.color,
131 borderRadius:
132 BorderRadius.all(Radius.circular(6))),
131 - child: Image.asset('assets/images/qr_code_icon.png')),
133 + child: Image.asset('assets/images/qr_code_icon.png',
134 + color: Theme.of(context).primaryTextTheme.display1.decorationColor,
135 + )),
136 ))
137 ],
138 if (this
@@ -147,7 +151,9 @@ class AddressTextField extends StatelessWidget {
151 borderRadius:
152 BorderRadius.all(Radius.circular(6))),
153 child: Image.asset(
150 - 'assets/images/open_book.png')),
154 + 'assets/images/open_book.png',
155 + color: Theme.of(context).primaryTextTheme.display1.decorationColor,
156 + )),
157 ))
158 ],
159 if (this
@@ -166,7 +172,9 @@ class AddressTextField extends StatelessWidget {
172 borderRadius:
173 BorderRadius.all(Radius.circular(6))),
174 child: Image.asset(
169 - 'assets/images/receive_icon_raw.png')),
175 + 'assets/images/receive_icon_raw.png',
176 + color: Theme.of(context).primaryTextTheme.display1.decorationColor,
177 + )),
178 )),
179 ],
180 ],
lib/src/widgets/template_tile.dart
+2 -3
@@ -47,8 +47,7 @@ class TemplateTileState extends State<TemplateTile> {
47
48 @override
49 Widget build(BuildContext context) {
50 - //final color = isRemovable ? Colors.white : Theme.of(context).primaryTextTheme.title.color;
51 - final color = Colors.white;
50 + final color = isRemovable ? Colors.white : Theme.of(context).primaryTextTheme.title.color;
51 final toIcon = Image.asset('assets/images/to_icon.png', color: color);
52
53 final content = Row(
@@ -106,7 +105,7 @@ class TemplateTileState extends State<TemplateTile> {
105 child: Container(
106 height: 40,
107 padding: EdgeInsets.only(left: 24, right: 24),
109 - color: PaletteDark.darkVioletBlue,
108 + color: Theme.of(context).primaryTextTheme.display3.decorationColor,
109 child: content,
110 ),
111 ),
lib/src/widgets/top_panel.dart
+9 -5
@@ -2,25 +2,28 @@ import 'package:flutter/material.dart';
2
3 class TopPanel extends StatefulWidget {
4 TopPanel({
5 - @required this.color,
5 @required this.widget,
7 - this.edgeInsets = const EdgeInsets.all(24)
6 + this.edgeInsets = const EdgeInsets.all(24),
7 + this.color,
8 + this.gradient
9 });
10
11 final Color color;
12 final Widget widget;
13 final EdgeInsets edgeInsets;
14 + final Gradient gradient;
15
16 @override
15 - TopPanelState createState() => TopPanelState(color, widget, edgeInsets);
17 + TopPanelState createState() => TopPanelState(widget, edgeInsets, color, gradient);
18 }
19
20 class TopPanelState extends State<TopPanel> {
19 - TopPanelState(this._color, this._widget, this._edgeInsets);
21 + TopPanelState(this._widget, this._edgeInsets, this._color, this._gradient);
22
23 final Color _color;
24 final Widget _widget;
25 final EdgeInsets _edgeInsets;
26 + final Gradient _gradient;
27
28 @override
29 Widget build(BuildContext context) {
@@ -32,7 +35,8 @@ class TopPanelState extends State<TopPanel> {
35 bottomLeft: Radius.circular(24),
36 bottomRight: Radius.circular(24)
37 ),
35 - color: _color
38 + color: _color,
39 + gradient: _gradient
40 ),
41 child: _widget,
42 );
lib/store/theme_changer_store.dart new
+13
@@ -0,0 +1,13 @@
1 +import 'package:cake_wallet/theme_changer.dart';
2 +import 'package:mobx/mobx.dart';
3 +
4 +part 'theme_changer_store.g.dart';
5 +
6 +class ThemeChangerStore = ThemeChangerStoreBase with _$ThemeChangerStore;
7 +
8 +abstract class ThemeChangerStoreBase with Store {
9 + ThemeChangerStoreBase({this.themeChanger});
10 +
11 + @observable
12 + ThemeChanger themeChanger;
13 +}
\ No newline at end of file
lib/themes.dart
+33 -18
@@ -80,25 +80,35 @@ class Themes {
80 color: Palette.darkGray, // transaction/trade details titles
81 decorationColor: Colors.white.withOpacity(0.5), // placeholder
82 ),
83 -
84 -
85 -
86 -
83 subhead: TextStyle(
88 - color: Colors.white.withOpacity(0.5) // send, exchange, buy buttons on dashboard page
84 + color: Palette.blueCraiola, // first gradient color (send page)
85 + decorationColor: Palette.pinkFlamingo // second gradient color (send page)
86 ),
87 headline: TextStyle(
91 - color: Palette.lightBlueGrey // historyPanelText
88 + color: Colors.white.withOpacity(0.5), // text field border color (send page)
89 + decorationColor: Colors.white.withOpacity(0.5), // text field hint color (send page)
90 ),
91 display1: TextStyle(
94 - color: Colors.white // menuList
92 + color: Colors.white.withOpacity(0.2), // text field button color (send page)
93 + decorationColor: Colors.white // text field button icon color (send page)
94 ),
95 display2: TextStyle(
97 - color: Palette.lavender // menuHeader
96 + color: Colors.white.withOpacity(0.5), // estimated fee (send page)
97 + decorationColor: Palette.shadowWhite // template dotted border (send page)
98 ),
99 display3: TextStyle(
100 - color: Palette.lavender // historyPanelButton
100 + color: Palette.darkBlueCraiola, // template new text (send page)
101 + decorationColor: Palette.shadowWhite // template background color (send page)
102 ),
103 +
104 +
105 +
106 +
107 +
108 +
109 +
110 +
111 +
112 display4: TextStyle(
113 color: Palette.oceanBlue // QR code
114 ),
@@ -182,7 +192,7 @@ class Themes {
192 decorationColor: PaletteDark.nightBlue // background of tiles (receive page)
193 ),
194 display3: TextStyle(
185 - color: Colors.blue, // text color of current tile (receive page)
195 + color: Palette.blueCraiola, // text color of current tile (receive page)
196 decorationColor: PaletteDark.lightOceanBlue // background of current tile (receive page)
197 ),
198 display4: TextStyle(
@@ -215,24 +225,29 @@ class Themes {
225 color: PaletteDark.lightBlueGrey, // transaction/trade details titles
226 decorationColor: Colors.grey, // placeholder
227 ),
218 -
219 -
220 -
228 subhead: TextStyle(
222 - color: PaletteDark.lightDistantBlue // send, exchange, buy buttons on dashboard page
229 + color: PaletteDark.darkNightBlue, // first gradient color (send page)
230 + decorationColor: PaletteDark.darkNightBlue // second gradient color (send page)
231 ),
232 headline: TextStyle(
225 - color: PaletteDark.pigeonBlue // historyPanelText
233 + color: PaletteDark.lightVioletBlue, // text field border color (send page)
234 + decorationColor: PaletteDark.darkCyanBlue, // text field hint color (send page)
235 ),
236 display1: TextStyle(
228 - color: PaletteDark.lightNightBlue // menuList
237 + color: PaletteDark.buttonNightBlue, // text field button color (send page)
238 + decorationColor: PaletteDark.gray // text field button icon color (send page)
239 ),
240 display2: TextStyle(
231 - color: PaletteDark.headerNightBlue // menuHeader
241 + color: Colors.white, // estimated fee (send page)
242 + decorationColor: PaletteDark.darkCyanBlue // template dotted border (send page)
243 ),
244 display3: TextStyle(
234 - color: PaletteDark.moderateNightBlue // historyPanelButton
245 + color: PaletteDark.darkCyanBlue, // template new text (send page)
246 + decorationColor: PaletteDark.darkVioletBlue // template background color (send page)
247 ),
248 +
249 +
250 +
251 display4: TextStyle(
252 color: PaletteDark.gray // QR code
253 ),
lib/view_model/settings/settings_view_model.dart
+6 -1
@@ -1,3 +1,6 @@
1 +import 'package:cake_wallet/di.dart';
2 +import 'package:cake_wallet/store/theme_changer_store.dart';
3 +import 'package:cake_wallet/themes.dart';
4 import 'package:flutter/cupertino.dart';
5 import 'package:mobx/mobx.dart';
6 import 'package:cake_wallet/routes.dart';
@@ -69,7 +72,9 @@ abstract class SettingsViewModelBase with Store {
72 title: S.current.settings_dark_mode,
73 value: () => _settingsStore.isDarkTheme,
74 onValueChange: (bool value) {
72 - // FIXME: Implement me
75 + _settingsStore.isDarkTheme = value;
76 + getIt.get<ThemeChangerStore>().themeChanger.setTheme(
77 + value ? Themes.darkTheme : Themes.lightTheme);
78 })
79 ],
80 [