-
Notifications
You must be signed in to change notification settings - Fork 6k
Fix Share Screen Crash on iPad #48220
Changes from all commits
52a11ea
2d678fa
4a65fdd
3b171dc
d7a55b5
7e72f93
ae1880d
20a8f10
12e23aa
0017713
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,8 @@ | |
| #import <UIKit/UIKit.h> | ||
|
|
||
| #include "flutter/fml/logging.h" | ||
| #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" | ||
| #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" | ||
| #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" | ||
| #import "flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h" | ||
|
|
||
|
|
@@ -154,10 +156,38 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { | |
|
|
||
| - (void)showShareViewController:(NSString*)content { | ||
| UIViewController* engineViewController = [_engine.get() viewController]; | ||
|
|
||
| NSArray* itemsToShare = @[ content ?: [NSNull null] ]; | ||
| UIActivityViewController* activityViewController = | ||
| [[[UIActivityViewController alloc] initWithActivityItems:itemsToShare | ||
| applicationActivities:nil] autorelease]; | ||
|
|
||
| if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { | ||
| // On iPad, the share screen is presented in a popover view, and requires a | ||
| // sourceView and sourceRect | ||
| FlutterTextInputPlugin* _textInputPlugin = [_engine.get() textInputPlugin]; | ||
| UITextRange* range = _textInputPlugin.textInputView.selectedTextRange; | ||
|
|
||
| // firstRectForRange cannot be used here as it's current implementation does | ||
| // not always return the full rect of the range. | ||
| CGRect firstRect = [(FlutterTextInputView*)_textInputPlugin.textInputView | ||
| caretRectForPosition:(FlutterTextPosition*)range.start]; | ||
| CGRect transformedFirstRect = [(FlutterTextInputView*)_textInputPlugin.textInputView | ||
| localRectFromFrameworkTransform:firstRect]; | ||
| CGRect lastRect = [(FlutterTextInputView*)_textInputPlugin.textInputView | ||
| caretRectForPosition:(FlutterTextPosition*)range.end]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. iirc range.end is exclusive. |
||
| CGRect transformedLastRect = [(FlutterTextInputView*)_textInputPlugin.textInputView | ||
| localRectFromFrameworkTransform:lastRect]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does this
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you get global coordinates from local ones
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gotcha. The naming is a bit weird and sounds like the opposite. |
||
|
|
||
| activityViewController.popoverPresentationController.sourceView = engineViewController.view; | ||
| // In case of RTL Language, get the minimum x coordinate | ||
| activityViewController.popoverPresentationController.sourceRect = | ||
| CGRectMake(fmin(transformedFirstRect.origin.x, transformedLastRect.origin.x), | ||
| transformedFirstRect.origin.y, | ||
| abs(transformedLastRect.origin.x - transformedFirstRect.origin.x), | ||
| transformedFirstRect.size.height); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this won't work for RTL language. possibly crash due to negative width
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, would it help if i just wrapped in abs() ? I dont know what rtl language is
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RTL = right-to-left, e.g. arabic/hebrew |
||
|
|
||
| [engineViewController presentViewController:activityViewController animated:YES completion:nil]; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -163,6 +163,10 @@ FLUTTER_DARWIN_EXPORT | |
| - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; | ||
| - (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin NS_DESIGNATED_INITIALIZER; | ||
|
|
||
| // TODO(louisehsu): These are being exposed to support Share in FlutterPlatformPlugin | ||
| // Consider moving that feature into FlutterTextInputPlugin to avoid exposing extra methods | ||
| - (CGRect)localRectFromFrameworkTransform:(CGRect)incomingRect; | ||
| - (CGRect)caretRectForPosition:(UITextPosition*)position; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are you exposing these APIs?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a TODO here, explaining that these are exposed to be used for your feature, but we should consider moving your feature inside this plugin so we don't have to expose it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you file an issue to further investigate this? |
||
| @end | ||
|
|
||
| @interface UIView (FindFirstResponder) | ||
|
|
||
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.
take a look at
firstRectForRangewhich takes the range directly.Uh oh!
There was an error while loading. Please reload this page.
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 doesnt, or at least not usably. After transforming it gives me the coordinates for the top right corner of the first character, which is right, but the size is super, super off.
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.
can you add a note here that we can't use
firstRectForRangeAPI since it's current implementation doesn't always return the full rect of the range.