From 97375b5262f2dcc895b43cefe9a726a1b935fc8a Mon Sep 17 00:00:00 2001 From: Jonathan Salmon Date: Sat, 3 Sep 2022 01:12:03 +0100 Subject: [PATCH] Moved embed toolbar items out --- example/lib/pages/home_page.dart | 32 +++-- example/lib/widgets/demo_scaffold.dart | 11 +- lib/flutter_quill.dart | 2 + lib/src/embeds/default_embed_builder.dart | 13 -- lib/src/embeds/default_embed_toolbar.dart | 111 ++++++++++++++++++ lib/src/embeds/embed_types.dart | 20 ++++ lib/src/embeds/toolbar/camera_button.dart | 1 + lib/src/embeds/toolbar/formula_button.dart | 1 + lib/src/embeds/toolbar/image_button.dart | 1 + lib/src/embeds/toolbar/image_video_utils.dart | 9 +- lib/src/embeds/toolbar/video_button.dart | 1 + lib/src/widgets/toolbar.dart | 78 ++---------- 12 files changed, 172 insertions(+), 108 deletions(-) create mode 100644 lib/src/embeds/default_embed_toolbar.dart create mode 100644 lib/src/embeds/embed_types.dart diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index 7f1d120c..4e1d77fd 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -152,30 +152,36 @@ class _HomePageState extends State { } var toolbar = QuillToolbar.basic( controller: _controller!, - // provide a callback to enable picking images from device. - // if omit, "image" button only allows adding images from url. - // same goes for videos. - onImagePickCallback: _onImagePickCallback, - onVideoPickCallback: _onVideoPickCallback, - // uncomment to provide a custom "pick from" dialog. - // mediaPickSettingSelector: _selectMediaPickSetting, - // uncomment to provide a custom "pick from" dialog. - // cameraPickSettingSelector: _selectCameraPickSetting, + embedToolbar: EmbedToolbar( + // provide a callback to enable picking images from device. + // if omit, "image" button only allows adding images from url. + // same goes for videos. + onImagePickCallback: _onImagePickCallback, + onVideoPickCallback: _onVideoPickCallback, + // uncomment to provide a custom "pick from" dialog. + // mediaPickSettingSelector: _selectMediaPickSetting, + // uncomment to provide a custom "pick from" dialog. + // cameraPickSettingSelector: _selectCameraPickSetting, + ), showAlignmentButtons: true, ); if (kIsWeb) { toolbar = QuillToolbar.basic( controller: _controller!, - onImagePickCallback: _onImagePickCallback, - webImagePickImpl: _webImagePickImpl, + embedToolbar: EmbedToolbar( + onImagePickCallback: _onImagePickCallback, + webImagePickImpl: _webImagePickImpl, + ), showAlignmentButtons: true, ); } if (_isDesktop()) { toolbar = QuillToolbar.basic( controller: _controller!, - onImagePickCallback: _onImagePickCallback, - filePickImpl: openFileSystemPickerForDesktop, + embedToolbar: EmbedToolbar( + onImagePickCallback: _onImagePickCallback, + filePickImpl: openFileSystemPickerForDesktop, + ), showAlignmentButtons: true, ); } diff --git a/example/lib/widgets/demo_scaffold.dart b/example/lib/widgets/demo_scaffold.dart index 50b9ddc6..87ce2f96 100644 --- a/example/lib/widgets/demo_scaffold.dart +++ b/example/lib/widgets/demo_scaffold.dart @@ -89,11 +89,16 @@ class _DemoScaffoldState extends State { return const Scaffold(body: Center(child: Text('Loading...'))); } final actions = widget.actions ?? []; - var toolbar = QuillToolbar.basic(controller: _controller!); + var toolbar = QuillToolbar.basic( + controller: _controller!, + embedToolbar: EmbedToolbar(), + ); if (_isDesktop()) { toolbar = QuillToolbar.basic( - controller: _controller!, - filePickImpl: openFileSystemPickerForDesktop); + controller: _controller!, + embedToolbar: + EmbedToolbar(filePickImpl: openFileSystemPickerForDesktop), + ); } return Scaffold( key: _scaffoldKey, diff --git a/lib/flutter_quill.dart b/lib/flutter_quill.dart index cad8fcbe..133d4f64 100644 --- a/lib/flutter_quill.dart +++ b/lib/flutter_quill.dart @@ -1,6 +1,8 @@ library flutter_quill; export 'src/embeds/default_embed_builder.dart'; +export 'src/embeds/default_embed_toolbar.dart'; +export 'src/embeds/embed_types.dart'; export 'src/embeds/widgets/image.dart'; export 'src/models/documents/attribute.dart'; export 'src/models/documents/document.dart'; diff --git a/lib/src/embeds/default_embed_builder.dart b/lib/src/embeds/default_embed_builder.dart index a813abfc..df7955b5 100644 --- a/lib/src/embeds/default_embed_builder.dart +++ b/lib/src/embeds/default_embed_builder.dart @@ -1,5 +1,3 @@ -import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -16,7 +14,6 @@ import '../utils/embeds.dart'; import '../utils/platform.dart'; import '../utils/string.dart'; import '../widgets/controller.dart'; -import 'toolbar/image_video_utils.dart'; import 'widgets/image.dart'; import 'widgets/image_resizer.dart'; import 'widgets/video_app.dart'; @@ -26,16 +23,6 @@ export 'toolbar/image_button.dart'; export 'toolbar/image_video_utils.dart'; export 'toolbar/video_button.dart'; -typedef OnImagePickCallback = Future Function(File file); -typedef OnVideoPickCallback = Future Function(File file); -typedef FilePickImpl = Future Function(BuildContext context); -typedef WebImagePickImpl = Future Function( - OnImagePickCallback onImagePickCallback); -typedef WebVideoPickImpl = Future Function( - OnVideoPickCallback onImagePickCallback); -typedef MediaPickSettingSelector = Future Function( - BuildContext context); - abstract class IEmbedBuilder { String get key; diff --git a/lib/src/embeds/default_embed_toolbar.dart b/lib/src/embeds/default_embed_toolbar.dart new file mode 100644 index 00000000..8de64ddc --- /dev/null +++ b/lib/src/embeds/default_embed_toolbar.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; + +import '../models/themes/quill_dialog_theme.dart'; +import '../models/themes/quill_icon_theme.dart'; +import '../widgets/controller.dart'; +import 'embed_types.dart'; +import 'toolbar/camera_button.dart'; +import 'toolbar/formula_button.dart'; +import 'toolbar/image_button.dart'; +import 'toolbar/video_button.dart'; + +abstract class IEmbedToolbar { + Iterable build(QuillController controller, double toolbarIconSize, + QuillIconTheme? iconTheme, QuillDialogTheme? dialogTheme); + + bool get notEmpty; +} + +class EmbedToolbar implements IEmbedToolbar { + EmbedToolbar({ + this.showImageButton = true, + this.showVideoButton = true, + this.showCameraButton = true, + this.showFormulaButton = false, + this.onImagePickCallback, + this.onVideoPickCallback, + this.mediaPickSettingSelector, + this.cameraPickSettingSelector, + this.filePickImpl, + this.webImagePickImpl, + this.webVideoPickImpl, + }); + + final bool showImageButton; + final bool showVideoButton; + final bool showCameraButton; + final bool showFormulaButton; + + final OnImagePickCallback? onImagePickCallback; + final OnVideoPickCallback? onVideoPickCallback; + final MediaPickSettingSelector? mediaPickSettingSelector; + final MediaPickSettingSelector? cameraPickSettingSelector; + final FilePickImpl? filePickImpl; + final WebImagePickImpl? webImagePickImpl; + final WebVideoPickImpl? webVideoPickImpl; + + @override + bool get notEmpty => + showImageButton || + showVideoButton || + (showCameraButton && + (onImagePickCallback != null || onVideoPickCallback != null)) || + showFormulaButton; + + @override + Iterable build(QuillController controller, double toolbarIconSize, + QuillIconTheme? iconTheme, QuillDialogTheme? dialogTheme) { + return [ + if (showImageButton) + ImageButton( + icon: Icons.image, + iconSize: toolbarIconSize, + controller: controller, + onImagePickCallback: onImagePickCallback, + filePickImpl: filePickImpl, + webImagePickImpl: webImagePickImpl, + mediaPickSettingSelector: mediaPickSettingSelector, + iconTheme: iconTheme, + dialogTheme: dialogTheme, + ), + if (showVideoButton) + VideoButton( + icon: Icons.movie_creation, + iconSize: toolbarIconSize, + controller: controller, + onVideoPickCallback: onVideoPickCallback, + filePickImpl: filePickImpl, + webVideoPickImpl: webImagePickImpl, + mediaPickSettingSelector: mediaPickSettingSelector, + iconTheme: iconTheme, + dialogTheme: dialogTheme, + ), + if ((onImagePickCallback != null || onVideoPickCallback != null) && + showCameraButton) + CameraButton( + icon: Icons.photo_camera, + iconSize: toolbarIconSize, + controller: controller, + onImagePickCallback: onImagePickCallback, + onVideoPickCallback: onVideoPickCallback, + filePickImpl: filePickImpl, + webImagePickImpl: webImagePickImpl, + webVideoPickImpl: webVideoPickImpl, + cameraPickSettingSelector: cameraPickSettingSelector, + iconTheme: iconTheme, + ), + if (showFormulaButton) + FormulaButton( + icon: Icons.functions, + iconSize: toolbarIconSize, + controller: controller, + onImagePickCallback: onImagePickCallback, + filePickImpl: filePickImpl, + webImagePickImpl: webImagePickImpl, + mediaPickSettingSelector: mediaPickSettingSelector, + iconTheme: iconTheme, + dialogTheme: dialogTheme, + ) + ]; + } +} diff --git a/lib/src/embeds/embed_types.dart b/lib/src/embeds/embed_types.dart new file mode 100644 index 00000000..814b77b6 --- /dev/null +++ b/lib/src/embeds/embed_types.dart @@ -0,0 +1,20 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; + +typedef OnImagePickCallback = Future Function(File file); +typedef OnVideoPickCallback = Future Function(File file); +typedef FilePickImpl = Future Function(BuildContext context); +typedef WebImagePickImpl = Future Function( + OnImagePickCallback onImagePickCallback); +typedef WebVideoPickImpl = Future Function( + OnVideoPickCallback onImagePickCallback); +typedef MediaPickSettingSelector = Future Function( + BuildContext context); + +enum MediaPickSetting { + Gallery, + Link, + Camera, + Video, +} diff --git a/lib/src/embeds/toolbar/camera_button.dart b/lib/src/embeds/toolbar/camera_button.dart index 6bd841d7..a6f6d89d 100644 --- a/lib/src/embeds/toolbar/camera_button.dart +++ b/lib/src/embeds/toolbar/camera_button.dart @@ -6,6 +6,7 @@ import '../../translations/toolbar.i18n.dart'; import '../../widgets/controller.dart'; import '../../widgets/toolbar.dart'; import '../default_embed_builder.dart'; +import '../embed_types.dart'; import 'image_video_utils.dart'; class CameraButton extends StatelessWidget { diff --git a/lib/src/embeds/toolbar/formula_button.dart b/lib/src/embeds/toolbar/formula_button.dart index 51d1d4f7..fb7b5b5e 100644 --- a/lib/src/embeds/toolbar/formula_button.dart +++ b/lib/src/embeds/toolbar/formula_button.dart @@ -6,6 +6,7 @@ import '../../models/themes/quill_icon_theme.dart'; import '../../widgets/controller.dart'; import '../../widgets/toolbar.dart'; import '../default_embed_builder.dart'; +import '../embed_types.dart'; class FormulaButton extends StatelessWidget { const FormulaButton({ diff --git a/lib/src/embeds/toolbar/image_button.dart b/lib/src/embeds/toolbar/image_button.dart index 5b73aa13..6774221a 100644 --- a/lib/src/embeds/toolbar/image_button.dart +++ b/lib/src/embeds/toolbar/image_button.dart @@ -7,6 +7,7 @@ import '../../models/themes/quill_icon_theme.dart'; import '../../widgets/controller.dart'; import '../../widgets/toolbar.dart'; import '../default_embed_builder.dart'; +import '../embed_types.dart'; import 'image_video_utils.dart'; class ImageButton extends StatelessWidget { diff --git a/lib/src/embeds/toolbar/image_video_utils.dart b/lib/src/embeds/toolbar/image_video_utils.dart index 7a6a6ba5..422c73bd 100644 --- a/lib/src/embeds/toolbar/image_video_utils.dart +++ b/lib/src/embeds/toolbar/image_video_utils.dart @@ -10,7 +10,7 @@ import '../../models/themes/quill_dialog_theme.dart'; import '../../translations/toolbar.i18n.dart'; import '../../utils/platform.dart'; import '../../widgets/controller.dart'; -import '../default_embed_builder.dart'; +import '../embed_types.dart'; class LinkDialog extends StatefulWidget { const LinkDialog({this.dialogTheme, this.link, Key? key}) : super(key: key); @@ -75,13 +75,6 @@ class LinkDialogState extends State { } } -enum MediaPickSetting { - Gallery, - Link, - Camera, - Video, -} - class ImageVideoUtils { static Future selectMediaPickSetting( BuildContext context, diff --git a/lib/src/embeds/toolbar/video_button.dart b/lib/src/embeds/toolbar/video_button.dart index aed4e9fd..fd59e728 100644 --- a/lib/src/embeds/toolbar/video_button.dart +++ b/lib/src/embeds/toolbar/video_button.dart @@ -7,6 +7,7 @@ import '../../models/themes/quill_icon_theme.dart'; import '../../widgets/controller.dart'; import '../../widgets/toolbar.dart'; import '../default_embed_builder.dart'; +import '../embed_types.dart'; import 'image_video_utils.dart'; class VideoButton extends StatelessWidget { diff --git a/lib/src/widgets/toolbar.dart b/lib/src/widgets/toolbar.dart index 820dd3de..efe50ba0 100644 --- a/lib/src/widgets/toolbar.dart +++ b/lib/src/widgets/toolbar.dart @@ -1,11 +1,7 @@ -import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:i18n_extension/i18n_widget.dart'; -import '../embeds/default_embed_builder.dart'; -import '../embeds/toolbar/camera_button.dart'; -import '../embeds/toolbar/formula_button.dart'; +import '../embeds/default_embed_toolbar.dart'; import '../models/documents/attribute.dart'; import '../models/themes/quill_custom_button.dart'; import '../models/themes/quill_dialog_theme.dart'; @@ -54,7 +50,6 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { this.toolbarSectionSpacing = 4, this.multiRowsDisplay = true, this.color, - this.filePickImpl, this.customButtons = const [], this.locale, Key? key, @@ -93,19 +88,8 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { bool showUndo = true, bool showRedo = true, bool multiRowsDisplay = true, - bool showImageButton = true, - bool showVideoButton = true, - bool showFormulaButton = false, - bool showCameraButton = true, bool showDirection = false, bool showSearchButton = true, - OnImagePickCallback? onImagePickCallback, - OnVideoPickCallback? onVideoPickCallback, - MediaPickSettingSelector? mediaPickSettingSelector, - MediaPickSettingSelector? cameraPickSettingSelector, - FilePickImpl? filePickImpl, - WebImagePickImpl? webImagePickImpl, - WebVideoPickImpl? webVideoPickImpl, List customButtons = const [], ///Map of font sizes in string @@ -114,6 +98,9 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { ///Map of font families in string Map? fontFamilyValues, + /// Toolbar items to display for controls of embed blocks + IEmbedToolbar? embedToolbar, + ///The theme to use for the icons in the toolbar, uses type [QuillIconTheme] QuillIconTheme? iconTheme, @@ -138,8 +125,7 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { showColorButton || showBackgroundColorButton || showClearFormat || - onImagePickCallback != null || - onVideoPickCallback != null, + embedToolbar?.notEmpty == true, showAlignmentButtons || showDirection, showLeftAlignment, showCenterAlignment, @@ -315,56 +301,8 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { controller: controller, iconTheme: iconTheme, ), - if (showImageButton) - ImageButton( - icon: Icons.image, - iconSize: toolbarIconSize, - controller: controller, - onImagePickCallback: onImagePickCallback, - filePickImpl: filePickImpl, - webImagePickImpl: webImagePickImpl, - mediaPickSettingSelector: mediaPickSettingSelector, - iconTheme: iconTheme, - dialogTheme: dialogTheme, - ), - if (showVideoButton) - VideoButton( - icon: Icons.movie_creation, - iconSize: toolbarIconSize, - controller: controller, - onVideoPickCallback: onVideoPickCallback, - filePickImpl: filePickImpl, - webVideoPickImpl: webImagePickImpl, - mediaPickSettingSelector: mediaPickSettingSelector, - iconTheme: iconTheme, - dialogTheme: dialogTheme, - ), - if ((onImagePickCallback != null || onVideoPickCallback != null) && - showCameraButton) - CameraButton( - icon: Icons.photo_camera, - iconSize: toolbarIconSize, - controller: controller, - onImagePickCallback: onImagePickCallback, - onVideoPickCallback: onVideoPickCallback, - filePickImpl: filePickImpl, - webImagePickImpl: webImagePickImpl, - webVideoPickImpl: webVideoPickImpl, - cameraPickSettingSelector: cameraPickSettingSelector, - iconTheme: iconTheme, - ), - if (showFormulaButton) - FormulaButton( - icon: Icons.functions, - iconSize: toolbarIconSize, - controller: controller, - onImagePickCallback: onImagePickCallback, - filePickImpl: filePickImpl, - webImagePickImpl: webImagePickImpl, - mediaPickSettingSelector: mediaPickSettingSelector, - iconTheme: iconTheme, - dialogTheme: dialogTheme, - ), + ...?embedToolbar?.build( + controller, toolbarIconSize, iconTheme, dialogTheme), if (showDividers && isButtonGroupShown[0] && (isButtonGroupShown[1] || @@ -539,8 +477,6 @@ class QuillToolbar extends StatelessWidget implements PreferredSizeWidget { /// is given. final Color? color; - final FilePickImpl? filePickImpl; - /// The locale to use for the editor toolbar, defaults to system locale /// More https://github.com/singerdmx/flutter-quill#translation final Locale? locale;