Skip to content

Commit

Permalink
Code documentations and new event for confirm remove the image (#1414)
Browse files Browse the repository at this point in the history
* Add a event that triggers after removing the image from the editor && delete unused dependencies and upgrade all packages and plugins and remove gallery_saver which has not been updated for more than 23 months, it was a great plugin but it old now, and I also add some simple documentation and other minor improvements

* I have add a documentation comments to flutter_quill_extensions, add new event to allow the user to confirm removing the image before actually remove it, translated some text in Arabic languague since it was incorrect or missing

* Fix analyzer error
  • Loading branch information
EchoEllet authored Sep 29, 2023
1 parent 3e0ed12 commit b722475
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 22 deletions.
2 changes: 2 additions & 0 deletions example/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import gal
import pasteboard
import path_provider_foundation
import url_launcher_macos
import video_player_avfoundation

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
Expand All @@ -19,4 +20,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PasteboardPlugin.register(with: registry.registrar(forPlugin: "PasteboardPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
}
27 changes: 20 additions & 7 deletions flutter_quill_extensions/lib/embeds/builders.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ import 'widgets/video_app.dart';
import 'widgets/youtube_video_app.dart';

class ImageEmbedBuilder extends EmbedBuilder {
ImageEmbedBuilder({required this.afterRemoveImageFromEditor});
ImageEmbedBuilder({
required this.afterRemoveImageFromEditor,
required this.shouldRemoveImageFromEditor,
});
final ImageEmbedBuilderAfterRemoveImageFromEditor afterRemoveImageFromEditor;
final ImageEmbedBuilderShouldRemoveImageFromEditor
shouldRemoveImageFromEditor;

@override
String get key => BlockEmbed.imageType;
Expand Down Expand Up @@ -128,18 +133,26 @@ class ImageEmbedBuilder extends EmbedBuilder {
color: Colors.red.shade200,
text: 'Remove'.i18n,
onPressed: () async {
final navigator = Navigator.of(context);
final offset =
getEmbedNode(controller, controller.selection.start)
.offset;
Navigator.of(context).pop();

final imageFile = File(imageUrl);
final shouldRemoveImage =
await shouldRemoveImageFromEditor(imageFile);

if (!shouldRemoveImage) {
return;
}
final offset = getEmbedNode(
controller,
controller.selection.start,
).offset;
controller.replaceText(
offset,
1,
'',
TextSelection.collapsed(offset: offset),
);
navigator.pop();
await afterRemoveImageFromEditor(File(imageUrl));
await afterRemoveImageFromEditor(imageFile);
},
);
return Padding(
Expand Down
8 changes: 7 additions & 1 deletion flutter_quill_extensions/lib/embeds/embed_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ class QuillFile {
}

typedef ImageEmbedBuilderAfterRemoveImageFromEditor = Future<void> Function(
File imageFile);
File imageFile,
);

typedef ImageEmbedBuilderShouldRemoveImageFromEditor = Future<bool> Function(
File imageFile,
);

105 changes: 97 additions & 8 deletions flutter_quill_extensions/lib/flutter_quill_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,44 +20,133 @@ export 'embeds/toolbar/video_button.dart';
export 'embeds/utils.dart';

class FlutterQuillEmbeds {
/// Returns a list of embed builders for Quill editors.
/// Returns a list of embed builders for QuillEditor.
///
/// **Note:** This method is not intended for web usage.
/// For web-specific embeds, use [webBuilders].
///
/// [onVideoInit] is called when a video is initialized.
/// [onRemoveImage] is called when an image is removed from the editor.
/// By default, [onRemoveImage] deletes the cached image if it still exists.
/// If you want to customize
/// the behavior, pass your own function that handles the removal.
///
/// Example of [onRemoveImage] customization:
/// [afterRemoveImageFromEditor] is called when an image
/// is removed from the editor.
/// By default, [afterRemoveImageFromEditor] deletes the cached
/// image if it still exists.
/// If you want to customize the behavior, pass your own function
/// that handles the removal.
///
/// Example of [afterRemoveImageFromEditor] customization:
/// ```dart
/// onRemoveImage: (imageFile) async {
/// afterRemoveImageFromEditor: (imageFile) async {
/// // Your custom logic here
/// // or leave it empty to do nothing
/// }
/// ```
///
/// [shouldRemoveImageFromEditor] is called when the user
/// attempts to remove an image
/// from the editor. It allows you to control whether the image
/// should be removed
/// based on your custom logic.
///
/// Example of [shouldRemoveImageFromEditor] customization:
/// ```dart
/// shouldRemoveImageFromEditor: (imageFile) async {
/// // Show a confirmation dialog before removing the image
/// final isShouldRemove = await showYesCancelDialog(
/// context: context,
/// options: const YesOrCancelDialogOptions(
/// title: 'Deleting an image',
/// message: 'Are you sure you want to delete this image
/// from the editor?',
/// ),
/// );
///
/// // Return `true` to allow image removal if the user confirms, otherwise `false`
/// return isShouldRemove;
/// }
/// ```
static List<EmbedBuilder> builders({
void Function(GlobalKey videoContainerKey)? onVideoInit,
ImageEmbedBuilderAfterRemoveImageFromEditor? afterRemoveImageFromEditor,
ImageEmbedBuilderShouldRemoveImageFromEditor? shouldRemoveImageFromEditor,
}) =>
[
ImageEmbedBuilder(
afterRemoveImageFromEditor: afterRemoveImageFromEditor ??
(imageFile) async {
// TODO: Please change this default code
// TODO: Change the default event if you want to
final fileExists = await imageFile.exists();
if (fileExists) {
await imageFile.delete();
}
},
shouldRemoveImageFromEditor: shouldRemoveImageFromEditor ??
(imageFile) {
// TODO: Before pubish the changes
// please consider change the name
// of the events if you want to
return Future.value(true);
},
),
VideoEmbedBuilder(onVideoInit: onVideoInit),
FormulaEmbedBuilder(),
];

/// Returns a list of embed builders specifically designed for web support.
///
/// [ImageEmbedBuilderWeb] is the embed builder for handling
/// images on the web.
///
static List<EmbedBuilder> webBuilders() => [
ImageEmbedBuilderWeb(),
];

/// Returns a list of embed button builders to customize the toolbar buttons.
///
/// [showImageButton] determines whether the image button should be displayed.
/// [showVideoButton] determines whether the video button should be displayed.
/// [showCameraButton] determines whether the camera button should
/// be displayed.
/// [showFormulaButton] determines whether the formula button
/// should be displayed.
///
/// [imageButtonTooltip] specifies the tooltip text for the image button.
/// [videoButtonTooltip] specifies the tooltip text for the video button.
/// [cameraButtonTooltip] specifies the tooltip text for the camera button.
/// [formulaButtonTooltip] specifies the tooltip text for the formula button.
///
/// [onImagePickCallback] is a callback function called when an
/// image is picked.
/// [onVideoPickCallback] is a callback function called when a
/// video is picked.
///
/// [mediaPickSettingSelector] allows customizing media pick settings.
/// [cameraPickSettingSelector] allows customizing camera pick settings.
///
/// Example of customizing media pick settings for the image button:
/// ```dart
/// mediaPickSettingSelector: (context) async {
/// final mediaPickSetting = await showModalBottomSheet<MediaPickSetting>(
/// showDragHandle: true,
/// context: context,
/// constraints: const BoxConstraints(maxWidth: 640),
/// builder: (context) => const SelectImageSourceDialog(),
/// );
/// if (mediaPickSetting == null) {
/// return null;
/// }
/// return mediaPickSetting;
/// }
/// ```
///
/// [filePickImpl] is an implementation for picking files.
/// [webImagePickImpl] is an implementation for picking web images.
/// [webVideoPickImpl] is an implementation for picking web videos.
///
/// [imageLinkRegExp] is a regular expression to identify image links.
/// [videoLinkRegExp] is a regular expression to identify video links.
///
/// The returned list contains embed button builders for the Quill toolbar.
static List<EmbedButtonBuilder> buttons({
bool showImageButton = true,
bool showVideoButton = true,
Expand Down
8 changes: 4 additions & 4 deletions lib/src/translations/toolbar.i18n.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ extension Localization on String {
'Align right': 'محاذاة اليمين',
// i think it should be 'Justify with width'
// it is wrong in all properties
'Justify win width': 'Justify win width',
'Justify win width': 'تبرير مع العرض',
'Text direction': 'اتجاه النص',
'Header style': 'ستايل العنوان',
'Numbered list': 'قائمة مرقمة',
Expand All @@ -217,9 +217,9 @@ extension Localization on String {
'Hex': 'Hex',
'Material': 'Material',
'Color': 'اللون',
'Find text': 'Find text',
'Move to previous occurrence': 'Move to previous occurrence',
'Move to next occurrence': 'Move to next occurrence',
'Find text': 'بحث عن نص',
'Move to previous occurrence': 'الانتقال إلى الحدث السابق',
'Move to next occurrence': 'الانتقال إلى الحدث التالي',
},
'da': {
'Paste a link': 'Indsæt link',
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ dependencies:
flutter_colorpicker: ^1.0.3
flutter_keyboard_visibility: ^5.4.1
quiver: ^3.2.1
url_launcher: ^6.1.12
url_launcher: ^6.1.14
pedantic: ^1.11.1
characters: ^1.3.0
diff_match_patch: ^0.4.1
i18n_extension: ^9.0.2
device_info_plus: ^9.0.3
platform: ^3.1.0
platform: ^3.1.2
pasteboard: ^0.2.0

# Dependencies for testing utilities
Expand Down

0 comments on commit b722475

Please sign in to comment.