dev
dart 191 lines 7.24 KB
Raw
1 import 'package:cake_wallet/core/seed_validator.dart';
2 import 'package:cake_wallet/generated/i18n.dart';
3 import 'package:cake_wallet/src/widgets/validable_annotated_editable_text.dart';
4 import 'package:cw_core/wallet_type.dart';
5 import 'package:flutter/material.dart';
6 import 'package:flutter/services.dart';
7
8 class SeedWidget extends StatefulWidget {
9 SeedWidget({
10 required this.language,
11 required this.type,
12 this.onSeedChange,
13 this.pasteButtonKey,
14 this.seedTextFieldKey,
15 this.initialSeed,
16 super.key,
17 });
18 final Key? seedTextFieldKey;
19 final Key? pasteButtonKey;
20 final String language;
21 final WalletType type;
22 final void Function(String)? onSeedChange;
23 final String? initialSeed;
24
25 @override
26 SeedWidgetState createState() => SeedWidgetState(language, type, initialSeed);
27 }
28
29 class SeedWidgetState extends State<SeedWidget> {
30 SeedWidgetState(String language, this.type, String? initialSeed)
31 : controller = TextEditingController(text: initialSeed ?? ''),
32 focusNode = FocusNode(),
33 words = SeedValidator.getWordList(type: type, language: language),
34 _showPlaceholder = initialSeed == null || initialSeed.isEmpty {
35 focusNode.addListener(() {
36 setState(() {
37 if (!focusNode.hasFocus && controller.text.isEmpty) {
38 _showPlaceholder = true;
39 }
40
41 if (focusNode.hasFocus) {
42 _showPlaceholder = false;
43 }
44 });
45 });
46 }
47
48 final TextEditingController controller;
49 final FocusNode focusNode;
50 final WalletType type;
51 List<String> words;
52 bool normalizeSeed = false;
53 bool _showPlaceholder;
54
55 String get text => controller.text;
56
57 @override
58 void initState() {
59 super.initState();
60 controller.addListener(() {
61 setState(() {
62 _showPlaceholder = controller.text.isEmpty;
63 });
64 widget.onSeedChange?.call(text);
65 });
66 Future.delayed(Duration.zero, () {
67 widget.onSeedChange?.call(text);
68 });
69 }
70
71 void changeSeedLanguage(String language) {
72 setState(() {
73 words = SeedValidator.getWordList(type: type, language: language);
74 normalizeSeed = SeedValidator.needsNormalization(language);
75 });
76 }
77
78 @override
79 Widget build(BuildContext context) {
80 return Container(
81 child: Column(
82 crossAxisAlignment: CrossAxisAlignment.start,
83 mainAxisAlignment: MainAxisAlignment.start,
84 children: [
85 Container(
86 decoration: ShapeDecoration(
87 shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18)),
88 color: Theme.of(context).colorScheme.surfaceContainer,
89 ),
90 child: Stack(
91 children: [
92 Padding(
93 padding: EdgeInsets.only(left: 12, right: 8, top: 8, bottom: 8),
94 child: Row(
95 children: [
96 Expanded(
97 child: Stack(
98 children: [
99 Container(
100 constraints: BoxConstraints(minHeight: 40),
101 child: Align(
102 alignment: Alignment.centerLeft,
103 child: ValidatableAnnotatedEditableText(
104 key: widget.seedTextFieldKey,
105 cursorColor: Theme.of(context).colorScheme.primary,
106 backgroundCursorColor: Theme.of(context).colorScheme.primary,
107 validStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
108 color: Theme.of(context).colorScheme.onSurfaceVariant,
109 backgroundColor: Colors.transparent,
110 fontWeight: FontWeight.normal,
111 fontSize: 16,
112 ),
113 invalidStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
114 color: Theme.of(context).colorScheme.errorContainer,
115 backgroundColor: Colors.transparent,
116 fontWeight: FontWeight.normal,
117 fontSize: 16,
118 ),
119 focusNode: focusNode,
120 controller: controller,
121 words: words,
122 normalizeSeed: normalizeSeed,
123 textStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
124 color: Theme.of(context).colorScheme.onSurfaceVariant,
125 backgroundColor: Colors.transparent,
126 fontWeight: FontWeight.normal,
127 fontSize: 16,
128 ),
129 ),
130 ),
131 ),
132 if (_showPlaceholder)
133 Positioned.fill(
134 child: IgnorePointer(
135 child: Align(
136 alignment: Alignment.centerLeft,
137 child: Text(
138 S.of(context).enter_seed_phrase,
139 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
140 color: Theme.of(context).colorScheme.onSurfaceVariant,
141 fontSize: 16,
142 ),
143 ),
144 ),
145 ),
146 ),
147 ],
148 ),
149 ),
150 Container(
151 width: 32,
152 height: 32,
153 child: InkWell(
154 key: widget.pasteButtonKey,
155 onTap: () async => _pasteText(),
156 child: Container(
157 padding: EdgeInsets.all(6),
158 decoration: ShapeDecoration(
159 color: Theme.of(context).colorScheme.surface,
160 shape: RoundedSuperellipseBorder(
161 borderRadius: BorderRadius.circular(18)),
162 ),
163 child: Image.asset(
164 'assets/images/paste_ios.png',
165 color: Theme.of(context).colorScheme.onSurfaceVariant,
166 ),
167 ),
168 ),
169 ),
170 ],
171 ),
172 ),
173 ],
174 ),
175 ),
176 ],
177 ),
178 );
179 }
180
181 Future<void> _pasteText() async {
182 final value = (await Clipboard.getData('text/plain'))?.text?.trim();
183
184 if (value?.isNotEmpty ?? false) {
185 setState(() {
186 _showPlaceholder = false;
187 controller.text = value!;
188 });
189 }
190 }
191 }