Skip to content
Merged
Show file tree
Hide file tree
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 Jul 6, 2022
2868e92
Rename cupertino buttons builder file
justinmc Jul 8, 2022
6d44ca1
Rename material buttons builder file and polish the docs
justinmc Jul 8, 2022
af58c98
Remove unnecessary Stack
justinmc Jul 8, 2022
140033b
Analyzer fix, accidentally removed export for file that was kept
justinmc Jul 8, 2022
aadb7df
No breaking change requiring buildContextMenu in textselectionoverlay
justinmc Jul 8, 2022
0cb9164
SelectableRegion works with real buildContextMenu, but hard to custom…
justinmc Jul 9, 2022
dc85106
Can pass custom buildContextMenu to SelectionArea
justinmc Jul 9, 2022
c345c78
Merge branch 'master' into context-menu-anywhere-2
justinmc Jul 11, 2022
73abc1c
Fix selectionarea test due to new handle controls class types
justinmc Jul 11, 2022
c9e315d
Missed adding a new file to material.dart, fixes docs check I hope
justinmc Jul 11, 2022
7d17623
When explicitly passed null, dont build any context menu
justinmc Jul 12, 2022
019ac7a
Remove asserts that are already covered by deprecations
justinmc Jul 12, 2022
aae4ae5
Fix toolbarOptions default causing contextmenu to build based on them
justinmc Jul 12, 2022
0bb36a8
Fix incorrect usage of toolbarOptions, mainly that its pass-through w…
justinmc Jul 13, 2022
7a731dd
Deprecate selectiondelegate methods that aren't innate to all mixers …
justinmc Jul 15, 2022
1fc8488
TODOs for fade fidelity and duplicate code, in a new issue
justinmc Jul 15, 2022
3126ef0
Review: missed a docs reference
justinmc Jul 15, 2022
9ab7e0d
Selection area anchoring works in SelectionArea, with code reuse with…
justinmc Jul 16, 2022
b53acf0
Analyzer fix, deprecation string
justinmc Jul 18, 2022
c46a525
Unnecessary param in canPaste
justinmc Jul 18, 2022
41b7c30
Move button datas builder for editable text to its own file
justinmc Jul 18, 2022
8b6c381
Clean up anchor calculation
justinmc Jul 19, 2022
2172d0d
Lets not do a Rect anchor. I think points are more flexible, though n…
justinmc Jul 21, 2022
aedc5df
Analyzer clampDouble that I always forget
justinmc Jul 21, 2022
e6813c6
Remove ContextMenu since it is trivial and not used in the framework.…
justinmc Jul 21, 2022
e044496
Four examples
justinmc Jul 21, 2022
99be01a
Rename buildContextMenu to contextMenuBuilder
justinmc Jul 21, 2022
c7e8311
Consolidate button label logic
justinmc Jul 22, 2022
700ccf2
Organize context_menu.dart into two separate files
justinmc Jul 22, 2022
f3fd205
Fix references after buttonLabel reorg, make label getter public
justinmc Jul 22, 2022
92529c8
A few places I missed consolidating ContextMenuController awareness t…
justinmc Jul 22, 2022
e9e840d
Missing license header
justinmc Jul 22, 2022
5b983da
Clean up todos and remove anchor caching stuff
justinmc Jul 22, 2022
d172045
Merge branch 'master' into context-menu-anywhere-2
justinmc Jul 22, 2022
23787ec
Cant make this public for now, remove TODOs
justinmc Jul 22, 2022
55593d8
Analyzer
justinmc Jul 22, 2022
1b6b08d
Remove commented code
justinmc Jul 22, 2022
94da5ce
Analyzer
justinmc Jul 22, 2022
1e7da69
Docs improvements for CupertinoDefaultTextSelectionToolbar
justinmc Jul 22, 2022
8019a0d
Rename button data to button item, for grammar and better coherence w…
justinmc Jul 22, 2022
f161bc1
Attempt to fix web test failures
justinmc Jul 22, 2022
7131007
Utilize the examples in the docs
justinmc Jul 22, 2022
f59269e
Tests for DefaultTextSelectionToolbar and TextSelectionToolbarButtons…
justinmc Jul 22, 2022
792a21b
Tests for DefaultCupertinoTextSelectionToolbar and CupertinoTextSelec…
justinmc Jul 22, 2022
2730215
Docs aliginment fix
justinmc Jul 22, 2022
88ab90a
Test EditableTextContextMenuButtonItemsBuilder
justinmc Jul 22, 2022
39c1d5f
Analyzer
justinmc Jul 22, 2022
1f1af13
Forgot _test suffix
justinmc Jul 22, 2022
7000163
Test ContextMenuController, and fix bug about multiple contextmenus a…
justinmc Jul 22, 2022
f58243a
Remove old commented code
justinmc Jul 23, 2022
a13144a
Skip test on web that depends on editabletext showing a context menu
justinmc Jul 23, 2022
c3d1dc2
Skip test thats irrelevant for web
justinmc Jul 25, 2022
b9a01a1
EditableText test for contextMenuBuilder
justinmc Jul 25, 2022
c372417
Test TextField and CupertinoTextField's context menu logic
justinmc Jul 25, 2022
1c46cf3
Add initialization for test, which was failing on web without it
justinmc Jul 25, 2022
308efb5
super.dispose should be called at the end of dispose
justinmc Jul 25, 2022
7698386
Another test that needed initialization to not fail on web
justinmc Jul 25, 2022
f070889
Test the anywhere example
justinmc Jul 25, 2022
dc9c308
Test the selection area example
justinmc Jul 25, 2022
395d372
Test email selection example
justinmc Jul 26, 2022
52d3271
Test custom_button_appearance example
justinmc Jul 26, 2022
6d8aa5d
Attempt to fix weird errors in linux web tests
justinmc Jul 26, 2022
a868759
Skip test on web due to html renderer bug
justinmc Jul 26, 2022
3bf89a5
Small docs improvements
justinmc Jul 26, 2022
f291f41
Another test to skip for the html renderer issue
justinmc Jul 26, 2022
74d17c9
Move desktop toolbars and buttons to their own files
justinmc Jul 26, 2022
6ed7138
Docs improvements
justinmc Jul 26, 2022
f7c4241
Merge branch 'master' into context-menu-anywhere-2
justinmc Jul 27, 2022
711ee01
Code review code style and docs fixes
justinmc Jul 28, 2022
c1c9ca7
Make SelectableRegionState public so that SelectableRegionContextMenu…
justinmc Jul 28, 2022
a59af1c
Analyzer, and rename delegate to selectableRegionState to match edita…
justinmc Jul 28, 2022
b281049
Typo in docs reference
justinmc Jul 29, 2022
1444df9
Proper naming for example files
justinmc Jul 29, 2022
e757ef8
More readable email regexp
justinmc Jul 29, 2022
58a59a8
Merge branch 'master' into context-menu-anywhere-2
justinmc Jul 29, 2022
69ccf3e
Fix broken links in examples tests after renaming examples
justinmc Jul 29, 2022
d8ebe5b
Code review docs fixes.
justinmc Jul 29, 2022
5e2e532
Merge branch 'master' into context-menu-anywhere-2
justinmc Aug 2, 2022
01c3b18
Magnifier code should consider contextMenuBuilder toolbar as well as …
justinmc Aug 8, 2022
2c8f07e
hideMagnifier shows the context menu toolbar again when done
justinmc Aug 9, 2022
91a7406
Merge branch 'master' into context-menu-anywhere-2
justinmc Aug 9, 2022
d7ede10
Analyzer: Now that SelectableRegionState is public, needs docs
justinmc Aug 9, 2022
d1e28fe
Merge branch 'master' into context-menu-anywhere-2
justinmc Aug 12, 2022
e5b6a4f
Split Default toolbar widgets into multiple constructors to make it e…
justinmc Aug 15, 2022
7991218
Merge branch 'master' into context-menu-anywhere-2
justinmc Aug 17, 2022
9f0fa2a
Fix invalid docs references
justinmc Aug 17, 2022
77de3f5
Merge branch 'master' into context-menu-anywhere-2
justinmc Aug 19, 2022
c5d235b
SelectableRegion Adaptive toolbar constructor, and docs improvements
justinmc Aug 19, 2022
527159b
Fix docs reference
justinmc Aug 20, 2022
d9a6540
Review docs
justinmc Aug 20, 2022
53f92ec
The rest of Greg's review responses
justinmc Aug 20, 2022
3343d2f
Rest of review comments
justinmc Aug 20, 2022
8517d06
Merge branch 'master' into context-menu-anywhere-2
justinmc Sep 7, 2022
036c0cf
Analyzer fixes
justinmc Sep 7, 2022
afd26c2
ContextMenuController is no longer a singleton
justinmc Sep 8, 2022
4982bd5
Fix test
justinmc Sep 8, 2022
4074845
Fix analyzer problems in example
justinmc Sep 8, 2022
be66aa9
Improved docs for ContextMenuController
justinmc Sep 8, 2022
a5659a0
Super call in the right place
justinmc Sep 8, 2022
bb3c6da
Code review fixes
justinmc Sep 8, 2022
1df6a8d
New GitHub issue to track TextSelectionDelegate in SelectableRegion
justinmc Sep 8, 2022
7d6dbd2
Break AdaptiveTextSelectionToolbar into separate widgets instead of s…
justinmc Sep 8, 2022
a47eebd
Dont use 'note that'
justinmc Sep 8, 2022
86de8c0
Change 'deprecated after' version now that that has changed a lot!
justinmc Sep 8, 2022
a8a972a
Fix example tests
justinmc Sep 9, 2022
ac6f275
Do ClipboardStatusNotifier inline instead of in a separate widget
justinmc Sep 9, 2022
5a7203e
Forgot the period at the end of my deprecation notices
justinmc Sep 9, 2022
c1fd322
Forgot an unused typedef when I remvoed ClipboardStatusBuilder
justinmc Sep 9, 2022
b87e021
Merge branch 'master' into context-menu-anywhere-2
justinmc Sep 9, 2022
e673e74
Fix overlapping logic with contextMenuBuilder and shouldShowToolbar
justinmc Sep 9, 2022
4cee48b
Remove TextSelectionDelegate from SelectableRegion, and deprecate Tex…
justinmc Sep 9, 2022
bd8e6d1
Revert previous commit, need to do it as part of deprecation.
justinmc Sep 10, 2022
20a2d95
Decouple dependence on EditableText and SelectableRegion, generic sel…
justinmc Sep 12, 2022
4c427e4
Refactoring Cupertino for decoupling like for Material in previous co…
justinmc Sep 13, 2022
a89ef5d
Attempt at fixing the examples with the new refactoring
justinmc Sep 13, 2022
27d3b21
Examples analyzer fixes
justinmc Sep 13, 2022
34f7747
Examples analyzer fix
justinmc Sep 14, 2022
2efa8d4
Missing license header
justinmc Sep 14, 2022
76af9f4
Analyzer errors and docs analyzer errors
justinmc Sep 14, 2022
6f1fddf
Docs fixes
justinmc Sep 14, 2022
ae396d3
Merge branch 'master' into context-menu-anywhere-2
justinmc Sep 14, 2022
ae5f8ca
Remove commented out deprecations and now unneeded deprecations
justinmc Sep 14, 2022
6f4d723
Remove irrelevant TODOs
justinmc Sep 14, 2022
cfea36c
Merge branch 'master' into context-menu-anywhere-2
justinmc Sep 15, 2022
5056ffd
Mistitled example
justinmc Sep 22, 2022
3ed6753
Comment I forgot to remove, found in code review
justinmc Sep 22, 2022
fd7c0ac
SizedBox.shrink
justinmc Sep 22, 2022
71906ac
No need to pass in targetPlatform, result is the same as defaultTarge…
justinmc Sep 22, 2022
40c7b32
Replace 'enabled' params with nullable callbacks instead
justinmc Sep 22, 2022
9f80e3e
Docs fix
justinmc Sep 22, 2022
f271502
Unnecessary import
justinmc Sep 22, 2022
b476ce5
Fix bug from removal of copyEnabled et.al.
justinmc Sep 23, 2022
86122c3
Migrate CupertinoTextFormFieldRow to contextMenuBuilder
justinmc Sep 23, 2022
39777b7
Code review and remove unused readOnly
justinmc Sep 23, 2022
365b0de
Dont pass EditableTextState/SelectableRegionState, pass button items …
justinmc Sep 23, 2022
a597a39
Merge branch 'master' into context-menu-anywhere-2
justinmc Sep 26, 2022
5cd6c59
Examples updated to receiving buttonItems instead of states
justinmc Sep 26, 2022
b4b884a
Tests updated to receive buttonItems instead of states
justinmc Sep 26, 2022
a735aca
Self-contained hidetoolbar logic instead of passing it in
justinmc Sep 26, 2022
4015035
Double newline
justinmc Sep 26, 2022
9119a08
Fix TextFormFieldRow not getting a contextMenuBuilder by default
justinmc Sep 26, 2022
49f507f
Docs reference fixes
justinmc Sep 26, 2022
6c81de4
Clean up private adaptive toolbar code
justinmc Sep 26, 2022
d694c5f
SelectableRegionState can remain private now that the button items ar…
justinmc Sep 26, 2022
c468b32
Code review extra parenthesis
justinmc Sep 27, 2022
a91866e
Guard against an unmounted widget
justinmc Sep 27, 2022
b145018
Decouple hideMagnifier and showToolbar
justinmc Sep 27, 2022
839ca5a
Fix delete context parameter
justinmc Sep 27, 2022
6eff1a1
getEditableButtonItems to EditableText to avoid top-level function, s…
justinmc Sep 27, 2022
e0c5631
Docs reference fixes after moving get button item methods
justinmc Sep 28, 2022
cf9e31b
WIP(pass editable text state) getting anchors via EditableTextState
justinmc Oct 3, 2022
1e92cc1
(pass editable text state) Working for Material
justinmc Oct 4, 2022
337c9e4
(pass editable text state) public anchors class and works for selecta…
justinmc Oct 4, 2022
3f4dac1
(pass editable text state) Handle right click position by saving a va…
justinmc Oct 4, 2022
831d002
(pass editable text state) Cupertino works too
justinmc Oct 4, 2022
4b1c82f
(pass editable text state) Code cleanup
justinmc Oct 4, 2022
0372d84
(pass editable text state) ContextMenuBuilder type can just be Widget…
justinmc Oct 4, 2022
e344ff0
(pass editable text state) Clean up selectableregion
justinmc Oct 4, 2022
131fb43
(pass editable text state) Clean up text_selection.dart
justinmc Oct 4, 2022
8afcb0a
(pass editable text state) Clean up tests, and fix bug with misuse of…
justinmc Oct 4, 2022
9238f77
(pass editable text state) Update examples
justinmc Oct 5, 2022
2a2438c
Analyzer
justinmc Oct 5, 2022
8c88f96
Merge branch 'master' into context-menu-anywhere-2
justinmc Oct 5, 2022
e45e08b
Remove accidental durations added while debugging a test
justinmc Oct 5, 2022
897fc82
Expose TextSelectionToolbarAnchors in widgets to avoid a Material-onl…
justinmc Oct 6, 2022
14aac7f
Analyzer fix
justinmc Oct 6, 2022
31466a4
Consolidate start/end glyph height calculation and use getBoxesForSel…
justinmc Oct 17, 2022
3af552c
LongCatIsLooong misc code review
justinmc Oct 17, 2022
327d47b
Anchor and buttonItems both are getters on EditableText/SelectableRegion
justinmc Oct 17, 2022
f8571e4
buttonItem constructors for Cupertino buttons for rebuild performance…
justinmc Oct 17, 2022
d275956
Update examples to new API changes
justinmc Oct 17, 2022
2f5bc7b
Merge branch 'master' into context-menu-anywhere-2
justinmc Oct 17, 2022
ffc1ec9
Analyzer
justinmc Oct 17, 2022
17f7b4c
Fix test failing on mobile only
justinmc Oct 17, 2022
2235694
Analyzer fix import
justinmc Oct 17, 2022
f3ba24d
Remove ignores by stating local type
justinmc Oct 17, 2022
59cddcb
Docs analyzer fix
justinmc Oct 18, 2022
fec9e7b
Fix bug in conversion from map to for loop
justinmc Oct 18, 2022
5e818a3
Fix material text field test for mobile similar to cupertino one
justinmc Oct 18, 2022
1c514e7
Merge branch 'master' into context-menu-anywhere-2
justinmc Oct 18, 2022
45844cc
Example for getAdaptiveButtons
justinmc Oct 21, 2022
6b92feb
Code review fixes
justinmc Oct 21, 2022
07663e3
Explain the spacer sizedbox in test
justinmc Oct 21, 2022
4f7de51
Analyzer fix
justinmc Oct 21, 2022
bb24a1d
Fix test with iOS not having 'select all' button when not collapsed
justinmc Oct 21, 2022
5e32f6f
Fix glyph height calculation and the related golden
justinmc Oct 21, 2022
0a17ef0
Merge branch 'master' into context-menu-anywhere-2
justinmc Oct 26, 2022
79c42ca
Fix analyzer
justinmc Oct 26, 2022
343c5ad
Normally instantiable contextmenucontroller. Takes builder on show
justinmc Oct 27, 2022
dbd5775
Analyzer fix in examples
justinmc Oct 28, 2022
d1da160
Use a long-lived instance of ContextMenuController for easy non-nulla…
justinmc Oct 28, 2022
6b6236f
Merge branch 'master' into context-menu-anywhere-2
justinmc Oct 28, 2022
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
159 changes: 159 additions & 0 deletions examples/api/lib/material/context_menu/context_menu_controller.0.dart
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,
);
}
}
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(),
);
},
),
],
),
),
),
);
}
}
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;
// 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);
}
Loading