Skip to content
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

[ios][secure_paste]Show context items based on framework's data #56362

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 114 additions & 3 deletions shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ @interface FlutterTextInputView ()
// etc)
@property(nonatomic, copy) NSString* temporarilyDeletedComposedCharacter;
@property(nonatomic, assign) CGRect editMenuTargetRect;
@property(nonatomic, strong) NSArray<NSDictionary*>* editMenuItems;

- (void)setEditableTransform:(NSArray*)matrix;
@end
Expand Down Expand Up @@ -868,10 +869,118 @@ - (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin {
return self;
}

- (void)handleSearchWebAction {
NSLog(@"put search web logic here");
}

- (void)handleLookUpAction {
NSLog(@"put look up logic here");
}

- (void)handleShareAction {
NSLog(@"put share logic here");
}

// DFS algorithm to search a UICommand from the menu tree.
- (UICommand*)searchCommandWithSelector:(SEL)selector
element:(UIMenuElement*)element API_AVAILABLE(ios(16.0)) {
if ([element isKindOfClass:UICommand.class]) {
UICommand* command = (UICommand*)element;
return command.action == selector ? command : nil;
} else if ([element isKindOfClass:UIMenu.class]) {
NSArray<UIMenuElement*>* children = ((UIMenu*)element).children;
for (UIMenuElement* child in children) {
UICommand* result = [self searchCommandWithSelector:selector element:child];
if (result) {
return result;
}
}
return nil;
} else {
return nil;
}
}

- (void)addBasicEditingCommandToItems:(NSMutableArray*)items
action:(NSString*)action
selector:(SEL)selector
suggestedMenu:(UIMenu*)suggestedMenu {
UICommand* command = [self searchCommandWithSelector:selector element:suggestedMenu];
if (command) {
[items addObject:command];
}
}

- (void)addAdditionalBasicCommandToItems:(NSMutableArray*)items
action:(NSString*)action
selector:(SEL)selector
encodedItem:(NSDictionary<NSString*, id>*)encodedItem {
NSString* title = encodedItem[@"title"];
if (title) {
UICommand* command = [UICommand commandWithTitle:title
image:nil
action:selector
propertyList:nil];
[items addObject:command];
}
}

- (UIMenu*)editMenuInteraction:(UIEditMenuInteraction*)interaction
menuForConfiguration:(UIEditMenuConfiguration*)configuration
suggestedActions:(NSArray<UIMenuElement*>*)suggestedActions API_AVAILABLE(ios(16.0)) {
return [UIMenu menuWithChildren:suggestedActions];
UIMenu* suggestedMenu = [UIMenu menuWithChildren:suggestedActions];
if (!_editMenuItems) {
return suggestedMenu;
}

NSMutableArray* items = [NSMutableArray array];
for (NSDictionary<NSString*, id>* encodedItem in _editMenuItems) {
if ([encodedItem[@"type"] isEqualToString:@"default"]) {
NSString* action = encodedItem[@"action"];
if ([action isEqualToString:@"copy"]) {
[self addBasicEditingCommandToItems:items
action:action
selector:@selector(copy:)
suggestedMenu:suggestedMenu];
} else if ([action isEqualToString:@"paste"]) {
[self addBasicEditingCommandToItems:items
action:action
selector:@selector(paste:)
suggestedMenu:suggestedMenu];
} else if ([action isEqualToString:@"cut"]) {
[self addBasicEditingCommandToItems:items
action:action
selector:@selector(cut:)
suggestedMenu:suggestedMenu];
} else if ([action isEqualToString:@"delete"]) {
[self addBasicEditingCommandToItems:items
action:action
selector:@selector(delete:)
suggestedMenu:suggestedMenu];
} else if ([action isEqualToString:@"selectAll"]) {
[self addBasicEditingCommandToItems:items
action:action
selector:@selector(selectAll:)
suggestedMenu:suggestedMenu];
} else if ([action isEqualToString:@"searchWeb"]) {
[self addAdditionalBasicCommandToItems:items
action:action
selector:@selector(handleSearchWebAction)
encodedItem:encodedItem];
} else if ([action isEqualToString:@"share"]) {
[self addAdditionalBasicCommandToItems:items
action:action
selector:@selector(handleShareAction)
encodedItem:encodedItem];
} else if ([action isEqualToString:@"lookUp"]) {
[self addAdditionalBasicCommandToItems:items
action:action
selector:@selector(handleLookUpAction)
encodedItem:encodedItem];
}
}
}
return [UIMenu menuWithChildren:items];
}

- (void)editMenuInteraction:(UIEditMenuInteraction*)interaction
Expand All @@ -887,8 +996,10 @@ - (CGRect)editMenuInteraction:(UIEditMenuInteraction*)interaction
return _editMenuTargetRect;
}

- (void)showEditMenuWithTargetRect:(CGRect)targetRect API_AVAILABLE(ios(16.0)) {
- (void)showEditMenuWithTargetRect:(CGRect)targetRect
items:(NSArray<NSDictionary*>*)items API_AVAILABLE(ios(16.0)) {
_editMenuTargetRect = targetRect;
_editMenuItems = items;
UIEditMenuConfiguration* config =
[UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:CGPointZero];
[self.editMenuInteraction presentEditMenuWithConfiguration:config];
Expand Down Expand Up @@ -2560,7 +2671,7 @@ - (BOOL)showEditMenu:(NSDictionary*)args API_AVAILABLE(ios(16.0)) {
[encodedTargetRect[@"x"] doubleValue], [encodedTargetRect[@"y"] doubleValue],
[encodedTargetRect[@"width"] doubleValue], [encodedTargetRect[@"height"] doubleValue]);
CGRect localTargetRect = [self.hostView convertRect:globalTargetRect toView:self.activeView];
[self.activeView showEditMenuWithTargetRect:localTargetRect];
[self.activeView showEditMenuWithTargetRect:localTargetRect items:args[@"items"]];
return YES;
}

Expand Down