-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Workaround iOS text input crash for emoji+Korean text #36295
Conversation
if (emoji) { | ||
self.lastEmoji = emoji; | ||
} | ||
if (text.length == 1 && !text.UTF8String && |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
dispatch_once(&onceToken, ^{ | ||
set = CFCharacterSetCreateMutableCopy( | ||
kCFAllocatorDefault, | ||
CTFontCopyCharacterSet(CTFontCreateWithName(CFSTR("AppleColorEmoji"), 0.0, NULL))); |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
99125e9
to
12dff9a
Compare
12dff9a
to
ad3c308
Compare
#34508 seems similar and we might be able to use some of the tests in the PR. |
engine/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm Lines 421 to 439 in a7accef
|
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 approach LGTM. I think the keyboard also handles grapheme clusters wrong. I'll check what the exact behavior is.
} | ||
// Only need to use lastComposedCharacters for the one insertion right after deletion. | ||
// Clear it even it is not used in the above if block. | ||
self.lastComposedCharacters = nil; |
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.
also maybe set the stored value to nil
at the end of the runloop?
// Workaround for https://github.com/flutter/flutter/issues/111494 | ||
// TODO(cyanglaz): revert this workaround if when flutter supports a minimum iOS version which | ||
// this bug is fixed by Apple. | ||
text = self.lastComposedCharacters; |
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.
So this step adds the emoji back, then the IME will call insertText:
again to insert "어"?
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.
why the text.length == 1
check? Shouldn't !text.UTF8String
be enough (I'm assuming this checks the string is not malformed)?
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.
nvm. I tried some grapheme clusters, the keyboard always inserts the first code unit.
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.
So this step adds the emoji back, then the IME will call
insertText:
again to insert "어"?
Yes. I'm going to add what the "bugged" behavior actually is in the PR description.
// Workaround for https://github.com/flutter/flutter/issues/111494 | ||
// TODO(cyanglaz): revert this workaround if when flutter supports a minimum iOS version which | ||
// this bug is fixed by Apple. | ||
text = self.lastComposedCharacters; | ||
text = self.temporarilyDeletedComposedCharacter; |
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: also clear the stored string here since it's consumed?
[inputView deleteBackward]; | ||
[inputView shouldChangeTextInRange:OCMClassMock([UITextRange class]) replacementText:@""]; | ||
|
||
// Insert the first unicode in the emoji. |
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: first unicode -> first unichar
@@ -1956,9 +1961,8 @@ - (void)deleteBackward { | |||
NSString* deletedText = [self.text substringWithRange:_selectedTextRange.range]; | |||
CFRange range = |
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: consider using fml::RangeForCharacterAtIndex
@cyanglaz is out this week, he will pick the nits for next week. |
b2806a2
to
b5856e7
Compare
@cyanglaz is this ready to merge? |
@LongCatIsLooong Updated to use |
range:charRange | ||
remainingRange:NULL]; | ||
if (gotCodePoint && u_hasBinaryProperty(codePoint, UCHAR_EMOJI)) { | ||
if (IsEmoji(self.text, charRange)) { |
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: some emojis are in plane 0 and require only one code point to encode, e.g.: https://www.compart.com/en/unicode/U+2764
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.
still LGTM
* Fix an issue that deleting an emoji may crash the app (#34508) * Workaround iOS text input crash for emoji+Korean text (#36295) Co-authored-by: Yang Chao <[email protected]> Co-authored-by: Chris Yang <[email protected]>
This is what iOS 16 does when transforming 2 Korean characters into 1 (for example ㅇ ㅏ) right after a unicode composed character (emoji etc):
However, in iOS 16.0, there is a bug that in step 2, only the first unicode is inserted, which creates an incomplete or different composed character.
To workaround this issue, this PR:
The issue is caused by an iOS bug and this PR only provides a workaround, we should revert this workaround when the issue is fixed by iOS.
fixes flutter/flutter#111494
Pre-launch Checklist
writing and running engine tests.
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.