mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: support pasting web image on mobile (#5987)
* fix: support pasting web image on mobile * fix: permission check will deactive editor focus
This commit is contained in:
parent
e6bf6a5c7d
commit
44fb610269
@ -100,9 +100,7 @@ class ClipboardService {
|
|||||||
|
|
||||||
for (final item in reader.items) {
|
for (final item in reader.items) {
|
||||||
final availableFormats = await item.rawReader!.getAvailableFormats();
|
final availableFormats = await item.rawReader!.getAvailableFormats();
|
||||||
Log.debug(
|
Log.info('availableFormats: $availableFormats');
|
||||||
'availableFormats: $availableFormats',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final plainText = await reader.readValue(Formats.plainText);
|
final plainText = await reader.readValue(Formats.plainText);
|
||||||
@ -115,6 +113,8 @@ class ClipboardService {
|
|||||||
image = ('jpeg', await reader.readFile(Formats.jpeg));
|
image = ('jpeg', await reader.readFile(Formats.jpeg));
|
||||||
} else if (reader.canProvide(Formats.gif)) {
|
} else if (reader.canProvide(Formats.gif)) {
|
||||||
image = ('gif', await reader.readFile(Formats.gif));
|
image = ('gif', await reader.readFile(Formats.gif));
|
||||||
|
} else if (reader.canProvide(Formats.webp)) {
|
||||||
|
image = ('webp', await reader.readFile(Formats.webp));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ClipboardServiceData(
|
return ClipboardServiceData(
|
||||||
|
@ -76,6 +76,7 @@ CommandShortcutEventHandler _pasteCommandHandler = (editorState) {
|
|||||||
image.$1,
|
image.$1,
|
||||||
image.$2!,
|
image.$2!,
|
||||||
documentId,
|
documentId,
|
||||||
|
selection: selection,
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
Log.info('Pasted image');
|
Log.info('Pasted image');
|
||||||
|
@ -9,7 +9,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/image/imag
|
|||||||
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
import 'package:appflowy/shared/patterns/common_patterns.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/application_data_storage.dart';
|
import 'package:appflowy/workspace/application/settings/application_data_storage.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/toast.dart';
|
import 'package:appflowy/workspace/presentation/widgets/dialogs.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:cross_file/cross_file.dart';
|
import 'package:cross_file/cross_file.dart';
|
||||||
@ -23,6 +23,7 @@ extension PasteFromImage on EditorState {
|
|||||||
'png',
|
'png',
|
||||||
'jpeg',
|
'jpeg',
|
||||||
'gif',
|
'gif',
|
||||||
|
'webp',
|
||||||
];
|
];
|
||||||
|
|
||||||
Future<void> dropImages(
|
Future<void> dropImages(
|
||||||
@ -64,18 +65,26 @@ extension PasteFromImage on EditorState {
|
|||||||
Future<bool> pasteImage(
|
Future<bool> pasteImage(
|
||||||
String format,
|
String format,
|
||||||
Uint8List imageBytes,
|
Uint8List imageBytes,
|
||||||
String documentId,
|
String documentId, {
|
||||||
) async {
|
Selection? selection,
|
||||||
if (!supportedImageFormats.contains(format)) {
|
}) async {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final context = document.root.context;
|
final context = document.root.context;
|
||||||
|
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!supportedImageFormats.contains(format)) {
|
||||||
|
Log.info('unsupported format: $format');
|
||||||
|
if (PlatformExtension.isMobile) {
|
||||||
|
showToastNotification(
|
||||||
|
context,
|
||||||
|
message: LocaleKeys.document_imageBlock_error_invalidImageFormat.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
final isLocalMode = context.read<DocumentBloc>().isLocalMode;
|
final isLocalMode = context.read<DocumentBloc>().isLocalMode;
|
||||||
|
|
||||||
final path = await getIt<ApplicationDataStorage>().getPath();
|
final path = await getIt<ApplicationDataStorage>().getPath();
|
||||||
@ -105,9 +114,9 @@ extension PasteFromImage on EditorState {
|
|||||||
final errorMessage = result.$2;
|
final errorMessage = result.$2;
|
||||||
|
|
||||||
if (errorMessage != null && context.mounted) {
|
if (errorMessage != null && context.mounted) {
|
||||||
showSnackBarMessage(
|
showToastNotification(
|
||||||
context,
|
context,
|
||||||
errorMessage,
|
message: errorMessage,
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -116,7 +125,7 @@ extension PasteFromImage on EditorState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
await insertImageNode(path);
|
await insertImageNode(path, selection: selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
await File(copyToPath).delete();
|
await File(copyToPath).delete();
|
||||||
@ -124,13 +133,55 @@ extension PasteFromImage on EditorState {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('cannot copy image file', e);
|
Log.error('cannot copy image file', e);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showSnackBarMessage(
|
showToastNotification(
|
||||||
context,
|
context,
|
||||||
LocaleKeys.document_imageBlock_error_invalidImage.tr(),
|
message: LocaleKeys.document_imageBlock_error_invalidImage.tr(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> insertImageNode(
|
||||||
|
String src, {
|
||||||
|
Selection? selection,
|
||||||
|
}) async {
|
||||||
|
selection ??= this.selection;
|
||||||
|
if (selection == null || !selection.isCollapsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final node = getNodeAtPath(selection.end.path);
|
||||||
|
if (node == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final transaction = this.transaction;
|
||||||
|
// if the current node is empty paragraph, replace it with image node
|
||||||
|
if (node.type == ParagraphBlockKeys.type &&
|
||||||
|
(node.delta?.isEmpty ?? false)) {
|
||||||
|
transaction
|
||||||
|
..insertNode(
|
||||||
|
node.path,
|
||||||
|
imageNode(
|
||||||
|
url: src,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
..deleteNode(node);
|
||||||
|
} else {
|
||||||
|
transaction.insertNode(
|
||||||
|
node.path.next,
|
||||||
|
imageNode(
|
||||||
|
url: src,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.afterSelection = Selection.collapsed(
|
||||||
|
Position(
|
||||||
|
path: node.path.next,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return apply(transaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart';
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -23,7 +24,7 @@ List<ContextMenuButtonItem> buildMobileFloatingToolbarItems(
|
|||||||
ContextMenuButtonItem(
|
ContextMenuButtonItem(
|
||||||
label: LocaleKeys.editor_copy.tr(),
|
label: LocaleKeys.editor_copy.tr(),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
copyCommand.execute(editorState);
|
customCopyCommand.execute(editorState);
|
||||||
closeToolbar();
|
closeToolbar();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -34,7 +35,7 @@ List<ContextMenuButtonItem> buildMobileFloatingToolbarItems(
|
|||||||
ContextMenuButtonItem(
|
ContextMenuButtonItem(
|
||||||
label: LocaleKeys.editor_paste.tr(),
|
label: LocaleKeys.editor_paste.tr(),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
pasteCommand.execute(editorState);
|
customPasteCommand.execute(editorState);
|
||||||
closeToolbar();
|
closeToolbar();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
Loading…
Reference in New Issue
Block a user