Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code documentations and new event for confirm remove the image #1414

Merged
merged 4 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be nullable, instead of passing the default parameter of the function that just returns true.

});
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't bump minimum plugin versions unless there is a major version/breaking change or we need to use a api feature that's only in a newer plugin

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