Handle backspace edgecase in trailing whitespace formatter. (#59379)
This commit is contained in:
@@ -2571,9 +2571,14 @@ class _WhitespaceDirectionalityFormatter extends TextInputFormatter {
|
||||
composingEnd -= outputCodepoints.length < composingEnd ? 1 : 0;
|
||||
}
|
||||
|
||||
final bool isBackspace = oldValue.text.runes.length - newValue.text.runes.length == 1 &&
|
||||
isDirectionalityMarker(oldValue.text.runes.last) &&
|
||||
oldValue.text.substring(0, oldValue.text.length - 1) == newValue.text;
|
||||
|
||||
bool previousWasWhitespace = false;
|
||||
bool previousWasDirectionalityMarker = false;
|
||||
int previousNonWhitespaceCodepoint;
|
||||
int index = 0;
|
||||
for (final int codepoint in newValue.text.runes) {
|
||||
if (isWhitespace(codepoint)) {
|
||||
// Only compute the directionality of the non-whitespace
|
||||
@@ -2587,9 +2592,15 @@ class _WhitespaceDirectionalityFormatter extends TextInputFormatter {
|
||||
subtractFromLength();
|
||||
outputCodepoints.removeLast();
|
||||
}
|
||||
outputCodepoints.add(codepoint);
|
||||
addToLength();
|
||||
outputCodepoints.add(_previousNonWhitespaceDirection == TextDirection.rtl ? _rlm : _lrm);
|
||||
// Handle trailing whitespace deleting the directionality char instead of the whitespace.
|
||||
if (isBackspace && index == newValue.text.runes.length - 1) {
|
||||
// Do not append the whitespace to the outputCodepoints.
|
||||
subtractFromLength();
|
||||
} else {
|
||||
outputCodepoints.add(codepoint);
|
||||
addToLength();
|
||||
outputCodepoints.add(_previousNonWhitespaceDirection == TextDirection.rtl ? _rlm : _lrm);
|
||||
}
|
||||
|
||||
previousWasWhitespace = true;
|
||||
previousWasDirectionalityMarker = false;
|
||||
@@ -2620,6 +2631,7 @@ class _WhitespaceDirectionalityFormatter extends TextInputFormatter {
|
||||
previousWasWhitespace = false;
|
||||
previousWasDirectionalityMarker = false;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
final String formatted = String.fromCharCodes(outputCodepoints);
|
||||
return TextEditingValue(
|
||||
|
||||
@@ -4923,6 +4923,46 @@ void main() {
|
||||
expect(state.currentTextEditingValue.text, equals('\u{200E}🇧🇼🇧🇷🇮🇴 🇻🇬🇧🇳wahhh!🇧🇬🇧🇫 🇧🇮🇰🇭عَ عَ \u{200F}🇨🇲 🇨🇦🇮🇨 🇨🇻🇧🇶 🇰🇾🇨🇫 🇹🇩🇨🇱 🇨🇳🇨🇽\u{200F}'));
|
||||
});
|
||||
|
||||
testWidgets('Whitespace directionality formatter handles deletion of trailing whitespace', (WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(text: 'testText');
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(devicePixelRatio: 1.0),
|
||||
child: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: FocusScope(
|
||||
node: focusScopeNode,
|
||||
autofocus: true,
|
||||
child: EditableText(
|
||||
backgroundCursorColor: Colors.blue,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
maxLines: 1, // Sets text keyboard implicitly.
|
||||
style: textStyle,
|
||||
cursorColor: cursorColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.byType(EditableText));
|
||||
await tester.showKeyboard(find.byType(EditableText));
|
||||
controller.text = '';
|
||||
await tester.idle();
|
||||
|
||||
final EditableTextState state =
|
||||
tester.state<EditableTextState>(find.byType(EditableText));
|
||||
expect(tester.testTextInput.editingState['text'], equals(''));
|
||||
expect(state.wantKeepAlive, true);
|
||||
|
||||
// Simulate deleting only the trailing RTL mark.
|
||||
state.updateEditingValue(const TextEditingValue(text: 'hello \u{200E}الْعَ بِيَّةُ \u{200F}'));
|
||||
state.updateEditingValue(const TextEditingValue(text: 'hello \u{200E}الْعَ بِيَّةُ '));
|
||||
// The trailing space should be gone here.
|
||||
expect(state.currentTextEditingValue.text, equals('hello \u{200E}الْعَ بِيَّةُ'));
|
||||
});
|
||||
|
||||
testWidgets('EditableText changes mouse cursor when hovered', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
|
||||
Reference in New Issue
Block a user