-
Notifications
You must be signed in to change notification settings - Fork 6k
[ios][secure_paste]Show context items based on items sent from framework #56362
Conversation
2593238 to
bb224ce
Compare
|
@justinmc This PR is not complete, but it should be good enough to start the framework side on top of it. Example usage: Also notice that I added |
|
@justinmc just added implementation for additional items (look up, search web, etc), and can confirm they worked. |
|
Cool I'm excited about this! I'll be OOO on Monday but I'll start playing around with this on Tuesday. |
86350c4 to
edb9a0b
Compare
|
Still planning to compile this and try talking to it from the framework by the end of the week. |
justinmc
left a comment
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.
Ok I was able to get this to compile and play around with it from the framework, and it works great. I still need to write some real framework code to interact with this and double check that it's what we want, but everything seems good.
One thought: Should there be some error checking to make sure that the items that are being passed are well-formatted? For example, if I pass this, it silently just doesn't show the button:
<String, dynamic>{
'type': 'default',
'action': 'share',
},| // DFS algorithm to search a UICommand from the menu tree. | ||
| - (UICommand*)searchCommandWithSelector:(SEL)selector | ||
| element:(UIMenuElement*)element API_AVAILABLE(ios(16.0)) { |
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.
Is this searching through the default menu (suggestedActions) trying to find the item given in the call to showSystemContextMenu? Won't all of the ones that we currently support never be nested? Or maybe I just don't understand how suggestedActions is structured.
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.
Actually all of them are nested at least 1 level deep in my observation - Apple uses UIMenuOptionsDisplayInline to make the items appear on the top level. And since this is not an API contract, we have to do a tree search here.
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.
Got it, thanks for the explanation!
|
@justinmc Added the check for missing
|
|
Ok I tried sending a mal-formatted item and indeed I got the error message 👍 . So with this approach, it will log an error but the call to |
My understanding is that flutter app developers won't be able to send invalid format from framework to engine, because the menu created using our dart API will be correctly translated into the right format in the framework. The error message is there just so that the framework contributors (i.e. you and future others) know what's going on during development phase, but the error shouldn't happen to flutter app developers. |
|
A Flutter app developer can always send whatever crazy json they want over the platform channels if they really want to: SystemChannels.platform.invokeMethod<Map<String, dynamic>>(
'ContextMenu.showSystemContextMenu',
<String, dynamic>{
'targetRect': myTargetRect,
'items': myCrazyItems,
'something else that doesnt make sense': 42,
);But you're right that normally a user would never mess with this low level API, and I'm writing a higher-level API that should make a mal-formatted request impossible at that level. I guess this is kind of splitting hairs. Either way is fine. In the long term hopefully we will be using FFI with compile time checking of these calls. |
|
What do you think about changing the name of the "default" type? It's a keyword in Dart so I have to work around it: enum SystemContextMenuType {
custom,
defaultType; // This can't be `default`, so I'm using `defaultType`.
String get json => switch (this) {
SystemContextMenuType.defaultType => 'default',
_ => name,
};
}But if we renamed it then it could be simpler: enum SystemContextMenuType {
custom,
builtIn; // Or some better name... `platform`? `platformDefault`?
} |
I'm ok with either. How about let's do |
|
Updated from |
|
Thank you! I like |
|
@hellohuanlin If I pass a I guess this is just a result of the two different types of actions that you mention in the PR description, but I want to make sure it's clear to app developers. |
Yes it's intended that I use the title from the system itself, and it is localized. I can also used the title passed from framework (except for the "paste" item which i cannot change), if you think it's necessary?
To app developers, do they have to pass in the title? or do they simply pass the ContextMenuButtonType? |
|
Thanks for the explanation. I guess let's keep it as-is. I'll enforce on the framework side that no title can be given for cut/copy/paste/selectall, and only the type is needed. |
|
@hellohuanlin Could we combine the I mention this because I noticed that in the framework I can just infer |
|
@justinmc no specific reason. I can do that if you like? (deleted internal link) |
|
@justinmc The new design is indeed simpler! i've just updated the PR. |
|
Thank you! I've updated my framework PR to work with it and it looks good. |
|
Are these rules correct for all of the types that we have now?
Edit: Updated my understanding of share, searchWeb, lookUp. |
By "not providing title", do you mean framework not providing title to the engine? or do you mean app developers not providing title to the framework? If you are talking about framework <-> engine communication, yes you are right. |
|
Great, thanks. Yes, this was about framework/engine communication. In the SystemContextMenu widget I will populate titles with default localized strings where I can, so the requirements are slightly different. |
|
@hellohuanlin Give the repo merge, I think these changes now need to happen in flutter/flutter right? Any idea on the best way to do that? Maybe you could apply the diff to my branch and then push a commit to my branch. |
It seems there are a few options:
I am leaning towards either (2) or (3 then 2). No strong opinion against (1) though. Let me know. |
|
Oh right I guess I can still build this branch from my separate local engine repo checkout in order to do local development, so let's go with 3 for now. For 2, do you mean that you would open a separate PR in flutter/flutter? |
Sounds good.
Yep. |
|
Could you actually update this branch with |
I'm not surprised that it's incompatible with the latest master. Do you have an old branch on flutter/flutter? Or if you want I can also put up a PR on flutter/flutter. |
|
I think I need you to open a PR on flutter/flutter. I tried updating this branch locally and it still wasn't able to run after rebuilding the engine. My flutter/flutter branch is up to date as of yesterday. Thank you! |
Sounds good. |
|
I think this PR can be closed in favor of flutter/flutter#161103. I was able to get these changes working in the monorepo by merging that branch with my PR flutter/flutter#159013. I had some struggles building the engine in the monorepo but I updated the docs in flutter/flutter#161184 with what I found to work. |
Thank you @justinmc and @hellohuanlin! Closing... |
…161103) This is moved from flutter/engine#56362 *List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.* *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
This PR shows the context menu based on what's received from the framework via method channel. There are 2 cases:
1. For basic editing actions (e.g. copy/paste):
We perform a DFS search inside
suggestedActions, so that we don't have to specify things like keyboard shortcut.2. For additional actions (e.g. look up, share, search web):
We manually create
UICommandbecause (1) some actions are not provided bysuggestedActions(2) these are simplyUICommand(rather thanUIKeyCommand), so we just need title and action (3) the actions are private APIs. However this would require framework to send the item title.List which issues are fixed by this PR. You must list at least one issue.
Second milestone for flutter/flutter#103163
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.