CWA-216 | applied new design to disclaimer page and faq page
Oleksandr Sobol committed
May 22, 2020 at 19:15 UTC
2356cda87918e2d557888735ae5bec35116320b6
2 files changed
+332
-261
lib/src/screens/disclaimer/disclaimer_page.dart
+230
-229
@@ -6,6 +6,8 @@ import 'package:cake_wallet/palette.dart';
6
import 'package:url_launcher/url_launcher.dart';
7
import 'package:cake_wallet/src/screens/base_page.dart';
8
import 'package:cake_wallet/src/widgets/primary_button.dart';
9
+import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
10
+import 'package:cake_wallet/generated/i18n.dart';
11
12
class DisclaimerPage extends BasePage {
13
DisclaimerPage({this.isReadOnly = false});
@@ -13,7 +15,7 @@ class DisclaimerPage extends BasePage {
15
final bool isReadOnly;
16
17
@override
16
- bool get isModalBackButton => false;
18
+ Color get backgroundColor => PaletteDark.historyPanel;
19
20
@override
21
String get title => 'Terms of Use';
@@ -34,7 +36,7 @@ class DisclaimerPageBody extends StatefulWidget {
36
class DisclaimerBodyState extends State<DisclaimerPageBody> {
37
DisclaimerBodyState(this._isAccepted);
38
37
- static const xmrtoUrl = 'https://xmr.to/app_static/html/tos.html';
39
+ static const xmrtoUrl = 'https://xmr.to/terms-of-service';
40
static const changenowUrl = 'https://changenow.io/terms-of-use';
41
static const morphUrl = 'http://morphtoken.com/terms';
42
@@ -55,22 +57,11 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
57
await showDialog<void>(
58
context: context,
59
builder: (BuildContext context) {
58
- return AlertDialog(
59
- title: Text(
60
- 'Terms and conditions',
61
- textAlign: TextAlign.center,
62
- ),
63
- content: Text(
64
- 'By using this app, you agree to the Terms of Agreement set forth to below',
65
- textAlign: TextAlign.center,
66
- ),
67
- actions: <Widget>[
68
- FlatButton(
69
- onPressed: () {
70
- Navigator.of(context).pop();
71
- },
72
- child: Text('OK')),
73
- ],
60
+ return AlertWithOneAction(
61
+ alertTitle: 'Terms and conditions',
62
+ alertContent: 'By using this app, you agree to the Terms of Agreement set forth to below',
63
+ buttonText: S.of(context).ok,
64
+ buttonAction: () => Navigator.of(context).pop()
65
);
66
});
67
}
@@ -86,245 +77,255 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
77
78
@override
79
Widget build(BuildContext context) {
89
- return Column(
90
- children: <Widget>[
91
- SizedBox(height: 10.0),
92
- Expanded(
93
- child: Stack(
94
- children: <Widget>[
95
- SingleChildScrollView(
96
- padding: EdgeInsets.only(left: 25.0, right: 25.0),
97
- child: Column(
80
+ return Container(
81
+ color: PaletteDark.historyPanel,
82
+ child: Column(
83
+ children: <Widget>[
84
+ SizedBox(height: 10.0),
85
+ Expanded(
86
+ child: Stack(
87
children: <Widget>[
99
- !_isAccepted
100
- ? Row(
88
+ SingleChildScrollView(
89
+ padding: EdgeInsets.only(left: 24.0, right: 24.0),
90
+ child: Column(
91
+ children: <Widget>[
92
+ !_isAccepted
93
+ ? Row(
94
children: <Widget>[
95
Expanded(
96
child: Text(
97
'Terms and conditions',
98
textAlign: TextAlign.center,
99
style: TextStyle(
107
- fontSize: 20.0,
108
- fontWeight: FontWeight.bold),
100
+ fontSize: 20.0,
101
+ fontWeight: FontWeight.bold,
102
+ color: Colors.white
103
+ ),
104
),
105
)
106
],
107
)
113
- : Offstage(),
114
- !_isAccepted
115
- ? SizedBox(
108
+ : Offstage(),
109
+ !_isAccepted
110
+ ? SizedBox(
111
height: 20.0,
112
)
118
- : Offstage(),
119
- Row(
120
- children: <Widget>[
121
- Expanded(
122
- child: Text(
123
- 'Legal Disclaimer\nAnd\nTerms of Use',
124
- textAlign: TextAlign.center,
125
- style: TextStyle(
126
- fontSize: 12.0, fontWeight: FontWeight.bold),
113
+ : Offstage(),
114
+ Row(
115
+ children: <Widget>[
116
+ Expanded(
117
+ child: Text(
118
+ 'Legal Disclaimer\nAnd\nTerms of Use',
119
+ textAlign: TextAlign.center,
120
+ style: TextStyle(
121
+ fontSize: 12.0,
122
+ fontWeight: FontWeight.bold,
123
+ color: Colors.white
124
+ ),
125
+ ),
126
+ )
127
+ ],
128
),
128
- )
129
- ],
130
- ),
131
- SizedBox(
132
- height: 16.0,
133
- ),
134
- Row(
135
- children: <Widget>[
136
- Expanded(
137
- child: Text(
138
- _fileText,
139
- style: TextStyle(fontSize: 12.0),
140
- ))
141
- ],
142
- ),
143
- SizedBox(
144
- height: 16.0,
145
- ),
146
- Row(
147
- mainAxisAlignment: MainAxisAlignment.start,
148
- children: <Widget>[
149
- Expanded(
150
- child: Text(
151
- 'Other Terms and Conditions',
152
- textAlign: TextAlign.left,
153
- style: TextStyle(
154
- fontSize: 14.0, fontWeight: FontWeight.bold),
129
+ SizedBox(
130
+ height: 16.0,
131
),
156
- )
157
- ],
158
- ),
159
- SizedBox(
160
- height: 16.0,
161
- ),
162
- Row(
163
- mainAxisAlignment: MainAxisAlignment.start,
164
- children: <Widget>[
165
- Expanded(
166
- child: GestureDetector(
167
- onTap: () => launchUrl(xmrtoUrl),
168
- child: Text(
169
- xmrtoUrl,
170
- textAlign: TextAlign.left,
171
- style: TextStyle(
172
- color: Colors.blue,
173
- fontSize: 14.0,
174
- fontWeight: FontWeight.normal,
175
- decoration: TextDecoration.underline),
132
+ Row(
133
+ children: <Widget>[
134
+ Expanded(
135
+ child: Text(
136
+ _fileText,
137
+ style: TextStyle(
138
+ fontSize: 12.0,
139
+ color: Colors.white
140
+ ),
141
+ ))
142
+ ],
143
),
177
- ))
178
- ],
179
- ),
180
- SizedBox(
181
- height: 16.0,
182
- ),
183
- Row(
184
- mainAxisAlignment: MainAxisAlignment.start,
185
- children: <Widget>[
186
- Expanded(
187
- child: GestureDetector(
188
- onTap: () => launchUrl(changenowUrl),
189
- child: Text(
190
- changenowUrl,
191
- textAlign: TextAlign.left,
192
- style: TextStyle(
193
- color: Colors.blue,
194
- fontSize: 14.0,
195
- fontWeight: FontWeight.normal,
196
- decoration: TextDecoration.underline),
144
+ SizedBox(
145
+ height: 16.0,
146
),
198
- ))
199
- ],
200
- ),
201
- SizedBox(
202
- height: 16.0,
147
+ Row(
148
+ mainAxisAlignment: MainAxisAlignment.start,
149
+ children: <Widget>[
150
+ Expanded(
151
+ child: Text(
152
+ 'Other Terms and Conditions',
153
+ textAlign: TextAlign.left,
154
+ style: TextStyle(
155
+ fontSize: 14.0,
156
+ fontWeight: FontWeight.bold,
157
+ color: Colors.white
158
+ ),
159
+ ),
160
+ )
161
+ ],
162
+ ),
163
+ SizedBox(
164
+ height: 16.0,
165
+ ),
166
+ Row(
167
+ mainAxisAlignment: MainAxisAlignment.start,
168
+ children: <Widget>[
169
+ Expanded(
170
+ child: GestureDetector(
171
+ onTap: () => launchUrl(xmrtoUrl),
172
+ child: Text(
173
+ xmrtoUrl,
174
+ textAlign: TextAlign.left,
175
+ style: TextStyle(
176
+ color: Colors.blue,
177
+ fontSize: 14.0,
178
+ fontWeight: FontWeight.normal,
179
+ decoration: TextDecoration.underline),
180
+ ),
181
+ ))
182
+ ],
183
+ ),
184
+ SizedBox(
185
+ height: 16.0,
186
+ ),
187
+ Row(
188
+ mainAxisAlignment: MainAxisAlignment.start,
189
+ children: <Widget>[
190
+ Expanded(
191
+ child: GestureDetector(
192
+ onTap: () => launchUrl(changenowUrl),
193
+ child: Text(
194
+ changenowUrl,
195
+ textAlign: TextAlign.left,
196
+ style: TextStyle(
197
+ color: Colors.blue,
198
+ fontSize: 14.0,
199
+ fontWeight: FontWeight.normal,
200
+ decoration: TextDecoration.underline),
201
+ ),
202
+ ))
203
+ ],
204
+ ),
205
+ SizedBox(
206
+ height: 16.0,
207
+ ),
208
+ Row(
209
+ mainAxisAlignment: MainAxisAlignment.start,
210
+ children: <Widget>[
211
+ Expanded(
212
+ child: GestureDetector(
213
+ onTap: () => launchUrl(morphUrl),
214
+ child: Text(
215
+ morphUrl,
216
+ textAlign: TextAlign.left,
217
+ style: TextStyle(
218
+ color: Colors.blue,
219
+ fontSize: 14.0,
220
+ fontWeight: FontWeight.normal,
221
+ decoration: TextDecoration.underline),
222
+ ),
223
+ ))
224
+ ],
225
+ ),
226
+ SizedBox(
227
+ height: 16.0,
228
+ )
229
+ ],
230
+ ),
231
),
204
- Row(
205
- mainAxisAlignment: MainAxisAlignment.start,
206
- children: <Widget>[
207
- Expanded(
208
- child: GestureDetector(
209
- onTap: () => launchUrl(morphUrl),
210
- child: Text(
211
- morphUrl,
212
- textAlign: TextAlign.left,
213
- style: TextStyle(
214
- color: Colors.blue,
215
- fontSize: 14.0,
216
- fontWeight: FontWeight.normal,
217
- decoration: TextDecoration.underline),
232
+ Container(
233
+ alignment: Alignment.bottomCenter,
234
+ child: Container(
235
+ height: 12.0,
236
+ child: ClipRect(
237
+ child: BackdropFilter(
238
+ filter: ImageFilter.blur(sigmaX: 0.7, sigmaY: 0.7),
239
+ child: Container(
240
+ decoration: BoxDecoration(
241
+ gradient: LinearGradient(
242
+ colors: [
243
+ PaletteDark.historyPanel.withOpacity(0.0),
244
+ PaletteDark.historyPanel,
245
+ ],
246
+ begin: FractionalOffset.topCenter,
247
+ end: FractionalOffset.bottomCenter,
248
+ ),
249
),
219
- ))
220
- ],
221
- ),
222
- SizedBox(
223
- height: 16.0,
250
+ ),
251
+ ),
252
+ ),
253
+ ),
254
)
255
],
226
- ),
227
- ),
228
- Container(
229
- alignment: Alignment.bottomCenter,
230
- child: Container(
231
- height: 12.0,
232
- child: ClipRect(
233
- child: BackdropFilter(
234
- filter: ImageFilter.blur(sigmaX: 0.7, sigmaY: 0.7),
235
- child: Container(
236
- decoration: BoxDecoration(
237
- gradient: LinearGradient(
238
- colors: [
239
- Theme.of(context).backgroundColor.withOpacity(0.0),
240
- Theme.of(context).backgroundColor,
256
+ )),
257
+ if (!widget.isReadOnly) ...[
258
+ !_isAccepted
259
+ ? Row(
260
+ children: <Widget>[
261
+ Expanded(
262
+ child: Container(
263
+ padding: EdgeInsets.only(
264
+ left: 24.0, top: 10.0, right: 24.0, bottom: 10.0),
265
+ child: InkWell(
266
+ onTap: () {
267
+ setState(() {
268
+ _checked = !_checked;
269
+ });
270
+ },
271
+ child: Row(
272
+ mainAxisAlignment: MainAxisAlignment.start,
273
+ children: <Widget>[
274
+ Container(
275
+ height: 24.0,
276
+ width: 24.0,
277
+ margin: EdgeInsets.only(
278
+ right: 10.0,
279
+ ),
280
+ decoration: BoxDecoration(
281
+ border: Border.all(
282
+ color: Palette.lightGrey, width: 1.0),
283
+ borderRadius: BorderRadius.all(
284
+ Radius.circular(8.0)),
285
+ color: PaletteDark.historyPanel),
286
+ child: _checked
287
+ ? Icon(
288
+ Icons.check,
289
+ color: Colors.blue,
290
+ size: 20.0,
291
+ )
292
+ : null,
293
+ ),
294
+ Text(
295
+ 'I agree to Terms of Use',
296
+ style: TextStyle(
297
+ fontWeight: FontWeight.bold,
298
+ fontSize: 14.0,
299
+ color: Colors.white
300
+ ),
301
+ )
302
],
242
- begin: FractionalOffset.topCenter,
243
- end: FractionalOffset.bottomCenter,
303
),
245
- ),
246
- ),
247
- ),
304
+ )),
305
),
306
+ ],
307
+ )
308
+ : Offstage(),
309
+ !_isAccepted
310
+ ? Container(
311
+ padding:
312
+ EdgeInsets.only(left: 24.0, right: 24.0, bottom: 24.0),
313
+ child: PrimaryButton(
314
+ onPressed: _checked ? () {} : null,
315
+ text: 'Accept',
316
+ color: Colors.green,
317
+ textColor: Colors.white,
318
),
319
)
320
+ : Offstage(),
321
+ _isAccepted
322
+ ? SizedBox(
323
+ height: 24.0,
324
+ )
325
+ : Offstage()
326
],
252
- )),
253
- if (!widget.isReadOnly) ...[
254
- !_isAccepted
255
- ? Row(
256
- children: <Widget>[
257
- Expanded(
258
- child: Container(
259
- padding: EdgeInsets.only(
260
- left: 25.0, top: 10.0, right: 25.0, bottom: 10.0),
261
- child: InkWell(
262
- onTap: () {
263
- setState(() {
264
- _checked = !_checked;
265
- });
266
- },
267
- child: Row(
268
- mainAxisAlignment: MainAxisAlignment.start,
269
- children: <Widget>[
270
- Container(
271
- height: 25.0,
272
- width: 25.0,
273
- margin: EdgeInsets.only(
274
- right: 10.0,
275
- ),
276
- decoration: BoxDecoration(
277
- border: Border.all(
278
- color: Palette.lightGrey, width: 1.0),
279
- borderRadius: BorderRadius.all(
280
- Radius.circular(8.0)),
281
- color: Theme.of(context).backgroundColor),
282
- child: _checked
283
- ? Icon(
284
- Icons.check,
285
- color: Colors.blue,
286
- size: 20.0,
287
- )
288
- : null,
289
- ),
290
- Text(
291
- 'I agree to Terms of Use',
292
- style: TextStyle(
293
- fontWeight: FontWeight.bold,
294
- fontSize: 14.0),
295
- )
296
- ],
297
- ),
298
- )),
299
- ),
300
- ],
301
- )
302
- : Offstage(),
303
- !_isAccepted
304
- ? Container(
305
- padding:
306
- EdgeInsets.only(left: 25.0, right: 25.0, bottom: 25.0),
307
- child: PrimaryButton(
308
- onPressed: _checked ? () {} : null,
309
- text: 'Accept',
310
- color: Theme.of(context)
311
- .primaryTextTheme
312
- .button
313
- .backgroundColor,
314
- textColor: Theme.of(context)
315
- .primaryTextTheme
316
- .button
317
- .color,
318
- ),
319
- )
320
- : Offstage(),
321
- _isAccepted
322
- ? SizedBox(
323
- height: 20.0,
324
- )
325
- : Offstage()
327
],
327
- ],
328
+ ),
329
);
330
}
331
}
lib/src/screens/faq/faq_page.dart
+102
-32
@@ -1,11 +1,11 @@
1
import 'dart:convert';
2
-import 'package:cake_wallet/palette.dart';
2
import 'package:flutter/material.dart';
3
import 'package:flutter/services.dart';
4
import 'package:provider/provider.dart';
5
import 'package:cake_wallet/generated/i18n.dart';
6
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
7
import 'package:cake_wallet/src/screens/base_page.dart';
8
+import 'package:cake_wallet/palette.dart';
9
10
class FaqPage extends BasePage {
11
@override
@@ -15,7 +15,23 @@ class FaqPage extends BasePage {
15
Color get backgroundColor => PaletteDark.historyPanel;
16
17
@override
18
- Widget body(BuildContext context) {
18
+ Widget body(BuildContext context) => FaqForm();
19
+}
20
+
21
+class FaqForm extends StatefulWidget {
22
+ @override
23
+ FaqFormState createState() => FaqFormState();
24
+}
25
+
26
+class FaqFormState extends State<FaqForm> {
27
+ final addIcon = Icon(Icons.add, color: Colors.white);
28
+ final removeIcon = Icon(Icons.remove, color: Colors.green);
29
+ List<Icon> icons;
30
+ List<Color> colors;
31
+ bool isLoaded = false;
32
+
33
+ @override
34
+ Widget build(BuildContext context) {
35
return Container(
36
color: PaletteDark.historyPanel,
37
padding: EdgeInsets.only(top: 12),
@@ -25,36 +41,79 @@ class FaqPage extends BasePage {
41
builder: (context, snapshot) {
42
final faqItems = jsonDecode(snapshot.data.toString()) as List;
43
28
- return ListView.separated(
29
- itemBuilder: (BuildContext context, int index) {
30
- final itemTitle = faqItems[index]["question"].toString();
31
- final itemChild = faqItems[index]["answer"].toString();
44
+ if (snapshot.hasData) {
45
+ setIconsAndColors(faqItems.length);
46
+ }
47
+
48
+ return SingleChildScrollView(
49
+ child: ListView.separated(
50
+ shrinkWrap: true,
51
+ physics: NeverScrollableScrollPhysics(),
52
+ itemBuilder: (BuildContext context, int index) {
53
+ final itemTitle = faqItems[index]["question"].toString();
54
+ final itemChild = faqItems[index]["answer"].toString();
55
33
- return ExpansionTile(
34
- title: Padding(
35
- padding: EdgeInsets.only(left: 8, top: 12, bottom: 12),
36
- child: Text(itemTitle),
37
- ),
38
- backgroundColor: PaletteDark.menuHeader,
39
- children: <Widget>[
40
- Row(
41
- mainAxisAlignment: MainAxisAlignment.start,
42
- children: <Widget>[
43
- Expanded(
44
- child: Container(
45
- padding: EdgeInsets.only(left: 24.0, right: 24.0, bottom: 4),
46
- child: Text(
47
- itemChild,
48
- ),
49
- ))
50
- ],
51
- )
52
- ],
53
- );
54
- },
55
- separatorBuilder: (_, __) =>
56
- Divider(color: PaletteDark.mainBackgroundColor, height: 1.0),
57
- itemCount: faqItems == null ? 0 : faqItems.length,
56
+ return ExpansionTile(
57
+ title: Padding(
58
+ padding: EdgeInsets.only(left: 8, top: 12, bottom: 12),
59
+ child: Text(
60
+ itemTitle,
61
+ style: TextStyle(
62
+ fontSize: 14,
63
+ fontWeight: FontWeight.w600,
64
+ color: colors[index]
65
+ ),
66
+ ),
67
+ ),
68
+ trailing: Padding(
69
+ padding: EdgeInsets.only(right: 24),
70
+ child: Container(
71
+ width: double.minPositive,
72
+ child: Center(
73
+ child: icons[index]
74
+ ),
75
+ ),
76
+ ),
77
+ backgroundColor: PaletteDark.menuHeader,
78
+ onExpansionChanged: (value) {
79
+ setState(() {
80
+ if (value) {
81
+ icons[index] = removeIcon;
82
+ colors[index] = Colors.green;
83
+ } else {
84
+ icons[index] = addIcon;
85
+ colors[index] = Colors.white;
86
+ }
87
+ });
88
+ },
89
+ children: <Widget>[
90
+ Row(
91
+ mainAxisAlignment: MainAxisAlignment.start,
92
+ children: <Widget>[
93
+ Expanded(
94
+ child: Container(
95
+ padding: EdgeInsets.only(
96
+ left: 24.0,
97
+ right: 24.0,
98
+ bottom: 8
99
+ ),
100
+ child: Text(
101
+ itemChild,
102
+ style: TextStyle(
103
+ fontSize: 12,
104
+ color: Colors.white
105
+ ),
106
+ ),
107
+ ))
108
+ ],
109
+ )
110
+ ],
111
+ );
112
+ },
113
+ separatorBuilder: (_, __) =>
114
+ Container(color: PaletteDark.mainBackgroundColor, height: 1.0),
115
+ itemCount: faqItems == null ? 0 : faqItems.length,
116
+ ),
117
);
118
},
119
future: rootBundle.loadString(getFaqPath(context)),
@@ -63,6 +122,17 @@ class FaqPage extends BasePage {
122
);
123
}
124
125
+ void setIconsAndColors(int index) {
126
+ if (isLoaded) {
127
+ return;
128
+ }
129
+
130
+ icons = List.generate(index, (int i) => addIcon);
131
+ colors = List.generate(index, (int i) => Colors.white);
132
+
133
+ isLoaded = true;
134
+ }
135
+
136
String getFaqPath(BuildContext context) {
137
final settingsStore = Provider.of<SettingsStore>(context);
138
@@ -95,4 +165,4 @@ class FaqPage extends BasePage {
165
return 'assets/faq/faq_en.json';
166
}
167
}
98
-}
168
+}
\ No newline at end of file