Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit bb224ce

Browse files
committed
[ios]allow reordering and more items in native context menu
1 parent aa3423f commit bb224ce

File tree

1 file changed

+114
-3
lines changed

1 file changed

+114
-3
lines changed

shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm

Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ @interface FlutterTextInputView ()
795795
// etc)
796796
@property(nonatomic, copy) NSString* temporarilyDeletedComposedCharacter;
797797
@property(nonatomic, assign) CGRect editMenuTargetRect;
798+
@property(nonatomic, strong) NSArray<NSDictionary*>* editMenuItems;
798799

799800
- (void)setEditableTransform:(NSArray*)matrix;
800801
@end
@@ -868,10 +869,118 @@ - (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin {
868869
return self;
869870
}
870871

872+
- (void)handleSearchWebAction {
873+
NSLog(@"put search web logic here");
874+
}
875+
876+
- (void)handleLookUpAction {
877+
NSLog(@"put look up logic here");
878+
}
879+
880+
- (void)handleShareAction {
881+
NSLog(@"put share logic here");
882+
}
883+
884+
// DFS algorithm to search a UICommand from the menu tree.
885+
- (UICommand*)searchCommandWithSelector:(SEL)selector
886+
element:(UIMenuElement*)element API_AVAILABLE(ios(16.0)) {
887+
if ([element isKindOfClass:UICommand.class]) {
888+
UICommand* command = (UICommand*)element;
889+
return command.action == selector ? command : nil;
890+
} else if ([element isKindOfClass:UIMenu.class]) {
891+
NSArray<UIMenuElement*>* children = ((UIMenu*)element).children;
892+
for (UIMenuElement* child in children) {
893+
UICommand* result = [self searchCommandWithSelector:selector element:child];
894+
if (result) {
895+
return result;
896+
}
897+
}
898+
return nil;
899+
} else {
900+
return nil;
901+
}
902+
}
903+
904+
- (void)addBasicEditingCommandToItems:(NSMutableArray*)items
905+
action:(NSString*)action
906+
selector:(SEL)selector
907+
suggestedMenu:(UIMenu*)suggestedMenu {
908+
UICommand* command = [self searchCommandWithSelector:selector element:suggestedMenu];
909+
if (command) {
910+
[items addObject:command];
911+
}
912+
}
913+
914+
- (void)addAdditionalBasicCommandToItems:(NSMutableArray*)items
915+
action:(NSString*)action
916+
selector:(SEL)selector
917+
encodedItem:(NSDictionary<NSString*, id>*)encodedItem {
918+
NSString* title = encodedItem[@"title"];
919+
if (title) {
920+
UICommand* command = [UICommand commandWithTitle:title
921+
image:nil
922+
action:selector
923+
propertyList:nil];
924+
[items addObject:command];
925+
}
926+
}
927+
871928
- (UIMenu*)editMenuInteraction:(UIEditMenuInteraction*)interaction
872929
menuForConfiguration:(UIEditMenuConfiguration*)configuration
873930
suggestedActions:(NSArray<UIMenuElement*>*)suggestedActions API_AVAILABLE(ios(16.0)) {
874-
return [UIMenu menuWithChildren:suggestedActions];
931+
UIMenu* suggestedMenu = [UIMenu menuWithChildren:suggestedActions];
932+
if (!_editMenuItems) {
933+
return suggestedMenu;
934+
}
935+
936+
NSMutableArray* items = [NSMutableArray array];
937+
for (NSDictionary<NSString*, id>* encodedItem in _editMenuItems) {
938+
if ([encodedItem[@"type"] isEqualToString:@"default"]) {
939+
NSString* action = encodedItem[@"action"];
940+
if ([action isEqualToString:@"copy"]) {
941+
[self addBasicEditingCommandToItems:items
942+
action:action
943+
selector:@selector(copy:)
944+
suggestedMenu:suggestedMenu];
945+
} else if ([action isEqualToString:@"paste"]) {
946+
[self addBasicEditingCommandToItems:items
947+
action:action
948+
selector:@selector(paste:)
949+
suggestedMenu:suggestedMenu];
950+
} else if ([action isEqualToString:@"cut"]) {
951+
[self addBasicEditingCommandToItems:items
952+
action:action
953+
selector:@selector(cut:)
954+
suggestedMenu:suggestedMenu];
955+
} else if ([action isEqualToString:@"delete"]) {
956+
[self addBasicEditingCommandToItems:items
957+
action:action
958+
selector:@selector(delete:)
959+
suggestedMenu:suggestedMenu];
960+
} else if ([action isEqualToString:@"selectAll"]) {
961+
[self addBasicEditingCommandToItems:items
962+
action:action
963+
selector:@selector(selectAll:)
964+
suggestedMenu:suggestedMenu];
965+
} else if ([action isEqualToString:@"searchWeb"]) {
966+
[self addAdditionalBasicCommandToItems:items
967+
action:action
968+
selector:@selector(handleSearchWebAction)
969+
encodedItem:encodedItem];
970+
} else if ([action isEqualToString:@"share"]) {
971+
[self addAdditionalBasicCommandToItems:items
972+
action:action
973+
selector:@selector(handleShareAction)
974+
encodedItem:encodedItem];
975+
} else if ([action isEqualToString:@"lookUp"]) {
976+
[self addAdditionalBasicCommandToItems:items
977+
action:action
978+
selector:@selector(handleLookUpAction)
979+
encodedItem:encodedItem];
980+
}
981+
}
982+
}
983+
return [UIMenu menuWithChildren:items];
875984
}
876985

877986
- (void)editMenuInteraction:(UIEditMenuInteraction*)interaction
@@ -887,8 +996,10 @@ - (CGRect)editMenuInteraction:(UIEditMenuInteraction*)interaction
887996
return _editMenuTargetRect;
888997
}
889998

890-
- (void)showEditMenuWithTargetRect:(CGRect)targetRect API_AVAILABLE(ios(16.0)) {
999+
- (void)showEditMenuWithTargetRect:(CGRect)targetRect
1000+
items:(NSArray<NSDictionary*>*)items API_AVAILABLE(ios(16.0)) {
8911001
_editMenuTargetRect = targetRect;
1002+
_editMenuItems = items;
8921003
UIEditMenuConfiguration* config =
8931004
[UIEditMenuConfiguration configurationWithIdentifier:nil sourcePoint:CGPointZero];
8941005
[self.editMenuInteraction presentEditMenuWithConfiguration:config];
@@ -2560,7 +2671,7 @@ - (BOOL)showEditMenu:(NSDictionary*)args API_AVAILABLE(ios(16.0)) {
25602671
[encodedTargetRect[@"x"] doubleValue], [encodedTargetRect[@"y"] doubleValue],
25612672
[encodedTargetRect[@"width"] doubleValue], [encodedTargetRect[@"height"] doubleValue]);
25622673
CGRect localTargetRect = [self.hostView convertRect:globalTargetRect toView:self.activeView];
2563-
[self.activeView showEditMenuWithTargetRect:localTargetRect];
2674+
[self.activeView showEditMenuWithTargetRect:localTargetRect items:args[@"items"]];
25642675
return YES;
25652676
}
25662677

0 commit comments

Comments
 (0)