From e7e71f1cb2824d92da03a34fc3f15a33e5c35a0d Mon Sep 17 00:00:00 2001 From: Ellet <73608287+freshtechtips@users.noreply.github.com> Date: Fri, 10 Nov 2023 01:29:37 +0300 Subject: [PATCH] Update QuillCustomButton (#1517) * Update QuillCustomButton * Update README.md --- CHANGELOG.md | 6 ++ README.md | 34 +++---- example/lib/pages/home_page.dart | 23 +++++ flutter_quill_test/CHANGELOG.md | 3 + flutter_quill_test/pubspec.yaml | 2 +- .../config/toolbar/base_configurations.dart | 3 +- .../config/toolbar/buttons/custom_button.dart | 32 ++++++ .../models/config/toolbar/configurations.dart | 10 +- .../models/themes/quill_custom_button.dart | 38 ++++---- .../toolbar/buttons/custom_button.dart | 97 ++++++++++++++----- lib/src/widgets/toolbar/toolbar.dart | 71 ++++++++------ pubspec.yaml | 2 +- test/bug_fix_test.dart | 8 +- 13 files changed, 227 insertions(+), 102 deletions(-) create mode 100644 lib/src/models/config/toolbar/buttons/custom_button.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index a2a037c6..2c73ec2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [8.4.0] +- **Breaking change**: Update the `QuillCustomButton` to have `QuillCustomButtonOptions`. We moved everything that is in the `QuillCustomButton` to `QuillCustomButtonOptions` but replaced the `iconData` with `icon` widget for more customizations +- **Breaking change**: the `customButtons` in the `QuillToolbarConfigurations` is now of type `List` +- Bug fixes with the new `8.0.0` update +- Update `README.md` + ## [8.3.0] - Added a `iconButtonFactor` property to `QuillToolbarBaseButtonOptions` to customise how big the button is compared to its icon size (defaults to `kIconButtonFactor` which is the same as previous releases) diff --git a/README.md b/README.md index 7d2892e2..9bc98324 100644 --- a/README.md +++ b/README.md @@ -199,17 +199,17 @@ To use your own fonts, update your [assets folder](https://github.com/singerdmx/ ### Custom Buttons -You may add custom buttons to the _end_ of the toolbar, via the `customButtons` option, which is a `List` of `QuillCustomButton`. +You may add custom buttons to the _end_ of the toolbar, via the `customButtons` option, which is a `List` of `QuillToolbarCustomButtonOptions`. -To add an Icon, we should use a new QuillCustomButton class +To add an Icon, we should use a new `QuillToolbarCustomButtonOptions` class ```dart - QuillCustomButton( - iconData: Icons.ac_unit, - onTap: () { - debugPrint('snowflake'); - } - ), + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + tooltip: '', + onPressed: () {}, + afterButtonPressed: () {}, + ), ``` Each `QuillCustomButton` is used as part of the `customButtons` option as follows: @@ -218,21 +218,21 @@ Each `QuillCustomButton` is used as part of the `customButtons` option as follow QuillToolbar( configurations: QuillToolbarConfigurations( customButtons: [ - QuillCustomButton( - iconData: Icons.ac_unit, - onTap: () { + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { debugPrint('snowflake1'); }, ), - QuillCustomButton( - iconData: Icons.ac_unit, - onTap: () { + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { debugPrint('snowflake2'); }, ), - QuillCustomButton( - iconData: Icons.ac_unit, - onTap: () { + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { debugPrint('snowflake3'); }, ), diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index a1c71d06..538e8f40 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -457,9 +457,30 @@ class _HomePageState extends State { } QuillToolbar get quillToolbar { + final customButtons = [ + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { + debugPrint('snowflake1'); + }, + ), + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { + debugPrint('snowflake2'); + }, + ), + QuillToolbarCustomButtonOptions( + icon: const Icon(Icons.ac_unit), + onPressed: () { + debugPrint('snowflake3'); + }, + ), + ]; if (kIsWeb) { return QuillToolbar( configurations: QuillToolbarConfigurations( + customButtons: customButtons, embedButtons: FlutterQuillEmbeds.toolbarButtons( imageButtonOptions: QuillToolbarImageButtonOptions( imageButtonConfigurations: QuillToolbarImageConfigurations( @@ -482,6 +503,7 @@ class _HomePageState extends State { if (isDesktop()) { return QuillToolbar( configurations: QuillToolbarConfigurations( + customButtons: customButtons, embedButtons: FlutterQuillEmbeds.toolbarButtons( imageButtonOptions: QuillToolbarImageButtonOptions( imageButtonConfigurations: QuillToolbarImageConfigurations( @@ -502,6 +524,7 @@ class _HomePageState extends State { } return QuillToolbar( configurations: QuillToolbarConfigurations( + customButtons: customButtons, embedButtons: FlutterQuillEmbeds.toolbarButtons( videoButtonOptions: QuillToolbarVideoButtonOptions( videoConfigurations: QuillToolbarVideoConfigurations( diff --git a/flutter_quill_test/CHANGELOG.md b/flutter_quill_test/CHANGELOG.md index ac01b9bc..60aa40e3 100644 --- a/flutter_quill_test/CHANGELOG.md +++ b/flutter_quill_test/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.0.4+1 +* Update `README.md` + ## 0.0.4 * Update `README.md` * Documentation comments. diff --git a/flutter_quill_test/pubspec.yaml b/flutter_quill_test/pubspec.yaml index 1cb77744..8fa7094e 100644 --- a/flutter_quill_test/pubspec.yaml +++ b/flutter_quill_test/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_quill_test description: Test utilities for flutter_quill which includes methods to simplify interacting with the editor in test cases. -version: 0.0.4 +version: 0.0.4+1 homepage: https://1o24bbs.com/c/bulletjournal/108 repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_test diff --git a/lib/src/models/config/toolbar/base_configurations.dart b/lib/src/models/config/toolbar/base_configurations.dart index 132fdc8d..1c4d1ff3 100644 --- a/lib/src/models/config/toolbar/base_configurations.dart +++ b/lib/src/models/config/toolbar/base_configurations.dart @@ -4,7 +4,6 @@ import 'package:flutter/widgets.dart' import '../../../widgets/toolbar/base_toolbar.dart'; import '../../structs/link_dialog_action.dart'; -import '../../themes/quill_custom_button.dart'; @immutable class QuillBaseToolbarConfigurations extends Equatable { @@ -41,7 +40,7 @@ class QuillBaseToolbarConfigurations extends Equatable { final Color? color; /// List of custom buttons - final List customButtons; + final List customButtons; /// The color to use when painting the toolbar section divider. /// diff --git a/lib/src/models/config/toolbar/buttons/custom_button.dart b/lib/src/models/config/toolbar/buttons/custom_button.dart new file mode 100644 index 00000000..9a862e83 --- /dev/null +++ b/lib/src/models/config/toolbar/buttons/custom_button.dart @@ -0,0 +1,32 @@ +import 'package:flutter/widgets.dart' show VoidCallback, Widget; + +import 'base.dart'; + +class QuillToolbarCustomButtonExtraOptions + extends QuillToolbarBaseButtonExtraOptions { + const QuillToolbarCustomButtonExtraOptions({ + required super.controller, + required super.context, + required super.onPressed, + }); +} + +class QuillToolbarCustomButtonOptions extends QuillToolbarBaseButtonOptions< + QuillToolbarBaseButtonOptions, QuillToolbarCustomButtonExtraOptions> { + const QuillToolbarCustomButtonOptions({ + this.icon, + this.iconButtonFactor, + this.iconSize, + super.afterButtonPressed, + super.tooltip, + super.iconTheme, + super.childBuilder, + super.controller, + this.onPressed, + }); + + final double? iconButtonFactor; + final double? iconSize; + final VoidCallback? onPressed; + final Widget? icon; +} diff --git a/lib/src/models/config/toolbar/configurations.dart b/lib/src/models/config/toolbar/configurations.dart index 00412042..c609cd80 100644 --- a/lib/src/models/config/toolbar/configurations.dart +++ b/lib/src/models/config/toolbar/configurations.dart @@ -2,15 +2,15 @@ import 'package:equatable/equatable.dart'; import 'package:flutter/foundation.dart' show immutable; import 'package:flutter/widgets.dart' show Axis, Color, Decoration, Widget, WrapAlignment, WrapCrossAlignment; -import '../../../widgets/embeds.dart'; +import '../../../widgets/embeds.dart'; import '../../structs/link_dialog_action.dart'; -import '../../themes/quill_custom_button.dart'; import '../../themes/quill_dialog_theme.dart'; import '../../themes/quill_icon_theme.dart'; import 'buttons/base.dart'; import 'buttons/clear_format.dart'; import 'buttons/color.dart'; +import 'buttons/custom_button.dart'; import 'buttons/font_family.dart'; import 'buttons/font_size.dart'; import 'buttons/history.dart'; @@ -26,6 +26,7 @@ export './../../../widgets/toolbar/buttons/search/search_dialog.dart'; export './buttons/base.dart'; export './buttons/clear_format.dart'; export './buttons/color.dart'; +export './buttons/custom_button.dart'; export './buttons/font_family.dart'; export './buttons/font_size.dart'; export './buttons/history.dart'; @@ -211,7 +212,7 @@ class QuillToolbarConfigurations extends Equatable { final bool showSearchButton; final bool showSubscript; final bool showSuperscript; - final List customButtons; + final List customButtons; /// The decoration to use for the toolbar. final Decoration? decoration; @@ -284,6 +285,7 @@ class QuillToolbarButtonOptions extends Equatable { this.selectHeaderStyleButtons = const QuillToolbarSelectHeaderStyleButtonsOptions(), this.linkStyle = const QuillToolbarLinkStyleButtonOptions(), + this.customButtons = const QuillToolbarCustomButtonOptions(), }); /// The base configurations for all the buttons which will apply to all @@ -329,6 +331,8 @@ class QuillToolbarButtonOptions extends Equatable { final QuillToolbarLinkStyleButtonOptions linkStyle; + final QuillToolbarCustomButtonOptions customButtons; + @override List get props => [ base, diff --git a/lib/src/models/themes/quill_custom_button.dart b/lib/src/models/themes/quill_custom_button.dart index da1eb06d..111ab13e 100644 --- a/lib/src/models/themes/quill_custom_button.dart +++ b/lib/src/models/themes/quill_custom_button.dart @@ -1,26 +1,22 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import '../../widgets/toolbar/base_toolbar.dart'; +// import '../../widgets/toolbar/base_toolbar.dart'; -class QuillCustomButton extends QuillToolbarBaseButtonOptions { - const QuillCustomButton({ - super.iconData, - this.iconColor, - this.onTap, - super.tooltip, - this.iconSize, - this.child, - super.iconTheme, - }); +// class QuillCustomButton extends QuillToolbarBaseButtonOptions { +// const QuillCustomButton({ +// this.icon, +// this.onTap, +// super.tooltip, +// this.child, +// super.iconTheme, +// }); - ///The icon color; - final Color? iconColor; +// /// The icon widget +// final Widget? icon; - ///The function when the icon is tapped - final VoidCallback? onTap; +// /// The function when the icon is tapped +// final VoidCallback? onTap; - ///The customButton placeholder - final Widget? child; - - final double? iconSize; -} +// /// The customButton placeholder +// final Widget? child; +// } diff --git a/lib/src/widgets/toolbar/buttons/custom_button.dart b/lib/src/widgets/toolbar/buttons/custom_button.dart index 741a6e7e..0d736a10 100644 --- a/lib/src/widgets/toolbar/buttons/custom_button.dart +++ b/lib/src/widgets/toolbar/buttons/custom_button.dart @@ -1,43 +1,92 @@ import 'package:flutter/material.dart'; import '../../../models/themes/quill_icon_theme.dart'; +import '../../../utils/extensions/build_context.dart'; +import '../../controller.dart'; import '../base_toolbar.dart'; -class CustomButton extends StatelessWidget { - const CustomButton({ - required this.onPressed, - required this.icon, - this.iconColor, - this.iconSize = kDefaultIconSize, - this.iconButtonFactor = kIconButtonFactor, - this.iconTheme, - this.afterButtonPressed, - this.tooltip, +class QuillToolbarCustomButton extends StatelessWidget { + const QuillToolbarCustomButton({ + required this.options, + required this.controller, super.key, }); - final VoidCallback? onPressed; - final IconData? icon; - final Color? iconColor; - final double iconSize; - final double iconButtonFactor; - final QuillIconTheme? iconTheme; - final VoidCallback? afterButtonPressed; - final String? tooltip; + final QuillController controller; + final QuillToolbarCustomButtonOptions options; + + double _iconSize(BuildContext context) { + final baseFontSize = baseButtonExtraOptions(context).globalIconSize; + final iconSize = options.iconSize; + return iconSize ?? baseFontSize; + } + + double _iconButtonFactor(BuildContext context) { + final baseIconFactor = + baseButtonExtraOptions(context).globalIconButtonFactor; + final iconButtonFactor = options.iconButtonFactor; + return iconButtonFactor ?? baseIconFactor; + } + + VoidCallback? _afterButtonPressed(BuildContext context) { + return options.afterButtonPressed ?? + baseButtonExtraOptions(context).afterButtonPressed; + } + + QuillIconTheme? _iconTheme(BuildContext context) { + return options.iconTheme ?? baseButtonExtraOptions(context).iconTheme; + } + + QuillToolbarBaseButtonOptions baseButtonExtraOptions(BuildContext context) { + return context.requireQuillToolbarBaseButtonOptions; + } + + String? _tooltip(BuildContext context) { + return options.tooltip ?? baseButtonExtraOptions(context).tooltip; + } + + void _onPressed(BuildContext context) { + options.onPressed?.call(); + _afterButtonPressed(context)?.call(); + } @override Widget build(BuildContext context) { - final theme = Theme.of(context); + final iconTheme = _iconTheme(context); + final tooltip = _tooltip(context); + final iconSize = _iconSize(context); + final iconButtonFactor = _iconButtonFactor(context); + + final childBuilder = + options.childBuilder ?? baseButtonExtraOptions(context).childBuilder; + final afterButtonPressed = _afterButtonPressed(context); - final iconColor = iconTheme?.iconUnselectedColor ?? theme.iconTheme.color; + if (childBuilder != null) { + return childBuilder( + QuillToolbarCustomButtonOptions( + iconButtonFactor: iconButtonFactor, + iconSize: iconSize, + afterButtonPressed: afterButtonPressed, + controller: controller, + iconTheme: iconTheme, + tooltip: tooltip, + icon: options.icon, + ), + QuillToolbarCustomButtonExtraOptions( + context: context, + controller: controller, + onPressed: () => _onPressed(context), + ), + ); + } + + final theme = Theme.of(context); return QuillToolbarIconButton( - highlightElevation: 0, - hoverElevation: 0, size: iconSize * iconButtonFactor, - icon: Icon(icon, size: iconSize, color: iconColor), + icon: options.icon, tooltip: tooltip, borderRadius: iconTheme?.borderRadius ?? 2, - onPressed: onPressed, + onPressed: () => _onPressed(context), afterPressed: afterButtonPressed, fillColor: iconTheme?.iconUnselectedFillColor ?? theme.canvasColor, ); diff --git a/lib/src/widgets/toolbar/toolbar.dart b/lib/src/widgets/toolbar/toolbar.dart index 6749f0b5..1361e550 100644 --- a/lib/src/widgets/toolbar/toolbar.dart +++ b/lib/src/widgets/toolbar/toolbar.dart @@ -59,8 +59,6 @@ class QuillToolbar extends StatelessWidget { sectionDividerSpace: configurations.sectionDividerSpace, toolbarSize: configurations.toolbarSize, childrenBuilder: (context) { - final controller = context.requireQuillController; - final toolbarConfigurations = context.requireQuillToolbarConfigurations; @@ -192,7 +190,9 @@ class QuillToolbar extends StatelessWidget { ], if (configurations.showColorButton) ...[ QuillToolbarColorButton( - controller: controller, + controller: + toolbarConfigurations.buttonOptions.color.controller ?? + globalController, isBackground: false, options: toolbarConfigurations.buttonOptions.color, ), @@ -201,14 +201,18 @@ class QuillToolbar extends StatelessWidget { if (configurations.showBackgroundColorButton) ...[ QuillToolbarColorButton( options: toolbarConfigurations.buttonOptions.backgroundColor, - controller: controller, + controller: + toolbarConfigurations.buttonOptions.color.controller ?? + globalController, isBackground: true, ), spacerWidget, ], if (configurations.showClearFormat) ...[ QuillToolbarClearFormatButton( - controller: controller, + controller: toolbarConfigurations + .buttonOptions.clearFormat.controller ?? + globalController, options: toolbarConfigurations.buttonOptions.clearFormat, ), spacerWidget, @@ -216,7 +220,7 @@ class QuillToolbar extends StatelessWidget { if (theEmbedButtons != null) for (final builder in theEmbedButtons) builder( - controller, + globalController, globalIconSize, context.requireQuillToolbarBaseButtonOptions.iconTheme, configurations.dialogTheme), @@ -234,7 +238,9 @@ class QuillToolbar extends StatelessWidget { ), if (configurations.showAlignmentButtons) ...[ QuillToolbarSelectAlignmentButton( - controller: controller, + controller: toolbarConfigurations + .buttonOptions.selectAlignmentButtons.controller ?? + globalController, options: toolbarConfigurations .buttonOptions.selectAlignmentButtons, // tooltips: Map.of(buttonTooltips) @@ -274,7 +280,9 @@ class QuillToolbar extends StatelessWidget { ), if (configurations.showHeaderStyle) ...[ QuillToolbarSelectHeaderStyleButtons( - controller: controller, + controller: toolbarConfigurations + .buttonOptions.selectHeaderStyleButtons.controller ?? + globalController, options: toolbarConfigurations .buttonOptions.selectHeaderStyleButtons, ), @@ -379,14 +387,18 @@ class QuillToolbar extends StatelessWidget { ), if (configurations.showLink) ...[ QuillToolbarLinkStyleButton( - controller: controller, + controller: toolbarConfigurations + .buttonOptions.linkStyle.controller ?? + globalController, options: toolbarConfigurations.buttonOptions.linkStyle, ), spacerWidget, ], if (configurations.showSearchButton) ...[ QuillToolbarSearchButton( - controller: controller, + controller: + toolbarConfigurations.buttonOptions.search.controller ?? + globalController, options: toolbarConfigurations.buttonOptions.search, ), spacerWidget, @@ -399,27 +411,24 @@ class QuillToolbar extends StatelessWidget { space: configurations.sectionDividerSpace, ), for (final customButton in configurations.customButtons) - if (customButton.child != null) ...[ - InkWell( - onTap: customButton.onTap, - child: customButton.child, - ), - ] else ...[ - CustomButton( - onPressed: customButton.onTap, - icon: customButton.iconData ?? - context.quillToolbarBaseButtonOptions?.iconData, - iconColor: customButton.iconColor, - iconSize: customButton.iconSize ?? globalIconSize, - iconTheme: context - .requireQuillToolbarBaseButtonOptions.iconTheme, - afterButtonPressed: customButton.afterButtonPressed ?? - context.quillToolbarBaseButtonOptions - ?.afterButtonPressed, - tooltip: customButton.tooltip ?? - context.quillToolbarBaseButtonOptions?.tooltip, - ), - ], + QuillToolbarCustomButton( + options: customButton, + controller: customButton.controller ?? globalController, + ), + // if (customButton.child != null) ...[ + // InkWell( + // onTap: customButton.onTap, + // child: customButton.child, + // ), + // ] else ...[ + // QuillToolbarCustomButton( + // options: + // toolbarConfigurations.buttonOptions.customButtons, + // controller: toolbarConfigurations + // .buttonOptions.customButtons.controller ?? + // globalController, + // ), + // ], spacerWidget, ], ]; diff --git a/pubspec.yaml b/pubspec.yaml index 2eb967b1..8cbbdbc7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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.3.0 +version: 8.4.0 homepage: https://1o24bbs.com/c/bulletjournal/108 repository: https://github.com/singerdmx/flutter-quill diff --git a/test/bug_fix_test.dart b/test/bug_fix_test.dart index 041b7d2f..81849459 100644 --- a/test/bug_fix_test.dart +++ b/test/bug_fix_test.dart @@ -12,17 +12,21 @@ void main() { (tester) async { const tooltip = 'custom button'; + final controller = QuillController.basic(); + await tester.pumpWidget( MaterialApp( home: QuillProvider( configurations: QuillConfigurations( - controller: QuillController.basic(), + controller: controller, ), child: const QuillToolbar( configurations: QuillToolbarConfigurations( showRedo: false, customButtons: [ - QuillCustomButton(tooltip: tooltip), + QuillToolbarCustomButtonOptions( + tooltip: tooltip, + ) ], ), ),