dev
dart 250 lines 9.43 KB
Raw
1 import 'package:cake_wallet/generated/i18n.dart';
2 import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
3 import 'package:cw_core/amount/amount_sanitizer.dart';
4 import 'package:cw_core/crypto_amount_format.dart';
5 import 'package:flutter/material.dart';
6 import 'package:flutter/services.dart';
7
8 class CurrencyAmountTextField extends StatelessWidget {
9 const CurrencyAmountTextField({
10 required this.selectedCurrency,
11 required this.selectedCurrencyDecimals,
12 required this.amountFocusNode,
13 required this.amountController,
14 required this.isAmountEditable,
15 this.allAmountButton = false,
16 this.isPickerEnable = false,
17 this.isSelected = false,
18 this.onTapPicker,
19 this.padding,
20 this.imageArrow,
21 this.hintText,
22 this.tag,
23 this.tagBackgroundColor,
24 this.currencyValueValidator,
25 this.allAmountCallback,
26 this.sendAllButtonKey,
27 this.amountTextfieldKey,
28 this.currencyPickerButtonKey,
29 this.selectedCurrencyTextKey,
30 this.selectedCurrencyTagTextKey,
31 this.currencyAmountTextFieldWidgetKey,
32 this.fillColor,
33 this.borderColor,
34 this.hasUnderlineBorder = false,
35 this.borderWidth = 1.0,
36 }) : super(key: currencyAmountTextFieldWidgetKey);
37
38 final Key? sendAllButtonKey;
39 final Key? amountTextfieldKey;
40 final Key? currencyPickerButtonKey;
41 final Key? selectedCurrencyTextKey;
42 final Key? selectedCurrencyTagTextKey;
43 final Key? currencyAmountTextFieldWidgetKey;
44 final Widget? imageArrow;
45 final String selectedCurrency;
46 final int selectedCurrencyDecimals;
47 final String? tag;
48 final String? hintText;
49 final Color? tagBackgroundColor;
50 final EdgeInsets? padding;
51 final FocusNode? amountFocusNode;
52 final TextEditingController amountController;
53 final bool isAmountEditable;
54 final FormFieldValidator<String>? currencyValueValidator;
55 final bool isPickerEnable;
56 final bool isSelected;
57 final bool allAmountButton;
58 final VoidCallback? allAmountCallback;
59 final VoidCallback? onTapPicker;
60 final Color? fillColor;
61 final Color? borderColor;
62 final bool hasUnderlineBorder;
63 final double borderWidth;
64
65 @override
66 Widget build(BuildContext context) {
67 final textColor = Theme.of(context).colorScheme.onSurface;
68 final _prefixContent = Row(
69 children: [
70 isPickerEnable
71 ? Container(
72 height: 32,
73 child: InkWell(
74 key: currencyPickerButtonKey,
75 onTap: onTapPicker,
76 child: Row(
77 mainAxisAlignment: MainAxisAlignment.spaceBetween,
78 mainAxisSize: MainAxisSize.min,
79 children: <Widget>[
80 Padding(
81 padding: const EdgeInsets.only(right: 5),
82 child: imageArrow ??
83 Image.asset(
84 'assets/images/arrow_bottom_purple_icon.png',
85 color: Theme.of(context).colorScheme.primary,
86 height: 8,
87 ),
88 ),
89 Text(
90 key: selectedCurrencyTextKey,
91 selectedCurrency,
92 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
93 fontWeight: FontWeight.w600,
94 fontSize: 16,
95 color: textColor,
96 ),
97 ),
98 ],
99 ),
100 ),
101 )
102 : Text(
103 key: selectedCurrencyTextKey,
104 selectedCurrency,
105 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
106 fontWeight: FontWeight.w600,
107 fontSize: 16,
108 color: textColor,
109 ),
110 ),
111 if (tag != null)
112 Padding(
113 padding: const EdgeInsets.symmetric(horizontal: 3.0),
114 child: Container(
115 height: 32,
116 decoration: BoxDecoration(
117 color: tagBackgroundColor ?? Theme.of(context).colorScheme.surfaceContainerHighest,
118 borderRadius: const BorderRadius.all(Radius.circular(6)),
119 ),
120 child: Center(
121 child: Padding(
122 padding: const EdgeInsets.all(6.0),
123 child: Text(
124 key: selectedCurrencyTagTextKey,
125 tag!,
126 style: Theme.of(context).textTheme.bodySmall?.copyWith(
127 fontWeight: FontWeight.bold,
128 color: Theme.of(context).colorScheme.onSurfaceVariant,
129 ),
130 ),
131 ),
132 ),
133 ),
134 ),
135 Padding(
136 padding: EdgeInsets.only(right: 4.0),
137 child: Text(
138 ':',
139 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
140 fontWeight: FontWeight.w600,
141 fontSize: 16,
142 color: textColor,
143 ),
144 ),
145 ),
146 ],
147 );
148 return Padding(
149 padding: padding ?? const EdgeInsets.only(top: 20),
150 child: Row(
151 children: [
152 isSelected
153 ? Container(
154 child: _prefixContent,
155 padding: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
156 margin: const EdgeInsets.only(right: 8),
157 decoration: BoxDecoration(
158 border: Border.all(
159 color: textColor,
160 ),
161 borderRadius: BorderRadius.circular(10),
162 color: Theme.of(context).colorScheme.primary,
163 ),
164 )
165 : _prefixContent,
166 Expanded(
167 child: Row(
168 mainAxisAlignment: MainAxisAlignment.spaceBetween,
169 children: [
170 Flexible(
171 child: FocusTraversalOrder(
172 order: NumericFocusOrder(1),
173 child: BaseTextFormField(
174 hasUnderlineBorder: hasUnderlineBorder,
175 borderWidth: borderWidth,
176 key: amountTextfieldKey,
177 focusNode: amountFocusNode,
178 controller: amountController,
179 enabled: isAmountEditable,
180 textAlign: TextAlign.left,
181 keyboardType: const TextInputType.numberWithOptions(
182 signed: false,
183 decimal: true,
184 ),
185 inputFormatters: [
186 FilteringTextInputFormatter.deny(RegExp('[\\-|\\ ]')),
187 ],
188 hintText: hintText ?? (selectedCurrencyDecimals == 0 ? '0' : '0.0000'),
189 fillColor: fillColor,
190 textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(
191 fontSize: 16,
192 fontWeight: FontWeight.w600,
193 color: textColor,
194 ),
195 placeholderTextStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(
196 fontSize: 16,
197 fontWeight: FontWeight.w600,
198 color: Theme.of(context).colorScheme.onSurfaceVariant,
199 ),
200 validator: isAmountEditable ? currencyValueValidator : null,
201 onChanged: (value) {
202 var sanitized = value.sanitized().withMaxDecimals(selectedCurrencyDecimals);
203
204 if (selectedCurrencyDecimals == 0) {
205 sanitized = sanitized.replaceAll('.', '');
206 }
207
208 if (sanitized != amountController.text) {
209 // Update text while preserving a sane cursor position to avoid auto-selection
210 amountController.value = amountController.value.copyWith(
211 text: sanitized,
212 selection: TextSelection.collapsed(offset: sanitized.length),
213 composing: TextRange.empty,
214 );
215 }
216 },
217 ),
218 ),
219 ),
220 if (allAmountButton)
221 Container(
222 height: 32,
223 width: 32,
224 decoration: BoxDecoration(
225 color: Theme.of(context).colorScheme.surface,
226 borderRadius: const BorderRadius.all(Radius.circular(6)),
227 ),
228 child: InkWell(
229 key: sendAllButtonKey,
230 onTap: allAmountCallback,
231 child: Center(
232 child: Text(
233 S.of(context).all,
234 textAlign: TextAlign.center,
235 style: Theme.of(context).textTheme.bodySmall?.copyWith(
236 fontWeight: FontWeight.bold,
237 color: Theme.of(context).colorScheme.onSurfaceVariant,
238 ),
239 ),
240 ),
241 ),
242 ),
243 ],
244 ),
245 ),
246 ],
247 ),
248 );
249 }
250 }