From 1557a5de1ed7a0df49530073407fa8eaf566b87f Mon Sep 17 00:00:00 2001 From: Juno Burger Date: Fri, 21 Jul 2023 23:58:56 +0200 Subject: [PATCH] Allow for custom context menu (#1320) * Persist boolean logic for showSelectionToolbar * Add test for custom context menu * Adjust test to reflect custom context menu implementation --------- Co-authored-by: operatorultra <105389680+operatorultra@users.noreply.github.com> --- lib/src/widgets/editor.dart | 9 +++++-- test/widgets/editor_test.dart | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/lib/src/widgets/editor.dart b/lib/src/widgets/editor.dart index d757b813e..50e3e6cba 100644 --- a/lib/src/widgets/editor.dart +++ b/lib/src/widgets/editor.dart @@ -191,6 +191,7 @@ class QuillEditor extends StatefulWidget { this.customLinkPrefixes = const [], this.dialogTheme, this.contentInsertionConfiguration, + this.contextMenuBuilder, Key? key, }) : super(key: key); @@ -432,6 +433,9 @@ class QuillEditor extends StatefulWidget { /// Configures the dialog theme. final QuillDialogTheme? dialogTheme; + // Allows for creating a custom context menu + final QuillEditorContextMenuBuilder? contextMenuBuilder; + /// Configuration of handler for media content inserted via the system input /// method. /// @@ -503,8 +507,9 @@ class QuillEditorState extends State readOnly: widget.readOnly, placeholder: widget.placeholder, onLaunchUrl: widget.onLaunchUrl, - contextMenuBuilder: - showSelectionToolbar ? RawEditor.defaultContextMenuBuilder : null, + contextMenuBuilder: showSelectionToolbar + ? (widget.contextMenuBuilder ?? RawEditor.defaultContextMenuBuilder) + : null, showSelectionHandles: isMobile(theme.platform), showCursor: widget.showCursor, cursorStyle: CursorStyle( diff --git a/test/widgets/editor_test.dart b/test/widgets/editor_test.dart index 3fd425fca..dccf85ea6 100644 --- a/test/widgets/editor_test.dart +++ b/test/widgets/editor_test.dart @@ -4,10 +4,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/flutter_quill_test.dart'; +import 'package:flutter_quill/src/widgets/raw_editor.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { late QuillController controller; + var didCopy = false; setUp(() { controller = QuillController.basic(); @@ -78,5 +80,54 @@ void main() { expect(error, isNull); expect(latestUri, equals(uri)); }); + + Widget customBuilder(BuildContext context, RawEditorState state) { + return AdaptiveTextSelectionToolbar( + anchors: state.contextMenuAnchors, + children: [ + Container( + height: 50, + color: Colors.white, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + IconButton( + onPressed: () { + didCopy = true; + }, + icon: const Icon(Icons.copy), + ), + ], + ), + ), + ], + ); + } + + testWidgets('custom context menu builder', (tester) async { + await tester.pumpWidget(MaterialApp( + home: QuillEditor( + controller: controller, + focusNode: FocusNode(), + scrollController: ScrollController(), + scrollable: true, + padding: EdgeInsets.zero, + autoFocus: true, + readOnly: false, + expands: true, + contextMenuBuilder: customBuilder, + ), + )); + + // Long press to show menu + await tester.longPress(find.byType(QuillEditor)); + await tester.pumpAndSettle(); + + // Verify custom widget shows + expect(find.byIcon(Icons.copy), findsOneWidget); + + await tester.tap(find.byIcon(Icons.copy)); + expect(didCopy, isTrue); + }); }); }