diff --git a/README.md b/README.md index 6bc0f26b..73195846 100644 --- a/README.md +++ b/README.md @@ -130,16 +130,18 @@ Instantiate a controller: QuillController _controller = QuillController.basic(); ``` -Use the `QuillEditor`, and `QuillToolbar` widgets, +Use the `QuillEditor`, and `QuillSimpleToolbar` widgets, and attach the `QuillController` to them: ```dart -QuillToolbar.simple( - configurations: QuillSimpleToolbarConfigurations(controller: _controller), +QuillSimpleToolbar( + controller: _controller, + configurations: QuillSimpleToolbarConfigurations(), ), Expanded( child: QuillEditor.basic( - configurations: QuillEditorConfigurations(controller: _controller), + controller: _controller, + configurations: const QuillEditorConfigurations(), ), ) ``` diff --git a/doc/attribute_introduction.md b/doc/attribute_introduction.md index b1704e01..e93ec8aa 100644 --- a/doc/attribute_introduction.md +++ b/doc/attribute_introduction.md @@ -85,8 +85,8 @@ On `QuillEditor` or `QuillEditorConfigurations` **doesn't exist** a param that l ##### The editor ```dart QuillEditor.basic( + controller: controller, configurations: QuillEditorConfigurations( - controller: controller, customStyleBuilder: (Attribute attribute) { if (attribute.key.equals(highlightKey)) { return TextStyle(color: Colors.black, backgroundColor: Colors.yellow); diff --git a/doc/configurations/custom_buttons.md b/doc/configurations/custom_buttons.md index 699b7b02..1bff246f 100644 --- a/doc/configurations/custom_buttons.md +++ b/doc/configurations/custom_buttons.md @@ -22,6 +22,7 @@ Each `QuillCustomButton` is used as part of the `customButtons` option as follow ```dart QuillToolbar.simple( + controller: _controller, configurations: QuillSimpleToolbarConfigurations( customButtons: [ QuillToolbarCustomButtonOptions( diff --git a/doc/custom_embed_blocks.md b/doc/custom_embed_blocks.md index 19f23ab5..d61b4faa 100644 --- a/doc/custom_embed_blocks.md +++ b/doc/custom_embed_blocks.md @@ -98,10 +98,8 @@ Future _addEditNote(BuildContext context, {Document? document}) async { ], ), content: QuillEditor.basic( - configurations: const QuillEditorConfigurations( - controller: quillEditorController, - readOnly: false, - ), + controller: quillEditorController, + configurations: const QuillEditorConfigurations(), ), ), ); diff --git a/doc/translation.md b/doc/translation.md index ec857bbb..35d813e6 100644 --- a/doc/translation.md +++ b/doc/translation.md @@ -6,8 +6,8 @@ with: ```dart QuillToolbar.simple( + controller: _controller, configurations: QuillSimpleToolbarConfigurations( - controller: _controller, sharedConfigurations: const QuillSharedConfigurations( locale: Locale('de'), ), @@ -15,8 +15,8 @@ QuillToolbar.simple( ), Expanded( child: QuillEditor.basic( + controller: _controller, configurations: QuillEditorConfigurations( - controller: _controller, sharedConfigurations: const QuillSharedConfigurations( locale: Locale('de'), ), diff --git a/example/lib/screens/quill/my_quill_editor.dart b/example/lib/screens/quill/my_quill_editor.dart index e7115bcb..dee4691f 100644 --- a/example/lib/screens/quill/my_quill_editor.dart +++ b/example/lib/screens/quill/my_quill_editor.dart @@ -18,12 +18,14 @@ import 'embeds/timestamp_embed.dart'; class MyQuillEditor extends StatelessWidget { const MyQuillEditor({ + required this.controller, required this.configurations, required this.scrollController, required this.focusNode, super.key, }); + final QuillController controller; final QuillEditorConfigurations configurations; final ScrollController scrollController; final FocusNode focusNode; @@ -34,6 +36,7 @@ class MyQuillEditor extends StatelessWidget { return QuillEditor( scrollController: scrollController, focusNode: focusNode, + controller: controller, configurations: configurations.copyWith( elementOptions: const QuillEditorElementOptions( codeBlock: QuillEditorCodeBlockElementOptions( diff --git a/example/lib/screens/quill/my_quill_toolbar.dart b/example/lib/screens/quill/my_quill_toolbar.dart index 2808cff5..9c4a270c 100644 --- a/example/lib/screens/quill/my_quill_toolbar.dart +++ b/example/lib/screens/quill/my_quill_toolbar.dart @@ -203,8 +203,12 @@ class MyQuillToolbar extends StatelessWidget { ); } return QuillToolbar.simple( + controller: controller, + + /// configurations parameter: + /// Optional: if not provided will use the configuration set when the controller was instantiated. + /// Override: Provide parameter here to override the default configuration - useful if configuration will change. configurations: QuillSimpleToolbarConfigurations( - controller: controller, showAlignmentButtons: true, multiRowsDisplay: true, fontFamilyValues: { diff --git a/example/lib/screens/quill/quill_screen.dart b/example/lib/screens/quill/quill_screen.dart index 220ca8a7..e242ab71 100644 --- a/example/lib/screens/quill/quill_screen.dart +++ b/example/lib/screens/quill/quill_screen.dart @@ -33,6 +33,7 @@ class QuillScreen extends StatefulWidget { } class _QuillScreenState extends State { + /// Instantiate the controller final _controller = QuillController.basic(); final _editorFocusNode = FocusNode(); final _editorScrollController = ScrollController(); @@ -101,9 +102,9 @@ class _QuillScreenState extends State { builder: (context) { return Expanded( child: MyQuillEditor( + controller: _controller, configurations: QuillEditorConfigurations( sharedConfigurations: _sharedConfigurations, - controller: _controller, ), scrollController: _editorScrollController, focusNode: _editorFocusNode, diff --git a/example/lib/screens/simple/simple_screen.dart b/example/lib/screens/simple/simple_screen.dart index a49d48ba..15ab1e5e 100644 --- a/example/lib/screens/simple/simple_screen.dart +++ b/example/lib/screens/simple/simple_screen.dart @@ -18,14 +18,14 @@ class _SimpleScreenState extends State { body: Column( children: [ QuillToolbar.simple( - configurations: - QuillSimpleToolbarConfigurations(controller: _controller), + controller: _controller, + configurations: const QuillSimpleToolbarConfigurations(), ), Expanded( child: QuillEditor.basic( - configurations: QuillEditorConfigurations( - controller: _controller, - padding: const EdgeInsets.all(16), + controller: _controller, + configurations: const QuillEditorConfigurations( + padding: EdgeInsets.all(16), ), ), ), diff --git a/lib/src/controller/provider.dart b/lib/src/controller/provider.dart index 45ed01aa..add8ad10 100644 --- a/lib/src/controller/provider.dart +++ b/lib/src/controller/provider.dart @@ -6,12 +6,16 @@ import 'quill_controller.dart'; extension QuillControllerExt on BuildContext { QuillController? get quilController { + // ignore: deprecated_member_use_from_same_package return quillSimpleToolbarConfigurations?.controller ?? + // ignore: deprecated_member_use_from_same_package quillEditorConfigurations?.controller; } QuillController get requireQuillController { + // ignore: deprecated_member_use_from_same_package return quillSimpleToolbarConfigurations?.controller ?? + // ignore: deprecated_member_use_from_same_package quillEditorConfigurations?.controller ?? (throw ArgumentError( 'The quill provider is required, you must only call requireQuillController inside the QuillToolbar and QuillEditor')); diff --git a/lib/src/controller/quill_controller.dart b/lib/src/controller/quill_controller.dart index 5f85b623..53ae646d 100644 --- a/lib/src/controller/quill_controller.dart +++ b/lib/src/controller/quill_controller.dart @@ -19,6 +19,7 @@ import '../document/structs/doc_change.dart'; import '../document/style.dart'; import '../editor/config/editor_configurations.dart'; import '../editor_toolbar_controller_shared/clipboard/clipboard_service_provider.dart'; +import '../toolbar/config/simple_toolbar_configurations.dart'; import 'quill_controller_configurations.dart'; typedef ReplaceTextCallback = bool Function(int index, int len, Object? data); @@ -52,13 +53,24 @@ class QuillController extends ChangeNotifier { final QuillControllerConfigurations configurations; - /// Local copy of editor configurations enables fail-safe setting from editor _initState method + /// Editor configurations + /// + /// Caches configuration set in QuillEditor ctor. QuillEditorConfigurations? _editorConfigurations; - QuillEditorConfigurations? get editorConfigurations => - configurations.editorConfigurations ?? _editorConfigurations; + QuillEditorConfigurations get editorConfigurations => + _editorConfigurations ?? const QuillEditorConfigurations(); set editorConfigurations(QuillEditorConfigurations? value) => _editorConfigurations = value; + /// Toolbar configurations + /// + /// Caches configuration set in QuillSimpleToolbar ctor. + QuillSimpleToolbarConfigurations? _toolbarConfigurations; + QuillSimpleToolbarConfigurations get toolbarConfigurations => + _toolbarConfigurations ?? const QuillSimpleToolbarConfigurations(); + set toolbarConfigurations(QuillSimpleToolbarConfigurations? value) => + _toolbarConfigurations = value; + /// Document managed by this controller. Document _document; diff --git a/lib/src/controller/quill_controller_configurations.dart b/lib/src/controller/quill_controller_configurations.dart index 86ee9bbc..3f0926fd 100644 --- a/lib/src/controller/quill_controller_configurations.dart +++ b/lib/src/controller/quill_controller_configurations.dart @@ -1,14 +1,16 @@ -import '../editor/config/editor_configurations.dart'; +import '../editor/config/editor_configurations.dart' + show QuillEditorConfigurations; class QuillControllerConfigurations { const QuillControllerConfigurations( - {this.editorConfigurations, + {@Deprecated( + 'This parameter is not used and will be removed in future versions.') + this.editorConfigurations, this.onClipboardPaste, this.requireScriptFontFeatures = false}); - /// Provides central access to editor configurations required for controller actions - /// - /// Future: will be changed to 'required final' + @Deprecated( + 'This parameter is not used and will be removed in future versions.') final QuillEditorConfigurations? editorConfigurations; /// Callback when the user pastes and data has not already been processed diff --git a/lib/src/editor/config/editor_configurations.dart b/lib/src/editor/config/editor_configurations.dart index 421fcc43..bbfdcd05 100644 --- a/lib/src/editor/config/editor_configurations.dart +++ b/lib/src/editor/config/editor_configurations.dart @@ -24,7 +24,9 @@ class QuillEditorConfigurations extends Equatable { /// Important note for the maintainers /// When editing this class please update the [copyWith] function too. const QuillEditorConfigurations({ - required this.controller, + @Deprecated( + 'controller should be passed directly to the editor - this parameter will be removed in future versions.') + this.controller, this.sharedConfigurations = const QuillSharedConfigurations(), this.scrollable = true, this.padding = EdgeInsets.zero, @@ -86,7 +88,8 @@ class QuillEditorConfigurations extends Equatable { final QuillSharedConfigurations sharedConfigurations; - final QuillController controller; + @Deprecated('controller will be removed in future versions.') + final QuillController? controller; /// The text placeholder in the quill editor final String? placeholder; @@ -97,7 +100,8 @@ class QuillEditorConfigurations extends Equatable { /// by any shortcut or keyboard operation. The text is still selectable. /// /// Defaults to `false`. Must not be `null`. - bool get readOnly => controller.readOnly; + // ignore: deprecated_member_use_from_same_package + bool get readOnly => controller?.readOnly != false; /// Override [readOnly] for checkbox. /// @@ -381,7 +385,8 @@ class QuillEditorConfigurations extends Equatable { @override List get props => [ placeholder, - controller.readOnly, + // ignore: deprecated_member_use_from_same_package + controller?.readOnly, ]; // We might use code generator like freezed but sometimes it can be limited @@ -445,6 +450,7 @@ class QuillEditorConfigurations extends Equatable { }) { return QuillEditorConfigurations( sharedConfigurations: sharedConfigurations ?? this.sharedConfigurations, + // ignore: deprecated_member_use_from_same_package controller: controller ?? this.controller, placeholder: placeholder ?? this.placeholder, checkBoxReadOnly: checkBoxReadOnly ?? this.checkBoxReadOnly, diff --git a/lib/src/editor/editor.dart b/lib/src/editor/editor.dart index 9681c515..3a4ca35c 100644 --- a/lib/src/editor/editor.dart +++ b/lib/src/editor/editor.dart @@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import '../common/utils/platform.dart'; +import '../controller/quill_controller.dart'; import '../document/attribute.dart'; import '../document/document.dart'; import '../document/nodes/container.dart' as container_node; @@ -120,36 +121,80 @@ abstract class RenderAbstractEditor implements TextLayoutMetrics { } class QuillEditor extends StatefulWidget { - const QuillEditor({ - required this.configurations, - required this.focusNode, - required this.scrollController, - super.key, - }); + /// Quick start guide: + /// + /// Instantiate a controller: + /// QuillController _controller = QuillController.basic(); + /// + /// Connect the controller to the `QuillEditor` and `QuillSimpleToolbar` widgets. + /// QuillSimpleToolbar( + /// controller: _controller, + /// configurations: const QuillSimpleToolbarConfigurations(), + /// ), + /// Expanded( + /// child: QuillEditor.basic( + /// controller: _controller, + /// configurations: const QuillEditorConfigurations(), + /// ), + /// ), + /// + factory QuillEditor({ + required FocusNode focusNode, + required ScrollController scrollController, + + /// Controller and configurations are required + /// + /// Prefer: use controller and pass QuillEditorConfigurations in constructor for controller (using QuillControllerConfigurations). + /// Backward compatibility: use configurations and pass QuillController in constructor for configurations. (Will be removed in future versions.) + QuillController? controller, + QuillEditorConfigurations? configurations, + }) { + // ignore: deprecated_member_use_from_same_package + controller ??= configurations?.controller; + assert(controller != null, + 'controller required. Provide controller directly (preferred) or indirectly through configurations (not recommended - will be removed in future versions).'); + controller ??= QuillController( + document: Document(), + selection: const TextSelection.collapsed(offset: 0)); + // + controller + ..editorConfigurations = configurations + ..editorFocusNode = focusNode; + // + return QuillEditor._( + focusNode: focusNode, + scrollController: scrollController, + controller: controller); + } + + const QuillEditor._( + {required this.focusNode, + required this.scrollController, + required this.controller}); factory QuillEditor.basic({ + /// The controller for the quill editor widget of flutter quill + QuillController? controller, + /// The configurations for the quill editor widget of flutter quill - required QuillEditorConfigurations configurations, + QuillEditorConfigurations? configurations, FocusNode? focusNode, ScrollController? scrollController, }) { return QuillEditor( scrollController: scrollController ?? ScrollController(), focusNode: focusNode ?? FocusNode(), - configurations: configurations.copyWith( - textSelectionThemeData: configurations.textSelectionThemeData, - autoFocus: configurations.autoFocus, - expands: configurations.expands, - padding: configurations.padding, - keyboardAppearance: configurations.keyboardAppearance, - embedBuilders: configurations.embedBuilders, - editorKey: configurations.editorKey, - ), + controller: controller, + configurations: configurations?.copyWith(), ); } + /// The controller for the quill editor widget of flutter quill + final QuillController controller; + /// The configurations for the quill editor widget of flutter quill - final QuillEditorConfigurations configurations; + QuillEditorConfigurations get configurations => + controller.editorConfigurations; /// Controls whether this editor has keyboard focus. final FocusNode focusNode; @@ -167,9 +212,9 @@ class QuillEditorState extends State late EditorTextSelectionGestureDetectorBuilder _selectionGestureDetectorBuilder; - QuillEditorConfigurations get configurations { - return widget.configurations; - } + QuillController get controller => widget.controller; + + QuillEditorConfigurations get configurations => widget.configurations; @override void initState() { @@ -181,11 +226,7 @@ class QuillEditorState extends State configurations.detectWordBoundary, ); - widget.configurations.controller.editorConfigurations ??= - widget.configurations; - - final focusNode = - widget.configurations.controller.editorFocusNode ??= widget.focusNode; + final focusNode = widget.focusNode; if (configurations.autoFocus) { focusNode.requestFocus(); @@ -241,13 +282,13 @@ class QuillEditorState extends State final child = FlutterQuillLocalizationsWidget( child: QuillEditorProvider( - editorConfigurations: configurations, + controller: controller, child: QuillEditorBuilderWidget( builder: configurations.builder, child: QuillRawEditor( key: _editorKey, + controller: controller, configurations: QuillRawEditorConfigurations( - controller: configurations.controller, focusNode: widget.focusNode, scrollController: widget.scrollController, scrollable: configurations.scrollable, @@ -255,7 +296,7 @@ class QuillEditorState extends State configurations.enableMarkdownStyleConversion, scrollBottomInset: configurations.scrollBottomInset, padding: configurations.padding, - readOnly: configurations.readOnly, + readOnly: controller.readOnly, checkBoxReadOnly: configurations.checkBoxReadOnly, disableClipboard: configurations.disableClipboard, placeholder: configurations.placeholder, @@ -445,19 +486,19 @@ class _QuillEditorSelectionGestureDetectorBuilder } bool _isPositionSelected(TapUpDetails details) { - if (_state.configurations.controller.document.isEmpty()) { + if (_state.controller.document.isEmpty()) { return false; } final pos = renderEditor!.getPositionForOffset(details.globalPosition); - final result = editor!.widget.configurations.controller.document - .querySegmentLeafNode(pos.offset); + final result = + editor!.widget.controller.document.querySegmentLeafNode(pos.offset); final line = result.line; if (line == null) { return false; } final segmentLeaf = result.leaf; if (segmentLeaf == null && line.length == 1) { - editor!.widget.configurations.controller.updateSelection( + editor!.widget.controller.updateSelection( TextSelection.collapsed(offset: pos.offset), ChangeSource.local, ); diff --git a/lib/src/editor/provider.dart b/lib/src/editor/provider.dart index 159ce1ea..d5974631 100644 --- a/lib/src/editor/provider.dart +++ b/lib/src/editor/provider.dart @@ -2,15 +2,32 @@ import 'package:flutter/foundation.dart' show debugPrint, kDebugMode; import 'package:flutter/widgets.dart' show BuildContext, InheritedWidget, Widget; +import '../controller/quill_controller.dart'; import 'config/editor_configurations.dart'; class QuillEditorProvider extends InheritedWidget { - const QuillEditorProvider({ + QuillEditorProvider({ required super.child, - required this.editorConfigurations, + + /// Controller and configurations are required but should only be provided from one. + /// + /// Passing the controller as part of configurations is being deprecated and will be removed in the future. + /// Prefer: use controller and set QuillEditorConfigurations in the controller. + /// Current: use configurations and pass QuillController in constructor for configurations. + QuillController? controller, + @Deprecated( + 'editorConfigurations are no longer needed and will be removed in future versions. Set configurations in the controller') + QuillEditorConfigurations? editorConfigurations, super.key, - }); + }) : editorConfigurations = editorConfigurations ?? + controller?.editorConfigurations ?? + const QuillEditorConfigurations(), + controller = controller ?? + // ignore: deprecated_member_use_from_same_package + editorConfigurations?.controller ?? + QuillController.basic(); + final QuillController controller; final QuillEditorConfigurations editorConfigurations; @override @@ -52,8 +69,9 @@ class QuillEditorProvider extends InheritedWidget { required QuillEditorProvider value, required Widget child, }) { + value.controller.editorConfigurations = value.editorConfigurations; return QuillEditorProvider( - editorConfigurations: value.editorConfigurations, + controller: value.controller, child: child, ); } diff --git a/lib/src/editor/raw_editor/config/raw_editor_configurations.dart b/lib/src/editor/raw_editor/config/raw_editor_configurations.dart index dedd3fb3..9d5e41dc 100644 --- a/lib/src/editor/raw_editor/config/raw_editor_configurations.dart +++ b/lib/src/editor/raw_editor/config/raw_editor_configurations.dart @@ -40,7 +40,6 @@ import '../../../toolbar/theme/quill_dialog_theme.dart'; @immutable class QuillRawEditorConfigurations extends Equatable { const QuillRawEditorConfigurations({ - required this.controller, required this.focusNode, required this.scrollController, required this.scrollBottomInset, @@ -49,6 +48,9 @@ class QuillRawEditorConfigurations extends Equatable { required this.selectionCtrls, required this.embedBuilder, required this.autoFocus, + @Deprecated( + 'controller should be passed directly to the editor - this parameter will be removed in future versions.') + this.controller, this.showCursor = true, this.scrollable = true, this.padding = EdgeInsets.zero, @@ -93,7 +95,8 @@ class QuillRawEditorConfigurations extends Equatable { }); /// Controls the document being edited. - final QuillController controller; + @Deprecated('controller will be removed in future versions.') + final QuillController? controller; /// Controls whether this editor has keyboard focus. final FocusNode focusNode; diff --git a/lib/src/editor/raw_editor/raw_editor.dart b/lib/src/editor/raw_editor/raw_editor.dart index 5a6d04cf..23b3130b 100644 --- a/lib/src/editor/raw_editor/raw_editor.dart +++ b/lib/src/editor/raw_editor/raw_editor.dart @@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart' immutable; import '../../common/structs/offset_value.dart'; +import '../../controller/quill_controller.dart'; import '../editor.dart'; import '../widgets/text/text_selection.dart'; import 'config/raw_editor_configurations.dart'; @@ -20,8 +21,14 @@ import 'raw_editor_state.dart'; class QuillRawEditor extends StatefulWidget { QuillRawEditor({ required this.configurations, + controller, super.key, - }) : assert( + }) : + // ignore: deprecated_member_use_from_same_package + assert((controller ?? configurations.controller) != null), + // ignore: deprecated_member_use_from_same_package + controller = controller ?? configurations.controller, + assert( configurations.maxHeight == null || configurations.maxHeight! > 0, 'maxHeight cannot be null'), assert( @@ -33,6 +40,7 @@ class QuillRawEditor extends StatefulWidget { configurations.maxHeight! >= configurations.minHeight!, 'maxHeight cannot be null'); + final QuillController controller; final QuillRawEditorConfigurations configurations; @override diff --git a/lib/src/editor/raw_editor/raw_editor_state.dart b/lib/src/editor/raw_editor/raw_editor_state.dart index 37f4bc2c..0525a6f1 100644 --- a/lib/src/editor/raw_editor/raw_editor_state.dart +++ b/lib/src/editor/raw_editor/raw_editor_state.dart @@ -77,7 +77,7 @@ class QuillRawEditorState extends EditorState // Cursors late CursorCont _cursorCont; - QuillController get controller => widget.configurations.controller; + QuillController get controller => widget.controller; // Focus bool _didAutoFocus = false; @@ -1274,9 +1274,8 @@ class QuillRawEditorState extends EditorState _cursorCont.show.value = widget.configurations.showCursor; _cursorCont.style = widget.configurations.cursorStyle; - if (controller != oldWidget.configurations.controller) { - oldWidget.configurations.controller - .removeListener(_didChangeTextEditingValue); + if (controller != oldWidget.controller) { + oldWidget.controller.removeListener(_didChangeTextEditingValue); controller.addListener(_didChangeTextEditingValue); updateRemoteValueIfNeeded(); } @@ -1293,7 +1292,7 @@ class QuillRawEditorState extends EditorState updateKeepAlive(); } - if (controller.selection != oldWidget.configurations.controller.selection) { + if (controller.selection != oldWidget.controller.selection) { _selectionOverlay?.update(textEditingValue); } @@ -1348,7 +1347,7 @@ class QuillRawEditorState extends EditorState /// operating on stale data. void _markNeedsBuild() { if (_dirty) { - // No need to rebuilt if it already darty + // No need to rebuilt if it already dirty return; } setState(() { @@ -1626,7 +1625,7 @@ class QuillRawEditorState extends EditorState final QuillEditorTextBoundary boundary; // final TextEditingValue textEditingValue = - // _textEditingValueforTextLayoutMetrics; + // _textEditingValueForTextLayoutMetrics; atomicTextBoundary = QuillEditorCharacterBoundary(textEditingValue); // This isn't enough. Newline characters. boundary = QuillEditorExpandedTextBoundary( diff --git a/lib/src/editor/raw_editor/raw_editor_state_selection_delegate_mixin.dart b/lib/src/editor/raw_editor/raw_editor_state_selection_delegate_mixin.dart index 55cda637..247e7728 100644 --- a/lib/src/editor/raw_editor/raw_editor_state_selection_delegate_mixin.dart +++ b/lib/src/editor/raw_editor/raw_editor_state_selection_delegate_mixin.dart @@ -11,22 +11,21 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState implements TextSelectionDelegate { @override TextEditingValue get textEditingValue { - return widget.configurations.controller.plainTextEditingValue; + return widget.controller.plainTextEditingValue; } set textEditingValue(TextEditingValue value) { final cursorPosition = value.selection.extentOffset; - final oldText = widget.configurations.controller.document.toPlainText(); + final oldText = widget.controller.document.toPlainText(); final newText = value.text; final diff = getDiff(oldText, newText, cursorPosition); if (diff.deleted == '' && diff.inserted == '') { // Only changing selection range - widget.configurations.controller - .updateSelection(value.selection, ChangeSource.local); + widget.controller.updateSelection(value.selection, ChangeSource.local); return; } - widget.configurations.controller.replaceTextWithEmbeds( + widget.controller.replaceTextWithEmbeds( diff.start, diff.deleted.length, diff.inserted, value.selection); } diff --git a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart index 7aacc28f..d9f2fa14 100644 --- a/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart +++ b/lib/src/editor/raw_editor/raw_editor_state_text_input_client_mixin.dart @@ -198,10 +198,9 @@ mixin RawEditorStateTextInputClientMixin on EditorState final cursorPosition = value.selection.extentOffset; final diff = getDiff(oldText, text, cursorPosition); if (diff.deleted.isEmpty && diff.inserted.isEmpty) { - widget.configurations.controller - .updateSelection(value.selection, ChangeSource.local); + widget.controller.updateSelection(value.selection, ChangeSource.local); } else { - widget.configurations.controller.replaceText( + widget.controller.replaceText( diff.start, diff.deleted.length, diff.inserted, diff --git a/lib/src/toolbar/base_toolbar.dart b/lib/src/toolbar/base_toolbar.dart index 72636f73..1634ca9e 100644 --- a/lib/src/toolbar/base_toolbar.dart +++ b/lib/src/toolbar/base_toolbar.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import '../../flutter_quill.dart' show QuillToolbarProvider, kDefaultToolbarSize; +import '../controller/quill_controller.dart'; import '../l10n/widgets/localizations.dart'; import 'config/simple_toolbar_configurations.dart'; import 'config/toolbar_configurations.dart'; @@ -40,8 +41,10 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { }); static QuillSimpleToolbar simple( - {required QuillSimpleToolbarConfigurations configurations}) { + {QuillController? controller, + QuillSimpleToolbarConfigurations? configurations}) { return QuillSimpleToolbar( + controller: controller, configurations: configurations, ); } diff --git a/lib/src/toolbar/config/simple_toolbar_configurations.dart b/lib/src/toolbar/config/simple_toolbar_configurations.dart index 71e44119..1579ee69 100644 --- a/lib/src/toolbar/config/simple_toolbar_configurations.dart +++ b/lib/src/toolbar/config/simple_toolbar_configurations.dart @@ -80,7 +80,9 @@ enum SearchButtonType { @immutable class QuillSimpleToolbarConfigurations extends QuillSharedToolbarProperties { const QuillSimpleToolbarConfigurations({ - required this.controller, + @Deprecated( + 'controller should be passed directly to the toolbar - this parameter will be removed in future versions.') + this.controller, super.sharedConfigurations, super.toolbarSectionSpacing = kToolbarSectionSpacing, super.toolbarIconAlignment = WrapAlignment.center, @@ -166,7 +168,8 @@ class QuillSimpleToolbarConfigurations extends QuillSharedToolbarProperties { final Map? fontFamilyValues; - final QuillController controller; + @Deprecated('controller will be removed in future versions.') + final QuillController? controller; /// By default it will be /// ```dart diff --git a/lib/src/toolbar/simple_toolbar.dart b/lib/src/toolbar/simple_toolbar.dart index 264792f5..ea669861 100644 --- a/lib/src/toolbar/simple_toolbar.dart +++ b/lib/src/toolbar/simple_toolbar.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import '../controller/quill_controller.dart'; import '../document/attribute.dart'; +import '../document/document.dart'; import 'base_toolbar.dart'; import 'buttons/alignment/select_alignment_buttons.dart'; import 'buttons/arrow_indicated_list_button.dart'; @@ -9,13 +11,37 @@ import 'simple_toolbar_provider.dart'; class QuillSimpleToolbar extends StatelessWidget implements PreferredSizeWidget { - const QuillSimpleToolbar({ - required this.configurations, + factory QuillSimpleToolbar({ + required QuillSimpleToolbarConfigurations? configurations, + QuillController? controller, + Key? key, + }) { + // ignore: deprecated_member_use_from_same_package + controller ??= configurations?.controller; + assert(controller != null, + 'controller required. Provide controller directly (preferred) or indirectly through configurations (not recommended - will be removed in future versions).'); + controller ??= QuillController( + document: Document(), + selection: const TextSelection.collapsed(offset: 0)); + // + controller.toolbarConfigurations = configurations; + // + return QuillSimpleToolbar._( + controller: controller, + key: key, + ); + } + + const QuillSimpleToolbar._({ + required this.controller, super.key, }); + final QuillController controller; + /// The configurations for the toolbar widget of flutter quill - final QuillSimpleToolbarConfigurations configurations; + QuillSimpleToolbarConfigurations get configurations => + controller.toolbarConfigurations; double get _toolbarSize => configurations.toolbarSize * 1.4; @@ -30,7 +56,6 @@ class QuillSimpleToolbar extends StatelessWidget final globalIconSize = toolbarConfigurations.buttonOptions.base.iconSize; final axis = toolbarConfigurations.axis; - final globalController = configurations.controller; final divider = SizedBox( height: _toolbarSize, @@ -46,93 +71,93 @@ class QuillSimpleToolbar extends StatelessWidget QuillToolbarHistoryButton( isUndo: true, options: toolbarConfigurations.buttonOptions.undoHistory, - controller: globalController, + controller: controller, ), if (configurations.showRedo) QuillToolbarHistoryButton( isUndo: false, options: toolbarConfigurations.buttonOptions.redoHistory, - controller: globalController, + controller: controller, ), if (configurations.showFontFamily) QuillToolbarFontFamilyButton( options: toolbarConfigurations.buttonOptions.fontFamily, - controller: globalController, + controller: controller, ), if (configurations.showFontSize) QuillToolbarFontSizeButton( options: toolbarConfigurations.buttonOptions.fontSize, - controller: globalController, + controller: controller, ), if (configurations.showBoldButton) QuillToolbarToggleStyleButton( attribute: Attribute.bold, options: toolbarConfigurations.buttonOptions.bold, - controller: globalController, + controller: controller, ), if (configurations.showItalicButton) QuillToolbarToggleStyleButton( attribute: Attribute.italic, options: toolbarConfigurations.buttonOptions.italic, - controller: globalController, + controller: controller, ), if (configurations.showUnderLineButton) QuillToolbarToggleStyleButton( attribute: Attribute.underline, options: toolbarConfigurations.buttonOptions.underLine, - controller: globalController, + controller: controller, ), if (configurations.showStrikeThrough) QuillToolbarToggleStyleButton( attribute: Attribute.strikeThrough, options: toolbarConfigurations.buttonOptions.strikeThrough, - controller: globalController, + controller: controller, ), if (configurations.showInlineCode) QuillToolbarToggleStyleButton( attribute: Attribute.inlineCode, options: toolbarConfigurations.buttonOptions.inlineCode, - controller: globalController, + controller: controller, ), if (configurations.showSubscript) QuillToolbarToggleStyleButton( attribute: Attribute.subscript, options: toolbarConfigurations.buttonOptions.subscript, - controller: globalController, + controller: controller, ), if (configurations.showSuperscript) QuillToolbarToggleStyleButton( attribute: Attribute.superscript, options: toolbarConfigurations.buttonOptions.superscript, - controller: globalController, + controller: controller, ), if (configurations.showSmallButton) QuillToolbarToggleStyleButton( attribute: Attribute.small, options: toolbarConfigurations.buttonOptions.small, - controller: globalController, + controller: controller, ), if (configurations.showColorButton) QuillToolbarColorButton( - controller: globalController, + controller: controller, isBackground: false, options: toolbarConfigurations.buttonOptions.color, ), if (configurations.showBackgroundColorButton) QuillToolbarColorButton( options: toolbarConfigurations.buttonOptions.backgroundColor, - controller: globalController, + controller: controller, isBackground: true, ), if (configurations.showClearFormat) QuillToolbarClearFormatButton( - controller: globalController, + controller: controller, options: toolbarConfigurations.buttonOptions.clearFormat, ), if (theEmbedButtons != null) for (final builder in theEmbedButtons) builder( - globalController, + controller, globalIconSize ?? kDefaultIconSize, context.quillToolbarBaseButtonOptions?.iconTheme, configurations.dialogTheme), @@ -140,7 +165,7 @@ class QuillSimpleToolbar extends StatelessWidget [ if (configurations.showAlignmentButtons) QuillToolbarSelectAlignmentButtons( - controller: globalController, + controller: controller, options: toolbarConfigurations .buttonOptions.selectAlignmentButtons .copyWith( @@ -154,26 +179,26 @@ class QuillSimpleToolbar extends StatelessWidget QuillToolbarToggleStyleButton( attribute: Attribute.rtl, options: toolbarConfigurations.buttonOptions.direction, - controller: globalController, + controller: controller, ), ], [ if (configurations.showLineHeightButton) QuillToolbarSelectLineHeightStyleDropdownButton( - controller: globalController, + controller: controller, options: toolbarConfigurations .buttonOptions.selectLineHeightStyleDropdownButton, ), if (configurations.showHeaderStyle) ...[ if (configurations.headerStyleType.isOriginal) QuillToolbarSelectHeaderStyleDropdownButton( - controller: globalController, + controller: controller, options: toolbarConfigurations .buttonOptions.selectHeaderStyleDropdownButton, ) else QuillToolbarSelectHeaderStyleButtons( - controller: globalController, + controller: controller, options: toolbarConfigurations .buttonOptions.selectHeaderStyleButtons, ), @@ -184,42 +209,42 @@ class QuillSimpleToolbar extends StatelessWidget QuillToolbarToggleStyleButton( attribute: Attribute.ol, options: toolbarConfigurations.buttonOptions.listNumbers, - controller: globalController, + controller: controller, ), if (configurations.showListBullets) QuillToolbarToggleStyleButton( attribute: Attribute.ul, options: toolbarConfigurations.buttonOptions.listBullets, - controller: globalController, + controller: controller, ), if (configurations.showListCheck) QuillToolbarToggleCheckListButton( options: toolbarConfigurations.buttonOptions.toggleCheckList, - controller: globalController, + controller: controller, ), if (configurations.showCodeBlock) QuillToolbarToggleStyleButton( attribute: Attribute.codeBlock, options: toolbarConfigurations.buttonOptions.codeBlock, - controller: globalController, + controller: controller, ), ], [ if (configurations.showQuote) QuillToolbarToggleStyleButton( options: toolbarConfigurations.buttonOptions.quote, - controller: globalController, + controller: controller, attribute: Attribute.blockQuote, ), if (configurations.showIndent) QuillToolbarIndentButton( - controller: globalController, + controller: controller, isIncrease: true, options: toolbarConfigurations.buttonOptions.indentIncrease, ), if (configurations.showIndent) QuillToolbarIndentButton( - controller: globalController, + controller: controller, isIncrease: false, options: toolbarConfigurations.buttonOptions.indentDecrease, ), @@ -228,40 +253,40 @@ class QuillSimpleToolbar extends StatelessWidget if (configurations.showLink) toolbarConfigurations.linkStyleType.isOriginal ? QuillToolbarLinkStyleButton( - controller: globalController, + controller: controller, options: toolbarConfigurations.buttonOptions.linkStyle, ) : QuillToolbarLinkStyleButton2( - controller: globalController, + controller: controller, options: toolbarConfigurations.buttonOptions.linkStyle2, ), if (configurations.showSearchButton) switch (configurations.searchButtonType) { SearchButtonType.legacy => QuillToolbarLegacySearchButton( - controller: globalController, + controller: controller, options: toolbarConfigurations.buttonOptions.search, ), SearchButtonType.modern => QuillToolbarSearchButton( - controller: globalController, + controller: controller, options: toolbarConfigurations.buttonOptions.search, ), }, if (configurations.showClipboardCut) QuillToolbarClipboardButton( options: toolbarConfigurations.buttonOptions.clipboardCut, - controller: globalController, + controller: controller, clipboardAction: ClipboardAction.cut, ), if (configurations.showClipboardCopy) QuillToolbarClipboardButton( options: toolbarConfigurations.buttonOptions.clipboardCopy, - controller: globalController, + controller: controller, clipboardAction: ClipboardAction.copy, ), if (configurations.showClipboardPaste) QuillToolbarClipboardButton( options: toolbarConfigurations.buttonOptions.clipboardPaste, - controller: globalController, + controller: controller, clipboardAction: ClipboardAction.paste, ), ], @@ -269,7 +294,7 @@ class QuillSimpleToolbar extends StatelessWidget for (final customButton in configurations.customButtons) QuillToolbarCustomButton( options: customButton, - controller: globalController, + controller: controller, ), ], ]; diff --git a/test/bug_fix_test.dart b/test/bug_fix_test.dart index 5834b714..e1a72823 100644 --- a/test/bug_fix_test.dart +++ b/test/bug_fix_test.dart @@ -19,10 +19,10 @@ void main() { MaterialApp( home: Scaffold( body: QuillSimpleToolbar( - configurations: QuillSimpleToolbarConfigurations( - controller: controller, + controller: controller, + configurations: const QuillSimpleToolbarConfigurations( showRedo: false, - customButtons: const [ + customButtons: [ QuillToolbarCustomButtonOptions( tooltip: tooltip, ) @@ -56,9 +56,7 @@ void main() { setUp(() { controller = QuillController.basic(); editor = QuillEditor.basic( - configurations: QuillEditorConfigurations( - controller: controller, - ), + controller: controller, ); }); @@ -142,8 +140,8 @@ void main() { home: QuillEditor( focusNode: FocusNode(), scrollController: ScrollController(), - configurations: QuillEditorConfigurations( - controller: controller, + controller: controller, + configurations: const QuillEditorConfigurations( autoFocus: true, expands: true, ), diff --git a/test/editor/editor_test.dart b/test/editor/editor_test.dart index 4e3a79f6..8f8d1051 100644 --- a/test/editor/editor_test.dart +++ b/test/editor/editor_test.dart @@ -24,11 +24,11 @@ void main() { await tester.pumpWidget( MaterialApp( home: QuillEditor.basic( + controller: controller, // ignore: avoid_redundant_argument_values - configurations: QuillEditorConfigurations( - controller: controller, - // ignore: avoid_redundant_argument_values - ), + configurations: const QuillEditorConfigurations( + // ignore: avoid_redundant_argument_values + ), ), ), ); @@ -44,8 +44,8 @@ void main() { home: QuillEditor( focusNode: FocusNode(), scrollController: ScrollController(), + controller: controller, configurations: QuillEditorConfigurations( - controller: controller, // ignore: avoid_redundant_argument_values autoFocus: true, expands: true, @@ -116,9 +116,9 @@ void main() { home: QuillEditor( focusNode: FocusNode(), scrollController: ScrollController(), + controller: controller, // ignore: avoid_redundant_argument_values configurations: QuillEditorConfigurations( - controller: controller, // ignore: avoid_redundant_argument_values autoFocus: true, expands: true, @@ -146,7 +146,8 @@ void main() { await tester.pumpWidget( MaterialApp( home: QuillEditor.basic( - configurations: QuillEditorConfigurations(controller: controller), + controller: controller, + configurations: const QuillEditorConfigurations(), focusNode: editorFocusNode, ), ),