mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: unable to upload image from clipboard (#4728)
* fix: unable to upload image from clipboard * chore: apply suggestion
This commit is contained in:
parent
537fa52e77
commit
b60d25a0e3
@ -12,7 +12,7 @@ import 'package:appflowy/workspace/application/view/view_listener.dart';
|
|||||||
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pbserver.dart';
|
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart'
|
import 'package:appflowy_editor/appflowy_editor.dart'
|
||||||
show
|
show
|
||||||
EditorState,
|
EditorState,
|
||||||
@ -54,6 +54,12 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
|
|
||||||
StreamSubscription? _subscription;
|
StreamSubscription? _subscription;
|
||||||
|
|
||||||
|
bool get isLocalMode {
|
||||||
|
final userProfilePB = state.userProfilePB;
|
||||||
|
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
|
||||||
|
return type == AuthenticatorPB.Local;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _documentListener.stop();
|
await _documentListener.stop();
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/application/doc_bloc.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.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_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:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/uuid.dart';
|
import 'package:flowy_infra/uuid.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
extension PasteFromImage on EditorState {
|
extension PasteFromImage on EditorState {
|
||||||
static final supportedImageFormats = [
|
static final supportedImageFormats = [
|
||||||
@ -20,11 +26,20 @@ extension PasteFromImage on EditorState {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final context = document.root.context;
|
||||||
|
|
||||||
|
if (context == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final isLocalMode = context.read<DocumentBloc>().isLocalMode;
|
||||||
|
|
||||||
final path = await getIt<ApplicationDataStorage>().getPath();
|
final path = await getIt<ApplicationDataStorage>().getPath();
|
||||||
final imagePath = p.join(
|
final imagePath = p.join(
|
||||||
path,
|
path,
|
||||||
'images',
|
'images',
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// create the directory if not exists
|
// create the directory if not exists
|
||||||
final directory = Directory(imagePath);
|
final directory = Directory(imagePath);
|
||||||
@ -33,14 +48,52 @@ extension PasteFromImage on EditorState {
|
|||||||
}
|
}
|
||||||
final copyToPath = p.join(
|
final copyToPath = p.join(
|
||||||
imagePath,
|
imagePath,
|
||||||
'${uuid()}.$format',
|
'tmp_${uuid()}.$format',
|
||||||
);
|
);
|
||||||
await File(copyToPath).writeAsBytes(imageBytes);
|
await File(copyToPath).writeAsBytes(imageBytes);
|
||||||
await insertImageNode(copyToPath);
|
final String? path;
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
LocaleKeys.document_imageBlock_imageIsUploading.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocalMode) {
|
||||||
|
path = await saveImageToLocalStorage(copyToPath);
|
||||||
|
} else {
|
||||||
|
final result = await saveImageToCloudStorage(copyToPath);
|
||||||
|
|
||||||
|
final errorMessage = result.$2;
|
||||||
|
|
||||||
|
if (errorMessage != null && context.mounted) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
errorMessage,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = result.$1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path != null) {
|
||||||
|
await insertImageNode(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
await File(copyToPath).delete();
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Log.error('cannot copy image file', e);
|
Log.error('cannot copy image file', e);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBarMessage(
|
||||||
|
context,
|
||||||
|
LocaleKeys.document_imageBlock_error_invalidImage.tr(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import 'package:appflowy/plugins/document/presentation/editor_style.dart';
|
|||||||
import 'package:appflowy/shared/appflowy_network_image.dart';
|
import 'package:appflowy/shared/appflowy_network_image.dart';
|
||||||
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
import 'package:appflowy/workspace/application/view/view_listener.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide UploadImageMenu;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide UploadImageMenu;
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -629,9 +628,7 @@ class DocumentCoverState extends State<DocumentCover> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _isLocalMode() {
|
bool _isLocalMode() {
|
||||||
final userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
|
return context.read<DocumentBloc>().isLocalMode;
|
||||||
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
|
|
||||||
return type == AuthenticatorPB.Local;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,9 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/image/cust
|
|||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_util.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
import 'package:appflowy/util/file_extension.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/home/toast.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
|
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide Log, UploadImageMenu;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log, UploadImageMenu;
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
@ -194,24 +192,9 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> insertLocalImage(String? url) async {
|
Future<void> insertLocalImage(String? url) async {
|
||||||
if (url == null || url.isEmpty) {
|
|
||||||
controller.close();
|
controller.close();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final size = url.fileSize;
|
if (url == null || url.isEmpty) {
|
||||||
if (size == null || size > 10 * 1024 * 1024) {
|
|
||||||
controller.close();
|
|
||||||
setState(() {
|
|
||||||
showLoading = false;
|
|
||||||
this.errorMessage =
|
|
||||||
LocaleKeys.document_imageBlock_uploadImageErrorImageSizeTooBig.tr();
|
|
||||||
});
|
|
||||||
// show error
|
|
||||||
showSnackBarMessage(
|
|
||||||
context,
|
|
||||||
LocaleKeys.document_imageBlock_uploadImageErrorImageSizeTooBig.tr(),
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +206,7 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
|
|||||||
|
|
||||||
// if the user is using local authenticator, we need to save the image to local storage
|
// if the user is using local authenticator, we need to save the image to local storage
|
||||||
if (_isLocalMode()) {
|
if (_isLocalMode()) {
|
||||||
|
// don't limit the image size for local mode.
|
||||||
path = await saveImageToLocalStorage(url);
|
path = await saveImageToLocalStorage(url);
|
||||||
} else {
|
} else {
|
||||||
// else we should save the image to cloud storage
|
// else we should save the image to cloud storage
|
||||||
@ -313,8 +297,6 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool _isLocalMode() {
|
bool _isLocalMode() {
|
||||||
final userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
|
return context.read<DocumentBloc>().isLocalMode;
|
||||||
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
|
|
||||||
return type == AuthenticatorPB.Local;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/application/prelude.dart';
|
import 'package:appflowy/plugins/document/application/prelude.dart';
|
||||||
import 'package:appflowy/shared/custom_image_cache_manager.dart';
|
import 'package:appflowy/shared/custom_image_cache_manager.dart';
|
||||||
import 'package:appflowy/startup/startup.dart';
|
import 'package:appflowy/startup/startup.dart';
|
||||||
|
import 'package:appflowy/util/file_extension.dart';
|
||||||
import 'package:appflowy/workspace/application/settings/application_data_storage.dart';
|
import 'package:appflowy/workspace/application/settings/application_data_storage.dart';
|
||||||
import 'package:appflowy_backend/log.dart';
|
import 'package:appflowy_backend/log.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/uuid.dart';
|
import 'package:flowy_infra/uuid.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
@ -37,6 +40,14 @@ Future<String?> saveImageToLocalStorage(String localImagePath) async {
|
|||||||
Future<(String? path, String? errorMessage)> saveImageToCloudStorage(
|
Future<(String? path, String? errorMessage)> saveImageToCloudStorage(
|
||||||
String localImagePath,
|
String localImagePath,
|
||||||
) async {
|
) async {
|
||||||
|
final size = localImagePath.fileSize;
|
||||||
|
if (size == null || size > 10 * 1024 * 1024) {
|
||||||
|
// 10MB
|
||||||
|
return (
|
||||||
|
null,
|
||||||
|
LocaleKeys.document_imageBlock_uploadImageErrorImageSizeTooBig.tr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
final documentService = DocumentService();
|
final documentService = DocumentService();
|
||||||
final result = await documentService.uploadFile(
|
final result = await documentService.uploadFile(
|
||||||
localFilePath: localImagePath,
|
localFilePath: localImagePath,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user