Skip to content

Commit 3e273b1

Browse files
[web & desktop] Hide all characters in a TextField, when obscureText is true on web & desktop (flutter#56794)
1 parent ab68721 commit 3e273b1

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

packages/flutter/lib/src/widgets/editable_text.dart

+10-4
Original file line numberDiff line numberDiff line change
@@ -2129,10 +2129,16 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
21292129
if (widget.obscureText) {
21302130
String text = _value.text;
21312131
text = widget.obscuringCharacter * text.length;
2132-
final int o =
2133-
_obscureShowCharTicksPending > 0 ? _obscureLatestCharIndex : null;
2134-
if (o != null && o >= 0 && o < text.length)
2135-
text = text.replaceRange(o, o + 1, _value.text.substring(o, o + 1));
2132+
// Reveal the latest character in an obscured field only on mobile.
2133+
if ((defaultTargetPlatform == TargetPlatform.android ||
2134+
defaultTargetPlatform == TargetPlatform.iOS ||
2135+
defaultTargetPlatform == TargetPlatform.fuchsia) &&
2136+
!kIsWeb) {
2137+
final int o =
2138+
_obscureShowCharTicksPending > 0 ? _obscureLatestCharIndex : null;
2139+
if (o != null && o >= 0 && o < text.length)
2140+
text = text.replaceRange(o, o + 1, _value.text.substring(o, o + 1));
2141+
}
21362142
return TextSpan(style: widget.style, text: text);
21372143
}
21382144
// Read only mode should not paint text composing.

packages/flutter/test/material/text_field_test.dart

+41-2
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ void main() {
758758
expect(cursorOffsetSpaces.dx, inputWidth - _kCaretGap);
759759
});
760760

761-
testWidgets('obscureText control test', (WidgetTester tester) async {
761+
testWidgets('mobile obscureText control test', (WidgetTester tester) async {
762762
await tester.pumpWidget(
763763
overlay(
764764
child: const TextField(
@@ -796,7 +796,46 @@ void main() {
796796

797797
editText = findRenderEditable(tester).text.text;
798798
expect(editText.substring(editText.length - 1), '\u2022');
799-
});
799+
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android }));
800+
801+
testWidgets('desktop obscureText control test', (WidgetTester tester) async {
802+
await tester.pumpWidget(
803+
overlay(
804+
child: const TextField(
805+
obscureText: true,
806+
decoration: InputDecoration(
807+
hintText: 'Placeholder',
808+
),
809+
),
810+
),
811+
);
812+
await tester.showKeyboard(find.byType(TextField));
813+
814+
const String testValue = 'ABC';
815+
tester.testTextInput.updateEditingValue(const TextEditingValue(
816+
text: testValue,
817+
selection: TextSelection.collapsed(offset: testValue.length),
818+
));
819+
820+
await tester.pump();
821+
822+
// Enter a character into the obscured field and verify that the character
823+
// isn't shown to the user.
824+
const String newChar = 'X';
825+
tester.testTextInput.updateEditingValue(const TextEditingValue(
826+
text: testValue + newChar,
827+
selection: TextSelection.collapsed(offset: testValue.length + 1),
828+
));
829+
830+
await tester.pump();
831+
832+
final String editText = findRenderEditable(tester).text.text;
833+
expect(editText.substring(editText.length - 1), '\u2022');
834+
}, variant: const TargetPlatformVariant(<TargetPlatform>{
835+
TargetPlatform.macOS,
836+
TargetPlatform.linux,
837+
TargetPlatform.windows,
838+
}));
800839

801840
testWidgets('Caret position is updated on tap', (WidgetTester tester) async {
802841
final TextEditingController controller = TextEditingController();

0 commit comments

Comments
 (0)