CAKE-150
M committed
Nov 4, 2020 at 00:29 UTC
7e33f1ae0afad359a4f86996e71afb3f7bffe5b5
5 files changed
+188
-165
lib/src/screens/restore/wallet_restore_from_seed_form.dart
+5
@@ -46,6 +46,11 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
46
context: context,
47
builder: (BuildContext context) =>
48
SeedLanguagePicker(selected: language));
49
+
50
+ if (selected == null || selected.isEmpty) {
51
+ return;
52
+ }
53
+
54
_changeLanguage(selected);
55
},
56
child: Container(
lib/src/screens/seed_language/widgets/seed_language_picker.dart
+1
@@ -92,6 +92,7 @@ class SeedLanguagePickerState extends State<SeedLanguagePicker> {
92
width: 300,
93
color: Theme.of(context).accentTextTheme.title.backgroundColor,
94
child: GridView.count(
95
+ padding: EdgeInsets.all(0),
96
shrinkWrap: true,
97
crossAxisCount: 3,
98
childAspectRatio: 1,
lib/src/widgets/annotated_editable_text.dart
deleted
-160
@@ -1,160 +0,0 @@
1
-import 'package:flutter/material.dart';
2
-
3
-class Annotation extends Comparable<Annotation> {
4
- Annotation({@required this.range, this.style});
5
-
6
- final TextRange range;
7
- final TextStyle style;
8
-
9
- @override
10
- int compareTo(Annotation other) => range.start.compareTo(other.range.start);
11
-}
12
-
13
-class TextAnnotation extends Comparable<TextAnnotation> {
14
- TextAnnotation({@required this.text, this.style});
15
-
16
- final TextStyle style;
17
- final String text;
18
-
19
- @override
20
- int compareTo(TextAnnotation other) => text.compareTo(other.text);
21
-}
22
-
23
-class AnnotatedEditableText extends EditableText {
24
- AnnotatedEditableText({
25
- Key key,
26
- FocusNode focusNode,
27
- TextEditingController controller,
28
- TextStyle style,
29
- ValueChanged<String> onChanged,
30
- ValueChanged<String> onSubmitted,
31
- Color cursorColor,
32
- Color selectionColor,
33
- Color backgroundCursorColor,
34
- TextSelectionControls selectionControls,
35
- TextStyle textStyle = const TextStyle(
36
- color: Colors.black,
37
- backgroundColor: Colors.transparent,
38
- fontWeight: FontWeight.normal,
39
- fontSize: 16),
40
- @required this.words,
41
- }) : textAnnotations = words
42
- .map((word) => TextAnnotation(text: word, style: textStyle))
43
- .toList(),
44
- super(
45
- maxLines: null,
46
- key: key,
47
- focusNode: focusNode,
48
- controller: controller,
49
- cursorColor: cursorColor,
50
- style: style,
51
- keyboardType: TextInputType.text,
52
- autocorrect: false,
53
- autofocus: false,
54
- selectionColor: selectionColor,
55
- selectionControls: selectionControls,
56
- backgroundCursorColor: backgroundCursorColor,
57
- onChanged: onChanged,
58
- onSubmitted: onSubmitted,
59
- toolbarOptions: const ToolbarOptions(
60
- copy: true,
61
- cut: true,
62
- paste: true,
63
- selectAll: true,
64
- ),
65
- enableSuggestions: false,
66
- enableInteractiveSelection: true,
67
- showSelectionHandles: true,
68
- showCursor: true,
69
- ) {
70
- textAnnotations.add(TextAnnotation(
71
- text: ' ', style: TextStyle(backgroundColor: Colors.transparent)));
72
- }
73
-
74
- final List<String> words;
75
- final List<TextAnnotation> textAnnotations;
76
-
77
- @override
78
- AnnotatedEditableTextState createState() => AnnotatedEditableTextState();
79
-}
80
-
81
-class AnnotatedEditableTextState extends EditableTextState {
82
- @override
83
- AnnotatedEditableText get widget => super.widget as AnnotatedEditableText;
84
-
85
- List<Annotation> getRanges() {
86
- final source = widget.textAnnotations
87
- .map((item) => range(item.text, textEditingValue.text)
88
- .map((range) => Annotation(style: item.style, range: range)))
89
- .expand((e) => e)
90
- .toList();
91
- final result = List<Annotation>();
92
- final text = textEditingValue.text;
93
- source.sort();
94
- Annotation prev;
95
-
96
- for (var item in source) {
97
- if (prev == null) {
98
- if (item.range.start > 0) {
99
- result.add(Annotation(
100
- range: TextRange(start: 0, end: item.range.start),
101
- style: TextStyle(
102
- color: Colors.black, backgroundColor: Colors.transparent)));
103
- }
104
- result.add(item);
105
- prev = item;
106
- continue;
107
- } else {
108
- if (prev.range.end > item.range.start) {
109
- // throw StateError('Invalid (intersecting) ranges for annotated field');
110
- } else if (prev.range.end < item.range.start) {
111
- result.add(Annotation(
112
- range: TextRange(start: prev.range.end, end: item.range.start),
113
- style: TextStyle(
114
- color: Colors.red, backgroundColor: Colors.transparent)));
115
- }
116
-
117
- result.add(item);
118
- prev = item;
119
- }
120
- }
121
-
122
- if (result.length > 0 && result.last.range.end < text.length) {
123
- result.add(Annotation(
124
- range: TextRange(start: result.last.range.end, end: text.length),
125
- style: TextStyle(backgroundColor: Colors.transparent)));
126
- }
127
- return result;
128
- }
129
-
130
- List<TextRange> range(String pattern, String source) {
131
- final result = List<TextRange>();
132
-
133
- for (int index = source.indexOf(pattern);
134
- index >= 0;
135
- index = source.indexOf(pattern, index + 1)) {
136
- final start = index;
137
- final end = start + pattern.length;
138
- result.add(TextRange(start: start, end: end));
139
- }
140
-
141
- return result;
142
- }
143
-
144
- @override
145
- TextSpan buildTextSpan() {
146
- final text = textEditingValue.text;
147
- final ranges = getRanges();
148
-
149
- if (ranges.isNotEmpty) {
150
- return TextSpan(
151
- style: widget.style,
152
- children: ranges
153
- .map((item) => TextSpan(
154
- style: item.style, text: item.range.textInside(text)))
155
- .toList());
156
- }
157
-
158
- return TextSpan(style: widget.style, text: text);
159
- }
160
-}
lib/src/widgets/seed_widget.dart
+10
-5
@@ -1,5 +1,5 @@
1
import 'package:cake_wallet/entities/wallet_type.dart';
2
-import 'package:cake_wallet/src/widgets/annotated_editable_text.dart';
2
+import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
3
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
4
import 'package:flutter/cupertino.dart';
5
import 'package:flutter/material.dart';
@@ -77,10 +77,15 @@ class SeedWidgetState extends State<SeedWidget> {
77
fontSize: 16.0, color: Theme.of(context).hintColor))),
78
Padding(
79
padding: EdgeInsets.only(right: 40, top: 10),
80
- child: AnnotatedEditableText(
80
+ child: ValidableAnnotatedEditableText(
81
cursorColor: Colors.blue,
82
backgroundCursorColor: Colors.blue,
83
- style: TextStyle(
83
+ validStyle: TextStyle(
84
+ color: Theme.of(context).primaryTextTheme.title.color,
85
+ backgroundColor: Colors.transparent,
86
+ fontWeight: FontWeight.normal,
87
+ fontSize: 16),
88
+ invalidStyle: TextStyle(
89
fontSize: 16,
90
color: Colors.red,
91
fontWeight: FontWeight.normal,
@@ -101,7 +106,7 @@ class SeedWidgetState extends State<SeedWidget> {
106
width: 34,
107
height: 34,
108
child: InkWell(
104
- onTap: () async => _pasteAddress(),
109
+ onTap: () async => _pasteText(),
110
child: Container(
111
padding: EdgeInsets.all(8),
112
decoration: BoxDecoration(
@@ -122,7 +127,7 @@ class SeedWidgetState extends State<SeedWidget> {
127
]));
128
}
129
125
- Future<void> _pasteAddress() async {
130
+ Future<void> _pasteText() async {
131
final value = await Clipboard.getData('text/plain');
132
133
if (value?.text?.isNotEmpty ?? false) {
lib/src/widgets/validable_annotated_editable_text.dart
new
+172
@@ -0,0 +1,172 @@
1
+import 'package:cake_wallet/core/seed_validator.dart';
2
+import 'package:cake_wallet/entities/wallet_type.dart';
3
+import 'package:flutter/material.dart';
4
+
5
+class Annotation extends Comparable<Annotation> {
6
+ Annotation({@required this.range, this.style});
7
+
8
+ final TextRange range;
9
+ final TextStyle style;
10
+
11
+ @override
12
+ int compareTo(Annotation other) => range.start.compareTo(other.range.start);
13
+}
14
+
15
+class TextAnnotation extends Comparable<TextAnnotation> {
16
+ TextAnnotation({@required this.text, this.style});
17
+
18
+ final TextStyle style;
19
+ final String text;
20
+
21
+ @override
22
+ int compareTo(TextAnnotation other) => text.compareTo(other.text);
23
+}
24
+
25
+class ValidableAnnotatedEditableText extends EditableText {
26
+ ValidableAnnotatedEditableText({
27
+ Key key,
28
+ FocusNode focusNode,
29
+ TextEditingController controller,
30
+ List<String> wordList,
31
+ ValueChanged<String> onChanged,
32
+ ValueChanged<String> onSubmitted,
33
+ Color cursorColor,
34
+ Color selectionColor,
35
+ Color backgroundCursorColor,
36
+ TextSelectionControls selectionControls,
37
+ this.validStyle,
38
+ this.invalidStyle,
39
+ TextStyle textStyle = const TextStyle(
40
+ color: Colors.black,
41
+ backgroundColor: Colors.transparent,
42
+ fontWeight: FontWeight.normal,
43
+ fontSize: 16),
44
+ @required this.words,
45
+ }) : super(
46
+ maxLines: null,
47
+ key: key,
48
+ focusNode: focusNode,
49
+ controller: controller,
50
+ cursorColor: cursorColor,
51
+ style: validStyle,
52
+ keyboardType: TextInputType.text,
53
+ autocorrect: false,
54
+ autofocus: false,
55
+ selectionColor: selectionColor,
56
+ selectionControls: selectionControls,
57
+ backgroundCursorColor: backgroundCursorColor,
58
+ onChanged: onChanged,
59
+ onSubmitted: onSubmitted,
60
+ toolbarOptions: const ToolbarOptions(
61
+ copy: true,
62
+ cut: true,
63
+ paste: true,
64
+ selectAll: true,
65
+ ),
66
+ enableSuggestions: false,
67
+ enableInteractiveSelection: true,
68
+ showSelectionHandles: true,
69
+ showCursor: true);
70
+
71
+ final List<String> words;
72
+ final TextStyle validStyle;
73
+ final TextStyle invalidStyle;
74
+
75
+ @override
76
+ ValidableAnnotatedEditableTextState createState() => ValidableAnnotatedEditableTextState();
77
+}
78
+
79
+class ValidableAnnotatedEditableTextState extends EditableTextState {
80
+ @override
81
+ ValidableAnnotatedEditableText get widget => super.widget as ValidableAnnotatedEditableText;
82
+
83
+ List<Annotation> getRanges() {
84
+ final result = List<Annotation>();
85
+ final text = textEditingValue.text;
86
+ final source = text
87
+ .split(' ')
88
+ .map((word) {
89
+ final ranges = range(word, text);
90
+ final isValid = validate(word);
91
+
92
+ return ranges.map((range) => Annotation(
93
+ style: isValid ? widget.validStyle : widget.invalidStyle,
94
+ range: range));
95
+ })
96
+ .expand((e) => e)
97
+ .toList();
98
+ source.sort();
99
+ Annotation prev;
100
+
101
+ for (var item in source) {
102
+ Annotation annotation;
103
+
104
+ if (prev == null) {
105
+ annotation = Annotation(
106
+ range: TextRange(start: 0, end: item.range.start),
107
+ style: TextStyle(
108
+ color: Colors.black, backgroundColor: Colors.transparent));
109
+ } else if (prev.range.end < item.range.start) {
110
+ annotation = Annotation(
111
+ range: TextRange(start: prev.range.end, end: item.range.start),
112
+ style: TextStyle(
113
+ color: Colors.red, backgroundColor: Colors.transparent));
114
+ }
115
+
116
+ if (annotation != null) {
117
+ result.add(annotation);
118
+ result.add(item);
119
+ prev = item;
120
+ }
121
+ }
122
+
123
+ if (result.length > 0 && result.last.range.end < text.length) {
124
+ result.add(Annotation(
125
+ range: TextRange(start: result.last.range.end, end: text.length),
126
+ style: TextStyle(backgroundColor: Colors.transparent)));
127
+ }
128
+
129
+ return result;
130
+ }
131
+
132
+ bool validate(String source) => widget.words.indexOf(source) >= 0;
133
+
134
+ List<TextRange> range(String pattern, String source) {
135
+ final result = List<TextRange>();
136
+
137
+ if (pattern.isEmpty || source.isEmpty) {
138
+ return result;
139
+ }
140
+
141
+ for (int index = source.indexOf(pattern);
142
+ index >= 0;
143
+ index = source.indexOf(pattern, index + 1)) {
144
+ final start = index;
145
+ final end = start + pattern.length;
146
+ result.add(TextRange(start: start, end: end));
147
+ }
148
+
149
+ return result;
150
+ }
151
+
152
+ @override
153
+ TextSpan buildTextSpan() {
154
+ final text = textEditingValue.text;
155
+ final ranges = getRanges().toSet();
156
+
157
+ print('text $text');
158
+
159
+ if (ranges.isNotEmpty) {
160
+ return TextSpan(
161
+ style: widget.style,
162
+ children: ranges.map((item) {
163
+ final _text = item.range.textInside(text);
164
+ print(
165
+ '_text $_text; range ${item.range.start} : ${item.range.end}');
166
+ return TextSpan(style: item.style, text: _text);
167
+ }).toList());
168
+ }
169
+
170
+ return TextSpan(style: widget.style, text: text);
171
+ }
172
+}