Unverified Commit af9a409e authored by Pedro Massango's avatar Pedro Massango Committed by GitHub

Prevent WhitelistingTextInputFormatter to return a empty string if the current...

Prevent WhitelistingTextInputFormatter to return a empty string if the current value does not satisfy the formatter (#57264)
parent fed18fc4
...@@ -107,10 +107,11 @@ class BlacklistingTextInputFormatter extends TextInputFormatter { ...@@ -107,10 +107,11 @@ class BlacklistingTextInputFormatter extends TextInputFormatter {
@override @override
TextEditingValue formatEditUpdate( TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused. TextEditingValue oldValue,
TextEditingValue newValue, TextEditingValue newValue,
) { ) {
return _selectionAwareTextManipulation( return _selectionAwareTextManipulation(
oldValue,
newValue, newValue,
(String substring) { (String substring) {
return substring.replaceAll(blacklistedPattern, replacementString); return substring.replaceAll(blacklistedPattern, replacementString);
...@@ -239,10 +240,11 @@ class WhitelistingTextInputFormatter extends TextInputFormatter { ...@@ -239,10 +240,11 @@ class WhitelistingTextInputFormatter extends TextInputFormatter {
@override @override
TextEditingValue formatEditUpdate( TextEditingValue formatEditUpdate(
TextEditingValue oldValue, // unused. TextEditingValue oldValue,
TextEditingValue newValue, TextEditingValue newValue,
) { ) {
return _selectionAwareTextManipulation( return _selectionAwareTextManipulation(
oldValue,
newValue, newValue,
(String substring) { (String substring) {
return whitelistedPattern return whitelistedPattern
...@@ -259,6 +261,7 @@ class WhitelistingTextInputFormatter extends TextInputFormatter { ...@@ -259,6 +261,7 @@ class WhitelistingTextInputFormatter extends TextInputFormatter {
} }
TextEditingValue _selectionAwareTextManipulation( TextEditingValue _selectionAwareTextManipulation(
TextEditingValue oldValue,
TextEditingValue value, TextEditingValue value,
String substringManipulation(String substring), String substringManipulation(String substring),
) { ) {
...@@ -268,6 +271,19 @@ TextEditingValue _selectionAwareTextManipulation( ...@@ -268,6 +271,19 @@ TextEditingValue _selectionAwareTextManipulation(
TextSelection manipulatedSelection; TextSelection manipulatedSelection;
if (selectionStartIndex < 0 || selectionEndIndex < 0) { if (selectionStartIndex < 0 || selectionEndIndex < 0) {
manipulatedText = substringManipulation(value.text); manipulatedText = substringManipulation(value.text);
} else if (value.selection.isCollapsed) { // Non-selection text manipulation
int cursorPosition = value.selection.baseOffset;
manipulatedText = substringManipulation(value.text);
// We only return the old valid value if the current value is not empty and
// if manipulation fails.
if (value.text.isNotEmpty && manipulatedText.isEmpty) {
manipulatedText = oldValue.text;
// We decrease cursorPosition by one because
// user entered a invalid character.
cursorPosition -= 1;
}
// Move the caret to its previous position.
manipulatedSelection = TextSelection.collapsed(offset: cursorPosition);
} else { } else {
final String beforeSelection = substringManipulation( final String beforeSelection = substringManipulation(
value.text.substring(0, selectionStartIndex) value.text.substring(0, selectionStartIndex)
......
...@@ -84,4 +84,55 @@ void main() { ...@@ -84,4 +84,55 @@ void main() {
}); });
}); });
}); });
group('WhitelistingTextInputFormatter', () {
test('should return the old value if new value contains non-white-listed character', () {
const TextEditingValue oldValue = TextEditingValue(text: '12345');
const TextEditingValue newValue = TextEditingValue(text: '12345@');
final WhitelistingTextInputFormatter formatter = WhitelistingTextInputFormatter.digitsOnly;
final TextEditingValue formatted = formatter.formatEditUpdate(oldValue, newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('12345'));
// The new value is always the oldValue plus a non-digit character (user press @)
expect(newValue.text, equals('12345@'));
// we expect that the formatted value returns the oldValue only since the newValue does not
// satisfy the formatter condition (wich is, in this case digitsOnly)
expect(formatted.text, equals('12345'));
});
test('should move the cursor to the right position', () {
TextEditingValue collapsedValue(String text, int offset) =>
TextEditingValue(
text: text,
selection: TextSelection.collapsed(offset: offset),
);
TextEditingValue oldValue = collapsedValue('123', 0);
TextEditingValue newValue = collapsedValue('123456', 6);
final WhitelistingTextInputFormatter formatter =
WhitelistingTextInputFormatter.digitsOnly;
TextEditingValue formatted = formatter.formatEditUpdate(oldValue,
newValue);
// assert that we are passing digits only at the first time
expect(oldValue.text, equals('123'));
// assert that we are passing digits only at the second time
expect(newValue.text, equals('123456'));
// assert that cursor is at the end of the text
expect(formatted.selection.baseOffset, equals(6));
// move cursor at the middle of the text and then add the number 9.
oldValue = newValue.copyWith(
selection: const TextSelection.collapsed(offset: 4));
newValue = oldValue.copyWith(text: '1239456');
formatted = formatter.formatEditUpdate(oldValue, newValue);
// cursor must be now at fourth position (right after the number 9)
expect(formatted.selection.baseOffset, equals(4));
});
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment