From e30786cd95740dbbb0fb46e2780fc02a3278ffdd Mon Sep 17 00:00:00 2001 From: Jonathan Salmon Date: Sat, 3 Sep 2022 02:18:20 +0100 Subject: [PATCH] Moved embed code to separate package --- example/lib/pages/home_page.dart | 9 ++-- example/lib/pages/read_only_page.dart | 3 +- example/lib/universal_ui/universal_ui.dart | 1 + example/lib/widgets/demo_scaffold.dart | 5 +- example/pubspec.yaml | 6 +++ flutter_quill_extensions/.metadata | 10 ++++ flutter_quill_extensions/CHANGELOG.md | 3 ++ flutter_quill_extensions/LICENSE | 1 + flutter_quill_extensions/README.md | 22 ++++++++ .../analysis_options.yaml | 37 +++++++++++++ .../lib/embeds/builders.dart | 53 +++++-------------- .../lib}/embeds/embed_types.dart | 0 .../lib/embeds/toolbar.dart | 19 +++---- .../lib}/embeds/toolbar/camera_button.dart | 8 ++- .../lib}/embeds/toolbar/formula_button.dart | 7 +-- .../lib}/embeds/toolbar/image_button.dart | 7 +-- .../embeds/toolbar/image_video_utils.dart | 10 ++-- .../lib}/embeds/toolbar/video_button.dart | 7 +-- .../lib/embeds/utils.dart | 5 ++ .../lib}/embeds/widgets/image.dart | 10 +--- .../lib}/embeds/widgets/image_resizer.dart | 2 +- .../lib}/embeds/widgets/video_app.dart | 3 +- .../embeds/widgets/youtube_video_app.dart | 3 +- .../lib/flutter_quill_extensions.dart | 18 +++++++ flutter_quill_extensions/pubspec.yaml | 36 +++++++++++++ lib/extensions.dart | 6 +++ lib/flutter_quill.dart | 5 +- lib/src/widgets/editor.dart | 7 +-- lib/src/widgets/embeds.dart | 25 +++++++++ lib/src/widgets/raw_editor.dart | 1 - lib/src/widgets/toolbar.dart | 2 +- lib/translations.dart | 3 ++ pubspec.yaml | 7 --- 33 files changed, 223 insertions(+), 118 deletions(-) create mode 100644 flutter_quill_extensions/.metadata create mode 100644 flutter_quill_extensions/CHANGELOG.md create mode 100644 flutter_quill_extensions/LICENSE create mode 100644 flutter_quill_extensions/README.md create mode 100644 flutter_quill_extensions/analysis_options.yaml rename lib/src/embeds/default_embed_builder.dart => flutter_quill_extensions/lib/embeds/builders.dart (88%) rename {lib/src => flutter_quill_extensions/lib}/embeds/embed_types.dart (100%) rename lib/src/embeds/default_embed_toolbar.dart => flutter_quill_extensions/lib/embeds/toolbar.dart (89%) rename {lib/src => flutter_quill_extensions/lib}/embeds/toolbar/camera_button.dart (95%) rename {lib/src => flutter_quill_extensions/lib}/embeds/toolbar/formula_button.dart (85%) rename {lib/src => flutter_quill_extensions/lib}/embeds/toolbar/image_button.dart (90%) rename {lib/src => flutter_quill_extensions/lib}/embeds/toolbar/image_video_utils.dart (95%) rename {lib/src => flutter_quill_extensions/lib}/embeds/toolbar/video_button.dart (90%) create mode 100644 flutter_quill_extensions/lib/embeds/utils.dart rename {lib/src => flutter_quill_extensions/lib}/embeds/widgets/image.dart (93%) rename {lib/src => flutter_quill_extensions/lib}/embeds/widgets/image_resizer.dart (98%) rename {lib/src => flutter_quill_extensions/lib}/embeds/widgets/video_app.dart (98%) rename {lib/src => flutter_quill_extensions/lib}/embeds/widgets/youtube_video_app.dart (97%) create mode 100644 flutter_quill_extensions/lib/flutter_quill_extensions.dart create mode 100644 flutter_quill_extensions/pubspec.yaml create mode 100644 lib/extensions.dart create mode 100644 lib/src/widgets/embeds.dart create mode 100644 lib/translations.dart diff --git a/example/lib/pages/home_page.dart b/example/lib/pages/home_page.dart index 4e1d77fd..45843960 100644 --- a/example/lib/pages/home_page.dart +++ b/example/lib/pages/home_page.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_quill/flutter_quill.dart' hide Text; +import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:tuple/tuple.dart'; @@ -120,7 +121,7 @@ class _HomePageState extends State { sizeSmall: const TextStyle(fontSize: 9), ), embedBuilders: [ - ...defaultEmbedBuilders, + ...FlutterQuillEmbeds.builders, NotesEmbedBuilder(addEditNote: _addEditNote) ], ); @@ -152,7 +153,7 @@ class _HomePageState extends State { } var toolbar = QuillToolbar.basic( controller: _controller!, - embedToolbar: EmbedToolbar( + embedToolbar: QuillEmbedToolbar( // provide a callback to enable picking images from device. // if omit, "image" button only allows adding images from url. // same goes for videos. @@ -168,7 +169,7 @@ class _HomePageState extends State { if (kIsWeb) { toolbar = QuillToolbar.basic( controller: _controller!, - embedToolbar: EmbedToolbar( + embedToolbar: QuillEmbedToolbar( onImagePickCallback: _onImagePickCallback, webImagePickImpl: _webImagePickImpl, ), @@ -178,7 +179,7 @@ class _HomePageState extends State { if (_isDesktop()) { toolbar = QuillToolbar.basic( controller: _controller!, - embedToolbar: EmbedToolbar( + embedToolbar: QuillEmbedToolbar( onImagePickCallback: _onImagePickCallback, filePickImpl: openFileSystemPickerForDesktop, ), diff --git a/example/lib/pages/read_only_page.dart b/example/lib/pages/read_only_page.dart index 8eecf33a..478d7924 100644 --- a/example/lib/pages/read_only_page.dart +++ b/example/lib/pages/read_only_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart' hide Text; +import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import '../universal_ui/universal_ui.dart'; import '../widgets/demo_scaffold.dart'; @@ -38,7 +39,7 @@ class _ReadOnlyPageState extends State { readOnly: !_edit, expands: false, padding: EdgeInsets.zero, - embedBuilders: defaultEmbedBuilders, + embedBuilders: FlutterQuillEmbeds.builders, ); if (kIsWeb) { quillEditor = QuillEditor( diff --git a/example/lib/universal_ui/universal_ui.dart b/example/lib/universal_ui/universal_ui.dart index 1a37f552..b7ec9f5a 100644 --- a/example/lib/universal_ui/universal_ui.dart +++ b/example/lib/universal_ui/universal_ui.dart @@ -3,6 +3,7 @@ library universal_ui; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_quill/flutter_quill.dart'; +import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:universal_html/html.dart' as html; import 'package:youtube_player_flutter_quill/youtube_player_flutter_quill.dart'; diff --git a/example/lib/widgets/demo_scaffold.dart b/example/lib/widgets/demo_scaffold.dart index 87ce2f96..7f997062 100644 --- a/example/lib/widgets/demo_scaffold.dart +++ b/example/lib/widgets/demo_scaffold.dart @@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_quill/flutter_quill.dart' hide Text; +import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:path_provider/path_provider.dart'; typedef DemoContentBuilder = Widget Function( @@ -91,13 +92,13 @@ class _DemoScaffoldState extends State { final actions = widget.actions ?? []; var toolbar = QuillToolbar.basic( controller: _controller!, - embedToolbar: EmbedToolbar(), + embedToolbar: QuillEmbedToolbar(), ); if (_isDesktop()) { toolbar = QuillToolbar.basic( controller: _controller!, embedToolbar: - EmbedToolbar(filePickImpl: openFileSystemPickerForDesktop), + QuillEmbedToolbar(filePickImpl: openFileSystemPickerForDesktop), ); } return Scaffold( diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 5b5a8360..e79b0c7e 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -34,6 +34,12 @@ dependencies: file_picker: ^4.6.1 flutter_quill: path: ../ + flutter_quill_extensions: + path: ../flutter_quill_extensions + +dependency_overrides: + flutter_quill: + path: ../ dev_dependencies: flutter_test: diff --git a/flutter_quill_extensions/.metadata b/flutter_quill_extensions/.metadata new file mode 100644 index 00000000..e7011f64 --- /dev/null +++ b/flutter_quill_extensions/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + channel: stable + +project_type: package diff --git a/flutter_quill_extensions/CHANGELOG.md b/flutter_quill_extensions/CHANGELOG.md new file mode 100644 index 00000000..41cc7d81 --- /dev/null +++ b/flutter_quill_extensions/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/flutter_quill_extensions/LICENSE b/flutter_quill_extensions/LICENSE new file mode 100644 index 00000000..ba75c69f --- /dev/null +++ b/flutter_quill_extensions/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/flutter_quill_extensions/README.md b/flutter_quill_extensions/README.md new file mode 100644 index 00000000..f0a5f7aa --- /dev/null +++ b/flutter_quill_extensions/README.md @@ -0,0 +1,22 @@ +# Flutter Quill Extensions + +Helpers to support embed widgets in flutter_quill. + +## Usage + +Set the `embedBuilders` and `embedToolbar` params in `QuillEditor` and `QuillToolbar` with the +values provided by this repository. + +``` +QuillEditor.basic( + controller: controller, + embedBuilders: FlutterQuillEmbeds.builders, +); +``` + +``` +QuillToolbar.basic( + controller: controller, + embedToolbar: QuillEmbedToolbar(), +); +``` diff --git a/flutter_quill_extensions/analysis_options.yaml b/flutter_quill_extensions/analysis_options.yaml new file mode 100644 index 00000000..7749c861 --- /dev/null +++ b/flutter_quill_extensions/analysis_options.yaml @@ -0,0 +1,37 @@ +include: package:pedantic/analysis_options.yaml + +analyzer: + errors: + undefined_prefixed_name: ignore + unsafe_html: ignore +linter: + rules: + - always_declare_return_types + - always_put_required_named_parameters_first + - annotate_overrides + - avoid_empty_else + - avoid_escaping_inner_quotes + - avoid_print + - avoid_redundant_argument_values + - avoid_types_on_closure_parameters + - avoid_void_async + - cascade_invocations + - directives_ordering + - lines_longer_than_80_chars + - omit_local_variable_types + - prefer_const_constructors + - prefer_const_constructors_in_immutables + - prefer_const_declarations + - prefer_final_fields + - prefer_final_in_for_each + - prefer_final_locals + - prefer_initializing_formals + - prefer_int_literals + - prefer_interpolation_to_compose_strings + - prefer_relative_imports + - prefer_single_quotes + - sort_constructors_first + - sort_unnamed_constructors_first + - unnecessary_lambdas + - unnecessary_parenthesis + - unnecessary_string_interpolations diff --git a/lib/src/embeds/default_embed_builder.dart b/flutter_quill_extensions/lib/embeds/builders.dart similarity index 88% rename from lib/src/embeds/default_embed_builder.dart rename to flutter_quill_extensions/lib/embeds/builders.dart index df7955b5..3b98e0e7 100644 --- a/lib/src/embeds/default_embed_builder.dart +++ b/flutter_quill_extensions/lib/embeds/builders.dart @@ -2,39 +2,20 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_quill/flutter_quill.dart' hide Text; import 'package:gallery_saver/gallery_saver.dart'; import 'package:math_keyboard/math_keyboard.dart'; import 'package:tuple/tuple.dart'; -import '../models/documents/attribute.dart'; -import '../models/documents/nodes/embeddable.dart'; -import '../models/documents/nodes/leaf.dart' as leaf; -import '../translations/toolbar.i18n.dart'; -import '../utils/embeds.dart'; -import '../utils/platform.dart'; -import '../utils/string.dart'; -import '../widgets/controller.dart'; +import 'package:flutter_quill/translations.dart'; +import 'package:flutter_quill/extensions.dart' as base; + +import 'utils.dart'; import 'widgets/image.dart'; import 'widgets/image_resizer.dart'; import 'widgets/video_app.dart'; import 'widgets/youtube_video_app.dart'; -export 'toolbar/image_button.dart'; -export 'toolbar/image_video_utils.dart'; -export 'toolbar/video_button.dart'; - -abstract class IEmbedBuilder { - String get key; - - Widget build( - BuildContext context, - QuillController controller, - leaf.Embed node, - bool readOnly, - void Function(GlobalKey videoContainerKey)? onVideoInit, - ); -} - class ImageEmbedBuilder implements IEmbedBuilder { @override String get key => BlockEmbed.imageType; @@ -43,7 +24,7 @@ class ImageEmbedBuilder implements IEmbedBuilder { Widget build( BuildContext context, QuillController controller, - leaf.Embed node, + base.Embed node, bool readOnly, void Function(GlobalKey videoContainerKey)? onVideoInit, ) { @@ -53,8 +34,8 @@ class ImageEmbedBuilder implements IEmbedBuilder { final imageUrl = standardizeImageUrl(node.value.data); Tuple2? _widthHeight; final style = node.style.attributes['style']; - if (isMobile() && style != null) { - final _attrs = parseKeyValuePairs(style.value.toString(), { + if (base.isMobile() && style != null) { + final _attrs = base.parseKeyValuePairs(style.value.toString(), { Attribute.mobileWidth, Attribute.mobileHeight, Attribute.mobileMargin, @@ -71,7 +52,7 @@ class ImageEmbedBuilder implements IEmbedBuilder { final m = _attrs[Attribute.mobileMargin] == null ? 0.0 : double.parse(_attrs[Attribute.mobileMargin]!); - final a = getAlignment(_attrs[Attribute.mobileAlignment]); + final a = base.getAlignment(_attrs[Attribute.mobileAlignment]); image = Padding( padding: EdgeInsets.all(m), child: imageByUrl(imageUrl, width: w, height: h, alignment: a)); @@ -83,7 +64,7 @@ class ImageEmbedBuilder implements IEmbedBuilder { _widthHeight = Tuple2((image as Image).width, image.height); } - if (!readOnly && isMobile()) { + if (!readOnly && base.isMobile()) { return GestureDetector( onTap: () { showDialog( @@ -103,7 +84,7 @@ class ImageEmbedBuilder implements IEmbedBuilder { onImageResize: (w, h) { final res = getEmbedNode( controller, controller.selection.start); - final attr = replaceStyleString( + final attr = base.replaceStyleString( getImageStyleString(controller), w, h); controller ..skipRequestKeyboard = true @@ -157,7 +138,7 @@ class ImageEmbedBuilder implements IEmbedBuilder { child: image); } - if (!readOnly || !isMobile() || isImageBase64(imageUrl)) { + if (!readOnly || !base.isMobile() || isImageBase64(imageUrl)) { return image; } @@ -174,7 +155,7 @@ class VideoEmbedBuilder implements IEmbedBuilder { Widget build( BuildContext context, QuillController controller, - leaf.Embed node, + base.Embed node, bool readOnly, void Function(GlobalKey videoContainerKey)? onVideoInit) { assert(!kIsWeb, 'Please provide video EmbedBuilder for Web'); @@ -201,7 +182,7 @@ class FormulaEmbedBuilder implements IEmbedBuilder { Widget build( BuildContext context, QuillController controller, - leaf.Embed node, + base.Embed node, bool readOnly, void Function(GlobalKey videoContainerKey)? onVideoInit) { assert(!kIsWeb, 'Please provide formula EmbedBuilder for Web'); @@ -225,12 +206,6 @@ class FormulaEmbedBuilder implements IEmbedBuilder { } } -List get defaultEmbedBuilders => [ - ImageEmbedBuilder(), - VideoEmbedBuilder(), - FormulaEmbedBuilder(), - ]; - Widget _menuOptionsForReadonlyImage( BuildContext context, String imageUrl, Widget image) { return GestureDetector( diff --git a/lib/src/embeds/embed_types.dart b/flutter_quill_extensions/lib/embeds/embed_types.dart similarity index 100% rename from lib/src/embeds/embed_types.dart rename to flutter_quill_extensions/lib/embeds/embed_types.dart diff --git a/lib/src/embeds/default_embed_toolbar.dart b/flutter_quill_extensions/lib/embeds/toolbar.dart similarity index 89% rename from lib/src/embeds/default_embed_toolbar.dart rename to flutter_quill_extensions/lib/embeds/toolbar.dart index 8de64ddc..23623543 100644 --- a/lib/src/embeds/default_embed_toolbar.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar.dart @@ -1,23 +1,20 @@ import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.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; -} +export 'toolbar/image_button.dart'; +export 'toolbar/image_video_utils.dart'; +export 'toolbar/video_button.dart'; +export 'toolbar/formula_button.dart'; +export 'toolbar/camera_button.dart'; -class EmbedToolbar implements IEmbedToolbar { - EmbedToolbar({ +class QuillEmbedToolbar implements IEmbedToolbar { + QuillEmbedToolbar({ this.showImageButton = true, this.showVideoButton = true, this.showCameraButton = true, diff --git a/lib/src/embeds/toolbar/camera_button.dart b/flutter_quill_extensions/lib/embeds/toolbar/camera_button.dart similarity index 95% rename from lib/src/embeds/toolbar/camera_button.dart rename to flutter_quill_extensions/lib/embeds/toolbar/camera_button.dart index a6f6d89d..e1d544b8 100644 --- a/lib/src/embeds/toolbar/camera_button.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar/camera_button.dart @@ -1,11 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart' hide Text; import 'package:image_picker/image_picker.dart'; -import '../../models/themes/quill_icon_theme.dart'; -import '../../translations/toolbar.i18n.dart'; -import '../../widgets/controller.dart'; -import '../../widgets/toolbar.dart'; -import '../default_embed_builder.dart'; +import 'package:flutter_quill/translations.dart'; + import '../embed_types.dart'; import 'image_video_utils.dart'; diff --git a/lib/src/embeds/toolbar/formula_button.dart b/flutter_quill_extensions/lib/embeds/toolbar/formula_button.dart similarity index 85% rename from lib/src/embeds/toolbar/formula_button.dart rename to flutter_quill_extensions/lib/embeds/toolbar/formula_button.dart index fb7b5b5e..bf777b67 100644 --- a/lib/src/embeds/toolbar/formula_button.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar/formula_button.dart @@ -1,11 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; -import '../../models/documents/nodes/embeddable.dart'; -import '../../models/themes/quill_dialog_theme.dart'; -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 { diff --git a/lib/src/embeds/toolbar/image_button.dart b/flutter_quill_extensions/lib/embeds/toolbar/image_button.dart similarity index 90% rename from lib/src/embeds/toolbar/image_button.dart rename to flutter_quill_extensions/lib/embeds/toolbar/image_button.dart index 6774221a..5cc51aff 100644 --- a/lib/src/embeds/toolbar/image_button.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar/image_button.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:image_picker/image_picker.dart'; -import '../../models/documents/nodes/embeddable.dart'; -import '../../models/themes/quill_dialog_theme.dart'; -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'; diff --git a/lib/src/embeds/toolbar/image_video_utils.dart b/flutter_quill_extensions/lib/embeds/toolbar/image_video_utils.dart similarity index 95% rename from lib/src/embeds/toolbar/image_video_utils.dart rename to flutter_quill_extensions/lib/embeds/toolbar/image_video_utils.dart index 422c73bd..a40c3c2b 100644 --- a/lib/src/embeds/toolbar/image_video_utils.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar/image_video_utils.dart @@ -2,14 +2,12 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart' hide Text; import 'package:image_picker/image_picker.dart'; -import '../../models/documents/nodes/embeddable.dart'; -import '../../models/rules/insert.dart'; -import '../../models/themes/quill_dialog_theme.dart'; -import '../../translations/toolbar.i18n.dart'; -import '../../utils/platform.dart'; -import '../../widgets/controller.dart'; +import 'package:flutter_quill/translations.dart'; +import 'package:flutter_quill/extensions.dart'; + import '../embed_types.dart'; class LinkDialog extends StatefulWidget { diff --git a/lib/src/embeds/toolbar/video_button.dart b/flutter_quill_extensions/lib/embeds/toolbar/video_button.dart similarity index 90% rename from lib/src/embeds/toolbar/video_button.dart rename to flutter_quill_extensions/lib/embeds/toolbar/video_button.dart index fd59e728..e6193622 100644 --- a/lib/src/embeds/toolbar/video_button.dart +++ b/flutter_quill_extensions/lib/embeds/toolbar/video_button.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:image_picker/image_picker.dart'; -import '../../models/documents/nodes/embeddable.dart'; -import '../../models/themes/quill_dialog_theme.dart'; -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'; diff --git a/flutter_quill_extensions/lib/embeds/utils.dart b/flutter_quill_extensions/lib/embeds/utils.dart new file mode 100644 index 00000000..360fb5d5 --- /dev/null +++ b/flutter_quill_extensions/lib/embeds/utils.dart @@ -0,0 +1,5 @@ +import 'package:string_validator/string_validator.dart'; + +bool isImageBase64(String imageUrl) { + return !imageUrl.startsWith('http') && isBase64(imageUrl); +} diff --git a/lib/src/embeds/widgets/image.dart b/flutter_quill_extensions/lib/embeds/widgets/image.dart similarity index 93% rename from lib/src/embeds/widgets/image.dart rename to flutter_quill_extensions/lib/embeds/widgets/image.dart index 9ed183ad..d4df2a4c 100644 --- a/lib/src/embeds/widgets/image.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/image.dart @@ -2,12 +2,10 @@ import 'dart:convert'; import 'dart:io' as io; import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:photo_view/photo_view.dart'; -import 'package:string_validator/string_validator.dart'; -import '../../models/documents/attribute.dart'; -import '../../models/documents/style.dart'; -import '../../widgets/controller.dart'; +import '../utils.dart'; const List imageFileExtensions = [ '.jpeg', @@ -19,10 +17,6 @@ const List imageFileExtensions = [ '.heic' ]; -bool isImageBase64(String imageUrl) { - return !imageUrl.startsWith('http') && isBase64(imageUrl); -} - String getImageStyleString(QuillController controller) { final String? s = controller .getAllSelectionStyles() diff --git a/lib/src/embeds/widgets/image_resizer.dart b/flutter_quill_extensions/lib/embeds/widgets/image_resizer.dart similarity index 98% rename from lib/src/embeds/widgets/image_resizer.dart rename to flutter_quill_extensions/lib/embeds/widgets/image_resizer.dart index 03e3f623..e520d0c9 100644 --- a/lib/src/embeds/widgets/image_resizer.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/image_resizer.dart @@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; -import '../../translations/toolbar.i18n.dart'; +import 'package:flutter_quill/translations.dart'; class ImageResizer extends StatefulWidget { const ImageResizer( diff --git a/lib/src/embeds/widgets/video_app.dart b/flutter_quill_extensions/lib/embeds/widgets/video_app.dart similarity index 98% rename from lib/src/embeds/widgets/video_app.dart rename to flutter_quill_extensions/lib/embeds/widgets/video_app.dart index ce1ce881..c05fe600 100644 --- a/lib/src/embeds/widgets/video_app.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/video_app.dart @@ -2,11 +2,10 @@ import 'dart:io'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:video_player/video_player.dart'; -import '../../../flutter_quill.dart'; - /// Widget for playing back video /// Refer to https://github.com/flutter/plugins/tree/master/packages/video_player/video_player class VideoApp extends StatefulWidget { diff --git a/lib/src/embeds/widgets/youtube_video_app.dart b/flutter_quill_extensions/lib/embeds/widgets/youtube_video_app.dart similarity index 97% rename from lib/src/embeds/widgets/youtube_video_app.dart rename to flutter_quill_extensions/lib/embeds/widgets/youtube_video_app.dart index 7b0a6fcb..8032b30f 100644 --- a/lib/src/embeds/widgets/youtube_video_app.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/youtube_video_app.dart @@ -1,10 +1,9 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:youtube_player_flutter_quill/youtube_player_flutter_quill.dart'; -import '../../widgets/default_styles.dart'; - class YoutubeVideoApp extends StatefulWidget { const YoutubeVideoApp( {required this.videoUrl, required this.context, required this.readOnly}); diff --git a/flutter_quill_extensions/lib/flutter_quill_extensions.dart b/flutter_quill_extensions/lib/flutter_quill_extensions.dart new file mode 100644 index 00000000..74e8affb --- /dev/null +++ b/flutter_quill_extensions/lib/flutter_quill_extensions.dart @@ -0,0 +1,18 @@ +library flutter_quill_extensions; + +import 'package:flutter_quill/flutter_quill.dart'; + +import 'embeds/builders.dart'; + +export 'embeds/toolbar.dart'; +export 'embeds/builders.dart'; +export 'embeds/embed_types.dart'; +export 'embeds/utils.dart'; + +class FlutterQuillEmbeds { + static List get builders => [ + ImageEmbedBuilder(), + VideoEmbedBuilder(), + FormulaEmbedBuilder(), + ]; +} diff --git a/flutter_quill_extensions/pubspec.yaml b/flutter_quill_extensions/pubspec.yaml new file mode 100644 index 00000000..fe77b5aa --- /dev/null +++ b/flutter_quill_extensions/pubspec.yaml @@ -0,0 +1,36 @@ +name: flutter_quill_extensions +description: Embed extensions for flutter_quill +version: 0.0.1 +homepage: https://bulletjournal.us/home/index.html +#author: bulletjournal +repository: https://github.com/singerdmx/flutter-quill/flutter_quill_extensions + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.0.0" + +dependencies: + flutter: + sdk: flutter + + flutter_quill: ^6.0.0 + + image_picker: ^0.8.5+3 + photo_view: ^0.14.0 + video_player: ^2.4.2 + youtube_player_flutter_quill: ^8.2.2 + gallery_saver: ^2.3.2 + math_keyboard: ^0.1.6 + string_validator: ^0.3.0 + +dependency_overrides: + flutter_quill: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + pedantic: ^1.11.1 + +# The following section is specific to Flutter packages. +flutter: diff --git a/lib/extensions.dart b/lib/extensions.dart new file mode 100644 index 00000000..12e961c2 --- /dev/null +++ b/lib/extensions.dart @@ -0,0 +1,6 @@ +library flutter_quill.extensions; + +export 'src/models/documents/nodes/leaf.dart' hide Text; +export 'src/models/rules/insert.dart'; +export 'src/utils/platform.dart'; +export 'src/utils/string.dart'; diff --git a/lib/flutter_quill.dart b/lib/flutter_quill.dart index 133d4f64..eae6c5de 100644 --- a/lib/flutter_quill.dart +++ b/lib/flutter_quill.dart @@ -1,9 +1,5 @@ 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'; export 'src/models/documents/nodes/embeddable.dart'; @@ -18,6 +14,7 @@ export 'src/utils/embeds.dart'; export 'src/widgets/controller.dart'; export 'src/widgets/default_styles.dart'; export 'src/widgets/editor.dart'; +export 'src/widgets/embeds.dart'; export 'src/widgets/link.dart' show LinkActionPickerDelegate, LinkMenuAction; export 'src/widgets/style_widgets/style_widgets.dart'; export 'src/widgets/toolbar.dart'; diff --git a/lib/src/widgets/editor.dart b/lib/src/widgets/editor.dart index 6d8f5d96..3c5e2e9c 100644 --- a/lib/src/widgets/editor.dart +++ b/lib/src/widgets/editor.dart @@ -10,17 +10,12 @@ import 'package:i18n_extension/i18n_widget.dart'; import 'package:tuple/tuple.dart'; import '../../flutter_quill.dart'; -import '../embeds/default_embed_builder.dart'; -import '../models/documents/document.dart'; import '../models/documents/nodes/container.dart' as container_node; -import '../models/documents/nodes/embeddable.dart'; -import '../models/documents/style.dart'; import '../utils/platform.dart'; import 'box.dart'; -import 'controller.dart'; import 'cursor.dart'; -import 'default_styles.dart'; import 'delegate.dart'; +import 'embeds.dart'; import 'float_cursor.dart'; import 'link.dart'; import 'raw_editor.dart'; diff --git a/lib/src/widgets/embeds.dart b/lib/src/widgets/embeds.dart new file mode 100644 index 00000000..83c1dae8 --- /dev/null +++ b/lib/src/widgets/embeds.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +import '../models/documents/nodes/leaf.dart' as leaf; +import '../models/themes/quill_dialog_theme.dart'; +import '../models/themes/quill_icon_theme.dart'; +import 'controller.dart'; + +abstract class IEmbedBuilder { + String get key; + + Widget build( + BuildContext context, + QuillController controller, + leaf.Embed node, + bool readOnly, + void Function(GlobalKey videoContainerKey)? onVideoInit, + ); +} + +abstract class IEmbedToolbar { + Iterable build(QuillController controller, double toolbarIconSize, + QuillIconTheme? iconTheme, QuillDialogTheme? dialogTheme); + + bool get notEmpty; +} diff --git a/lib/src/widgets/raw_editor.dart b/lib/src/widgets/raw_editor.dart index 30a93948..27cea907 100644 --- a/lib/src/widgets/raw_editor.dart +++ b/lib/src/widgets/raw_editor.dart @@ -26,7 +26,6 @@ import 'cursor.dart'; import 'default_styles.dart'; import 'delegate.dart'; import 'editor.dart'; -import '../embeds/default_embed_builder.dart'; import 'keyboard_listener.dart'; import 'link.dart'; import 'proxy.dart'; diff --git a/lib/src/widgets/toolbar.dart b/lib/src/widgets/toolbar.dart index efe50ba0..0ba6fd65 100644 --- a/lib/src/widgets/toolbar.dart +++ b/lib/src/widgets/toolbar.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:i18n_extension/i18n_widget.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'; @@ -9,6 +8,7 @@ import '../models/themes/quill_icon_theme.dart'; import '../translations/toolbar.i18n.dart'; import '../utils/font.dart'; import 'controller.dart'; +import 'embeds.dart'; import 'toolbar/arrow_indicated_button_list.dart'; import 'toolbar/clear_format_button.dart'; import 'toolbar/color_button.dart'; diff --git a/lib/translations.dart b/lib/translations.dart new file mode 100644 index 00000000..d9a743c5 --- /dev/null +++ b/lib/translations.dart @@ -0,0 +1,3 @@ +library flutter_quill.translations; + +export 'src/translations/toolbar.i18n.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 4f939f25..a937e7af 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,22 +15,15 @@ dependencies: collection: ^1.16.0 flutter_colorpicker: ^1.0.3 flutter_keyboard_visibility: ^5.2.0 - image_picker: ^0.8.5+3 - photo_view: ^0.14.0 quiver: ^3.1.0 - string_validator: ^0.3.0 tuple: ^2.0.0 url_launcher: ^6.1.2 pedantic: ^1.11.1 - video_player: ^2.4.2 characters: ^1.2.0 - youtube_player_flutter_quill: ^8.2.2 diff_match_patch: ^0.4.1 i18n_extension: ^5.0.0 - gallery_saver: ^2.3.2 device_info_plus: ^4.0.0 platform: ^3.1.0 - math_keyboard: ^0.1.6 dev_dependencies: flutter_test: