From bf6d7b4e48bfb6abfdb70fb5943a5ac87bd3dd26 Mon Sep 17 00:00:00 2001 From: Mouad Debbar Date: Tue, 18 Aug 2020 23:11:02 -0700 Subject: [PATCH] [web] Prepare for read-only input fields (#20520) --- .../text_editing/text_capitalization.dart | 2 +- .../src/engine/text_editing/text_editing.dart | 47 +++++++----- lib/web_ui/test/text_editing_test.dart | 74 +++++++------------ 3 files changed, 58 insertions(+), 65 deletions(-) diff --git a/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart b/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart index 9b8007ee05..a9f04137bb 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_capitalization.dart @@ -37,7 +37,7 @@ class TextCapitalizationConfig { const TextCapitalizationConfig.defaultCapitalization() : textCapitalization = TextCapitalization.none; - TextCapitalizationConfig.fromInputConfiguration(String inputConfiguration) + const TextCapitalizationConfig.fromInputConfiguration(String inputConfiguration) : this.textCapitalization = inputConfiguration == 'TextCapitalization.words' ? TextCapitalization.words diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index edca86424f..e5640764ff 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -180,9 +180,9 @@ class EngineAutofillForm { // Add a seperator between element identifiers. for (final String id in ids) { if (idBuffer.length > 0) { - idBuffer.write('*'); - } - idBuffer.write(id); + idBuffer.write('*'); + } + idBuffer.write(id); } final String formIdentifier = idBuffer.toString(); @@ -490,11 +490,13 @@ class EditingState { /// This corresponds to Flutter's [TextInputConfiguration]. class InputConfiguration { InputConfiguration({ - required this.inputType, - required this.inputAction, - required this.obscureText, - required this.autocorrect, - required this.textCapitalization, + this.inputType = EngineInputType.text, + this.inputAction = 'TextInputAction.done', + this.obscureText = false, + this.readOnly = false, + this.autocorrect = true, + this.textCapitalization = + const TextCapitalizationConfig.defaultCapitalization(), this.autofill, this.autofillGroup, }); @@ -502,14 +504,17 @@ class InputConfiguration { InputConfiguration.fromFrameworkMessage( Map flutterInputConfiguration) : inputType = EngineInputType.fromName( - flutterInputConfiguration['inputType']['name'], - isDecimal: - flutterInputConfiguration['inputType']['decimal'] ?? false), - inputAction = flutterInputConfiguration['inputAction'], - obscureText = flutterInputConfiguration['obscureText'], - autocorrect = flutterInputConfiguration['autocorrect'], + flutterInputConfiguration['inputType']['name'], + isDecimal: flutterInputConfiguration['inputType']['decimal'] ?? false, + ), + inputAction = + flutterInputConfiguration['inputAction'] ?? 'TextInputAction.done', + obscureText = flutterInputConfiguration['obscureText'] ?? false, + readOnly = flutterInputConfiguration['readOnly'] ?? false, + autocorrect = flutterInputConfiguration['autocorrect'] ?? true, textCapitalization = TextCapitalizationConfig.fromInputConfiguration( - flutterInputConfiguration['textCapitalization']), + flutterInputConfiguration['textCapitalization'], + ), autofill = flutterInputConfiguration.containsKey('autofill') ? AutofillInfo.fromFrameworkMessage( flutterInputConfiguration['autofill']) @@ -522,7 +527,12 @@ class InputConfiguration { final EngineInputType inputType; /// The default action for the input field. - final String? inputAction; + final String inputAction; + + /// Whether the text field can be edited or not. + /// + /// Defaults to false. + final bool readOnly; /// Whether to hide the text being edited. final bool? obscureText; @@ -534,7 +544,7 @@ class InputConfiguration { /// /// For future manual tests, note that autocorrect is an attribute only /// supported by Safari. - final bool? autocorrect; + final bool autocorrect; final AutofillInfo? autofill; @@ -742,6 +752,9 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy { this._inputConfiguration = inputConfig; _domElement = inputConfig.inputType.createDomElement(); + if (inputConfig.readOnly) { + domElement.setAttribute('readonly', 'readonly'); + } if (inputConfig.obscureText!) { domElement.setAttribute('type', 'password'); } diff --git a/lib/web_ui/test/text_editing_test.dart b/lib/web_ui/test/text_editing_test.dart index 8e5eeb36a3..9b2137d386 100644 --- a/lib/web_ui/test/text_editing_test.dart +++ b/lib/web_ui/test/text_editing_test.dart @@ -30,22 +30,14 @@ String lastInputAction; final InputConfiguration singlelineConfig = InputConfiguration( inputType: EngineInputType.text, - obscureText: false, - inputAction: 'TextInputAction.done', - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none'), ); final Map flutterSinglelineConfig = createFlutterConfig('text'); final InputConfiguration multilineConfig = InputConfiguration( - inputType: EngineInputType.multiline, - obscureText: false, - inputAction: 'TextInputAction.newline', - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + inputType: EngineInputType.multiline, + inputAction: 'TextInputAction.newline', +); final Map flutterMultilineConfig = createFlutterConfig('multiline'); @@ -115,14 +107,23 @@ void testMain() { expect(document.activeElement, document.body); }); + test('Respects read-only config', () { + final InputConfiguration config = InputConfiguration(readOnly: true); + editingElement.enable( + config, + onChange: trackEditingState, + onAction: trackInputAction, + ); + expect(document.getElementsByTagName('input'), hasLength(1)); + final InputElement input = document.getElementsByTagName('input')[0]; + expect(editingElement.domElement, input); + expect(input.getAttribute('readonly'), 'readonly'); + + editingElement.disable(); + }); + test('Knows how to create password fields', () { - final InputConfiguration config = InputConfiguration( - inputType: EngineInputType.text, - inputAction: 'TextInputAction.done', - obscureText: true, - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + final InputConfiguration config = InputConfiguration(obscureText: true); editingElement.enable( config, onChange: trackEditingState, @@ -137,13 +138,7 @@ void testMain() { }); test('Knows to turn autocorrect off', () { - final InputConfiguration config = InputConfiguration( - inputType: EngineInputType.text, - inputAction: 'TextInputAction.done', - obscureText: false, - autocorrect: false, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + final InputConfiguration config = InputConfiguration(autocorrect: false); editingElement.enable( config, onChange: trackEditingState, @@ -158,13 +153,7 @@ void testMain() { }); test('Knows to turn autocorrect on', () { - final InputConfiguration config = InputConfiguration( - inputType: EngineInputType.text, - inputAction: 'TextInputAction.done', - obscureText: false, - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + final InputConfiguration config = InputConfiguration(autocorrect: true); editingElement.enable( config, onChange: trackEditingState, @@ -298,13 +287,7 @@ void testMain() { }); test('Triggers input action', () { - final InputConfiguration config = InputConfiguration( - inputType: EngineInputType.text, - obscureText: false, - inputAction: 'TextInputAction.done', - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + final InputConfiguration config = InputConfiguration(inputAction: 'TextInputAction.done'); editingElement.enable( config, onChange: trackEditingState, @@ -326,12 +309,9 @@ void testMain() { test('Does not trigger input action in multi-line mode', () { final InputConfiguration config = InputConfiguration( - inputType: EngineInputType.multiline, - obscureText: false, - inputAction: 'TextInputAction.done', - autocorrect: true, - textCapitalization: TextCapitalizationConfig.fromInputConfiguration( - 'TextCapitalization.none')); + inputType: EngineInputType.multiline, + inputAction: 'TextInputAction.done', + ); editingElement.enable( config, onChange: trackEditingState, @@ -1693,7 +1673,8 @@ void testMain() { // Autofill value is applied to the element. expect(firstElement.name, BrowserAutofillHints.instance.flutterToEngine('password')); - expect(firstElement.id, BrowserAutofillHints.instance.flutterToEngine('password')); + expect(firstElement.id, + BrowserAutofillHints.instance.flutterToEngine('password')); expect(firstElement.type, 'password'); if (browserEngine == BrowserEngine.firefox) { expect(firstElement.name, @@ -1722,7 +1703,6 @@ void testMain() { EngineAutofillForm.fromFrameworkMessage( createAutofillInfo('username', 'field1'), fields); - expect(autofillForm.formIdentifier, 'aabbcc*jjkkll*zzyyxx'); }); -- GitLab