-
Notifications
You must be signed in to change notification settings - Fork 27.1k
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
Native ios context menu #143002
Native ios context menu #143002
Conversation
…ed to its own thing on flutter/platform
// TODO(justinmc): Flag it off by default. | ||
// TODO(justinmc): Don't forget CupertinoTextField. Anything else like TextFormField? | ||
if (defaultTargetPlatform == TargetPlatform.iOS && | ||
(MediaQuery.maybeSupportsShowingSystemContextMenu(context) ?? false)) { |
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.
also check if it's for text field vs non-text field widget?
… that menu must be used with text fields
…eing called too late.
88f4d7c
to
457a536
Compare
e8bb51d
to
3b9a8de
Compare
Reverts: #143002 Initiated by: cbracken Reason for reverting: unresolved docs links. See failure here: https://ci.chromium.org/ui/p/flutter/builders/prod/Linux%20docs_test/16540/overview ``` dartdoc:stdout: Generating docs for package flutter... dartdoc:stderr: error: unresolved doc reference [TextInput.showSystemContextMenu] dartdoc:stderr: from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutt Original PR Author: justinmc Reviewed By: {Renzo-Olivares, hellohuanlin} This change reverts the following previous change: In order to work around the fact that iOS 15 shows a notification on pressing Flutter's paste button (#103163), this PR allows showing the iOS system context menu in text fields. <img width="385" alt="Screenshot 2024-02-06 at 11 52 25 AM" src="https://github.com/flutter/flutter/assets/389558/d82e18ee-b8a3-4082-9225-cf47fa7f3674"> It is currently opt-in, which a user would typically do like this (also in example system_context_menu.0.dart): ```dart contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) { // If supported, show the system context menu. if (SystemContextMenu.isSupported(context)) { return SystemContextMenu.editableText( editableTextState: editableTextState, ); } // Otherwise, show the flutter-rendered context menu for the current // platform. return AdaptiveTextSelectionToolbar.editableText( editableTextState: editableTextState, ); }, ``` Requires engine PR flutter/engine#50095. ## API changes ### SystemContextMenu A widget that shows the system context menu when built, and removes it when disposed. The main high-level way that most users would use this PR. Only works on later versions of iOS. ### SystemContextMenuController Used under the hood to hide and show a system context menu. There can only be one visible at a time. ### MediaQuery.supportsShowingSystemContextMenu Sent by the iOS embedder to tell the framework whether or not the platform supports showing the system context menu. That way the framework, or Flutter developers, can decide to show a different menu. ### `flutter/platform ContextMenu.showSystemContextMenu` Sent by the framework to show the menu at a given `targetRect`, which is the current selection rect. ### `flutter/platform ContextMenu.hideSystemContextMenu` Sent by the framework to hide the menu. Typically not needed, because the platform will hide the menu when the user taps outside of it and after the user presses a button, but it handles edge cases where the user programmatically rebuilds the context menu, for example. ### `flutter/platform System.onDismissSystemContextMenu` Sent by the iOS embedder to indicate that the system context menu has been hidden by the system, such as when the user taps outside of the menu. This is useful when there are multiple instances of SystemContextMenu, such as with multiple text fields.
Whoops, how did that not get caught in presubmit? Well I'll create a new PR and fix those. |
It's now possible to use the native-rendered text selection context menu on iOS. This sacrifices customizability in exchange for avoiding showing a notification when the user presses "Paste". It's off by default, but to enable, see the example system_context_menu.0.dart.
Reverts: #148238 Initiated by: zanderso Reason for reverting: Failures in post submit https://logs.chromium.org/logs/flutter/buildbucket/cr-buildbucket/8748025189669617649/+/u/run_test.dart_for_web_canvaskit_tests_shard_and_subshard_3/stdout Original PR Author: justinmc Reviewed By: {hellohuanlin} This change reverts the following previous change: Reland of #143002, which was reverted in #148237 due to unresolved docs references. Not sure why those weren't caught in presubmit. ``` dartdoc:stdout: Generating docs for package flutter... dartdoc:stderr: error: unresolved doc reference [TextInput.showSystemContextMenu] dartdoc:stderr: from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/widgets/media_query.dart:579:14) dartdoc:stderr: in documentation inherited from widgets.MediaQueryData.supportsShowingSystemContextMenu: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/widgets/media_query.dart:579:14) dartdoc:stderr: error: unresolved doc reference [showSystemContextMenu] dartdoc:stderr: from services.SystemContextMenuController.hide: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/services/text_input.dart:2554:16) dartdoc:stderr: error: unresolved doc reference [hideSystemContextMenu] dartdoc:stderr: from services.SystemContextMenuController.show: (file:///b/s/w/ir/x/w/flutter/packages/flutter/lib/src/services/text_input.dart:2509:16) ```
* master: (2580 commits) plugin_ffi template comment fix (flutter#148378) Roll Flutter Engine from 942d7c35de75 to 9e17588b330c (2 revisions) (flutter#148455) Reland fix TextField helper top padding on M3 (flutter#146754) Removing duplicate assert on `VisualDensity` constructor (flutter#148281) Roll Flutter Engine from 65ac4bf96ed7 to 942d7c35de75 (1 revision) (flutter#148450) Roll Flutter Engine from c11d64be5102 to 65ac4bf96ed7 (3 revisions) (flutter#148448) Roll Flutter Engine from f6195e9d4b4b to c11d64be5102 (1 revision) (flutter#148445) Roll Flutter Engine from cd150986ae63 to f6195e9d4b4b (2 revisions) (flutter#148441) Fix leaky tests. (flutter#148434) Roll Flutter Engine from 41b86b59f0ab to cd150986ae63 (2 revisions) (flutter#148430) Roll Flutter Engine from bf1c6da0dd31 to 41b86b59f0ab (15 revisions) (flutter#148428) Update _handlePushRouteInformation to Future<bool> to indicate whether any of the observer has handled the route or not (flutter#147901) Fix memory leaks in `_PopupMenuRoute` (flutter#148373) Add `clipBehavior` to `DrawerThemeData` (flutter#148061) Reland Native ios context menu (flutter#143002) (flutter#148238) (flutter#148265) Roll Packages from fd714bd7d516 to 87a02e393be0 (8 revisions) (flutter#148419) Stop running module_test_ios in devicelab and x64 Macs (flutter#148264) Roll Flutter Engine from d35a1a603c80 to bf1c6da0dd31 (1 revision) (flutter#148369) Roll Flutter Engine from 55c62ff82c7e to d35a1a603c80 (4 revisions) (flutter#148367) Roll Flutter Engine from a1d930a3a84d to 55c62ff82c7e (3 revisions) (flutter#148365) ...
…#6723) flutter/flutter@1dfb46e...1255435 2024-05-13 jmccandless@google.com Native ios context menu (flutter/flutter#143002) 2024-05-13 82763757+NobodyForNothing@users.noreply.github.com test sliver fill remaining examples (flutter/flutter#148041) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from fab7a7417888 to 0050bf9a8094 (1 revision) (flutter/flutter#148211) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from e568e5db9391 to fab7a7417888 (1 revision) (flutter/flutter#148207) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from 57e74a1b3860 to e568e5db9391 (2 revisions) (flutter/flutter#148204) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from 34fd28e8c7bd to 57e74a1b3860 (1 revision) (flutter/flutter#148196) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC rmistry@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@justinmc is there a reason that the new widget for displaying the toolbar only works with Flutter's built-in text field implementation? It has a private constructor and the factory constructor requires a |
@justinmc I'm also curious, is a I ask that because in |
@justinmc I'm continuing integration with this and I have another question. This widget, and surrounding classes, are all given platform-agnostic names. For example: Do you have meaningful evidence that a singular API will be able to work across all platforms? As far as I can tell this work has only attempted to integrate with iOS APIs. I'm wondering if there's a good chance that over time this API (especially once you add the ability to customize the buttons) will only work for iOS due to platform API differences. If so, at that point Flutter will be stuck with an iOS-specific class called |
Assuming you are talking about the
There's an alternative iOS API that takes the
Currently we don't see a need to implement this on Android. However, we did try to make the API platform agnostic, if such need arise in the future. The current milestone requires developers to adopt this API manually, since it lacks of feature parity (e.g. look up, search web, custom actions). In the next milestone we want to enable it by default, so that developers get system menu on iOS 16+, and Flutter menu on other platforms. |
Ok, as I mentioned in my previous comment, I would expect that this is more likely to end up in a bad place than a good place. If you and @justinmc haven't inspected these APIs on Android/Windows/Linux, then there's no indication that the API you've created here would work at all with any other platform. I think if Flutter is going to bring in little pieces of specific platforms, it's much safer to name them after that platform, which is what it really represents anyway. Then, after all platforms are accumulated, you can create a lowest common denominator on top, if desired. |
@matthew-carroll Note that once milestone 2 is done, developers should get secure paste out of box. I am not expecting them to use these types directly. I believe they are only exposed so that we can share code between Cupertino and Material. I am not an expert on flutter/dart tho, so I will ask for @justinmc's opinion. |
Please do NOT make that assumption. This is a long-lived blind spot for Flutter framework developers. @justinmc I'd really appreciate it if you would socialize this problem. Assume that EVERYTHING will be used externally. The reason I'm commenting on this is precisely because I'm adding the use of these APIs to SuperTextField and SuperEditor, neither of which uses any of Flutter's built-in RenderEditable system. Cupertino and Material do not define the universe. They're just two arbitrary UI themes. |
EditableTextState requirementThe reason why the constructor requires EditableTextState is because currently the system context menu won't work without an active text input connection, so I'm trying to lock it down for the time being to avoid people using it in situations where the native menu won't work. I'd like to generalize it in the future so that it can work with arbitrary buttons that may not have to do with any text input connection. Maybe instead of taking an EditableTextState it should take an interface that EditableTextState implements? What do you think? SystemContextMenu namingI think I'm probably in agreement about the SystemContextMenu name now that I'm facing a similar situation in trying to support Android's Scribe and iOS's Scribble... I think I'm going to try to expose the native APIs to the framework more or less verbatim, and then build any abstraction on top of that. I'll see how it goes over there and then see if anything can be done for SystemContextMenu going forward. @matthew-carroll you've probably seen SystemContextMenuController, will that work for your case? There is an assert about needing a text input connection, but it's meant to be more generic. |
I'm glad you've finally joined me in that view! 😅
That's probably fine for us. Though, if iOS technically makes it possible to show and orient a toolbar without an active IME connection, then I don't know why Flutter would want to add that restriction. |
I am happy with this too, as long as both of you agree on a long term vision. I suspect Android may introduce a similar restriction and we should have a good plan for that. Ideally most developers shouldn't have to deal with things like which platform they are working on, and menu's arrow direction.
It is non-trivial effort to support showing iOS edit menu for non-text field in the engine. We would need a UIView similar to |
+1, if/when we add support for that we should remove that assert. |
…#6723) flutter/flutter@1dfb46e...1255435 2024-05-13 jmccandless@google.com Native ios context menu (flutter/flutter#143002) 2024-05-13 82763757+NobodyForNothing@users.noreply.github.com test sliver fill remaining examples (flutter/flutter#148041) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from fab7a7417888 to 0050bf9a8094 (1 revision) (flutter/flutter#148211) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from e568e5db9391 to fab7a7417888 (1 revision) (flutter/flutter#148207) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from 57e74a1b3860 to e568e5db9391 (2 revisions) (flutter/flutter#148204) 2024-05-13 engine-flutter-autoroll@skia.org Roll Flutter Engine from 34fd28e8c7bd to 57e74a1b3860 (1 revision) (flutter/flutter#148196) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC rmistry@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@justinmc Are there any plans in the near future to support button customisation? |
We will start working on it soon. |
In order to work around the fact that iOS 15 shows a notification on pressing Flutter's paste button (#103163), this PR allows showing the iOS system context menu in text fields.
It is currently opt-in, which a user would typically do like this (also in example system_context_menu.0.dart):
Requires engine PR flutter/engine#50095.
API changes
SystemContextMenu
A widget that shows the system context menu when built, and removes it when disposed. The main high-level way that most users would use this PR. Only works on later versions of iOS.
SystemContextMenuController
Used under the hood to hide and show a system context menu. There can only be one visible at a time.
MediaQuery.supportsShowingSystemContextMenu
Sent by the iOS embedder to tell the framework whether or not the platform supports showing the system context menu. That way the framework, or Flutter developers, can decide to show a different menu.
flutter/platform ContextMenu.showSystemContextMenu
Sent by the framework to show the menu at a given
targetRect
, which is the current selection rect.flutter/platform ContextMenu.hideSystemContextMenu
Sent by the framework to hide the menu. Typically not needed, because the platform will hide the menu when the user taps outside of it and after the user presses a button, but it handles edge cases where the user programmatically rebuilds the context menu, for example.
flutter/platform System.onDismissSystemContextMenu
Sent by the iOS embedder to indicate that the system context menu has been hidden by the system, such as when the user taps outside of the menu. This is useful when there are multiple instances of SystemContextMenu, such as with multiple text fields.