Create centralized SuperIme to share IME connections across SuperEditor subtree recreations, includes various other fixes (Resolves #2807) #2809
+1,084
−205
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Create centralized SuperIme to share IME connections across SuperEditor subtree recreations, includes various other fixes (Resolves #2807)
SuperIme
SuperImeis a singleton, which at any time may or may not have an "owner". The idea is that the "owner" is allowed to open an IME connection, access the IME connection, and clear the IME connection, but non-owners can't.The "owner" implementation is just a convenience. Nothing stops Flutter code from calling
TextInput.attach()on their own and taking control of the whole app's IME. However, all code withinsuper_editorcan choose to access the IME throughSuperIme, and to honor the ownership paradigm.The ID of an owner includes two pieces: a role, and an instance. The role differentiates one editor from a completely different editor in the UI. For example, one editor might be used for "chat" and another might be used for "documents".
But sometimes two different widgets are actually the same editor. Specifically, when a
SuperEditoris reparented, it results in the entireSuperEditortree being dispossed and anotherSuperEditortree is initialized, for the same editor. So, for a moment, a single "chat" editor will actually have twoSuperEditorwidgets. In this case, both have the role of "chat", but to further differentiate, an "owner" also includes an "instance". In this case, eachStateobject can pass itself as the "instance" in the owner ID.The "role" makes it clear when one input wants to take control from another input, and the "instance" makes it clear when an editor tree is going through recreation and should retain the existing IME connection.
IME Fixes
DocumentImeInputClient- In the constructor, it seems that we forgot to pass the IME connection through to the super class, which means the document was being sent to the IME upon construction when it should be. Now we pass it through.Other Fixes
OverlayPortalin a demo, and also indocument_gestures_touch_android.dart, and inkeyboard_panel_scaffold.dart.didChangeDependenciesindocument_gestures_touch_android.dart.MessagePageScaffoldto support two sheet expansion points. We always had a max height for the bottom sheet. Now we have another max height as the content height grows, but the user has never dragged the sheet up to expand it. This gives the user some level of expansion for intrinsic height (maybe half way up), but then requires the user to opt in to the absolute maximum height by dragging up.MessagePageScaffoldby only starting a simulation if we're not already at the destination, and by correcting the velocity direction (we had it inverted from what it should be). Also fixed some situations where the sheet was getting stuck at an offset due to the order of some lines of code where theTickerwould stop when it shouldn't be stopped.RenderMessageEditorHeight- Fixed possible NPE when looking up ancestorMessagePageScaffold.Editor- Adjusted some order of operations dealing with when/how transactions are ended, and listeners are notified. This issue was found when implemeingSuperIme. One of the listeners happened to submit aClearSelectionRequestat just the right time to cause an error with the order that properties were cleaned up at the end of a transaction. The critical change here was to null out the active change list before notifying listeners that the transaction was over. This required holding onto a temporary copy of the list to pass the change list to those listeners, even though we already null'ed out the active change list.createDefaultEditor()so that you don't have to pass a document or a composer if you want empty default implementations. I wanted this for a long time and kept putting it off.