2023-06-16 23:04:39 +00:00
|
|
|
import 'dart:math';
|
|
|
|
|
2023-06-16 22:47:03 +00:00
|
|
|
import 'package:flutter/services.dart';
|
2024-05-27 23:56:22 +00:00
|
|
|
|
2024-05-23 00:37:06 +00:00
|
|
|
import '../util.dart';
|
2024-05-27 23:56:22 +00:00
|
|
|
import 'amount_unit.dart';
|
2023-06-16 22:47:03 +00:00
|
|
|
|
|
|
|
class AmountInputFormatter extends TextInputFormatter {
|
|
|
|
final int decimals;
|
|
|
|
final String locale;
|
2023-06-16 23:04:39 +00:00
|
|
|
final AmountUnit? unit;
|
2023-06-16 22:47:03 +00:00
|
|
|
|
2023-06-16 23:04:39 +00:00
|
|
|
AmountInputFormatter({
|
|
|
|
required this.decimals,
|
|
|
|
required this.locale,
|
|
|
|
this.unit,
|
|
|
|
});
|
2023-06-16 22:47:03 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
TextEditingValue formatEditUpdate(
|
2024-05-27 23:56:22 +00:00
|
|
|
TextEditingValue oldValue,
|
|
|
|
TextEditingValue newValue,
|
|
|
|
) {
|
2023-06-16 22:47:03 +00:00
|
|
|
// get number symbols for decimal place and group separator
|
2023-07-12 22:06:06 +00:00
|
|
|
final numberSymbols = Util.getSymbolsFor(locale: locale);
|
2023-06-16 22:47:03 +00:00
|
|
|
|
|
|
|
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
|
|
|
|
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";
|
|
|
|
|
|
|
|
String newText = newValue.text.replaceAll(groupSeparator, "");
|
|
|
|
|
|
|
|
final selectionIndexFromTheRight =
|
|
|
|
newValue.text.length - newValue.selection.end;
|
|
|
|
|
|
|
|
String? fraction;
|
|
|
|
if (newText.contains(decimalSeparator)) {
|
|
|
|
final parts = newText.split(decimalSeparator);
|
|
|
|
|
|
|
|
if (parts.length > 2) {
|
|
|
|
return oldValue;
|
|
|
|
}
|
2023-06-23 18:59:43 +00:00
|
|
|
|
|
|
|
final fractionDigits =
|
|
|
|
unit == null ? decimals : max(decimals - unit!.shift, 0);
|
|
|
|
|
2023-06-16 22:47:03 +00:00
|
|
|
if (newText.startsWith(decimalSeparator)) {
|
2023-06-23 18:59:43 +00:00
|
|
|
if (newText.length - 1 > fractionDigits) {
|
|
|
|
newText = newText.substring(0, fractionDigits + 1);
|
|
|
|
}
|
|
|
|
|
2023-06-16 22:47:03 +00:00
|
|
|
return TextEditingValue(
|
|
|
|
text: newText,
|
|
|
|
selection: TextSelection.collapsed(
|
|
|
|
offset: newText.length - selectionIndexFromTheRight,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
newText = parts.first;
|
|
|
|
if (parts.length == 2) {
|
|
|
|
fraction = parts.last;
|
|
|
|
} else {
|
|
|
|
fraction = "";
|
|
|
|
}
|
|
|
|
|
2023-06-16 23:04:39 +00:00
|
|
|
if (fraction.length > fractionDigits) {
|
2023-06-23 18:59:43 +00:00
|
|
|
fraction = fraction.substring(0, fractionDigits);
|
2023-06-16 22:47:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-23 18:59:43 +00:00
|
|
|
String newString;
|
|
|
|
final val = BigInt.tryParse(newText);
|
|
|
|
if (val == null || val < BigInt.one) {
|
|
|
|
newString = newText;
|
|
|
|
} else {
|
|
|
|
// insert group separator
|
|
|
|
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');
|
|
|
|
newString = newText.replaceAllMapped(
|
|
|
|
regex,
|
|
|
|
(m) => "${m.group(0)}${numberSymbols?.GROUP_SEP ?? ","}",
|
|
|
|
);
|
2023-06-16 22:47:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (fraction != null) {
|
|
|
|
newString += decimalSeparator;
|
|
|
|
if (fraction.isNotEmpty) {
|
|
|
|
newString += fraction;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return TextEditingValue(
|
|
|
|
text: newString,
|
|
|
|
selection: TextSelection.collapsed(
|
|
|
|
offset: newString.length - selectionIndexFromTheRight,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|