Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -154,18 +156,31 @@ - (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 CGRect
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requires a sourceView and a sourceRect

FlutterTextInputPlugin* _textInputPlugin = [_engine.get() textInputPlugin];
UITextRange* range = _textInputPlugin.textInputView.selectedTextRange;

CGRect firstRect = [(FlutterTextInputView*)_textInputPlugin.textInputView
caretRectForPosition:(FlutterTextPosition*)range.start];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a look at firstRectForRange which takes the range directly.

Copy link
Contributor Author

@LouiseHsu LouiseHsu Nov 21, 2023

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.

Copy link
Contributor

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 firstRectForRange API since it's current implementation doesn't always return the full rect of the range.

CGRect transformedRectLeft = [(FlutterTextInputView*)_textInputPlugin.textInputView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you avoid left/right since it's not correct for RTL languages?

localRectFromFrameworkTransform:firstRect];
CGRect lastRect = [(FlutterTextInputView*)_textInputPlugin.textInputView
caretRectForPosition:(FlutterTextPosition*)range.end];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc range.end is exclusive.

CGRect transformedRectRight = [(FlutterTextInputView*)_textInputPlugin.textInputView
localRectFromFrameworkTransform:lastRect];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this localRectFromFrameworkTransform do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you get global coordinates from local ones

Copy link
Contributor

Choose a reason for hiding this comment

The 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;
activityViewController.popoverPresentationController.sourceRect =
CGRectMake(CGRectGetWidth(engineViewController.view.bounds) / 2,
CGRectGetHeight(engineViewController.view.bounds) / 2, 0, 0);
activityViewController.popoverPresentationController.permittedArrowDirections =
UIPopoverArrowDirection();
CGRectMake(transformedRectLeft.origin.x, transformedRectLeft.origin.y,
transformedRectRight.origin.x - transformedRectLeft.origin.x,
transformedRectLeft.size.height);
}
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abs() should work. but please try it out

Copy link
Contributor

Choose a reason for hiding this comment

The 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];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ FLUTTER_DARWIN_EXPORT
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin NS_DESIGNATED_INITIALIZER;

- (CGRect)localRectFromFrameworkTransform:(CGRect)incomingRect;
- (CGRect)caretRectForPosition:(UITextPosition*)position;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are you exposing these APIs?

Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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)
Expand Down