pull/1566/head
Ellet 1 year ago
parent 039e3193d9
commit 35a9502d7e
No known key found for this signature in database
GPG Key ID: C488CC70BBCEF0D1
  1. 3
      CHANGELOG.md
  2. 8
      example/lib/presentation/quill/quill_screen.dart
  3. 3
      example/lib/presentation/quill/quill_toolbar.dart
  4. 19
      flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart
  5. 57
      flutter_quill_extensions/lib/embeds/image/editor/image_menu.dart
  6. 13
      flutter_quill_extensions/lib/embeds/image/toolbar/image_button.dart
  7. 8
      flutter_quill_extensions/lib/embeds/image/toolbar/select_image_source.dart
  8. 11
      flutter_quill_extensions/lib/embeds/video/toolbar/video_button.dart
  9. 2
      flutter_quill_extensions/lib/models/config/shared_configurations.dart
  10. 30
      lib/src/extensions/quill_provider.dart
  11. 2
      lib/src/l10n/widgets/localizations.dart
  12. 6
      lib/src/models/config/editor/configurations.dart
  13. 46
      lib/src/models/config/others/animations.dart
  14. 15
      lib/src/models/config/quill_configurations.dart
  15. 7
      lib/src/models/config/quill_shared_configurations.dart
  16. 6
      lib/src/models/config/raw_editor/configurations.dart
  17. 4
      lib/src/models/config/toolbar/toolbar_configurations.dart
  18. 9
      lib/src/widgets/editor/editor.dart
  19. 2
      lib/src/widgets/raw_editor/raw_editor_actions.dart
  20. 14
      lib/src/widgets/raw_editor/raw_editor_state.dart
  21. 4
      lib/src/widgets/raw_editor/raw_editor_state_selection_delegate_mixin.dart
  22. 6
      lib/src/widgets/raw_editor/raw_editor_state_text_input_client_mixin.dart
  23. 17
      lib/src/widgets/style_widgets/checkbox_point.dart
  24. 19
      lib/src/widgets/toolbar/buttons/color/color.dart
  25. 20
      lib/src/widgets/toolbar/buttons/link_style.dart
  26. 32
      lib/src/widgets/toolbar/buttons/link_style2.dart
  27. 18
      lib/src/widgets/toolbar/buttons/search/search.dart
  28. 6
      lib/src/widgets/toolbar/toolbar.dart
  29. 3
      pubspec.yaml
  30. 50
      test/bug_fix_test.dart
  31. 66
      test/widgets/editor_test.dart

@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
## 9.0.0-dev
* **Major Breaking change**: The `QuillProvider` is now optional, the `controller` parameter has been moved to the `QuillEditor` and `QuillToolbar` once again.
## 8.6.4
* The default value of `keyboardAppearance` for the iOS will be the one from the App/System theme mode instead of always using the `Brightness.light`
* Fix typos in `README.md`

@ -101,11 +101,9 @@ class _QuillScreenState extends State<QuillScreen> {
],
),
body: QuillProvider(
configurations: QuillConfigurations(
controller: _controller,
configurations: const QuillConfigurations(
sharedConfigurations: QuillSharedConfigurations(
animationConfigurations: QuillAnimationConfigurations.disableAll(),
extraConfigurations: const {
extraConfigurations: {
QuillSharedExtensionsConfigurations.key:
QuillSharedExtensionsConfigurations(
assetsPrefix: 'assets',
@ -117,6 +115,7 @@ class _QuillScreenState extends State<QuillScreen> {
children: [
if (!_isReadOnly)
MyQuillToolbar(
controller: _controller,
focusNode: _editorFocusNode,
),
Builder(
@ -124,6 +123,7 @@ class _QuillScreenState extends State<QuillScreen> {
return Expanded(
child: MyQuillEditor(
configurations: QuillEditorConfigurations(
controller: _controller,
readOnly: _isReadOnly,
),
scrollController: _editorScrollController,

@ -16,10 +16,12 @@ import 'embeds/timestamp_embed.dart';
class MyQuillToolbar extends StatelessWidget {
const MyQuillToolbar({
required this.controller,
required this.focusNode,
super.key,
});
final QuillController controller;
final FocusNode focusNode;
Future<void> onImageInsertWithCropping(
@ -224,6 +226,7 @@ class MyQuillToolbar extends StatelessWidget {
}
return QuillToolbar(
configurations: QuillToolbarConfigurations(
controller: controller,
showAlignmentButtons: true,
buttonOptions: QuillToolbarButtonOptions(
base: QuillToolbarBaseButtonOptions(

@ -56,17 +56,14 @@ class QuillEditorImageEmbedBuilder extends EmbedBuilder {
onTap: configurations.onImageClicked ??
() => showDialog(
context: context,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: ImageOptionsMenu(
controller: controller,
configurations: configurations,
imageSource: imageSource,
imageSize: imageSize,
isReadOnly: readOnly,
imageSaverService: imageSaverService,
),
builder: (_) => FlutterQuillLocalizationsWidget(
child: ImageOptionsMenu(
controller: controller,
configurations: configurations,
imageSource: imageSource,
imageSize: imageSize,
isReadOnly: readOnly,
imageSaverService: imageSaverService,
),
),
),

@ -1,13 +1,7 @@
import 'package:flutter/cupertino.dart' show showCupertinoModalPopup;
import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart'
show
ImageUrl,
QuillController,
QuillProvider,
QuillProviderExt,
StyleAttribute,
getEmbedNode;
show ImageUrl, QuillController, StyleAttribute, getEmbedNode;
import 'package:flutter_quill/translations.dart';
import '../../../models/config/editor/image/image.dart';
@ -55,34 +49,31 @@ class ImageOptionsMenu extends StatelessWidget {
context: context,
builder: (modalContext) {
final screenSize = MediaQuery.sizeOf(modalContext);
return QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: ImageResizer(
onImageResize: (width, height) {
final res = getEmbedNode(
controller,
controller.selection.start,
);
return FlutterQuillLocalizationsWidget(
child: ImageResizer(
onImageResize: (width, height) {
final res = getEmbedNode(
controller,
controller.selection.start,
);
final attr = replaceStyleStringWithSize(
getImageStyleString(controller),
width: width,
height: height,
final attr = replaceStyleStringWithSize(
getImageStyleString(controller),
width: width,
height: height,
);
controller
..skipRequestKeyboard = true
..formatText(
res.offset,
1,
StyleAttribute(attr),
);
controller
..skipRequestKeyboard = true
..formatText(
res.offset,
1,
StyleAttribute(attr),
);
},
imageWidth: imageSize.width,
imageHeight: imageSize.height,
maxWidth: screenSize.width,
maxHeight: screenSize.height,
),
},
imageWidth: imageSize.width,
imageHeight: imageSize.height,
maxWidth: screenSize.width,
maxHeight: screenSize.height,
),
);
},

@ -172,14 +172,11 @@ class QuillToolbarImageButton extends StatelessWidget {
Future<String?> _typeLink(BuildContext context) async {
final value = await showDialog<String>(
context: context,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: TypeLinkDialog(
dialogTheme: options.dialogTheme,
linkRegExp: options.linkRegExp,
linkType: LinkType.image,
),
builder: (_) => FlutterQuillLocalizationsWidget(
child: TypeLinkDialog(
dialogTheme: options.dialogTheme,
linkRegExp: options.linkRegExp,
linkType: LinkType.image,
),
),
);

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_quill/extensions.dart' show isDesktop;
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill/translations.dart';
import '../editor/image_embed_types.dart';
@ -55,11 +54,8 @@ Future<InsertImageSource?> showSelectImageSourceDialog({
showDragHandle: true,
context: context,
constraints: const BoxConstraints(maxWidth: 640),
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: const FlutterQuillLocalizationsWidget(
child: SelectImageSourceDialog(),
),
builder: (_) => const FlutterQuillLocalizationsWidget(
child: SelectImageSourceDialog(),
),
);
return imageSource;

@ -165,13 +165,10 @@ class QuillToolbarVideoButton extends StatelessWidget {
Future<String?> _typeLink(BuildContext context) async {
final value = await showDialog<String>(
context: context,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: TypeLinkDialog(
dialogTheme: options.dialogTheme,
linkType: LinkType.video,
),
builder: (_) => FlutterQuillLocalizationsWidget(
child: TypeLinkDialog(
dialogTheme: options.dialogTheme,
linkType: LinkType.video,
),
),
);

@ -48,7 +48,7 @@ class QuillSharedExtensionsConfigurations {
required BuildContext context,
}) {
final quillSharedExtensionsConfigurations =
context.requireQuillSharedConfigurations.extraConfigurations[key];
context.quillSharedConfigurations?.extraConfigurations[key];
if (quillSharedExtensionsConfigurations != null) {
if (quillSharedExtensionsConfigurations
is! QuillSharedExtensionsConfigurations) {

@ -6,12 +6,6 @@ import '../../flutter_quill.dart';
/// Public shared extension
extension QuillProviderExt on BuildContext {
/// return [QuillProvider] as not null
/// throw exception if it's not in the widget tree
QuillProvider get requireQuillProvider {
return QuillProvider.ofNotNull(this);
}
/// return nullable [QuillProvider]
/// don't throw exception if it's not in the widget tree
/// instead it will be null
@ -25,7 +19,8 @@ extension QuillProviderExt on BuildContext {
/// don't throw exception if [QuillProvider] is not in the widget tree
/// instead it will be null
QuillController? get quilController {
return quillProvider?.configurations.controller;
return quillToolbarConfigurations?.controller ??
quillEditorConfigurations?.controller;
}
/// return [QuillController] as not null
@ -33,15 +28,10 @@ extension QuillProviderExt on BuildContext {
/// the provider widget first and then we will return the controller
/// throw exception if [QuillProvider] is not in the widget tree
QuillController get requireQuillController {
return requireQuillProvider.configurations.controller;
}
/// return [QuillConfigurations] as not null
/// since the quill configurations is in the [QuillProvider] then we need to
/// get the provider widget first and then we will return quill configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillConfigurations get requireQuillConfigurations {
return requireQuillProvider.configurations;
return quillToolbarConfigurations?.controller ??
quillEditorConfigurations?.controller ??
(throw ArgumentError(
'The quill provider is required, you must only call requireQuillController inside the QuillToolbar and QuillEditor'));
}
/// return nullable [QuillConfigurations]
@ -52,14 +42,6 @@ extension QuillProviderExt on BuildContext {
return quillProvider?.configurations;
}
/// return [QuillSharedConfigurations] as not null. Since the quill
/// shared configurations is in the [QuillProvider] then we need to get the
/// provider widget first and then we will return shared configurations
/// throw exception if [QuillProvider] is not in the widget tree
QuillSharedConfigurations get requireQuillSharedConfigurations {
return requireQuillConfigurations.sharedConfigurations;
}
/// return nullable [QuillSharedConfigurations] . Since the quill
/// shared configurations is in the [QuillProvider] then we need to get the
/// provider widget first and then we will return shared configurations

@ -19,7 +19,7 @@ class FlutterQuillLocalizationsWidget extends StatelessWidget {
return child;
}
return Localizations(
locale: context.requireQuillSharedConfigurations.locale ??
locale: context.quillSharedConfigurations?.locale ??
Localizations.localeOf(context),
delegates: FlutterQuillLocalizations.localizationsDelegates,
child: child,

@ -6,6 +6,7 @@ import 'package:flutter/material.dart'
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart' show experimental;
import '../../../widgets/controller.dart';
import '../../../widgets/default_styles.dart';
import '../../../widgets/delegate.dart';
import '../../../widgets/editor/editor.dart';
@ -24,6 +25,7 @@ class QuillEditorConfigurations extends Equatable {
/// Important note for the maintainers
/// When editing this class please update the [copyWith] function too.
const QuillEditorConfigurations({
required this.controller,
this.scrollable = true,
this.padding = EdgeInsets.zero,
this.autoFocus = false,
@ -74,6 +76,8 @@ class QuillEditorConfigurations extends Equatable {
this.textInputAction = TextInputAction.newline,
});
final QuillController controller;
/// The text placeholder in the quill editor
final String? placeholder;
@ -331,6 +335,7 @@ class QuillEditorConfigurations extends Equatable {
// regenerate this function using extension in vs code or plugin in intellij
QuillEditorConfigurations copyWith({
QuillController? controller,
String? placeholder,
bool? readOnly,
bool? scrollable,
@ -376,6 +381,7 @@ class QuillEditorConfigurations extends Equatable {
TextInputAction? textInputAction,
}) {
return QuillEditorConfigurations(
controller: controller ?? this.controller,
placeholder: placeholder ?? this.placeholder,
readOnly: readOnly ?? this.readOnly,
scrollable: scrollable ?? this.scrollable,

@ -1,28 +1,28 @@
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart' show experimental, immutable;
// import 'package:equatable/equatable.dart';
// import 'package:meta/meta.dart' show experimental, immutable;
@immutable
@experimental
class QuillAnimationConfigurations extends Equatable {
const QuillAnimationConfigurations({
required this.checkBoxPointItem,
});
// @immutable
// @experimental
// class QuillAnimationConfigurations extends Equatable {
// const QuillAnimationConfigurations({
// required this.checkBoxPointItem,
// });
factory QuillAnimationConfigurations.disableAll() =>
const QuillAnimationConfigurations(
checkBoxPointItem: false,
);
// factory QuillAnimationConfigurations.disableAll() =>
// const QuillAnimationConfigurations(
// checkBoxPointItem: false,
// );
factory QuillAnimationConfigurations.enableAll() =>
const QuillAnimationConfigurations(
checkBoxPointItem: true,
);
// factory QuillAnimationConfigurations.enableAll() =>
// const QuillAnimationConfigurations(
// checkBoxPointItem: true,
// );
/// This currently has issue which the whole checkbox list will rebuilt
/// and the animation will replay when some value changes
/// which is why disabled by default
final bool checkBoxPointItem;
// /// This currently has issue which the whole checkbox list will rebuilt
// /// and the animation will replay when some value changes
// /// which is why disabled by default
// final bool checkBoxPointItem;
@override
List<Object?> get props => [];
}
// @override
// List<Object?> get props => [];
// }

@ -10,17 +10,16 @@ export 'toolbar/toolbar_configurations.dart';
@immutable
class QuillConfigurations extends Equatable {
const QuillConfigurations({
required this.controller,
this.sharedConfigurations = const QuillSharedConfigurations(),
});
/// Controller object which establishes a link between a rich text document
/// and this editor.
///
/// The controller is shared between [QuillEditorConfigurations] and
/// [QuillToolbarConfigurations] but to simplify things we will defined it
/// here, it should not be null
final QuillController controller;
// /// Controller object which establishes a link between a rich text document
// /// and this editor.
// ///
// /// The controller is shared between [QuillEditorConfigurations] and
// /// [QuillToolbarConfigurations] but to simplify things we will defined it
// /// here, it should not be null
// final QuillController controller;
/// The shared configurations between [QuillEditorConfigurations] and
/// [QuillToolbarConfigurations] so we don't duplicate things

@ -15,9 +15,6 @@ class QuillSharedConfigurations extends Equatable {
this.dialogBarrierColor = Colors.black54,
this.dialogTheme,
this.locale,
this.animationConfigurations = const QuillAnimationConfigurations(
checkBoxPointItem: false,
),
this.extraConfigurations = const {},
});
@ -37,9 +34,6 @@ class QuillSharedConfigurations extends Equatable {
/// `MaterialApp` or `WidgetsApp`
final Locale? locale;
/// To configure which animations you want to be enabled
final QuillAnimationConfigurations animationConfigurations;
/// Store custom configurations in here and use it in the widget tree
final Map<String, Object?> extraConfigurations;
@ -48,6 +42,5 @@ class QuillSharedConfigurations extends Equatable {
dialogBarrierColor,
dialogTheme,
locale,
animationConfigurations,
];
}

@ -49,7 +49,7 @@ class QuillRawEditorConfigurations extends Equatable {
this.showCursor = true,
this.scrollable = true,
this.padding = EdgeInsets.zero,
this.isReadOnly = false,
this.readOnly = false,
this.placeholder,
this.onLaunchUrl,
this.contextMenuBuilder = defaultContextMenuBuilder,
@ -97,7 +97,7 @@ class QuillRawEditorConfigurations extends Equatable {
/// by any shortcut or keyboard operation. The text is still selectable.
///
/// Defaults to false. Must not be null.
final bool isReadOnly;
final bool readOnly;
final String? placeholder;
@ -296,7 +296,7 @@ class QuillRawEditorConfigurations extends Equatable {
@override
List<Object?> get props => [
isReadOnly,
readOnly,
placeholder,
];
}

@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart' show immutable;
import 'package:flutter/widgets.dart'
show Axis, Widget, WrapAlignment, WrapCrossAlignment;
import '../../../widgets/controller.dart';
import '../../../widgets/embeds.dart';
import '../../themes/quill_dialog_theme.dart';
import '../../themes/quill_icon_theme.dart';
@ -67,6 +68,7 @@ enum LinkStyleType {
@immutable
class QuillToolbarConfigurations extends QuillSharedToolbarProperties {
const QuillToolbarConfigurations({
required this.controller,
super.toolbarSectionSpacing = kToolbarSectionSpacing,
super.toolbarIconAlignment = WrapAlignment.center,
super.toolbarIconCrossAlignment = WrapCrossAlignment.center,
@ -143,6 +145,8 @@ class QuillToolbarConfigurations extends QuillSharedToolbarProperties {
return buttonOptions.base.globalIconSize * 2;
}
final QuillController controller;
/// A widget that will placed between each button in the toolbar
/// can be used as a spacer
/// it will not used before the first button

@ -155,8 +155,7 @@ class QuillEditor extends StatefulWidget {
factory QuillEditor.basic({
/// The configurations for the quill editor widget of flutter quill
QuillEditorConfigurations configurations =
const QuillEditorConfigurations(),
required QuillEditorConfigurations configurations,
FocusNode? focusNode,
ScrollController? scrollController,
}) {
@ -257,13 +256,13 @@ class QuillEditorState extends State<QuillEditor>
child: QuillRawEditor(
key: _editorKey,
configurations: QuillRawEditorConfigurations(
controller: context.requireQuillController,
controller: configurations.controller,
focusNode: widget.focusNode,
scrollController: widget.scrollController,
scrollable: configurations.scrollable,
scrollBottomInset: configurations.scrollBottomInset,
padding: configurations.padding,
isReadOnly: configurations.readOnly,
readOnly: configurations.readOnly,
placeholder: configurations.placeholder,
onLaunchUrl: configurations.onLaunchUrl,
contextMenuBuilder: showSelectionToolbar
@ -442,7 +441,7 @@ class _QuillEditorSelectionGestureDetectorBuilder
}
bool _isPositionSelected(TapUpDetails details) {
if (_state.context.requireQuillController.document.isEmpty()) {
if (_state.configurations.controller.document.isEmpty()) {
return false;
}
final pos = renderEditor!.getPositionForOffset(details.globalPosition);

@ -76,7 +76,7 @@ class QuillEditorDeleteTextAction<T extends DirectionalTextEditingIntent>
@override
bool get isActionEnabled =>
!state.widget.configurations.isReadOnly &&
!state.widget.configurations.readOnly &&
state.textEditingValue.selection.isValid;
}

@ -552,7 +552,7 @@ class QuillRawEditorState extends EditorState
controller.document.queryChild(controller.selection.baseOffset);
KeyEventResult insertTabCharacter() {
if (widget.configurations.isReadOnly) {
if (widget.configurations.readOnly) {
return KeyEventResult.ignored;
}
controller.replaceText(controller.selection.baseOffset, 0, '\t', null);
@ -662,7 +662,7 @@ class QuillRawEditorState extends EditorState
void _handleCheckboxTap(int offset, bool value) {
final requestKeyboardFocusOnCheckListChanged =
widget.configurations.requestKeyboardFocusOnCheckListChanged;
if (!widget.configurations.isReadOnly) {
if (!widget.configurations.readOnly) {
_disableScrollControllerAnimateOnce = true;
final currentSelection = controller.selection.copyWith();
final attribute = value ? Attribute.checked : Attribute.unchecked;
@ -737,7 +737,7 @@ class QuillRawEditorState extends EditorState
indentLevelCounts: indentLevelCounts,
clearIndents: clearIndents,
onCheckboxTap: _handleCheckboxTap,
readOnly: widget.configurations.isReadOnly,
readOnly: widget.configurations.readOnly,
customStyleBuilder: widget.configurations.customStyleBuilder,
customLinkPrefixes: widget.configurations.customLinkPrefixes,
);
@ -767,7 +767,7 @@ class QuillRawEditorState extends EditorState
customStyleBuilder: widget.configurations.customStyleBuilder,
customRecognizerBuilder: widget.configurations.customRecognizerBuilder,
styles: _styles!,
readOnly: widget.configurations.isReadOnly,
readOnly: widget.configurations.readOnly,
controller: controller,
linkActionPicker: _linkActionPicker,
onLaunchUrl: widget.configurations.onLaunchUrl,
@ -968,7 +968,7 @@ class QuillRawEditorState extends EditorState
if (!shouldCreateInputConnection) {
closeConnectionIfNeeded();
} else {
if (oldWidget.configurations.isReadOnly && _hasFocus) {
if (oldWidget.configurations.readOnly && _hasFocus) {
openConnectionIfNeeded();
}
}
@ -1298,7 +1298,7 @@ class QuillRawEditorState extends EditorState
_pastePlainText = controller.getPlainText();
_pasteStyleAndEmbed = controller.getAllIndividualSelectionStylesAndEmbed();
if (widget.configurations.isReadOnly) {
if (widget.configurations.readOnly) {
return;
}
final selection = textEditingValue.selection;
@ -1318,7 +1318,7 @@ class QuillRawEditorState extends EditorState
/// Paste text from [Clipboard].
@override
Future<void> pasteText(SelectionChangedCause cause) async {
if (widget.configurations.isReadOnly) {
if (widget.configurations.readOnly) {
return;
}

@ -171,7 +171,7 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
@override
bool get cutEnabled =>
widget.configurations.contextMenuBuilder != null &&
!widget.configurations.isReadOnly;
!widget.configurations.readOnly;
@override
bool get copyEnabled => widget.configurations.contextMenuBuilder != null;
@ -179,7 +179,7 @@ mixin RawEditorStateSelectionDelegateMixin on EditorState
@override
bool get pasteEnabled =>
widget.configurations.contextMenuBuilder != null &&
!widget.configurations.isReadOnly;
!widget.configurations.readOnly;
@override
bool get selectAllEnabled => widget.configurations.contextMenuBuilder != null;

@ -30,7 +30,7 @@ mixin RawEditorStateTextInputClientMixin on EditorState
/// - cmd/ctrl+a to select all.
/// - Changing the selection using a physical keyboard.
bool get shouldCreateInputConnection =>
kIsWeb || !widget.configurations.isReadOnly;
kIsWeb || !widget.configurations.readOnly;
/// Returns `true` if there is open input connection.
bool get hasConnection =>
@ -58,9 +58,9 @@ mixin RawEditorStateTextInputClientMixin on EditorState
this,
TextInputConfiguration(
inputType: TextInputType.multiline,
readOnly: widget.configurations.isReadOnly,
readOnly: widget.configurations.readOnly,
inputAction: widget.configurations.textInputAction,
enableSuggestions: !widget.configurations.isReadOnly,
enableSuggestions: !widget.configurations.readOnly,
keyboardAppearance: widget.configurations.keyboardAppearance ??
CupertinoTheme.maybeBrightnessOf(context) ??
Theme.of(context).brightness,

@ -1,7 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import '../../extensions/quill_provider.dart';
class QuillEditorCheckboxPoint extends StatefulWidget {
const QuillEditorCheckboxPoint({
@ -76,20 +73,6 @@ class QuillEditorCheckboxPointState extends State<QuillEditorCheckboxPoint> {
),
),
);
if (context.requireQuillSharedConfigurations.animationConfigurations
.checkBoxPointItem) {
return Animate(
effects: const [
SlideEffect(
duration: Duration(milliseconds: 70),
),
ScaleEffect(
duration: Duration(milliseconds: 70),
)
],
child: child,
);
}
return child;
}
}

@ -8,7 +8,6 @@ import '../../../../models/documents/style.dart';
import '../../../../models/themes/quill_icon_theme.dart';
import '../../../../utils/color.dart';
import '../../../controller.dart';
import '../../../utils/provider.dart';
import '../../base_toolbar.dart';
import 'dialog.dart';
@ -226,16 +225,14 @@ class QuillToolbarColorButtonState extends State<QuillToolbarColorButton> {
showDialog<String>(
context: context,
barrierColor: options.dialogBarrierColor ??
context.requireQuillSharedConfigurations.dialogBarrierColor,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: ColorPickerDialog(
isBackground: widget.isBackground,
onRequestChangeColor: _changeColor,
isToggledColor: _isToggledColor,
selectionStyle: _selectionStyle,
),
context.quillSharedConfigurations?.dialogBarrierColor ??
Colors.black54,
builder: (_) => FlutterQuillLocalizationsWidget(
child: ColorPickerDialog(
isBackground: widget.isBackground,
onRequestChangeColor: _changeColor,
isToggledColor: _isToggledColor,
selectionStyle: _selectionStyle,
),
),
);

@ -100,7 +100,8 @@ class QuillToolbarLinkStyleButtonState
Color get dialogBarrierColor {
return options.dialogBarrierColor ??
context.requireQuillSharedConfigurations.dialogBarrierColor;
context.quillSharedConfigurations?.dialogBarrierColor ??
Colors.black54;
}
RegExp? get linkRegExp {
@ -181,16 +182,13 @@ class QuillToolbarLinkStyleButtonState
final len = controller.selection.end - index;
text ??= len == 0 ? '' : controller.document.getPlainText(index, len);
return QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: _LinkDialog(
dialogTheme: options.dialogTheme,
link: link,
text: text,
linkRegExp: linkRegExp,
action: options.linkDialogAction,
),
return FlutterQuillLocalizationsWidget(
child: _LinkDialog(
dialogTheme: options.dialogTheme,
link: link,
text: text,
linkRegExp: linkRegExp,
action: options.linkDialogAction,
),
);
},

@ -107,7 +107,8 @@ class _QuillToolbarLinkStyleButton2State
Color get dialogBarrierColor {
return options.dialogBarrierColor ??
context.requireQuillSharedConfigurations.dialogBarrierColor;
context.quillSharedConfigurations?.dialogBarrierColor ??
Colors.black54;
}
@override
@ -173,22 +174,19 @@ class _QuillToolbarLinkStyleButton2State
final textLink = await showDialog<QuillTextLink>(
context: context,
barrierColor: dialogBarrierColor,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: LinkStyleDialog(
dialogTheme: options.dialogTheme,
text: initialTextLink.text,
link: initialTextLink.link,
constraints: options.constraints,
addLinkLabel: options.addLinkLabel,
editLinkLabel: options.editLinkLabel,
linkColor: options.linkColor,
childrenSpacing: options.childrenSpacing,
autovalidateMode: options.autovalidateMode,
validationMessage: options.validationMessage,
buttonSize: options.buttonSize,
),
builder: (_) => FlutterQuillLocalizationsWidget(
child: LinkStyleDialog(
dialogTheme: options.dialogTheme,
text: initialTextLink.text,
link: initialTextLink.link,
constraints: options.constraints,
addLinkLabel: options.addLinkLabel,
editLinkLabel: options.editLinkLabel,
linkColor: options.linkColor,
childrenSpacing: options.childrenSpacing,
autovalidateMode: options.autovalidateMode,
validationMessage: options.validationMessage,
buttonSize: options.buttonSize,
),
),
);

@ -63,12 +63,13 @@ class QuillToolbarSearchButton extends StatelessWidget {
Color _dialogBarrierColor(BuildContext context) {
return options.dialogBarrierColor ??
context.requireQuillSharedConfigurations.dialogBarrierColor;
context.quillSharedConfigurations?.dialogBarrierColor ??
Colors.black54;
}
QuillDialogTheme? _dialogTheme(BuildContext context) {
return options.dialogTheme ??
context.requireQuillSharedConfigurations.dialogTheme;
context.quillSharedConfigurations?.dialogTheme;
}
@override
@ -142,14 +143,11 @@ class QuillToolbarSearchButton extends StatelessWidget {
await showDialog<String>(
barrierColor: _dialogBarrierColor(context),
context: context,
builder: (_) => QuillProvider.value(
value: context.requireQuillProvider,
child: FlutterQuillLocalizationsWidget(
child: QuillToolbarSearchDialog(
controller: controller,
dialogTheme: _dialogTheme(context),
text: '',
),
builder: (_) => FlutterQuillLocalizationsWidget(
child: QuillToolbarSearchDialog(
controller: controller,
dialogTheme: _dialogTheme(context),
text: '',
),
),
);

@ -9,8 +9,8 @@ import 'base_toolbar.dart';
class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
const QuillToolbar({
required this.configurations,
super.key,
this.configurations = const QuillToolbarConfigurations(),
});
/// The configurations for the toolbar widget of flutter quill
@ -71,7 +71,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
toolbarConfigurations.buttonOptions.base.globalIconSize;
final axis = toolbarConfigurations.axis;
final globalController = context.requireQuillController;
final globalController = configurations.controller;
final spacerWidget =
configurations.spacerWidget ?? const SizedBox.shrink();
@ -270,7 +270,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget {
options: toolbarConfigurations.buttonOptions.direction,
controller: toolbarConfigurations
.buttonOptions.direction.controller ??
context.requireQuillController,
globalController,
),
spacerWidget,
],

@ -1,6 +1,6 @@
name: flutter_quill
description: A rich text editor built for the modern Android, iOS, web and desktop platforms. It is the WYSIWYG editor and a Quill component for Flutter.
version: 8.6.4
version: 9.0.0-dev
homepage: https://1o24bbs.com/c/bulletjournal/108/
repository: https://github.com/singerdmx/flutter-quill/
issue_tracker: https://github.com/singerdmx/flutter-quill/issues/
@ -50,7 +50,6 @@ dependencies:
characters: ^1.3.0
diff_match_patch: ^0.4.1
equatable: ^2.0.5
flutter_animate: ^4.2.0+1
meta: ^1.9.1
# Plugins

@ -16,19 +16,15 @@ void main() {
await tester.pumpWidget(
MaterialApp(
home: QuillProvider(
configurations: QuillConfigurations(
home: QuillToolbar(
configurations: QuillToolbarConfigurations(
controller: controller,
),
child: const QuillToolbar(
configurations: QuillToolbarConfigurations(
showRedo: false,
customButtons: [
QuillToolbarCustomButtonOptions(
tooltip: tooltip,
)
],
),
showRedo: false,
customButtons: const [
QuillToolbarCustomButtonOptions(
tooltip: tooltip,
)
],
),
),
),
@ -64,7 +60,8 @@ void main() {
controller = QuillController.basic();
editor = QuillEditor.basic(
// ignore: avoid_redundant_argument_values
configurations: const QuillEditorConfigurations(
configurations: QuillEditorConfigurations(
controller: controller,
// ignore: avoid_redundant_argument_values
readOnly: false,
),
@ -78,12 +75,9 @@ void main() {
testWidgets('Refocus editor after controller clears document',
(tester) async {
await tester.pumpWidget(
QuillProvider(
configurations: QuillConfigurations(controller: controller),
child: MaterialApp(
home: Column(
children: [editor],
),
MaterialApp(
home: Column(
children: [editor],
),
),
);
@ -99,12 +93,9 @@ void main() {
testWidgets('Refocus editor after removing block attribute',
(tester) async {
await tester.pumpWidget(QuillProvider(
configurations: QuillConfigurations(controller: controller),
child: MaterialApp(
home: Column(
children: [editor],
),
await tester.pumpWidget(MaterialApp(
home: Column(
children: [editor],
),
));
await tester.quillEnterText(find.byType(QuillEditor), 'test\n');
@ -120,12 +111,9 @@ void main() {
testWidgets('Tap checkbox in unfocused editor', (tester) async {
await tester.pumpWidget(
QuillProvider(
configurations: QuillConfigurations(controller: controller),
child: MaterialApp(
home: Column(
children: [editor],
),
MaterialApp(
home: Column(
children: [editor],
),
),
);

@ -21,15 +21,13 @@ void main() {
group('QuillEditor', () {
testWidgets('Keyboard entered text is stored in document', (tester) async {
await tester.pumpWidget(
QuillProvider(
configurations: QuillConfigurations(controller: controller),
child: MaterialApp(
home: QuillEditor.basic(
MaterialApp(
home: QuillEditor.basic(
// ignore: avoid_redundant_argument_values
configurations: QuillEditorConfigurations(
controller: controller,
// ignore: avoid_redundant_argument_values
configurations: const QuillEditorConfigurations(
// ignore: avoid_redundant_argument_values
readOnly: false,
),
readOnly: false,
),
),
),
@ -43,24 +41,20 @@ void main() {
String? latestUri;
await tester.pumpWidget(
MaterialApp(
home: QuillProvider(
configurations: QuillConfigurations(
home: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
configurations: QuillEditorConfigurations(
controller: controller,
),
child: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
configurations: QuillEditorConfigurations(
// ignore: avoid_redundant_argument_values
readOnly: false,
autoFocus: true,
expands: true,
contentInsertionConfiguration: ContentInsertionConfiguration(
onContentInserted: (content) {
latestUri = content.uri;
},
allowedMimeTypes: <String>['image/gif'],
),
// ignore: avoid_redundant_argument_values
readOnly: false,
autoFocus: true,
expands: true,
contentInsertionConfiguration: ContentInsertionConfiguration(
onContentInserted: (content) {
latestUri = content.uri;
},
allowedMimeTypes: <String>['image/gif'],
),
),
),
@ -120,21 +114,17 @@ void main() {
testWidgets('custom context menu builder', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: QuillProvider(
configurations: QuillConfigurations(
home: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
// ignore: avoid_redundant_argument_values
configurations: QuillEditorConfigurations(
controller: controller,
),
child: QuillEditor(
focusNode: FocusNode(),
scrollController: ScrollController(),
// ignore: avoid_redundant_argument_values
configurations: QuillEditorConfigurations(
// ignore: avoid_redundant_argument_values
readOnly: false,
autoFocus: true,
expands: true,
contextMenuBuilder: customBuilder,
),
readOnly: false,
autoFocus: true,
expands: true,
contextMenuBuilder: customBuilder,
),
),
),

Loading…
Cancel
Save