fix: unable to upload image from clipboard (#4728)

* fix: unable to upload image from clipboard

* chore: apply suggestion
This commit is contained in:
Lucas.Xu 2024-02-25 17:50:35 +07:00 committed by GitHub
parent 537fa52e77
commit b60d25a0e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 78 additions and 29 deletions

View File

@ -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-error/errors.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'
show
EditorState,
@ -54,6 +54,12 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
StreamSubscription? _subscription;
bool get isLocalMode {
final userProfilePB = state.userProfilePB;
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
return type == AuthenticatorPB.Local;
}
@override
Future<void> close() async {
await _documentListener.stop();

View File

@ -1,12 +1,18 @@
import 'dart:io';
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/workspace/application/settings/application_data_storage.dart';
import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/uuid.dart';
import 'package:path/path.dart' as p;
import 'package:provider/provider.dart';
extension PasteFromImage on EditorState {
static final supportedImageFormats = [
@ -20,11 +26,20 @@ extension PasteFromImage on EditorState {
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 imagePath = p.join(
path,
'images',
);
try {
// create the directory if not exists
final directory = Directory(imagePath);
@ -33,14 +48,52 @@ extension PasteFromImage on EditorState {
}
final copyToPath = p.join(
imagePath,
'${uuid()}.$format',
'tmp_${uuid()}.$format',
);
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;
} catch (e) {
Log.error('cannot copy image file', e);
if (context.mounted) {
showSnackBarMessage(
context,
LocaleKeys.document_imageBlock_error_invalidImage.tr(),
);
}
}
return false;
}
}

View File

@ -13,7 +13,6 @@ import 'package:appflowy/plugins/document/presentation/editor_style.dart';
import 'package:appflowy/shared/appflowy_network_image.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-user/protobuf.dart';
import 'package:appflowy_editor/appflowy_editor.dart' hide UploadImageMenu;
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
@ -629,9 +628,7 @@ class DocumentCoverState extends State<DocumentCover> {
}
bool _isLocalMode() {
final userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
return type == AuthenticatorPB.Local;
return context.read<DocumentBloc>().isLocalMode;
}
}

View File

@ -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/upload_image_menu.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/presentation/home/toast.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_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
@ -194,24 +192,9 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
}
Future<void> insertLocalImage(String? url) async {
if (url == null || url.isEmpty) {
controller.close();
return;
}
controller.close();
final size = url.fileSize;
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(),
);
if (url == null || url.isEmpty) {
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 (_isLocalMode()) {
// don't limit the image size for local mode.
path = await saveImageToLocalStorage(url);
} else {
// else we should save the image to cloud storage
@ -313,8 +297,6 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
}
bool _isLocalMode() {
final userProfilePB = context.read<DocumentBloc>().state.userProfilePB;
final type = userProfilePB?.authenticator ?? AuthenticatorPB.Local;
return type == AuthenticatorPB.Local;
return context.read<DocumentBloc>().isLocalMode;
}
}

View File

@ -1,10 +1,13 @@
import 'dart:io';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/application/prelude.dart';
import 'package:appflowy/shared/custom_image_cache_manager.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_backend/log.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/uuid.dart';
import 'package:path/path.dart' as p;
@ -37,6 +40,14 @@ Future<String?> saveImageToLocalStorage(String localImagePath) async {
Future<(String? path, String? errorMessage)> saveImageToCloudStorage(
String localImagePath,
) async {
final size = localImagePath.fileSize;
if (size == null || size > 10 * 1024 * 1024) {
// 10MB
return (
null,
LocaleKeys.document_imageBlock_uploadImageErrorImageSizeTooBig.tr(),
);
}
final documentService = DocumentService();
final result = await documentService.uploadFile(
localFilePath: localImagePath,