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 @@ -158,6 +158,16 @@ - (void)showShareViewController:(NSString*)content {
UIActivityViewController* activityViewController =
[[[UIActivityViewController alloc] initWithActivityItems:itemsToShare
applicationActivities:nil] autorelease];

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
activityViewController.popoverPresentationController.sourceView = engineViewController.view;
activityViewController.popoverPresentationController.sourceRect =
CGRectMake(CGRectGetWidth(engineViewController.view.bounds) / 2,
CGRectGetHeight(engineViewController.view.bounds) / 2, 0, 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

UIKit uses this rect to tell where the pop over should be presented. This should be the rect of the selected text

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, but we would have to pass in the rect size/coords from the framework, and then add logic to make sure that the view is being rendered either above/below/next to the text so that it's not clipping off the screen depending on the position of the text and the current view bounds... which is totally doable but since this is a fatal crash I wanted to get it at least non-crashing as soon as possible

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Never mind, looks like the positioning is automatically handled 👀 will update this PR

activityViewController.popoverPresentationController.permittedArrowDirections =
UIPopoverArrowDirection();
}

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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 @@ -166,6 +166,44 @@ - (void)testShareScreenInvoked {
[self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testShareScreenInvokedOnIPad {
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
[engine runWithEntrypoint:nil];
std::unique_ptr<fml::WeakNSObjectFactory<FlutterEngine>> _weakFactory =
std::make_unique<fml::WeakNSObjectFactory<FlutterEngine>>(engine);

XCTestExpectation* presentExpectation =
[self expectationWithDescription:@"Share view controller presented on iPad"];

FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
OCMStub([mockEngineViewController
presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
animated:YES
completion:nil]);

id mockTraitCollection = OCMClassMock([UITraitCollection class]);
OCMStub([mockTraitCollection userInterfaceIdiom]).andReturn(UIUserInterfaceIdiomPad);

FlutterPlatformPlugin* plugin =
[[FlutterPlatformPlugin alloc] initWithEngine:_weakFactory->GetWeakNSObject()];
FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);

FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke"
arguments:@"Test"];
FlutterResult result = ^(id result) {
OCMVerify([mockEngineViewController
presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
animated:YES
completion:nil]);
[presentExpectation fulfill];
};
[mockPlugin handleMethodCall:methodCall result:result];
[self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testClipboardHasCorrectStrings {
[UIPasteboard generalPasteboard].string = nil;
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
Expand Down