-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Context Menus #107193
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
Merged
Merged
Context Menus #107193
Changes from all commits
Commits
Show all changes
193 commits
Select commit
Hold shift + click to select a range
a6c4a67
Reopening context-menu-anywhere from a diff in order to kick failing …
justinmc 2868e92
Rename cupertino buttons builder file
justinmc 6d44ca1
Rename material buttons builder file and polish the docs
justinmc af58c98
Remove unnecessary Stack
justinmc 140033b
Analyzer fix, accidentally removed export for file that was kept
justinmc aadb7df
No breaking change requiring buildContextMenu in textselectionoverlay
justinmc 0cb9164
SelectableRegion works with real buildContextMenu, but hard to custom…
justinmc dc85106
Can pass custom buildContextMenu to SelectionArea
justinmc c345c78
Merge branch 'master' into context-menu-anywhere-2
justinmc 73abc1c
Fix selectionarea test due to new handle controls class types
justinmc c9e315d
Missed adding a new file to material.dart, fixes docs check I hope
justinmc 7d17623
When explicitly passed null, dont build any context menu
justinmc 019ac7a
Remove asserts that are already covered by deprecations
justinmc aae4ae5
Fix toolbarOptions default causing contextmenu to build based on them
justinmc 0bb36a8
Fix incorrect usage of toolbarOptions, mainly that its pass-through w…
justinmc 7a731dd
Deprecate selectiondelegate methods that aren't innate to all mixers …
justinmc 1fc8488
TODOs for fade fidelity and duplicate code, in a new issue
justinmc 3126ef0
Review: missed a docs reference
justinmc 9ab7e0d
Selection area anchoring works in SelectionArea, with code reuse with…
justinmc b53acf0
Analyzer fix, deprecation string
justinmc c46a525
Unnecessary param in canPaste
justinmc 41b7c30
Move button datas builder for editable text to its own file
justinmc 8b6c381
Clean up anchor calculation
justinmc 2172d0d
Lets not do a Rect anchor. I think points are more flexible, though n…
justinmc aedc5df
Analyzer clampDouble that I always forget
justinmc e6813c6
Remove ContextMenu since it is trivial and not used in the framework.…
justinmc e044496
Four examples
justinmc 99be01a
Rename buildContextMenu to contextMenuBuilder
justinmc c7e8311
Consolidate button label logic
justinmc 700ccf2
Organize context_menu.dart into two separate files
justinmc f3fd205
Fix references after buttonLabel reorg, make label getter public
justinmc 92529c8
A few places I missed consolidating ContextMenuController awareness t…
justinmc e9e840d
Missing license header
justinmc 5b983da
Clean up todos and remove anchor caching stuff
justinmc d172045
Merge branch 'master' into context-menu-anywhere-2
justinmc 23787ec
Cant make this public for now, remove TODOs
justinmc 55593d8
Analyzer
justinmc 1b6b08d
Remove commented code
justinmc 94da5ce
Analyzer
justinmc 1e7da69
Docs improvements for CupertinoDefaultTextSelectionToolbar
justinmc 8019a0d
Rename button data to button item, for grammar and better coherence w…
justinmc f161bc1
Attempt to fix web test failures
justinmc 7131007
Utilize the examples in the docs
justinmc f59269e
Tests for DefaultTextSelectionToolbar and TextSelectionToolbarButtons…
justinmc 792a21b
Tests for DefaultCupertinoTextSelectionToolbar and CupertinoTextSelec…
justinmc 2730215
Docs aliginment fix
justinmc 88ab90a
Test EditableTextContextMenuButtonItemsBuilder
justinmc 39c1d5f
Analyzer
justinmc 1f1af13
Forgot _test suffix
justinmc 7000163
Test ContextMenuController, and fix bug about multiple contextmenus a…
justinmc f58243a
Remove old commented code
justinmc a13144a
Skip test on web that depends on editabletext showing a context menu
justinmc c3d1dc2
Skip test thats irrelevant for web
justinmc b9a01a1
EditableText test for contextMenuBuilder
justinmc c372417
Test TextField and CupertinoTextField's context menu logic
justinmc 1c46cf3
Add initialization for test, which was failing on web without it
justinmc 308efb5
super.dispose should be called at the end of dispose
justinmc 7698386
Another test that needed initialization to not fail on web
justinmc f070889
Test the anywhere example
justinmc dc9c308
Test the selection area example
justinmc 395d372
Test email selection example
justinmc 52d3271
Test custom_button_appearance example
justinmc 6d8aa5d
Attempt to fix weird errors in linux web tests
justinmc a868759
Skip test on web due to html renderer bug
justinmc 3bf89a5
Small docs improvements
justinmc f291f41
Another test to skip for the html renderer issue
justinmc 74d17c9
Move desktop toolbars and buttons to their own files
justinmc 6ed7138
Docs improvements
justinmc f7c4241
Merge branch 'master' into context-menu-anywhere-2
justinmc 711ee01
Code review code style and docs fixes
justinmc c1c9ca7
Make SelectableRegionState public so that SelectableRegionContextMenu…
justinmc a59af1c
Analyzer, and rename delegate to selectableRegionState to match edita…
justinmc b281049
Typo in docs reference
justinmc 1444df9
Proper naming for example files
justinmc e757ef8
More readable email regexp
justinmc 58a59a8
Merge branch 'master' into context-menu-anywhere-2
justinmc 69ccf3e
Fix broken links in examples tests after renaming examples
justinmc d8ebe5b
Code review docs fixes.
justinmc 5e2e532
Merge branch 'master' into context-menu-anywhere-2
justinmc 01c3b18
Magnifier code should consider contextMenuBuilder toolbar as well as …
justinmc 2c8f07e
hideMagnifier shows the context menu toolbar again when done
justinmc 91a7406
Merge branch 'master' into context-menu-anywhere-2
justinmc d7ede10
Analyzer: Now that SelectableRegionState is public, needs docs
justinmc d1e28fe
Merge branch 'master' into context-menu-anywhere-2
justinmc e5b6a4f
Split Default toolbar widgets into multiple constructors to make it e…
justinmc 7991218
Merge branch 'master' into context-menu-anywhere-2
justinmc 9f0fa2a
Fix invalid docs references
justinmc 77de3f5
Merge branch 'master' into context-menu-anywhere-2
justinmc c5d235b
SelectableRegion Adaptive toolbar constructor, and docs improvements
justinmc 527159b
Fix docs reference
justinmc d9a6540
Review docs
justinmc 53f92ec
The rest of Greg's review responses
justinmc 3343d2f
Rest of review comments
justinmc 8517d06
Merge branch 'master' into context-menu-anywhere-2
justinmc 036c0cf
Analyzer fixes
justinmc afd26c2
ContextMenuController is no longer a singleton
justinmc 4982bd5
Fix test
justinmc 4074845
Fix analyzer problems in example
justinmc be66aa9
Improved docs for ContextMenuController
justinmc a5659a0
Super call in the right place
justinmc bb3c6da
Code review fixes
justinmc 1df6a8d
New GitHub issue to track TextSelectionDelegate in SelectableRegion
justinmc 7d6dbd2
Break AdaptiveTextSelectionToolbar into separate widgets instead of s…
justinmc a47eebd
Dont use 'note that'
justinmc 86de8c0
Change 'deprecated after' version now that that has changed a lot!
justinmc a8a972a
Fix example tests
justinmc ac6f275
Do ClipboardStatusNotifier inline instead of in a separate widget
justinmc 5a7203e
Forgot the period at the end of my deprecation notices
justinmc c1fd322
Forgot an unused typedef when I remvoed ClipboardStatusBuilder
justinmc b87e021
Merge branch 'master' into context-menu-anywhere-2
justinmc e673e74
Fix overlapping logic with contextMenuBuilder and shouldShowToolbar
justinmc 4cee48b
Remove TextSelectionDelegate from SelectableRegion, and deprecate Tex…
justinmc bd8e6d1
Revert previous commit, need to do it as part of deprecation.
justinmc 20a2d95
Decouple dependence on EditableText and SelectableRegion, generic sel…
justinmc 4c427e4
Refactoring Cupertino for decoupling like for Material in previous co…
justinmc a89ef5d
Attempt at fixing the examples with the new refactoring
justinmc 27d3b21
Examples analyzer fixes
justinmc 34f7747
Examples analyzer fix
justinmc 2efa8d4
Missing license header
justinmc 76af9f4
Analyzer errors and docs analyzer errors
justinmc 6f1fddf
Docs fixes
justinmc ae396d3
Merge branch 'master' into context-menu-anywhere-2
justinmc ae5f8ca
Remove commented out deprecations and now unneeded deprecations
justinmc 6f4d723
Remove irrelevant TODOs
justinmc cfea36c
Merge branch 'master' into context-menu-anywhere-2
justinmc 5056ffd
Mistitled example
justinmc 3ed6753
Comment I forgot to remove, found in code review
justinmc fd7c0ac
SizedBox.shrink
justinmc 71906ac
No need to pass in targetPlatform, result is the same as defaultTarge…
justinmc 40c7b32
Replace 'enabled' params with nullable callbacks instead
justinmc 9f80e3e
Docs fix
justinmc f271502
Unnecessary import
justinmc b476ce5
Fix bug from removal of copyEnabled et.al.
justinmc 86122c3
Migrate CupertinoTextFormFieldRow to contextMenuBuilder
justinmc 39777b7
Code review and remove unused readOnly
justinmc 365b0de
Dont pass EditableTextState/SelectableRegionState, pass button items …
justinmc a597a39
Merge branch 'master' into context-menu-anywhere-2
justinmc 5cd6c59
Examples updated to receiving buttonItems instead of states
justinmc b4b884a
Tests updated to receive buttonItems instead of states
justinmc a735aca
Self-contained hidetoolbar logic instead of passing it in
justinmc 4015035
Double newline
justinmc 9119a08
Fix TextFormFieldRow not getting a contextMenuBuilder by default
justinmc 49f507f
Docs reference fixes
justinmc 6c81de4
Clean up private adaptive toolbar code
justinmc d694c5f
SelectableRegionState can remain private now that the button items ar…
justinmc c468b32
Code review extra parenthesis
justinmc a91866e
Guard against an unmounted widget
justinmc b145018
Decouple hideMagnifier and showToolbar
justinmc 839ca5a
Fix delete context parameter
justinmc 6eff1a1
getEditableButtonItems to EditableText to avoid top-level function, s…
justinmc e0c5631
Docs reference fixes after moving get button item methods
justinmc cf9e31b
WIP(pass editable text state) getting anchors via EditableTextState
justinmc 1e92cc1
(pass editable text state) Working for Material
justinmc 337c9e4
(pass editable text state) public anchors class and works for selecta…
justinmc 3f4dac1
(pass editable text state) Handle right click position by saving a va…
justinmc 831d002
(pass editable text state) Cupertino works too
justinmc 4b1c82f
(pass editable text state) Code cleanup
justinmc 0372d84
(pass editable text state) ContextMenuBuilder type can just be Widget…
justinmc e344ff0
(pass editable text state) Clean up selectableregion
justinmc 131fb43
(pass editable text state) Clean up text_selection.dart
justinmc 8afcb0a
(pass editable text state) Clean up tests, and fix bug with misuse of…
justinmc 9238f77
(pass editable text state) Update examples
justinmc 2a2438c
Analyzer
justinmc 8c88f96
Merge branch 'master' into context-menu-anywhere-2
justinmc e45e08b
Remove accidental durations added while debugging a test
justinmc 897fc82
Expose TextSelectionToolbarAnchors in widgets to avoid a Material-onl…
justinmc 14aac7f
Analyzer fix
justinmc 31466a4
Consolidate start/end glyph height calculation and use getBoxesForSel…
justinmc 3af552c
LongCatIsLooong misc code review
justinmc 327d47b
Anchor and buttonItems both are getters on EditableText/SelectableRegion
justinmc f8571e4
buttonItem constructors for Cupertino buttons for rebuild performance…
justinmc d275956
Update examples to new API changes
justinmc 2f5bc7b
Merge branch 'master' into context-menu-anywhere-2
justinmc ffc1ec9
Analyzer
justinmc 17f7b4c
Fix test failing on mobile only
justinmc 2235694
Analyzer fix import
justinmc f3ba24d
Remove ignores by stating local type
justinmc 59cddcb
Docs analyzer fix
justinmc fec9e7b
Fix bug in conversion from map to for loop
justinmc 5e818a3
Fix material text field test for mobile similar to cupertino one
justinmc 1c514e7
Merge branch 'master' into context-menu-anywhere-2
justinmc 45844cc
Example for getAdaptiveButtons
justinmc 6b92feb
Code review fixes
justinmc 07663e3
Explain the spacer sizedbox in test
justinmc 4f7de51
Analyzer fix
justinmc bb24a1d
Fix test with iOS not having 'select all' button when not collapsed
justinmc 5e32f6f
Fix glyph height calculation and the related golden
justinmc 0a17ef0
Merge branch 'master' into context-menu-anywhere-2
justinmc 79c42ca
Fix analyzer
justinmc 343c5ad
Normally instantiable contextmenucontroller. Takes builder on show
justinmc dbd5775
Analyzer fix in examples
justinmc d1da160
Use a long-lived instance of ContextMenuController for easy non-nulla…
justinmc 6b6236f
Merge branch 'master' into context-menu-anywhere-2
justinmc File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
159 changes: 159 additions & 0 deletions
159
examples/api/lib/material/context_menu/context_menu_controller.0.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| // Copyright 2014 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // This sample demonstrates allowing a context menu to be shown in a widget | ||
| // subtree in response to user gestures. | ||
|
|
||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:flutter/material.dart'; | ||
|
|
||
| void main() => runApp(const MyApp()); | ||
|
|
||
| /// A builder that includes an Offset to draw the context menu at. | ||
| typedef ContextMenuBuilder = Widget Function(BuildContext context, Offset offset); | ||
|
|
||
| class MyApp extends StatelessWidget { | ||
| const MyApp({super.key}); | ||
|
|
||
| void _showDialog (BuildContext context) { | ||
| Navigator.of(context).push( | ||
| DialogRoute<void>( | ||
| context: context, | ||
| builder: (BuildContext context) => | ||
| const AlertDialog(title: Text('You clicked print!')), | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return MaterialApp( | ||
| home: Scaffold( | ||
| appBar: AppBar( | ||
| title: const Text('Context menu outside of text'), | ||
| ), | ||
| body: _ContextMenuRegion( | ||
| contextMenuBuilder: (BuildContext context, Offset offset) { | ||
| // The custom context menu will look like the default context menu | ||
| // on the current platform with a single 'Print' button. | ||
| return AdaptiveTextSelectionToolbar.buttonItems( | ||
| anchors: TextSelectionToolbarAnchors( | ||
| primaryAnchor: offset, | ||
| ), | ||
| buttonItems: <ContextMenuButtonItem>[ | ||
| ContextMenuButtonItem( | ||
| onPressed: () { | ||
| ContextMenuController.removeAny(); | ||
| _showDialog(context); | ||
| }, | ||
| label: 'Print', | ||
| ), | ||
| ], | ||
| ); | ||
| }, | ||
| // In this case this wraps a big open space in a GestureDetector in | ||
| // order to show the context menu, but it could also wrap a single | ||
| // wiget like an Image to give it a context menu. | ||
| child: ListView( | ||
| children: <Widget>[ | ||
| Container(height: 20.0), | ||
| const Text('Right click or long press anywhere (not just on this text!) to show the custom menu.'), | ||
| ], | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// Shows and hides the context menu based on user gestures. | ||
| /// | ||
| /// By default, shows the menu on right clicks and long presses. | ||
| class _ContextMenuRegion extends StatefulWidget { | ||
| /// Creates an instance of [_ContextMenuRegion]. | ||
| const _ContextMenuRegion({ | ||
| required this.child, | ||
| required this.contextMenuBuilder, | ||
| }); | ||
|
|
||
| /// Builds the context menu. | ||
| final ContextMenuBuilder contextMenuBuilder; | ||
|
|
||
| /// The child widget that will be listened to for gestures. | ||
| final Widget child; | ||
|
|
||
| @override | ||
| State<_ContextMenuRegion> createState() => _ContextMenuRegionState(); | ||
| } | ||
|
|
||
| class _ContextMenuRegionState extends State<_ContextMenuRegion> { | ||
| Offset? _longPressOffset; | ||
|
|
||
| final ContextMenuController _contextMenuController = ContextMenuController(); | ||
|
|
||
| static bool get _longPressEnabled { | ||
| switch (defaultTargetPlatform) { | ||
| case TargetPlatform.android: | ||
| case TargetPlatform.iOS: | ||
| return true; | ||
| case TargetPlatform.macOS: | ||
| case TargetPlatform.fuchsia: | ||
| case TargetPlatform.linux: | ||
| case TargetPlatform.windows: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| void _onSecondaryTapUp(TapUpDetails details) { | ||
| _show(details.globalPosition); | ||
| } | ||
|
|
||
| void _onTap() { | ||
| if (!_contextMenuController.isShown) { | ||
| return; | ||
| } | ||
| _hide(); | ||
| } | ||
|
|
||
| void _onLongPressStart(LongPressStartDetails details) { | ||
| _longPressOffset = details.globalPosition; | ||
| } | ||
|
|
||
| void _onLongPress() { | ||
| assert(_longPressOffset != null); | ||
| _show(_longPressOffset!); | ||
| _longPressOffset = null; | ||
| } | ||
|
|
||
| void _show(Offset position) { | ||
| _contextMenuController.show( | ||
| context: context, | ||
| contextMenuBuilder: (BuildContext context) { | ||
| return widget.contextMenuBuilder(context, position); | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| void _hide() { | ||
| _contextMenuController.remove(); | ||
| } | ||
|
|
||
| @override | ||
| void dispose() { | ||
| _hide(); | ||
| super.dispose(); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return GestureDetector( | ||
| behavior: HitTestBehavior.opaque, | ||
| onSecondaryTapUp: _onSecondaryTapUp, | ||
| onTap: _onTap, | ||
| onLongPress: _longPressEnabled ? _onLongPress : null, | ||
| onLongPressStart: _longPressEnabled ? _onLongPressStart : null, | ||
| child: widget.child, | ||
| ); | ||
| } | ||
| } | ||
64 changes: 64 additions & 0 deletions
64
examples/api/lib/material/context_menu/editable_text_toolbar_builder.0.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // Copyright 2014 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // This example demonstrates showing the default buttons, but customizing their | ||
| // appearance. | ||
|
|
||
| import 'package:flutter/cupertino.dart'; | ||
| import 'package:flutter/material.dart'; | ||
|
|
||
| void main() => runApp(MyApp()); | ||
|
|
||
| class MyApp extends StatelessWidget { | ||
| MyApp({super.key}); | ||
|
|
||
| final TextEditingController _controller = TextEditingController( | ||
| text: 'Right click or long press to see the menu with custom buttons.', | ||
| ); | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return MaterialApp( | ||
| home: Scaffold( | ||
| appBar: AppBar( | ||
| title: const Text('Custom button appearance'), | ||
| ), | ||
| body: Center( | ||
| child: Column( | ||
| children: <Widget>[ | ||
| const SizedBox(height: 20.0), | ||
| TextField( | ||
| controller: _controller, | ||
| contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) { | ||
| return AdaptiveTextSelectionToolbar( | ||
| anchors: editableTextState.contextMenuAnchors, | ||
| // Build the default buttons, but make them look custom. | ||
| // In a real project you may want to build different | ||
| // buttons depending on the platform. | ||
| children: editableTextState.contextMenuButtonItems.map((ContextMenuButtonItem buttonItem) { | ||
| return CupertinoButton( | ||
| borderRadius: null, | ||
| color: const Color(0xffaaaa00), | ||
| disabledColor: const Color(0xffaaaaff), | ||
| onPressed: buttonItem.onPressed, | ||
| padding: const EdgeInsets.all(10.0), | ||
| pressedOpacity: 0.7, | ||
| child: SizedBox( | ||
| width: 200.0, | ||
| child: Text( | ||
| CupertinoTextSelectionToolbarButton.getButtonLabel(context, buttonItem), | ||
| ), | ||
| ), | ||
| ); | ||
| }).toList(), | ||
| ); | ||
| }, | ||
| ), | ||
| ], | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } |
83 changes: 83 additions & 0 deletions
83
examples/api/lib/material/context_menu/editable_text_toolbar_builder.1.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| // Copyright 2014 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // This example demonstrates showing a custom context menu only when some | ||
| // narrowly defined text is selected. | ||
|
|
||
| import 'package:flutter/material.dart'; | ||
|
|
||
| void main() => runApp(MyApp()); | ||
|
|
||
| const String emailAddress = '[email protected]'; | ||
| const String text = 'Select the email address and open the menu: $emailAddress'; | ||
|
|
||
| class MyApp extends StatelessWidget { | ||
| MyApp({super.key}); | ||
|
|
||
| final TextEditingController _controller = TextEditingController( | ||
| text: text, | ||
| ); | ||
|
|
||
| void _showDialog (BuildContext context) { | ||
| Navigator.of(context).push( | ||
| DialogRoute<void>( | ||
| context: context, | ||
| builder: (BuildContext context) => | ||
| const AlertDialog(title: Text('You clicked send email!')), | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
| @override | ||
| Widget build(BuildContext context) { | ||
| return MaterialApp( | ||
| home: Scaffold( | ||
| appBar: AppBar( | ||
| title: const Text('Custom button for emails'), | ||
| ), | ||
| body: Center( | ||
| child: Column( | ||
| children: <Widget>[ | ||
| Container(height: 20.0), | ||
| TextField( | ||
| controller: _controller, | ||
| contextMenuBuilder: (BuildContext context, EditableTextState editableTextState) { | ||
| final List<ContextMenuButtonItem> buttonItems = | ||
| editableTextState.contextMenuButtonItems; | ||
chunhtai marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Here we add an "Email" button to the default TextField | ||
| // context menu for the current platform, but only if an email | ||
| // address is currently selected. | ||
| final TextEditingValue value = _controller.value; | ||
| if (_isValidEmail(value.selection.textInside(value.text))) { | ||
| buttonItems.insert(0, ContextMenuButtonItem( | ||
| label: 'Send email', | ||
| onPressed: () { | ||
| ContextMenuController.removeAny(); | ||
| _showDialog(context); | ||
| }, | ||
| )); | ||
| } | ||
| return AdaptiveTextSelectionToolbar.buttonItems( | ||
| anchors: editableTextState.contextMenuAnchors, | ||
| buttonItems: buttonItems, | ||
| ); | ||
| }, | ||
| ), | ||
| ], | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| bool _isValidEmail(String text) { | ||
| return RegExp( | ||
| r'(?<name>[a-zA-Z0-9]+)' | ||
| r'@' | ||
| r'(?<domain>[a-zA-Z0-9]+)' | ||
| r'\.' | ||
| r'(?<topLevelDomain>[a-zA-Z0-9]+)', | ||
| ).hasMatch(text); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.