From 0d88c0201a2ea1fdf958e9265c256888c7c584d3 Mon Sep 17 00:00:00 2001 From: Ellet Date: Mon, 4 Dec 2023 17:21:49 +0300 Subject: [PATCH] First step of improving flutter quill extensions --- .gitignore | 5 +- .../lib/presentation/quill/quill_editor.dart | 4 +- flutter_quill_extensions/CHANGELOG.md | 6 + .../embeds/embed_types.dart | 0 .../formula/editor/formula_embed.dart} | 0 .../formula}/toolbar/formula_button.dart | 2 +- .../lib/embeds/image/editor/image_embed.dart | 86 ++++++++ .../image/editor/image_embed_types.dart} | 4 +- .../image/editor}/image_menu.dart | 7 +- .../image/editor/image_web_embed.dart} | 6 +- .../image/toolbar}/image_button.dart | 8 +- .../image/toolbar}/select_image_source.dart | 2 +- .../others}/camera_button/camera_button.dart | 6 +- .../others/camera_button/camera_types.dart} | 4 +- .../camera_button/select_camera_action.dart | 2 +- .../others}/image_video_utils.dart | 0 .../others}/media_button/media_button.dart | 0 .../unknown/editor/unknown_embed.dart} | 0 .../video/editor/video_embed.dart} | 1 + .../video/editor/video_web_embed.dart} | 6 +- .../video/toolbar}/select_video_source.dart | 2 +- .../video/toolbar}/video_button.dart | 8 +- .../embed_types => embeds/video}/video.dart | 4 +- .../embeds/widgets/image.dart | 2 +- .../embeds/widgets/image_resizer.dart | 0 .../embeds/widgets/video_app.dart | 2 +- .../embeds/widgets/youtube_video_app.dart | 0 .../lib/{logic => }/extensions/attribute.dart | 0 .../{logic => }/extensions/controller.dart | 23 -- .../lib/flutter_quill_extensions.dart | 87 ++++---- .../models/config/editor/image/image.dart | 2 +- .../models/config/editor/image/image_web.dart | 0 .../models/config/editor/video/video.dart | 0 .../models/config/editor/video/video_web.dart | 0 .../models/config/editor/webview.dart | 0 .../models/config/shared_configurations.dart | 0 .../models/config/toolbar/buttons/camera.dart | 2 +- .../config/toolbar/buttons/formula.dart | 0 .../models/config/toolbar/buttons/image.dart | 2 +- .../config/toolbar/buttons/media_button.dart | 0 .../models/config/toolbar/buttons/video.dart | 2 +- .../embeds/editor/image/image.dart | 150 ------------- .../presentation/embeds/editor/webview.dart | 58 ----- .../lib/presentation/utils/utils.dart | 201 ------------------ .../services/image_picker/image_options.dart | 0 .../services/image_picker/image_picker.dart | 0 .../image_picker/packages/image_picker.dart | 0 .../services/image_picker/s_image_picker.dart | 0 .../services/image_saver/exceptions.dart | 0 .../services/image_saver/image_saver.dart | 0 .../services/image_saver/packages/gal.dart | 0 .../services/image_saver/s_image_saver.dart | 0 .../shims => utils/dart_ui}/dart_ui_fake.dart | 0 .../shims => utils/dart_ui}/dart_ui_real.dart | 0 .../element_utils/element_shared_utils.dart | 15 ++ .../utils/element_utils/element_utils.dart | 108 ++++++++++ .../element_utils/element_web_utils.dart} | 10 +- .../{logic => }/utils/quill_image_utils.dart | 2 +- .../lib/{logic => }/utils/string.dart | 0 flutter_quill_extensions/lib/utils/utils.dart | 89 ++++++++ flutter_quill_extensions/pubspec.yaml | 2 +- 61 files changed, 395 insertions(+), 525 deletions(-) rename flutter_quill_extensions/lib/{presentation => }/embeds/embed_types.dart (100%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/formula.dart => embeds/formula/editor/formula_embed.dart} (100%) rename flutter_quill_extensions/lib/{presentation/embeds => embeds/formula}/toolbar/formula_button.dart (98%) create mode 100644 flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart rename flutter_quill_extensions/lib/{presentation/embeds/embed_types/image.dart => embeds/image/editor/image_embed_types.dart} (95%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/image => embeds/image/editor}/image_menu.dart (97%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/image/image_web.dart => embeds/image/editor/image_web_embed.dart} (91%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar/image_button => embeds/image/toolbar}/image_button.dart (96%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar/image_button => embeds/image/toolbar}/select_image_source.dart (97%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar => embeds/others}/camera_button/camera_button.dart (96%) rename flutter_quill_extensions/lib/{presentation/embeds/embed_types/camera.dart => embeds/others/camera_button/camera_types.dart} (94%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar => embeds/others}/camera_button/select_camera_action.dart (95%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar/utils => embeds/others}/image_video_utils.dart (100%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar => embeds/others}/media_button/media_button.dart (100%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/unknown.dart => embeds/unknown/editor/unknown_embed.dart} (100%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/video/video.dart => embeds/video/editor/video_embed.dart} (96%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/video/video_web.dart => embeds/video/editor/video_web_embed.dart} (89%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar/video_button => embeds/video/toolbar}/select_video_source.dart (97%) rename flutter_quill_extensions/lib/{presentation/embeds/toolbar/video_button => embeds/video/toolbar}/video_button.dart (96%) rename flutter_quill_extensions/lib/{presentation/embeds/embed_types => embeds/video}/video.dart (94%) rename flutter_quill_extensions/lib/{presentation => }/embeds/widgets/image.dart (99%) rename flutter_quill_extensions/lib/{presentation => }/embeds/widgets/image_resizer.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/embeds/widgets/video_app.dart (98%) rename flutter_quill_extensions/lib/{presentation => }/embeds/widgets/youtube_video_app.dart (100%) rename flutter_quill_extensions/lib/{logic => }/extensions/attribute.dart (100%) rename flutter_quill_extensions/lib/{logic => }/extensions/controller.dart (70%) rename flutter_quill_extensions/lib/{presentation => }/models/config/editor/image/image.dart (98%) rename flutter_quill_extensions/lib/{presentation => }/models/config/editor/image/image_web.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/editor/video/video.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/editor/video/video_web.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/editor/webview.dart (100%) rename flutter_quill_extensions/lib/{logic => }/models/config/shared_configurations.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/toolbar/buttons/camera.dart (93%) rename flutter_quill_extensions/lib/{presentation => }/models/config/toolbar/buttons/formula.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/toolbar/buttons/image.dart (95%) rename flutter_quill_extensions/lib/{presentation => }/models/config/toolbar/buttons/media_button.dart (100%) rename flutter_quill_extensions/lib/{presentation => }/models/config/toolbar/buttons/video.dart (95%) delete mode 100644 flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart delete mode 100644 flutter_quill_extensions/lib/presentation/embeds/editor/webview.dart delete mode 100644 flutter_quill_extensions/lib/presentation/utils/utils.dart rename flutter_quill_extensions/lib/{logic => }/services/image_picker/image_options.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_picker/image_picker.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_picker/packages/image_picker.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_picker/s_image_picker.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_saver/exceptions.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_saver/image_saver.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_saver/packages/gal.dart (100%) rename flutter_quill_extensions/lib/{logic => }/services/image_saver/s_image_saver.dart (100%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/shims => utils/dart_ui}/dart_ui_fake.dart (100%) rename flutter_quill_extensions/lib/{presentation/embeds/editor/shims => utils/dart_ui}/dart_ui_real.dart (100%) create mode 100644 flutter_quill_extensions/lib/utils/element_utils/element_shared_utils.dart create mode 100644 flutter_quill_extensions/lib/utils/element_utils/element_utils.dart rename flutter_quill_extensions/lib/{presentation/utils/web_utils.dart => utils/element_utils/element_web_utils.dart} (86%) rename flutter_quill_extensions/lib/{logic => }/utils/quill_image_utils.dart (99%) rename flutter_quill_extensions/lib/{logic => }/utils/string.dart (100%) create mode 100644 flutter_quill_extensions/lib/utils/utils.dart diff --git a/.gitignore b/.gitignore index cee99ed04..fc03c2767 100644 --- a/.gitignore +++ b/.gitignore @@ -80,4 +80,7 @@ pubspec.lock # For local development pubspec_overrides.yaml -old_example \ No newline at end of file +old_example + +# A directory where you put all of your local things that you don't want to push +.flutter-quill \ No newline at end of file diff --git a/example/lib/presentation/quill/quill_editor.dart b/example/lib/presentation/quill/quill_editor.dart index 133f9997f..06f7eb766 100644 --- a/example/lib/presentation/quill/quill_editor.dart +++ b/example/lib/presentation/quill/quill_editor.dart @@ -7,9 +7,9 @@ import 'package:desktop_drop/desktop_drop.dart' show DropTarget; import 'package:flutter/material.dart'; import 'package:flutter_quill/extensions.dart' show isAndroid, isIOS, isWeb; import 'package:flutter_quill/flutter_quill.dart'; -import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; -import 'package:flutter_quill_extensions/presentation/embeds/widgets/image.dart' +import 'package:flutter_quill_extensions/embeds/widgets/image.dart' show getImageProviderByImageSource, imageFileExtensions; +import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:path/path.dart' as path; import '../extensions/scaffold_messenger.dart'; diff --git a/flutter_quill_extensions/CHANGELOG.md b/flutter_quill_extensions/CHANGELOG.md index cd3ec636f..cc2cb0bee 100644 --- a/flutter_quill_extensions/CHANGELOG.md +++ b/flutter_quill_extensions/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## 0.8.0 +* **Breaking Change**: Completly change the way how the source code structured to more basic and simple way, organize folders and file names, if you use the library +from `flutter_quill_extensions.dart` then there is nothing you need to do, but if you are using any other import then you need to re-imports +* Add support for unoffical css property called `deletable` in the image embed, this won't affect how quill js work +* Improvemenets to the image embed + ## 0.7.2 * Fix a bug when opening the link dialog for both video and image buttons * Update `README.md` diff --git a/flutter_quill_extensions/lib/presentation/embeds/embed_types.dart b/flutter_quill_extensions/lib/embeds/embed_types.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/embed_types.dart rename to flutter_quill_extensions/lib/embeds/embed_types.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/formula.dart b/flutter_quill_extensions/lib/embeds/formula/editor/formula_embed.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/editor/formula.dart rename to flutter_quill_extensions/lib/embeds/formula/editor/formula_embed.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/formula_button.dart b/flutter_quill_extensions/lib/embeds/formula/toolbar/formula_button.dart similarity index 98% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/formula_button.dart rename to flutter_quill_extensions/lib/embeds/formula/toolbar/formula_button.dart index e821d689d..935389f6b 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/formula_button.dart +++ b/flutter_quill_extensions/lib/embeds/formula/toolbar/formula_button.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; -import '../../models/config/toolbar/buttons/formula.dart'; +import '../../../models/config/toolbar/buttons/formula.dart'; class QuillToolbarFormulaButton extends StatelessWidget { const QuillToolbarFormulaButton({ diff --git a/flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart b/flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart new file mode 100644 index 000000000..5a9fdc336 --- /dev/null +++ b/flutter_quill_extensions/lib/embeds/image/editor/image_embed.dart @@ -0,0 +1,86 @@ +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter/material.dart'; +import 'package:flutter_quill/extensions.dart' as base; +import 'package:flutter_quill/flutter_quill.dart' hide OptionalSize; + +import '../../../models/config/editor/image/image.dart'; +import '../../../models/config/shared_configurations.dart'; +import '../../../utils/element_utils/element_utils.dart'; +import '../../widgets/image.dart'; +import 'image_menu.dart'; + +class QuillEditorImageEmbedBuilder extends EmbedBuilder { + QuillEditorImageEmbedBuilder({ + required this.configurations, + }); + final QuillEditorImageEmbedConfigurations configurations; + + @override + String get key => BlockEmbed.imageType; + + @override + bool get expanded => false; + + @override + Widget build( + BuildContext context, + QuillController controller, + base.Embed node, + bool readOnly, + bool inline, + TextStyle textStyle, + ) { + assert(!kIsWeb, 'Please provide image EmbedBuilder for Web'); + + final imageSource = standardizeImageUrl(node.value.data); + final ((imageSize), margin, alignment) = getElementAttributes(node); + + final width = imageSize.width; + final height = imageSize.height; + + final image = getImageWidgetByImageSource( + imageSource, + imageProviderBuilder: configurations.imageProviderBuilder, + imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder, + alignment: alignment, + height: height, + width: width, + assetsPrefix: QuillSharedExtensionsConfigurations.get(context: context) + .assetsPrefix, + ); + + final imageSaverService = + QuillSharedExtensionsConfigurations.get(context: context) + .imageSaverService; + return GestureDetector( + 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, + ), + ), + ), + ), + child: Builder( + builder: (context) { + if (margin != null) { + return Padding( + padding: EdgeInsets.all(margin), + child: image, + ); + } + return image; + }, + ), + ); + } +} diff --git a/flutter_quill_extensions/lib/presentation/embeds/embed_types/image.dart b/flutter_quill_extensions/lib/embeds/image/editor/image_embed_types.dart similarity index 95% rename from flutter_quill_extensions/lib/presentation/embeds/embed_types/image.dart rename to flutter_quill_extensions/lib/embeds/image/editor/image_embed_types.dart index c53796efa..44d2dfaa1 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/embed_types/image.dart +++ b/flutter_quill_extensions/lib/embeds/image/editor/image_embed_types.dart @@ -4,8 +4,8 @@ import 'package:flutter/widgets.dart' show BuildContext; import 'package:flutter_quill/flutter_quill.dart'; import 'package:meta/meta.dart' show immutable; -import '../../../logic/extensions/controller.dart'; -import '../../../logic/services/image_picker/s_image_picker.dart'; +import '../../../extensions/controller.dart'; +import '../../../services/image_picker/s_image_picker.dart'; /// When request picking an image, for example when the image button toolbar /// clicked, it should be null in case the user didn't choose any image or diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart b/flutter_quill_extensions/lib/embeds/image/editor/image_menu.dart similarity index 97% rename from flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart rename to flutter_quill_extensions/lib/embeds/image/editor/image_menu.dart index 1ee3201ad..26e3c1c40 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_menu.dart +++ b/flutter_quill_extensions/lib/embeds/image/editor/image_menu.dart @@ -12,10 +12,11 @@ import 'package:flutter_quill/flutter_quill.dart' getEmbedNode; import 'package:flutter_quill/translations.dart'; -import '../../../../logic/models/config/shared_configurations.dart'; -import '../../../../logic/services/image_saver/s_image_saver.dart'; -import '../../../../logic/utils/string.dart'; import '../../../models/config/editor/image/image.dart'; +import '../../../models/config/shared_configurations.dart'; +import '../../../services/image_saver/s_image_saver.dart'; +import '../../../utils/element_utils/element_utils.dart'; +import '../../../utils/string.dart'; import '../../../utils/utils.dart'; import '../../widgets/image.dart' show ImageTapWrapper, getImageStyleString; import '../../widgets/image_resizer.dart' show ImageResizer; diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_web.dart b/flutter_quill_extensions/lib/embeds/image/editor/image_web_embed.dart similarity index 91% rename from flutter_quill_extensions/lib/presentation/embeds/editor/image/image_web.dart rename to flutter_quill_extensions/lib/embeds/image/editor/image_web_embed.dart index 2ed5b967e..d754b8dfb 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image_web.dart +++ b/flutter_quill_extensions/lib/embeds/image/editor/image_web_embed.dart @@ -4,10 +4,10 @@ import 'package:flutter_quill/flutter_quill.dart'; import 'package:universal_html/html.dart' as html; import '../../../models/config/editor/image/image_web.dart'; +import '../../../utils/dart_ui/dart_ui_fake.dart' + if (dart.library.html) '../../../utils/dart_ui/dart_ui_real.dart' as ui; +import '../../../utils/element_utils/element_web_utils.dart'; import '../../../utils/utils.dart'; -import '../../../utils/web_utils.dart'; -import '../shims/dart_ui_fake.dart' - if (dart.library.html) '../shims/dart_ui_real.dart' as ui; class QuillEditorWebImageEmbedBuilder extends EmbedBuilder { const QuillEditorWebImageEmbedBuilder({ diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/image_button.dart b/flutter_quill_extensions/lib/embeds/image/toolbar/image_button.dart similarity index 96% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/image_button.dart rename to flutter_quill_extensions/lib/embeds/image/toolbar/image_button.dart index 552211b19..fb00a6564 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/image_button.dart +++ b/flutter_quill_extensions/lib/embeds/image/toolbar/image_button.dart @@ -4,11 +4,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; import 'package:flutter_quill/translations.dart'; -import '../../../../logic/models/config/shared_configurations.dart'; -import '../../../../logic/services/image_picker/image_picker.dart'; +import '../../../models/config/shared_configurations.dart'; import '../../../models/config/toolbar/buttons/image.dart'; -import '../../embed_types/image.dart'; -import '../utils/image_video_utils.dart'; +import '../../../services/image_picker/image_picker.dart'; +import '../../others/image_video_utils.dart'; +import '../editor/image_embed_types.dart'; import 'select_image_source.dart'; class QuillToolbarImageButton extends StatelessWidget { diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/select_image_source.dart b/flutter_quill_extensions/lib/embeds/image/toolbar/select_image_source.dart similarity index 97% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/select_image_source.dart rename to flutter_quill_extensions/lib/embeds/image/toolbar/select_image_source.dart index d40fd8f14..812ecf10f 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/image_button/select_image_source.dart +++ b/flutter_quill_extensions/lib/embeds/image/toolbar/select_image_source.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/extensions.dart' show isDesktop; -import '../../embed_types/image.dart'; +import '../editor/image_embed_types.dart'; class SelectImageSourceDialog extends StatelessWidget { const SelectImageSourceDialog({super.key}); diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart b/flutter_quill_extensions/lib/embeds/others/camera_button/camera_button.dart similarity index 96% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart rename to flutter_quill_extensions/lib/embeds/others/camera_button/camera_button.dart index 937d64435..c62976cb4 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/camera_button.dart +++ b/flutter_quill_extensions/lib/embeds/others/camera_button/camera_button.dart @@ -8,10 +8,10 @@ import 'package:flutter_quill/flutter_quill.dart' QuillToolbarIconButton; import 'package:flutter_quill/translations.dart'; -import '../../../../logic/models/config/shared_configurations.dart'; -import '../../../../logic/services/image_picker/image_options.dart'; +import '../../../models/config/shared_configurations.dart'; import '../../../models/config/toolbar/buttons/camera.dart'; -import '../../embed_types/camera.dart'; +import '../../../services/image_picker/image_options.dart'; +import 'camera_types.dart'; import 'select_camera_action.dart'; class QuillToolbarCameraButton extends StatelessWidget { diff --git a/flutter_quill_extensions/lib/presentation/embeds/embed_types/camera.dart b/flutter_quill_extensions/lib/embeds/others/camera_button/camera_types.dart similarity index 94% rename from flutter_quill_extensions/lib/presentation/embeds/embed_types/camera.dart rename to flutter_quill_extensions/lib/embeds/others/camera_button/camera_types.dart index 1e2931230..28f7c5aac 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/embed_types/camera.dart +++ b/flutter_quill_extensions/lib/embeds/others/camera_button/camera_types.dart @@ -1,8 +1,8 @@ import 'package:flutter/widgets.dart' show BuildContext; import 'package:meta/meta.dart' show immutable; -import 'image.dart'; -import 'video.dart'; +import '../../image/editor/image_embed_types.dart'; +import '../../video/video.dart'; enum CameraAction { video, diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/select_camera_action.dart b/flutter_quill_extensions/lib/embeds/others/camera_button/select_camera_action.dart similarity index 95% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/select_camera_action.dart rename to flutter_quill_extensions/lib/embeds/others/camera_button/select_camera_action.dart index f8823cf13..bd6527db7 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/camera_button/select_camera_action.dart +++ b/flutter_quill_extensions/lib/embeds/others/camera_button/select_camera_action.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/translations.dart'; -import '../../embed_types/camera.dart'; +import 'camera_types.dart'; class SelectCameraActionDialog extends StatelessWidget { const SelectCameraActionDialog({super.key}); diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/utils/image_video_utils.dart b/flutter_quill_extensions/lib/embeds/others/image_video_utils.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/utils/image_video_utils.dart rename to flutter_quill_extensions/lib/embeds/others/image_video_utils.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/media_button/media_button.dart b/flutter_quill_extensions/lib/embeds/others/media_button/media_button.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/media_button/media_button.dart rename to flutter_quill_extensions/lib/embeds/others/media_button/media_button.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/unknown.dart b/flutter_quill_extensions/lib/embeds/unknown/editor/unknown_embed.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/editor/unknown.dart rename to flutter_quill_extensions/lib/embeds/unknown/editor/unknown_embed.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/video/video.dart b/flutter_quill_extensions/lib/embeds/video/editor/video_embed.dart similarity index 96% rename from flutter_quill_extensions/lib/presentation/embeds/editor/video/video.dart rename to flutter_quill_extensions/lib/embeds/video/editor/video_embed.dart index a4b2a9b80..ab2a3c0da 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/video/video.dart +++ b/flutter_quill_extensions/lib/embeds/video/editor/video_embed.dart @@ -4,6 +4,7 @@ import 'package:flutter_quill/extensions.dart' as base; import 'package:flutter_quill/flutter_quill.dart'; import '../../../models/config/editor/video/video.dart'; +import '../../../utils/element_utils/element_utils.dart'; import '../../../utils/utils.dart'; import '../../widgets/video_app.dart'; import '../../widgets/youtube_video_app.dart'; diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/video/video_web.dart b/flutter_quill_extensions/lib/embeds/video/editor/video_web_embed.dart similarity index 89% rename from flutter_quill_extensions/lib/presentation/embeds/editor/video/video_web.dart rename to flutter_quill_extensions/lib/embeds/video/editor/video_web_embed.dart index abc821d08..650cd5431 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/video/video_web.dart +++ b/flutter_quill_extensions/lib/embeds/video/editor/video_web_embed.dart @@ -5,10 +5,10 @@ import 'package:youtube_player_flutter/youtube_player_flutter.dart' show YoutubePlayer; import '../../../models/config/editor/video/video_web.dart'; +import '../../../utils/dart_ui/dart_ui_fake.dart' + if (dart.library.html) '../../../utils/dart_ui/dart_ui_real.dart' as ui; +import '../../../utils/element_utils/element_web_utils.dart'; import '../../../utils/utils.dart'; -import '../../../utils/web_utils.dart'; -import '../shims/dart_ui_fake.dart' - if (dart.library.html) '../shims/dart_ui_real.dart' as ui; class QuillEditorWebVideoEmbedBuilder extends EmbedBuilder { const QuillEditorWebVideoEmbedBuilder({ diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/select_video_source.dart b/flutter_quill_extensions/lib/embeds/video/toolbar/select_video_source.dart similarity index 97% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/select_video_source.dart rename to flutter_quill_extensions/lib/embeds/video/toolbar/select_video_source.dart index 78fe6177b..2626d6f7f 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/select_video_source.dart +++ b/flutter_quill_extensions/lib/embeds/video/toolbar/select_video_source.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/extensions.dart' show isDesktop; -import '../../embed_types/video.dart'; +import '../video.dart'; class SelectVideoSourceDialog extends StatelessWidget { const SelectVideoSourceDialog({super.key}); diff --git a/flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/video_button.dart b/flutter_quill_extensions/lib/embeds/video/toolbar/video_button.dart similarity index 96% rename from flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/video_button.dart rename to flutter_quill_extensions/lib/embeds/video/toolbar/video_button.dart index dd2fb8f58..787165ddf 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/toolbar/video_button/video_button.dart +++ b/flutter_quill_extensions/lib/embeds/video/toolbar/video_button.dart @@ -3,11 +3,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_quill/flutter_quill.dart'; -import '../../../../logic/models/config/shared_configurations.dart'; -import '../../../../logic/services/image_picker/image_options.dart'; +import '../../../models/config/shared_configurations.dart'; import '../../../models/config/toolbar/buttons/video.dart'; -import '../../embed_types/video.dart'; -import '../utils/image_video_utils.dart'; +import '../../../services/image_picker/image_options.dart'; +import '../../others/image_video_utils.dart'; +import '../video.dart'; import 'select_video_source.dart'; class QuillToolbarVideoButton extends StatelessWidget { diff --git a/flutter_quill_extensions/lib/presentation/embeds/embed_types/video.dart b/flutter_quill_extensions/lib/embeds/video/video.dart similarity index 94% rename from flutter_quill_extensions/lib/presentation/embeds/embed_types/video.dart rename to flutter_quill_extensions/lib/embeds/video/video.dart index d69ab5e05..b2e1ca24e 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/embed_types/video.dart +++ b/flutter_quill_extensions/lib/embeds/video/video.dart @@ -2,8 +2,8 @@ import 'package:flutter/widgets.dart' show BuildContext; import 'package:flutter_quill/flutter_quill.dart'; import 'package:meta/meta.dart' show immutable; -import '../../../logic/extensions/controller.dart'; -import '../../../logic/services/image_picker/s_image_picker.dart'; +import '../../extensions/controller.dart'; +import '../../services/image_picker/s_image_picker.dart'; /// When request picking an video, for example when the video button toolbar /// clicked, it should be null in case the user didn't choose any video or diff --git a/flutter_quill_extensions/lib/presentation/embeds/widgets/image.dart b/flutter_quill_extensions/lib/embeds/widgets/image.dart similarity index 99% rename from flutter_quill_extensions/lib/presentation/embeds/widgets/image.dart rename to flutter_quill_extensions/lib/embeds/widgets/image.dart index 13c77eb9d..d072f202b 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/widgets/image.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/image.dart @@ -7,7 +7,7 @@ import 'package:photo_view/photo_view.dart'; import '../../models/config/editor/image/image.dart'; import '../../utils/utils.dart'; -import '../embed_types/image.dart'; +import '../image/editor/image_embed_types.dart'; const List imageFileExtensions = [ '.jpeg', diff --git a/flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart b/flutter_quill_extensions/lib/embeds/widgets/image_resizer.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/widgets/image_resizer.dart rename to flutter_quill_extensions/lib/embeds/widgets/image_resizer.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/widgets/video_app.dart b/flutter_quill_extensions/lib/embeds/widgets/video_app.dart similarity index 98% rename from flutter_quill_extensions/lib/presentation/embeds/widgets/video_app.dart rename to flutter_quill_extensions/lib/embeds/widgets/video_app.dart index 5b794394b..334f64ca1 100644 --- a/flutter_quill_extensions/lib/presentation/embeds/widgets/video_app.dart +++ b/flutter_quill_extensions/lib/embeds/widgets/video_app.dart @@ -6,7 +6,7 @@ import 'package:flutter_quill/flutter_quill.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:video_player/video_player.dart'; -import '../../../flutter_quill_extensions.dart'; +import '../../flutter_quill_extensions.dart'; /// Widget for playing back video /// Refer to https://github.com/flutter/plugins/tree/master/packages/video_player/video_player diff --git a/flutter_quill_extensions/lib/presentation/embeds/widgets/youtube_video_app.dart b/flutter_quill_extensions/lib/embeds/widgets/youtube_video_app.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/widgets/youtube_video_app.dart rename to flutter_quill_extensions/lib/embeds/widgets/youtube_video_app.dart diff --git a/flutter_quill_extensions/lib/logic/extensions/attribute.dart b/flutter_quill_extensions/lib/extensions/attribute.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/extensions/attribute.dart rename to flutter_quill_extensions/lib/extensions/attribute.dart diff --git a/flutter_quill_extensions/lib/logic/extensions/controller.dart b/flutter_quill_extensions/lib/extensions/controller.dart similarity index 70% rename from flutter_quill_extensions/lib/logic/extensions/controller.dart rename to flutter_quill_extensions/lib/extensions/controller.dart index 474f3cf44..d1687ea7c 100644 --- a/flutter_quill_extensions/lib/logic/extensions/controller.dart +++ b/flutter_quill_extensions/lib/extensions/controller.dart @@ -1,7 +1,5 @@ import 'package:flutter_quill/flutter_quill.dart'; -// ignore: unused_import -import '../../presentation/embeds/editor/webview.dart'; import '../utils/quill_image_utils.dart'; /// Extension functions on [QuillController] @@ -12,27 +10,6 @@ extension QuillControllerExt on QuillController { int get index => selection.baseOffset; int get length => selection.extentOffset - index; - /// Insert webview embed block, it requires [initialUrl] to load - /// the initial page - // void insertWebViewBlock({ - // required String initialUrl, - // }) { - // final block = BlockEmbed.custom( - // QuillEditorWebViewBlockEmbed( - // initialUrl, - // ), - // ); - - // this - // ..skipRequestKeyboard = true - // ..replaceText( - // index, - // length, - // block, - // null, - // ); - // } - /// Insert image embed block, it requires the [imageSource] /// /// it could be local image on the system file diff --git a/flutter_quill_extensions/lib/flutter_quill_extensions.dart b/flutter_quill_extensions/lib/flutter_quill_extensions.dart index 22a69a4fe..b3f7f3bd0 100644 --- a/flutter_quill_extensions/lib/flutter_quill_extensions.dart +++ b/flutter_quill_extensions/lib/flutter_quill_extensions.dart @@ -6,52 +6,49 @@ import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter_quill/flutter_quill.dart'; import 'package:meta/meta.dart' show immutable; -import 'presentation/embeds/editor/image/image.dart'; -import 'presentation/embeds/editor/image/image_web.dart'; -import 'presentation/embeds/editor/video/video.dart'; -import 'presentation/embeds/editor/video/video_web.dart'; -import 'presentation/embeds/editor/webview.dart'; -import 'presentation/embeds/toolbar/camera_button/camera_button.dart'; -import 'presentation/embeds/toolbar/image_button/image_button.dart'; -import 'presentation/embeds/toolbar/video_button/video_button.dart'; -import 'presentation/models/config/editor/image/image.dart'; -import 'presentation/models/config/editor/image/image_web.dart'; -import 'presentation/models/config/editor/video/video.dart'; -import 'presentation/models/config/editor/video/video_web.dart'; -import 'presentation/models/config/editor/webview.dart'; -import 'presentation/models/config/toolbar/buttons/camera.dart'; -import 'presentation/models/config/toolbar/buttons/image.dart'; -import 'presentation/models/config/toolbar/buttons/media_button.dart'; -import 'presentation/models/config/toolbar/buttons/video.dart'; +import 'embeds/image/editor/image_embed.dart'; +import 'embeds/image/editor/image_web_embed.dart'; +import 'embeds/image/toolbar/image_button.dart'; +import 'embeds/others/camera_button/camera_button.dart'; +import 'embeds/video/editor/video_embed.dart'; +import 'embeds/video/editor/video_web_embed.dart'; +import 'embeds/video/toolbar/video_button.dart'; +import 'models/config/editor/image/image.dart'; +import 'models/config/editor/image/image_web.dart'; +import 'models/config/editor/video/video.dart'; +import 'models/config/editor/video/video_web.dart'; +import 'models/config/editor/webview.dart'; +import 'models/config/toolbar/buttons/camera.dart'; +import 'models/config/toolbar/buttons/image.dart'; +import 'models/config/toolbar/buttons/media_button.dart'; +import 'models/config/toolbar/buttons/video.dart'; -export '/logic/extensions/controller.dart'; -export '/presentation/models/config/editor/webview.dart'; -export 'logic/models/config/shared_configurations.dart'; -export 'presentation/embeds/editor/image/image.dart'; -export 'presentation/embeds/editor/image/image_web.dart'; -export 'presentation/embeds/editor/unknown.dart'; -export 'presentation/embeds/editor/video/video.dart'; -export 'presentation/embeds/editor/video/video_web.dart'; -export 'presentation/embeds/editor/webview.dart'; -export 'presentation/embeds/embed_types.dart'; -export 'presentation/embeds/embed_types/image.dart'; -export 'presentation/embeds/embed_types/video.dart'; -export 'presentation/embeds/toolbar/camera_button/camera_button.dart'; -export 'presentation/embeds/toolbar/formula_button.dart'; -export 'presentation/embeds/toolbar/image_button/image_button.dart'; -export 'presentation/embeds/toolbar/media_button/media_button.dart'; -export 'presentation/embeds/toolbar/utils/image_video_utils.dart'; -export 'presentation/embeds/toolbar/video_button/video_button.dart'; -export 'presentation/models/config/editor/image/image.dart'; -export 'presentation/models/config/editor/image/image_web.dart'; -export 'presentation/models/config/editor/video/video.dart'; -export 'presentation/models/config/editor/video/video_web.dart'; -export 'presentation/models/config/toolbar/buttons/camera.dart'; -export 'presentation/models/config/toolbar/buttons/formula.dart'; -export 'presentation/models/config/toolbar/buttons/image.dart'; -export 'presentation/models/config/toolbar/buttons/media_button.dart'; -export 'presentation/models/config/toolbar/buttons/video.dart'; -export 'presentation/utils/utils.dart'; +export 'embeds/embed_types.dart'; +export 'embeds/formula/toolbar/formula_button.dart'; +export 'embeds/image/editor/image_embed.dart'; +export 'embeds/image/editor/image_embed_types.dart'; +export 'embeds/image/editor/image_web_embed.dart'; +export 'embeds/image/toolbar/image_button.dart'; +export 'embeds/others/camera_button/camera_button.dart'; +export 'embeds/others/media_button/media_button.dart'; +export 'embeds/unknown/editor/unknown_embed.dart'; +export 'embeds/video/editor/video_embed.dart'; +export 'embeds/video/editor/video_web_embed.dart'; +export 'embeds/video/toolbar/video_button.dart'; +export 'embeds/video/video.dart'; +export 'extensions/controller.dart'; +export 'models/config/editor/image/image.dart'; +export 'models/config/editor/image/image_web.dart'; +export 'models/config/editor/video/video.dart'; +export 'models/config/editor/video/video_web.dart'; +export 'models/config/editor/webview.dart'; +export 'models/config/shared_configurations.dart'; +export 'models/config/toolbar/buttons/camera.dart'; +export 'models/config/toolbar/buttons/formula.dart'; +export 'models/config/toolbar/buttons/image.dart'; +export 'models/config/toolbar/buttons/media_button.dart'; +export 'models/config/toolbar/buttons/video.dart'; +export 'utils/utils.dart'; @immutable class FlutterQuillEmbeds { diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart b/flutter_quill_extensions/lib/models/config/editor/image/image.dart similarity index 98% rename from flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart rename to flutter_quill_extensions/lib/models/config/editor/image/image.dart index 8d6646f0a..208568bd1 100644 --- a/flutter_quill_extensions/lib/presentation/models/config/editor/image/image.dart +++ b/flutter_quill_extensions/lib/models/config/editor/image/image.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart' show VoidCallback; import 'package:flutter_quill/extensions.dart'; import 'package:meta/meta.dart' show immutable; -import '../../../../embeds/embed_types/image.dart'; +import '../../../../embeds/image/editor/image_embed_types.dart'; /// [QuillEditorImageEmbedConfigurations] for desktop, mobile and /// other platforms diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/image/image_web.dart b/flutter_quill_extensions/lib/models/config/editor/image/image_web.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/editor/image/image_web.dart rename to flutter_quill_extensions/lib/models/config/editor/image/image_web.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/video/video.dart b/flutter_quill_extensions/lib/models/config/editor/video/video.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/editor/video/video.dart rename to flutter_quill_extensions/lib/models/config/editor/video/video.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/video/video_web.dart b/flutter_quill_extensions/lib/models/config/editor/video/video_web.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/editor/video/video_web.dart rename to flutter_quill_extensions/lib/models/config/editor/video/video_web.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/editor/webview.dart b/flutter_quill_extensions/lib/models/config/editor/webview.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/editor/webview.dart rename to flutter_quill_extensions/lib/models/config/editor/webview.dart diff --git a/flutter_quill_extensions/lib/logic/models/config/shared_configurations.dart b/flutter_quill_extensions/lib/models/config/shared_configurations.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/models/config/shared_configurations.dart rename to flutter_quill_extensions/lib/models/config/shared_configurations.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/camera.dart b/flutter_quill_extensions/lib/models/config/toolbar/buttons/camera.dart similarity index 93% rename from flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/camera.dart rename to flutter_quill_extensions/lib/models/config/toolbar/buttons/camera.dart index dafdf1abe..32e2f7549 100644 --- a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/camera.dart +++ b/flutter_quill_extensions/lib/models/config/toolbar/buttons/camera.dart @@ -1,7 +1,7 @@ import 'package:flutter/widgets.dart' show Color; import 'package:flutter_quill/flutter_quill.dart'; -import '../../../../embeds/embed_types/camera.dart'; +import '../../../../embeds/others/camera_button/camera_types.dart'; class QuillToolbarCameraButtonExtraOptions extends QuillToolbarBaseButtonExtraOptions { diff --git a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/formula.dart b/flutter_quill_extensions/lib/models/config/toolbar/buttons/formula.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/formula.dart rename to flutter_quill_extensions/lib/models/config/toolbar/buttons/formula.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/image.dart b/flutter_quill_extensions/lib/models/config/toolbar/buttons/image.dart similarity index 95% rename from flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/image.dart rename to flutter_quill_extensions/lib/models/config/toolbar/buttons/image.dart index d1e5efbd1..61e8901a0 100644 --- a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/image.dart +++ b/flutter_quill_extensions/lib/models/config/toolbar/buttons/image.dart @@ -2,7 +2,7 @@ import 'package:flutter/widgets.dart' show Color; import 'package:flutter_quill/flutter_quill.dart'; import 'package:meta/meta.dart' show immutable; -import '../../../../embeds/embed_types/image.dart'; +import '../../../../embeds/image/editor/image_embed_types.dart'; class QuillToolbarImageButtonExtraOptions extends QuillToolbarBaseButtonExtraOptions { diff --git a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/media_button.dart b/flutter_quill_extensions/lib/models/config/toolbar/buttons/media_button.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/media_button.dart rename to flutter_quill_extensions/lib/models/config/toolbar/buttons/media_button.dart diff --git a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/video.dart b/flutter_quill_extensions/lib/models/config/toolbar/buttons/video.dart similarity index 95% rename from flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/video.dart rename to flutter_quill_extensions/lib/models/config/toolbar/buttons/video.dart index e7efba515..e1f86a761 100644 --- a/flutter_quill_extensions/lib/presentation/models/config/toolbar/buttons/video.dart +++ b/flutter_quill_extensions/lib/models/config/toolbar/buttons/video.dart @@ -1,7 +1,7 @@ import 'package:flutter/widgets.dart' show Color; import 'package:flutter_quill/flutter_quill.dart'; -import '../../../../embeds/embed_types/video.dart'; +import '../../../../embeds/video/video.dart'; class QuillToolbarVideoButtonExtraOptions extends QuillToolbarBaseButtonExtraOptions { diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart b/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart deleted file mode 100644 index e95cf9aa7..000000000 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/image/image.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_quill/extensions.dart' as base; -import 'package:flutter_quill/flutter_quill.dart' hide OptionalSize; - -import '../../../../logic/models/config/shared_configurations.dart'; -import '../../../models/config/editor/image/image.dart'; -import '../../../utils/utils.dart'; -import '../../widgets/image.dart'; -import 'image_menu.dart'; - -class QuillEditorImageEmbedBuilder extends EmbedBuilder { - QuillEditorImageEmbedBuilder({ - required this.configurations, - }); - final QuillEditorImageEmbedConfigurations configurations; - - @override - String get key => BlockEmbed.imageType; - - @override - bool get expanded => false; - - @override - Widget build( - BuildContext context, - QuillController controller, - base.Embed node, - bool readOnly, - bool inline, - TextStyle textStyle, - ) { - assert(!kIsWeb, 'Please provide image EmbedBuilder for Web'); - - final imageSource = standardizeImageUrl(node.value.data); - final ((imageSize), margin, alignment) = getElementAttributes(node); - - final width = imageSize.width; - final height = imageSize.height; - - final image = getImageWidgetByImageSource( - imageSource, - imageProviderBuilder: configurations.imageProviderBuilder, - imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder, - alignment: alignment, - height: height, - width: width, - assetsPrefix: QuillSharedExtensionsConfigurations.get(context: context) - .assetsPrefix, - ); - - // OptionalSize? imageSize; - // final style = node.style.attributes['style']; - - // if (style != null) { - // final attrs = base.isMobile(supportWeb: false) - // ? base.parseKeyValuePairs(style.value.toString(), { - // Attribute.mobileWidth, - // Attribute.mobileHeight, - // Attribute.mobileMargin, - // Attribute.mobileAlignment, - // }) - // : base.parseKeyValuePairs(style.value.toString(), { - // Attribute.width.key, - // Attribute.height.key, - // Attribute.margin, - // Attribute.alignment, - // }); - // if (attrs.isNotEmpty) { - // final width = double.tryParse( - // (base.isMobile(supportWeb: false) - // ? attrs[Attribute.mobileWidth] - // : attrs[Attribute.width.key]) ?? - // '', - // ); - // final height = double.tryParse( - // (base.isMobile(supportWeb: false) - // ? attrs[Attribute.mobileHeight] - // : attrs[Attribute.height.key]) ?? - // '', - // ); - // final alignment = base.getAlignment(base.isMobile(supportWeb: false) - // ? attrs[Attribute.mobileAlignment] - // : attrs[Attribute.alignment]); - // final margin = (base.isMobile(supportWeb: false) - // ? double.tryParse(Attribute.mobileMargin) - // : double.tryParse(Attribute.margin)) ?? - // 0.0; - - // imageSize = OptionalSize(width, height); - // image = Padding( - // padding: EdgeInsets.all(margin), - // child: getImageWidgetByImageSource( - // imageSource, - // width: width, - // height: height, - // alignment: alignment, - // imageProviderBuilder: configurations.imageProviderBuilder, - // imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder, - // ), - // ); - // } - // } - - // if (imageSize == null) { - // image = getImageWidgetByImageSource( - // imageSource, - // imageProviderBuilder: configurations.imageProviderBuilder, - // imageErrorWidgetBuilder: configurations.imageErrorWidgetBuilder, - // ); - // imageSize = OptionalSize((image as Image).width, image.height); - // } - - final imageSaverService = - QuillSharedExtensionsConfigurations.get(context: context) - .imageSaverService; - return GestureDetector( - onTap: configurations.onImageClicked ?? - () => showDialog( - context: context, - builder: (_) { - return QuillProvider.value( - value: context.requireQuillProvider, - child: FlutterQuillLocalizationsWidget( - child: ImageOptionsMenu( - controller: controller, - configurations: configurations, - imageSource: imageSource, - imageSize: imageSize, - isReadOnly: readOnly, - imageSaverService: imageSaverService, - ), - ), - ); - }, - ), - child: Builder( - builder: (context) { - if (margin != null) { - return Padding( - padding: EdgeInsets.all(margin), - child: image, - ); - } - return image; - }, - ), - ); - } -} diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/webview.dart b/flutter_quill_extensions/lib/presentation/embeds/editor/webview.dart deleted file mode 100644 index 388b39b48..000000000 --- a/flutter_quill_extensions/lib/presentation/embeds/editor/webview.dart +++ /dev/null @@ -1,58 +0,0 @@ -// import 'dart:convert' show jsonDecode, jsonEncode; - -// import 'package:flutter/widgets.dart'; -// import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -// import 'package:flutter_quill/flutter_quill.dart'; -// import 'package:meta/meta.dart' show experimental; - -// import '../../models/config/editor/webview.dart'; - -// @experimental -// class QuillEditorWebViewBlockEmbed extends CustomBlockEmbed { -// const QuillEditorWebViewBlockEmbed( -// String value, -// ) : super(webViewType, value); - -// factory QuillEditorWebViewBlockEmbed.fromDocument(Document document) => -// QuillEditorWebViewBlockEmbed(jsonEncode(document.toDelta().toJson())); - -// static const String webViewType = 'webview'; - -// Document get document => Document.fromJson(jsonDecode(data)); -// } - -// @experimental -// class QuillEditorWebViewEmbedBuilder extends EmbedBuilder { -// const QuillEditorWebViewEmbedBuilder({ -// required this.configurations, -// }); - -// @override -// bool get expanded => false; - -// final QuillEditorWebViewEmbedConfigurations configurations; -// @override -// Widget build( -// BuildContext context, -// QuillController controller, -// Embed node, -// bool readOnly, -// bool inline, -// TextStyle textStyle, -// ) { -// final url = node.value.data as String; - -// return SizedBox( -// width: double.infinity, -// height: 200, -// child: InAppWebView( -// initialUrlRequest: URLRequest( -// url: Uri.parse(url), -// ), -// ), -// ); -// } - -// @override -// String get key => 'webview'; -// } diff --git a/flutter_quill_extensions/lib/presentation/utils/utils.dart b/flutter_quill_extensions/lib/presentation/utils/utils.dart deleted file mode 100644 index 00e986fd2..000000000 --- a/flutter_quill_extensions/lib/presentation/utils/utils.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'dart:io' show File; - -import 'package:flutter/foundation.dart' show immutable; -import 'package:flutter/widgets.dart' show Alignment; -import 'package:flutter_quill/extensions.dart' as base; -import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node; -import '../../logic/extensions/attribute.dart'; -import '../../logic/services/image_saver/s_image_saver.dart'; -import '../embeds/widgets/image.dart'; - -RegExp _base64 = RegExp( - r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$', -); - -bool isBase64(String str) { - return _base64.hasMatch(str); -} - -bool isHttpBasedUrl(String url) { - try { - final uri = Uri.parse(url.trim()); - return uri.isScheme('HTTP') || uri.isScheme('HTTPS'); - } catch (_) { - return false; - } -} - -bool isImageBase64(String imageUrl) { - return !isHttpBasedUrl(imageUrl) && isBase64(imageUrl); -} - -bool isYouTubeUrl(String videoUrl) { - try { - final uri = Uri.parse(videoUrl); - return uri.host == 'www.youtube.com' || - uri.host == 'youtube.com' || - uri.host == 'youtu.be' || - uri.host == 'www.youtu.be'; - } catch (_) { - return false; - } -} - -enum SaveImageResultMethod { network, localStorage } - -@immutable -class SaveImageResult { - const SaveImageResult({required this.error, required this.method}); - - final String? error; - final SaveImageResultMethod method; -} - -Future saveImage({ - required String imageUrl, - required ImageSaverService imageSaverService, -}) async { - final imageFile = File(imageUrl); - final hasPermission = await imageSaverService.hasAccess(); - if (!hasPermission) { - await imageSaverService.requestAccess(); - } - final imageExistsLocally = await imageFile.exists(); - if (!imageExistsLocally) { - try { - await imageSaverService.saveImageFromNetwork( - Uri.parse(appendFileExtensionToImageUrl(imageUrl)), - ); - return const SaveImageResult( - error: null, - method: SaveImageResultMethod.network, - ); - } catch (e) { - return SaveImageResult( - error: e.toString(), - method: SaveImageResultMethod.network, - ); - } - } - try { - await imageSaverService.saveLocalImage(imageUrl); - return const SaveImageResult( - error: null, - method: SaveImageResultMethod.localStorage, - ); - } catch (e) { - return SaveImageResult( - error: e.toString(), - method: SaveImageResultMethod.localStorage, - ); - } -} - -( - OptionalSize elementSize, - double? margin, - Alignment alignment, -) getElementAttributes( - Node node, -) { - var elementSize = const OptionalSize(null, null); - var elementAlignment = Alignment.center; - double? elementMargin; - - // Usually double value - final heightValue = double.tryParse( - node.style.attributes[Attribute.height.key]?.value.toString() ?? ''); - final widthValue = double.tryParse( - node.style.attributes[Attribute.width.key]?.value.toString() ?? ''); - - if (heightValue != null) { - elementSize = elementSize.copyWith( - height: heightValue, - ); - } - if (widthValue != null) { - elementSize = elementSize.copyWith( - width: widthValue, - ); - } - - final cssStyle = node.style.attributes['style']; - - if (cssStyle != null) { - final attrs = base.isMobile(supportWeb: false) - ? base.parseKeyValuePairs(cssStyle.value.toString(), { - AttributeExt.mobileWidth.key, - AttributeExt.mobileHeight.key, - AttributeExt.mobileMargin.key, - AttributeExt.mobileAlignment.key, - }) - : base.parseKeyValuePairs(cssStyle.value.toString(), { - Attribute.width.key, - Attribute.height.key, - 'margin', - 'alignment', - }); - if (attrs.isEmpty) { - return (elementSize, elementMargin, elementAlignment); - } - - // It css value as string but we will try to support it anyway - - // TODO: This could be improved much better - final cssHeightValue = double.tryParse(((base.isMobile(supportWeb: false) - ? attrs[AttributeExt.mobileHeight.key] - : attrs[Attribute.height.key]) ?? - '') - .replaceFirst('px', '')); - final cssWidthValue = double.tryParse(((!base.isMobile(supportWeb: false) - ? attrs[Attribute.width.key] - : attrs[AttributeExt.mobileWidth.key]) ?? - '') - .replaceFirst('px', '')); - - if (cssHeightValue != null) { - elementSize = elementSize.copyWith(height: cssHeightValue); - } - if (cssWidthValue != null) { - elementSize = elementSize.copyWith(width: cssWidthValue); - } - - elementAlignment = base.getAlignment(base.isMobile(supportWeb: false) - ? attrs[AttributeExt.mobileAlignment.key] - : attrs['alignment']); - final margin = (base.isMobile(supportWeb: false) - ? double.tryParse(AttributeExt.mobileMargin.key) - : double.tryParse('margin')); - if (margin != null) { - elementMargin = margin; - } - } - - return (elementSize, elementMargin, elementAlignment); -} - -@immutable -class OptionalSize { - const OptionalSize( - this.width, - this.height, - ); - - /// If non-null, requires the child to have exactly this width. - /// If null, the child is free to choose its own width. - final double? width; - - /// If non-null, requires the child to have exactly this height. - /// If null, the child is free to choose its own height. - final double? height; - - OptionalSize copyWith({ - double? width, - double? height, - }) { - return OptionalSize( - width ?? this.width, - height ?? this.height, - ); - } -} diff --git a/flutter_quill_extensions/lib/logic/services/image_picker/image_options.dart b/flutter_quill_extensions/lib/services/image_picker/image_options.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_picker/image_options.dart rename to flutter_quill_extensions/lib/services/image_picker/image_options.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_picker/image_picker.dart b/flutter_quill_extensions/lib/services/image_picker/image_picker.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_picker/image_picker.dart rename to flutter_quill_extensions/lib/services/image_picker/image_picker.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_picker/packages/image_picker.dart b/flutter_quill_extensions/lib/services/image_picker/packages/image_picker.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_picker/packages/image_picker.dart rename to flutter_quill_extensions/lib/services/image_picker/packages/image_picker.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_picker/s_image_picker.dart b/flutter_quill_extensions/lib/services/image_picker/s_image_picker.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_picker/s_image_picker.dart rename to flutter_quill_extensions/lib/services/image_picker/s_image_picker.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_saver/exceptions.dart b/flutter_quill_extensions/lib/services/image_saver/exceptions.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_saver/exceptions.dart rename to flutter_quill_extensions/lib/services/image_saver/exceptions.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_saver/image_saver.dart b/flutter_quill_extensions/lib/services/image_saver/image_saver.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_saver/image_saver.dart rename to flutter_quill_extensions/lib/services/image_saver/image_saver.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_saver/packages/gal.dart b/flutter_quill_extensions/lib/services/image_saver/packages/gal.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_saver/packages/gal.dart rename to flutter_quill_extensions/lib/services/image_saver/packages/gal.dart diff --git a/flutter_quill_extensions/lib/logic/services/image_saver/s_image_saver.dart b/flutter_quill_extensions/lib/services/image_saver/s_image_saver.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/services/image_saver/s_image_saver.dart rename to flutter_quill_extensions/lib/services/image_saver/s_image_saver.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/shims/dart_ui_fake.dart b/flutter_quill_extensions/lib/utils/dart_ui/dart_ui_fake.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/editor/shims/dart_ui_fake.dart rename to flutter_quill_extensions/lib/utils/dart_ui/dart_ui_fake.dart diff --git a/flutter_quill_extensions/lib/presentation/embeds/editor/shims/dart_ui_real.dart b/flutter_quill_extensions/lib/utils/dart_ui/dart_ui_real.dart similarity index 100% rename from flutter_quill_extensions/lib/presentation/embeds/editor/shims/dart_ui_real.dart rename to flutter_quill_extensions/lib/utils/dart_ui/dart_ui_real.dart diff --git a/flutter_quill_extensions/lib/utils/element_utils/element_shared_utils.dart b/flutter_quill_extensions/lib/utils/element_utils/element_shared_utils.dart new file mode 100644 index 000000000..ec2126b66 --- /dev/null +++ b/flutter_quill_extensions/lib/utils/element_utils/element_shared_utils.dart @@ -0,0 +1,15 @@ +Map parseCssString(String cssString) { + final result = {}; + final declarations = cssString.split(';'); + + for (final declaration in declarations) { + final parts = declaration.split(':'); + if (parts.length == 2) { + final property = parts[0].trim(); + final value = parts[1].trim(); + result[property] = value; + } + } + + return result; +} diff --git a/flutter_quill_extensions/lib/utils/element_utils/element_utils.dart b/flutter_quill_extensions/lib/utils/element_utils/element_utils.dart new file mode 100644 index 000000000..da61f06f0 --- /dev/null +++ b/flutter_quill_extensions/lib/utils/element_utils/element_utils.dart @@ -0,0 +1,108 @@ +import 'package:flutter/foundation.dart' show immutable; +import 'package:flutter/widgets.dart' show Alignment; +import 'package:flutter_quill/extensions.dart' as base; +import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node; + +import '../../extensions/attribute.dart'; +import 'element_shared_utils.dart'; + +/// Theses properties are not officaly supported by quill js +/// but they are only used in all platforms other than web +/// and they will be stored in css style property so quill js ignore them +enum ExtraElementProperties { + deletable, +} + +( + OptionalSize elementSize, + double? margin, + Alignment alignment, +) getElementAttributes( + Node node, +) { + var elementSize = const OptionalSize(null, null); + var elementAlignment = Alignment.center; + double? elementMargin; + + // Usually double value + final heightValue = double.tryParse( + node.style.attributes[Attribute.height.key]?.value.toString() ?? ''); + final widthValue = double.tryParse( + node.style.attributes[Attribute.width.key]?.value.toString() ?? ''); + + if (heightValue != null) { + elementSize = elementSize.copyWith( + height: heightValue, + ); + } + if (widthValue != null) { + elementSize = elementSize.copyWith( + width: widthValue, + ); + } + + final cssStyle = node.style.attributes['style']; + + if (cssStyle != null) { + // It css value as string but we will try to support it anyway + + final cssAttrs = parseCssString(cssStyle.value.toString()); + + // TODO: This could be improved much better + final cssHeightValue = double.tryParse(((base.isMobile(supportWeb: false) + ? cssAttrs[AttributeExt.mobileHeight.key] + : cssAttrs[Attribute.height.key]) ?? + '') + .replaceFirst('px', '')); + final cssWidthValue = double.tryParse(((!base.isMobile(supportWeb: false) + ? cssAttrs[Attribute.width.key] + : cssAttrs[AttributeExt.mobileWidth.key]) ?? + '') + .replaceFirst('px', '')); + + if (cssHeightValue != null) { + elementSize = elementSize.copyWith(height: cssHeightValue); + } + if (cssWidthValue != null) { + elementSize = elementSize.copyWith(width: cssWidthValue); + } + + elementAlignment = base.getAlignment(base.isMobile(supportWeb: false) + ? cssAttrs[AttributeExt.mobileAlignment.key] + : cssAttrs['alignment']); + final margin = (base.isMobile(supportWeb: false) + ? double.tryParse(AttributeExt.mobileMargin.key) + : double.tryParse('margin')); + if (margin != null) { + elementMargin = margin; + } + } + + return (elementSize, elementMargin, elementAlignment); +} + +@immutable +class OptionalSize { + const OptionalSize( + this.width, + this.height, + ); + + /// If non-null, requires the child to have exactly this width. + /// If null, the child is free to choose its own width. + final double? width; + + /// If non-null, requires the child to have exactly this height. + /// If null, the child is free to choose its own height. + final double? height; + + OptionalSize copyWith({ + double? width, + double? height, + }) { + return OptionalSize( + width ?? this.width, + height ?? this.height, + ); + } +} diff --git a/flutter_quill_extensions/lib/presentation/utils/web_utils.dart b/flutter_quill_extensions/lib/utils/element_utils/element_web_utils.dart similarity index 86% rename from flutter_quill_extensions/lib/presentation/utils/web_utils.dart rename to flutter_quill_extensions/lib/utils/element_utils/element_web_utils.dart index b34d308fb..406c2fb12 100644 --- a/flutter_quill_extensions/lib/presentation/utils/web_utils.dart +++ b/flutter_quill_extensions/lib/utils/element_utils/element_web_utils.dart @@ -1,6 +1,7 @@ -import 'package:flutter_quill/extensions.dart' as base; import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node; +import 'element_shared_utils.dart'; + /// Prefer the width, and height from the css style attribute if exits /// it can be `auto` or `100px` so it's specific to HTML && CSS /// if not, we will use the one from attributes which is usually just an double @@ -27,12 +28,7 @@ import 'package:flutter_quill/flutter_quill.dart' show Attribute, Node; final widthValue = node.style.attributes[Attribute.width.key]?.value; if (cssStyle != null) { - final attrs = base.parseKeyValuePairs(cssStyle.value.toString(), { - Attribute.width.key, - Attribute.height.key, - 'margin', - 'alignment', - }); + final attrs = parseCssString(cssStyle.value.toString()); final cssHeightValue = attrs[Attribute.height.key]; if (cssHeightValue != null) { height = cssHeightValue; diff --git a/flutter_quill_extensions/lib/logic/utils/quill_image_utils.dart b/flutter_quill_extensions/lib/utils/quill_image_utils.dart similarity index 99% rename from flutter_quill_extensions/lib/logic/utils/quill_image_utils.dart rename to flutter_quill_extensions/lib/utils/quill_image_utils.dart index 30eca1286..4a366c092 100644 --- a/flutter_quill_extensions/lib/logic/utils/quill_image_utils.dart +++ b/flutter_quill_extensions/lib/utils/quill_image_utils.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter_quill/flutter_quill.dart' as quill; import 'package:path/path.dart' as path; -import '../../presentation/utils/utils.dart'; +import 'utils.dart'; typedef OnGenerateNewFileNameCallback = String Function( String currentFileName, diff --git a/flutter_quill_extensions/lib/logic/utils/string.dart b/flutter_quill_extensions/lib/utils/string.dart similarity index 100% rename from flutter_quill_extensions/lib/logic/utils/string.dart rename to flutter_quill_extensions/lib/utils/string.dart diff --git a/flutter_quill_extensions/lib/utils/utils.dart b/flutter_quill_extensions/lib/utils/utils.dart new file mode 100644 index 000000000..12c802a11 --- /dev/null +++ b/flutter_quill_extensions/lib/utils/utils.dart @@ -0,0 +1,89 @@ +import 'dart:io' show File; + +import 'package:flutter/foundation.dart' show immutable; + +import '../embeds/widgets/image.dart'; +import '../services/image_saver/s_image_saver.dart'; + +RegExp _base64 = RegExp( + r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$', +); + +bool isBase64(String str) { + return _base64.hasMatch(str); +} + +bool isHttpBasedUrl(String url) { + try { + final uri = Uri.parse(url.trim()); + return uri.isScheme('HTTP') || uri.isScheme('HTTPS'); + } catch (_) { + return false; + } +} + +bool isImageBase64(String imageUrl) { + return !isHttpBasedUrl(imageUrl) && isBase64(imageUrl); +} + +bool isYouTubeUrl(String videoUrl) { + try { + final uri = Uri.parse(videoUrl); + return uri.host == 'www.youtube.com' || + uri.host == 'youtube.com' || + uri.host == 'youtu.be' || + uri.host == 'www.youtu.be'; + } catch (_) { + return false; + } +} + +enum SaveImageResultMethod { network, localStorage } + +@immutable +class SaveImageResult { + const SaveImageResult({required this.error, required this.method}); + + final String? error; + final SaveImageResultMethod method; +} + +Future saveImage({ + required String imageUrl, + required ImageSaverService imageSaverService, +}) async { + final imageFile = File(imageUrl); + final hasPermission = await imageSaverService.hasAccess(); + if (!hasPermission) { + await imageSaverService.requestAccess(); + } + final imageExistsLocally = await imageFile.exists(); + if (!imageExistsLocally) { + try { + await imageSaverService.saveImageFromNetwork( + Uri.parse(appendFileExtensionToImageUrl(imageUrl)), + ); + return const SaveImageResult( + error: null, + method: SaveImageResultMethod.network, + ); + } catch (e) { + return SaveImageResult( + error: e.toString(), + method: SaveImageResultMethod.network, + ); + } + } + try { + await imageSaverService.saveLocalImage(imageUrl); + return const SaveImageResult( + error: null, + method: SaveImageResultMethod.localStorage, + ); + } catch (e) { + return SaveImageResult( + error: e.toString(), + method: SaveImageResultMethod.localStorage, + ); + } +} diff --git a/flutter_quill_extensions/pubspec.yaml b/flutter_quill_extensions/pubspec.yaml index da3c46d87..f15e8f79b 100644 --- a/flutter_quill_extensions/pubspec.yaml +++ b/flutter_quill_extensions/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_quill_extensions description: Embed extensions for flutter_quill including image, video, formula and etc. -version: 0.7.2 +version: 0.8.0 homepage: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/ repository: https://github.com/singerdmx/flutter-quill/tree/master/flutter_quill_extensions/ issue_tracker: https://github.com/singerdmx/flutter-quill/issues/