-
Notifications
You must be signed in to change notification settings - Fork 29.8k
[iOS] Add spell check suggestions toolbar on tap #119189
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
Conversation
|
|
||
| /// Replace composing region with specified text. | ||
| void replaceComposingRegion(SelectionChangedCause cause, String text) { | ||
| void replaceComposingRegion({required SelectionChangedCause cause, required String text, TextRange? composingRegionRange, bool shouldSelectWordEdgeAfterReplacement = false}) { |
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.
Particularly looking for feedback here. Need a way to do this same logic without access to the composing region for iOS, and this is what I came up with. Also considered a separate method for that case.
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.
Check out ReplaceTextIntent. I think it basically does the same thing as this and the API is nearly identical, so I think you're on the right track. I would just make these parameters match as closely with those as possible in name and order.
I wonder if this could be somehow combined with _replaceText, which uses ReplaceTextIntent in this file?
Also, maybe Android should be using this full API anyway, instead of relying on the composing region here. Especially since non-Gboard IMEs might not have a composing region, either. Maybe that's not this PR's responsibility, though.
Then I would drop the "composing region" terminology from this method.
This could be a breaking change so keep an eye out, but it's probably very unlikely since this was just released.
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.
We will ultimately need to move away from using the composing region to fix the Samsung and iOS issue (#119534), so I took your advice on not using it for Android or iOS. This method uses _replaceText already, which is used in other ways, as well, so I'm not sure if we should combine it. Maybe I could name this something like replaceTextFromToolbar since it contains toolbar-specific behavior.
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 talked to @LongCatIsLooong and @Renzo-Olivares about this. We came to some good conclusions about how to organize the code that updates TextEditingValue in EditableText, but I'm worried they won't be possible here...
We'd like to keep all mutations of TextEditingValue like this in userUpdateTextEditingValue. So in this case that would mean deleting replaceComposingRegion/replaceText and putting all of that logic inside of SpellCheckSuggestionsToolbar. The one reason I'm not sure if that will work is the call to _didChangeTextEditingValue, which is private...
Can you try this out and see if you can get it to work without being able to call _didChangeTextEditingValue directly? If not we're probably ok to turn this into a public replaceWithSuggestion method or something like that. Currently the other toolbar buttons like cut/copy/paste all have their own public methods on EditableTextState, so it wouldn't be too terrible if this has a public method too.
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.
Looking good, mostly small stuff besides some suggestions you asked for on replaceComposingRegion. Excited for this PR.
packages/flutter/lib/src/cupertino/spell_check_suggestions_toolbar.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/cupertino/spell_check_suggestions_toolbar.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/cupertino/spell_check_suggestions_toolbar.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/cupertino/spell_check_suggestions_toolbar.dart
Outdated
Show resolved
Hide resolved
| if (shouldSelectWordEdgeAfterReplacement) { | ||
| renderEditable.selectWordEdge(cause: cause); | ||
| } |
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.
Would it work out if it were the caller's responsibility to call selectWordEdge after calling this if they want that behavior?
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 mean as long as they call it, it should be fine. Otherwise, the word would stay highlighted after the replacement was made until another tap was made.
| expect(state.showSpellCheckSuggestionsToolbarCalled, isFalse); | ||
| expect(state.toggleToolbarCalled, isTrue); | ||
| }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS })); | ||
|
|
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.
Is it possible to do one test that does the full cycle of 1. tap misspelled word 2. tap suggestion in the toolbar 3. expect the suggestion to have replaced the misspelled word.
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 sort of behavior is tested in editable_text_test.dart, so I'll try adding a test for at least 2/3 there. And keep 1 tested here, like with the Material style toolbar.
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 looks fine to me now, thanks.
| } | ||
| buttonItems.add(ContextMenuButtonItem( | ||
| onPressed: () { | ||
| if (!editableTextState.mounted) { |
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.
@LongCatIsLooong like this? I think this is causing a test to break: https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8786435562172940817/+/u/run_test.dart_for_web_tests_shard_and_subshard_6/test_stdout
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 this is what I meant. Looks like the failure was caused by Path.combine not being implemented by the HTML renderer, but I double this mounted check is the direct cause of that failure.
| selection: TextSelection(affinity: TextAffinity.upstream, baseOffset: 0, extentOffset: 4), | ||
| ); | ||
| controller.value = value; | ||
| await tester.pumpWidget( |
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.
Nit: This block should be outdented 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.
This still looks like it needs its indentation fixed.
|
The actual setting of the updated TextEditingValue is what seems to cause this strange test failure. All the suspicious things from postFrameCallbacks etc. didn't seem to fix it though. I'll take a closer look if I have time. |
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 👍
| // Spell check suggestions toolbars are intended to be shown on non-web | ||
| // platforms. Additionally, the Cupertino style toolbar can't be drawn on | ||
| // the web with the HTML renderer due to | ||
| // https://github.com/flutter/flutter/issues/44572. |
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 just created an issue specific to this, can you link to that one instead? #123560
| } | ||
|
|
||
| /// Replace composing region with specified text. | ||
| void replaceComposingRegion(SelectionChangedCause cause, String text) { |
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.
Looks like Google tests passed 👍
| selection: TextSelection(affinity: TextAffinity.upstream, baseOffset: 0, extentOffset: 4), | ||
| ); | ||
| controller.value = value; | ||
| await tester.pumpWidget( |
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 still looks like it needs its indentation fixed.
[iOS] Add spell check suggestions toolbar on tap
Add iOS spell check toolbar to show spell check suggestions, as part of #34688. Fixes #119537.
This PR will cause the following to occur on single tap (touch only) if the word tapped is misspelled:
The toolbar shows on single tap up if the word tap is misspelled. Otherwise, the normal behavior takes precedent.
Pre-launch Checklist
///).