feat: add paste gif from clipboard (#1788)

pull/1794/head
Sobhan Moradi 1 year ago committed by GitHub
parent 63c8af67b3
commit 05c17e1ebc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 15
      example/lib/screens/quill/my_quill_editor.dart
  2. 8
      lib/src/models/config/editor/editor_configurations.dart
  3. 3
      lib/src/models/config/raw_editor/raw_editor_configurations.dart
  4. 1
      lib/src/widgets/editor/editor.dart
  5. 54
      lib/src/widgets/raw_editor/raw_editor_state.dart

@ -80,6 +80,21 @@ class MyQuillEditor extends StatelessWidget {
).writeAsBytes(imageBytes, flush: true);
return file.path;
},
onGifPaste: (gifBytes) async {
if (isWeb()) {
return null;
}
// We will save it to system temporary files
final newFileName = '${DateTime.now().toIso8601String()}.gif';
final newPath = path.join(
io.Directory.systemTemp.path,
newFileName,
);
final file = await io.File(
newPath,
).writeAsBytes(gifBytes, flush: true);
return file.path;
},
embedBuilders: [
...(isWeb()
? FlutterQuillEmbeds.editorWebBuilders()

@ -61,6 +61,7 @@ class QuillEditorConfigurations extends Equatable {
this.floatingCursorDisabled = false,
this.textSelectionControls,
this.onImagePaste,
this.onGifPaste,
this.customShortcuts,
this.customActions,
this.detectWordBoundary = true,
@ -282,6 +283,11 @@ class QuillEditorConfigurations extends Equatable {
/// Returns the url of the image if the image should be inserted.
final Future<String?> Function(Uint8List imageBytes)? onImagePaste;
/// Callback when the user pastes the given gif.
///
/// Returns the url of the gif if the gif should be inserted.
final Future<String?> Function(Uint8List imageBytes)? onGifPaste;
/// Contains user-defined shortcuts map.
///
/// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#shortcuts]
@ -391,6 +397,7 @@ class QuillEditorConfigurations extends Equatable {
bool? floatingCursorDisabled,
TextSelectionControls? textSelectionControls,
Future<String?> Function(Uint8List imageBytes)? onImagePaste,
Future<String?> Function(Uint8List imageBytes)? onGifPaste,
Map<ShortcutActivator, Intent>? customShortcuts,
Map<Type, Action<Intent>>? customActions,
bool? detectWordBoundary,
@ -449,6 +456,7 @@ class QuillEditorConfigurations extends Equatable {
textSelectionControls:
textSelectionControls ?? this.textSelectionControls,
onImagePaste: onImagePaste ?? this.onImagePaste,
onGifPaste: onGifPaste ?? this.onGifPaste,
customShortcuts: customShortcuts ?? this.customShortcuts,
customActions: customActions ?? this.customActions,
detectWordBoundary: detectWordBoundary ?? this.detectWordBoundary,

@ -73,6 +73,7 @@ class QuillRawEditorConfigurations extends Equatable {
this.customRecognizerBuilder,
this.floatingCursorDisabled = false,
this.onImagePaste,
this.onGifPaste,
this.customLinkPrefixes = const <String>[],
this.dialogTheme,
this.contentInsertionConfiguration,
@ -261,6 +262,8 @@ class QuillRawEditorConfigurations extends Equatable {
final Future<String?> Function(Uint8List imageBytes)? onImagePaste;
final Future<String?> Function(Uint8List imageBytes)? onGifPaste;
/// Contains user-defined shortcuts map.
///
/// [https://docs.flutter.dev/development/ui/advanced/actions-and-shortcuts#shortcuts]

@ -277,6 +277,7 @@ class QuillEditorState extends State<QuillEditor>
customRecognizerBuilder: configurations.customRecognizerBuilder,
floatingCursorDisabled: configurations.floatingCursorDisabled,
onImagePaste: configurations.onImagePaste,
onGifPaste: configurations.onGifPaste,
customShortcuts: configurations.customShortcuts,
customActions: configurations.customActions,
customLinkPrefixes: configurations.customLinkPrefixes,

@ -279,26 +279,50 @@ class QuillRawEditorState extends EditorState
if (onImagePaste != null) {
if (clipboard != null) {
final reader = await clipboard.read();
if (!reader.canProvide(Formats.png)) {
return;
if (reader.canProvide(Formats.png)) {
reader.getFile(Formats.png, (value) async {
final image = value;
final imageUrl = await onImagePaste(await image.readAll());
if (imageUrl == null) {
return;
}
controller.replaceText(
textEditingValue.selection.end,
0,
BlockEmbed.image(imageUrl),
null,
);
});
}
reader.getFile(Formats.png, (value) async {
final image = value;
}
}
final imageUrl = await onImagePaste(await image.readAll());
if (imageUrl == null) {
return;
}
final onGifPaste = widget.configurations.onGifPaste;
if (onGifPaste != null) {
if (clipboard != null) {
final reader = await clipboard.read();
if (reader.canProvide(Formats.gif)) {
reader.getFile(Formats.gif, (value) async {
final gif = value;
controller.replaceText(
textEditingValue.selection.end,
0,
BlockEmbed.image(imageUrl),
null,
);
});
final gifUrl = await onGifPaste(await gif.readAll());
if (gifUrl == null) {
return;
}
controller.replaceText(
textEditingValue.selection.end,
0,
BlockEmbed.image(gifUrl),
null,
);
});
}
}
}
return;
}
/// Select the entire text value.

Loading…
Cancel
Save