mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
updating editing state after location change. focusing on the element (flutter/engine#20620)
This commit is contained in:
parent
7d3b44dd47
commit
2919c3bbef
@ -614,10 +614,15 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy {
|
||||
|
||||
@override
|
||||
void placeElement() {
|
||||
super.placeElement();
|
||||
if (hasAutofillGroup) {
|
||||
_geometry?.applyToDomElement(focusedFormElement!);
|
||||
placeForm();
|
||||
// Set the last editing state if it exists, this is critical for a
|
||||
// users ongoing work to continue uninterrupted when there is an update to
|
||||
// the transform.
|
||||
if (_lastEditingState != null) {
|
||||
_lastEditingState!.applyToDomElement(domElement);
|
||||
}
|
||||
// On Chrome, when a form is focused, it opens an autofill menu
|
||||
// immediately.
|
||||
// Flutter framework sends `setEditableSizeAndTransform` for informing
|
||||
@ -627,7 +632,9 @@ class GloballyPositionedTextEditingStrategy extends DefaultTextEditingStrategy {
|
||||
// `setEditableSizeAndTransform` method is called and focus on the form
|
||||
// only after placing it to the correct position. Hence autofill menu
|
||||
// does not appear on top-left of the page.
|
||||
// Refocus on the elements after applying the geometry.
|
||||
focusedFormElement!.focus();
|
||||
domElement.focus();
|
||||
} else {
|
||||
_geometry?.applyToDomElement(domElement);
|
||||
}
|
||||
@ -663,6 +670,12 @@ class SafariDesktopTextEditingStrategy extends DefaultTextEditingStrategy {
|
||||
_geometry?.applyToDomElement(domElement);
|
||||
if (hasAutofillGroup) {
|
||||
placeForm();
|
||||
// Set the last editing state if it exists, this is critical for a
|
||||
// users ongoing work to continue uninterrupted when there is an update to
|
||||
// the transform.
|
||||
if (_lastEditingState != null) {
|
||||
_lastEditingState!.applyToDomElement(domElement);
|
||||
}
|
||||
// On Safari Desktop, when a form is focused, it opens an autofill menu
|
||||
// immediately.
|
||||
// Flutter framework sends `setEditableSizeAndTransform` for informing
|
||||
@ -1236,6 +1249,12 @@ class FirefoxTextEditingStrategy extends GloballyPositionedTextEditingStrategy {
|
||||
void placeElement() {
|
||||
domElement.focus();
|
||||
_geometry?.applyToDomElement(domElement);
|
||||
// Set the last editing state if it exists, this is critical for a
|
||||
// users ongoing work to continue uninterrupted when there is an update to
|
||||
// the transform.
|
||||
if (_lastEditingState != null) {
|
||||
_lastEditingState!.applyToDomElement(domElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1013,6 +1013,55 @@ void testMain() {
|
||||
expect(formsOnTheDom, hasLength(1));
|
||||
});
|
||||
|
||||
test(
|
||||
'singleTextField Autofill setEditableSizeAndTransform preserves'
|
||||
'editing state', () {
|
||||
// Create a configuration with focused element has autofil hint.
|
||||
final Map<String, dynamic> flutterSingleAutofillElementConfig =
|
||||
createFlutterConfig('text', autofillHint: 'username');
|
||||
final MethodCall setClient = MethodCall('TextInput.setClient',
|
||||
<dynamic>[123, flutterSingleAutofillElementConfig]);
|
||||
sendFrameworkMessage(codec.encodeMethodCall(setClient));
|
||||
|
||||
const MethodCall setEditingState1 =
|
||||
MethodCall('TextInput.setEditingState', <String, dynamic>{
|
||||
'text': 'abcd',
|
||||
'selectionBase': 2,
|
||||
'selectionExtent': 3,
|
||||
});
|
||||
sendFrameworkMessage(codec.encodeMethodCall(setEditingState1));
|
||||
|
||||
const MethodCall show = MethodCall('TextInput.show');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(show));
|
||||
|
||||
// The second [setEditingState] should override the first one.
|
||||
checkInputEditingState(
|
||||
textEditing.editingElement.domElement, 'abcd', 2, 3);
|
||||
|
||||
// The transform is changed. For example after a validation error, red
|
||||
// line appeared under the input field.
|
||||
final MethodCall setSizeAndTransform =
|
||||
configureSetSizeAndTransformMethodCall(150, 50,
|
||||
Matrix4.translationValues(10.0, 20.0, 30.0).storage.toList());
|
||||
sendFrameworkMessage(codec.encodeMethodCall(setSizeAndTransform));
|
||||
|
||||
// Check the element still has focus. User can keep editing.
|
||||
expect(document.activeElement, textEditing.editingElement.domElement);
|
||||
|
||||
// Check the cursor location is the same.
|
||||
checkInputEditingState(
|
||||
textEditing.editingElement.domElement, 'abcd', 2, 3);
|
||||
|
||||
const MethodCall clearClient = MethodCall('TextInput.clearClient');
|
||||
sendFrameworkMessage(codec.encodeMethodCall(clearClient));
|
||||
|
||||
// Confirm that [HybridTextEditing] didn't send any messages.
|
||||
expect(spy.messages, isEmpty);
|
||||
// Form stays on the DOM until autofill context is finalized.
|
||||
expect(document.getElementsByTagName('form'), isNotEmpty);
|
||||
expect(formsOnTheDom, hasLength(1));
|
||||
});
|
||||
|
||||
test(
|
||||
'multiTextField Autofill: setClient, setEditingState, show, '
|
||||
'setEditingState, clearClient', () {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user