22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5-
65part of engine;
76
87/// Make the content editable span visible to facilitate debugging.
@@ -115,8 +114,10 @@ class EngineAutofillForm {
115114 if (fields != null ) {
116115 for (Map <String , dynamic > field in fields.cast <Map <String , dynamic >>()) {
117116 final Map <String , dynamic > autofillInfo = field['autofill' ];
118- final AutofillInfo autofill =
119- AutofillInfo .fromFrameworkMessage (autofillInfo);
117+ final AutofillInfo autofill = AutofillInfo .fromFrameworkMessage (
118+ autofillInfo,
119+ textCapitalization: TextCapitalizationConfig .fromInputConfiguration (
120+ field['textCapitalization' ]));
120121
121122 // The focused text editing element will not be created here.
122123 final AutofillInfo focusedElement =
@@ -170,16 +171,24 @@ class EngineAutofillForm {
170171 keys.forEach ((String key) {
171172 final html.Element element = elements! [key]! ;
172173 subscriptions.add (element.onInput.listen ((html.Event e) {
173- _handleChange (element, key);
174+ if (items! [key] == null ) {
175+ throw StateError (
176+ 'Autofill would not work withuot Autofill value set' );
177+ } else {
178+ final AutofillInfo autofillInfo = items! [key] as AutofillInfo ;
179+ _handleChange (element, autofillInfo);
180+ }
174181 }));
175182 });
176183 return subscriptions;
177184 }
178185
179- void _handleChange (html.Element domElement, String ? tag) {
180- EditingState newEditingState = EditingState .fromDomElement (domElement as html.HtmlElement ? );
186+ void _handleChange (html.Element domElement, AutofillInfo autofillInfo) {
187+ EditingState newEditingState = EditingState .fromDomElement (
188+ domElement as html.HtmlElement ? ,
189+ textCapitalization: autofillInfo.textCapitalization);
181190
182- _sendAutofillEditingState (tag , newEditingState);
191+ _sendAutofillEditingState (autofillInfo.uniqueIdentifier , newEditingState);
183192 }
184193
185194 /// Sends the 'TextInputClient.updateEditingStateWithTag' message to the framework.
@@ -207,7 +216,11 @@ class EngineAutofillForm {
207216/// These values are to be used when a text field have autofill enabled.
208217@visibleForTesting
209218class AutofillInfo {
210- AutofillInfo ({required this .editingState, required this .uniqueIdentifier, required this .hint});
219+ AutofillInfo (
220+ {required this .editingState,
221+ required this .uniqueIdentifier,
222+ required this .hint,
223+ required this .textCapitalization});
211224
212225 /// The current text and selection state of a text field.
213226 final EditingState editingState;
@@ -217,14 +230,29 @@ class AutofillInfo {
217230 /// Used as id of the text field.
218231 final String uniqueIdentifier;
219232
233+ /// Information on how should autofilled text capitalized.
234+ ///
235+ /// For example for [TextCapitalization.characters] each letter is converted
236+ /// to upper case.
237+ ///
238+ /// This value is not necessary for autofilling the focused element since
239+ /// [DefaultTextEditingStrategy._inputConfiguration] already has this
240+ /// information.
241+ ///
242+ /// On the other hand for the multi element forms, for the input elements
243+ /// other the focused field, we need to use this information.
244+ final TextCapitalizationConfig textCapitalization;
245+
220246 /// Attribute used for autofill.
221247 ///
222248 /// Used as a guidance to the browser as to the type of information expected
223249 /// in the field.
224250 /// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete
225251 final String hint;
226252
227- factory AutofillInfo .fromFrameworkMessage (Map <String , dynamic > autofill) {
253+ factory AutofillInfo .fromFrameworkMessage (Map <String , dynamic > autofill,
254+ {TextCapitalizationConfig textCapitalization =
255+ const TextCapitalizationConfig .defaultCapitalization ()}) {
228256 assert (autofill != null ); // ignore: unnecessary_null_comparison
229257 final String uniqueIdentifier = autofill['uniqueIdentifier' ]! ;
230258 final List <dynamic > hintsList = autofill['hints' ];
@@ -233,7 +261,8 @@ class AutofillInfo {
233261 return AutofillInfo (
234262 uniqueIdentifier: uniqueIdentifier,
235263 hint: BrowserAutofillHints .instance.flutterToEngine (hintsList[0 ]),
236- editingState: editingState);
264+ editingState: editingState,
265+ textCapitalization: textCapitalization);
237266 }
238267
239268 void applyToDomElement (html.HtmlElement domElement,
@@ -302,7 +331,9 @@ class EditingState {
302331 ///
303332 /// [domElement] can be a [InputElement] or a [TextAreaElement] depending on
304333 /// the [InputType] of the text field.
305- factory EditingState .fromDomElement (html.HtmlElement ? domElement) {
334+ factory EditingState .fromDomElement (html.HtmlElement ? domElement,
335+ {TextCapitalizationConfig textCapitalization =
336+ const TextCapitalizationConfig .defaultCapitalization ()}) {
306337 if (domElement is html.InputElement ) {
307338 html.InputElement element = domElement;
308339 return EditingState (
@@ -352,10 +383,10 @@ class EditingState {
352383 if (runtimeType != other.runtimeType) {
353384 return false ;
354385 }
355- return other is EditingState
356- && other.text == text
357- && other.baseOffset == baseOffset
358- && other.extentOffset == extentOffset;
386+ return other is EditingState &&
387+ other.text == text &&
388+ other.baseOffset == baseOffset &&
389+ other.extentOffset == extentOffset;
359390 }
360391
361392 @override
@@ -396,6 +427,7 @@ class InputConfiguration {
396427 required this .inputAction,
397428 required this .obscureText,
398429 required this .autocorrect,
430+ required this .textCapitalization,
399431 this .autofill,
400432 this .autofillGroup,
401433 });
@@ -407,9 +439,12 @@ class InputConfiguration {
407439 inputAction = flutterInputConfiguration['inputAction' ],
408440 obscureText = flutterInputConfiguration['obscureText' ],
409441 autocorrect = flutterInputConfiguration['autocorrect' ],
442+ textCapitalization = TextCapitalizationConfig .fromInputConfiguration (
443+ flutterInputConfiguration['textCapitalization' ]),
410444 autofill = flutterInputConfiguration.containsKey ('autofill' )
411- ? AutofillInfo .fromFrameworkMessage (flutterInputConfiguration['autofill' ])
412- : null ,
445+ ? AutofillInfo .fromFrameworkMessage (
446+ flutterInputConfiguration['autofill' ])
447+ : null ,
413448 autofillGroup = EngineAutofillForm .fromFrameworkMessage (
414449 flutterInputConfiguration['autofill' ],
415450 flutterInputConfiguration['fields' ]);
@@ -435,6 +470,8 @@ class InputConfiguration {
435470 final AutofillInfo ? autofill;
436471
437472 final EngineAutofillForm ? autofillGroup;
473+
474+ final TextCapitalizationConfig textCapitalization;
438475}
439476
440477typedef _OnChangeCallback = void Function (EditingState ? editingState);
@@ -500,18 +537,18 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy {
500537 void placeElement () {
501538 super .placeElement ();
502539 if (hasAutofillGroup) {
503- _geometry? .applyToDomElement (focusedFormElement! );
504- placeForm ();
505- // On Chrome, when a form is focused, it opens an autofill menu
506- // immeddiately.
507- // Flutter framework sends `setEditableSizeAndTransform` for informing
508- // the engine about the location of the text field. This call will
509- // arrive after `show` call.
510- // Therefore on Chrome we place the element when
511- // `setEditableSizeAndTransform` method is called and focus on the form
512- // only after placing it to the correct position. Hence autofill menu
513- // does not appear on top-left of the page.
514- focusedFormElement! .focus ();
540+ _geometry? .applyToDomElement (focusedFormElement! );
541+ placeForm ();
542+ // On Chrome, when a form is focused, it opens an autofill menu
543+ // immeddiately.
544+ // Flutter framework sends `setEditableSizeAndTransform` for informing
545+ // the engine about the location of the text field. This call will
546+ // arrive after `show` call.
547+ // Therefore on Chrome we place the element when
548+ // `setEditableSizeAndTransform` method is called and focus on the form
549+ // only after placing it to the correct position. Hence autofill menu
550+ // does not appear on top-left of the page.
551+ focusedFormElement! .focus ();
515552 } else {
516553 _geometry? .applyToDomElement (domElement);
517554 }
@@ -551,6 +588,7 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy {
551588 set domElement (html.HtmlElement element) {
552589 _domElement = element;
553590 }
591+
554592 html.HtmlElement ? _domElement;
555593
556594 late InputConfiguration _inputConfiguration;
@@ -694,7 +732,8 @@ abstract class DefaultTextEditingStrategy implements TextEditingStrategy {
694732 void _handleChange (html.Event event) {
695733 assert (isEnabled);
696734
697- EditingState newEditingState = EditingState .fromDomElement (domElement);
735+ EditingState newEditingState = EditingState .fromDomElement (domElement,
736+ textCapitalization: _inputConfiguration.textCapitalization);
698737
699738 if (newEditingState != _lastEditingState) {
700739 _lastEditingState = newEditingState;
@@ -818,6 +857,7 @@ class IOSTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
818857 } else {
819858 domRenderer.glassPaneElement! .append (domElement);
820859 }
860+ inputConfig.textCapitalization.setAutocapitalizeAttribute (domElement);
821861 }
822862
823863 @override
@@ -948,6 +988,7 @@ class AndroidTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
948988 } else {
949989 domRenderer.glassPaneElement! .append (domElement);
950990 }
991+ inputConfig.textCapitalization.setAutocapitalizeAttribute (domElement);
951992 }
952993
953994 @override
0 commit comments