-
Notifications
You must be signed in to change notification settings - Fork 29.8k
More EditableText docs #66864
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More EditableText docs #66864
Conversation
…IsLooong/flutter into editable-text-updateEditingValue
8cb420f to
c3fc5cc
Compare
c3fc5cc to
21cc3c1
Compare
cbda64f to
60b7a93
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit questionable. For example if inputFormatters is updated and the same TextEditingValue is received a second time it should probably not shortcircuit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was recently added in #65754. I'm not sure what's up with the numeric keyboard problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit questionable. For example if
inputFormattersis updated and the sameTextEditingValueis received a second time it should probably not shortcircuit.
Yes, the situation you said should not be short-circuited. Maybe we should go through _formatAndSetValue if we receive duplicate values at this situation. Can we add a test case to test the situation you said?
There is also a scenario where duplicate values will be received. When the keyboard is hidden, the engine will send the current value again. #66036
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to update the formatter (and reapply it) when _textDirection changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to write a formatter that does something different depending on the text direction, right? If so I would say yes we need to reapply it. But I can't think of a real world example. Maybe open an issue for it for another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't take a very careful look but _WhitespaceDirectionalityFormatter maintains states and may need to be re-instantiated and re-applied.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is a bit different. We used to skip the _whitespaceFormatter when there's no other formatters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think flutter/engine#20160 prevents the repeat on iOS. The android text input plugin still does that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing this because this seems to be the path of least resistance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good to me. At some point did you say that you plan to implement the same kind of idea as flutter/engine#20160 in Android? Or is the plan to leave it as-is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the formatter caching altogether. I think a TextInputFormatter is allowed to have states? If that's the case we shouldn't cache the formatter outputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could imagine a formatter that has state. Not sure what Flutter's opinion on that is, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should inputFormatters work retroactively?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question... I'm not sure. I guess it would be easy for the user to apply their input formatter to the existing text if they want to. Maybe some users are doing that now. I guess I don't have a strong reason to change it.
60b7a93 to
d5f5bd8
Compare
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great clean up, we really needed this. The docs are much more useful now. I was constantly confused by how all of this engine/framework communication happens.
Most of my comments are just nits or attempts to answer some of your questions.
| /// | ||
| /// See also: | ||
| /// | ||
| /// * [EditableTextState.textEditingValue]: an implementation that appleis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo on "applies".
| /// See also: | ||
| /// | ||
| /// * [TextInput.attach] | ||
| /// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No empty line needed here I think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good to me. At some point did you say that you plan to implement the same kind of idea as flutter/engine#20160 in Android? Or is the plan to leave it as-is?
| /// [TextInputClient]'s [AutofillScope], and the [AutofillScope] will further | ||
| /// relay the value to the correct [TextInputClient]. | ||
| /// | ||
| /// When synchronizing the [TextEditingValue]s, the communication may stuck in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"may stuck" => "may get stuck"
| /// | ||
| /// Used in [_updateRemoteEditingValueIfNeeded] to determine whether the | ||
| /// remote value is outdated and needs updating. | ||
| TextEditingValue? _lastKnownRemoteTextEditingValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 for the name improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a great job to remove those caches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was recently added in #65754. I'm not sure what's up with the numeric keyboard problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to write a formatter that does something different depending on the text direction, right? If so I would say yes we need to reapply it. But I can't think of a real world example. Maybe open an issue for it for another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could imagine a formatter that has state. Not sure what Flutter's opinion on that is, though.
| // Before triggering the [_value] change notifier, we want to make sure | ||
| // [_updateRemoteEditingValueIfNeeded] is muted, so we can consolidate the | ||
| // changes and send them to the engine in one batch. | ||
| _muteRemoteUpdate = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the mute idea might have the potential to create confusing behavior if future editors aren't careful. I can't think of a better architecture though. I see why we need to batch these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sorry that I did not understand the purpose of this code, can you guys explain what were batched? thanks :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Is possible to modify this value on widget.onChanged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah onChanged and the listeners registered to TextEditingController both may update the editing value.
Should I call it beginBatchEdit & endBatchEdit, and allow nesting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// For consistency with Android behavior, send an update to the framework.
[self updateEditingState];The comments say consistency with Android, but sometimes the Android does not do this, is that right? Is it possible that we make modify it here?
Should we determine a data synchronization principle? For example, both sides do not respond to the changes notified by the other side, but only notify the local changes to remote. Otherwise, our scene will become complicated and difficult to maintain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit questionable. For example if
inputFormattersis updated and the sameTextEditingValueis received a second time it should probably not shortcircuit.
Yes, the situation you said should not be short-circuited. Maybe we should go through _formatAndSetValue if we receive duplicate values at this situation. Can we add a test case to test the situation you said?
There is also a scenario where duplicate values will be received. When the keyboard is hidden, the engine will send the current value again. #66036
| /// | ||
| /// ## Handling User Input | ||
| /// | ||
| /// Currently the user may change the text this widget contains via keyboard or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The user also can change the text by the controller directly. If change the text by controller [inpitFormatters] will not be applied. Should [inpitFormatters] work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "user" here refers to end-users (that use the app). I think inputFormatters is meant for sanitizing user input. If the developer decides to change the text programmatically then they should be responsible for making sure the new text is valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh in the documentation it only says "when the text input changes": https://api.flutter.dev/flutter/material/TextField/inputFormatters.html. I think we should make that clear.
|
|
||
| // If by coincidence the text input plugin sends the same value back, | ||
| // do nothing. | ||
| state.updateEditingValue(const TextEditingValue(text: 'remote listener onChanged listener')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the inputFormatters be applied?
This happens to be the scene we discussed above
This is a bit questionable. For example if inputFormatters is updated and the same TextEditingValue is received a second time it should probably not shortcircuit.
If the answer is yes and the iOS platform always returns this value, is it possible to cause an endless loop?
I think the answer depends on the situation. If it is the value sent back immediately (like iOS), it should not be applied, but if it is the user input later, it should be applied.
We really can’t let the plug-in send back the value to the framework, which will make the problem very tricky.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With flutter/engine#20160 the ios input plugin should never send values back if the change is initiated by the framework.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.
In addition, should the inputFormatters be applied here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure. In theory it should. I'll go find out if there's practically reasons about the current input formatter implementation, and open a new PR if there's anything needs changing.
| }); | ||
|
|
||
| testWidgets('input from text selection menu', (WidgetTester tester) async { | ||
| await tester.pumpWidget(widget); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to just be the same test case of the previous, although I'll be pleased to hear that I'm missing something :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not exactly the same as the previous "input from text input plugin" test, as it tests the textEditingValue setter call path instead of updateEditingValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.
| } | ||
|
|
||
| // Setting _value here ensures the selection and composing region info is passed. | ||
| // Before triggering the [_value] change notifier, we want to make sure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you comment here why batch processing is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed wording.
|
@justinmc @xu-baolin @GaryQian
|
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but FYI there is a merge conflict.
Linking @xu-baolin's PR #67892, which is related and may affect the text input formatter stuff you mentioned.
I'm on board with the platform/system nomenclature and will try to use it consistently!
|
Hi @justinmc , may I ask will this be patched to 1.22 or it will be in the next minor release (e.g. 1.23)? |
|
It looks like this has been reverted unfortunately, but we'll try to get it back in soon. Watch for another PR linked here. |
This reverts commit a57f45e.
|
Hi @justinmc , thanks for your help. May I ask is there any update on this issue? I understand it's reverted. Could you please share the new issue / PR related to this fix? |
|
Sure, this was relanded in #68043 and is currently in master. |
Description
Historically in text input plugins we send the
TextEditingValues we received from the framework back to the framework, in order to trigger user input callbacks for text selection menu operations (flutter/engine@a90d17b). This has caused a few issues including infinite loops.Related Issues
Fixes #66144
Tests
I added the following tests:
Checklist
Before you create this PR, confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.