From 141cb17e8a9d6bc26dacb1c7173356d698b93529 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Wed, 28 May 2025 19:03:14 +0530 Subject: [PATCH] fix: Optimize image uploads in Editor (#7129) * fix: memoize file upload functions * chore: update extension name * chore: update notation * chore: resolve chokidar package * fix: spelling mistakes --- package.json | 3 +- .../custom-image/components/image-block.tsx | 4 +-- .../custom-image/components/image-node.tsx | 4 +-- .../components/image-uploader.tsx | 34 ++++++++++++++----- .../editor/src/core/hooks/use-file-upload.ts | 10 +++++- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 593d84459..050615878 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "nanoid": "3.3.8", "esbuild": "0.25.0", "@babel/helpers": "7.26.10", - "@babel/runtime": "7.26.10" + "@babel/runtime": "7.26.10", + "chokidar": "3.6.0" }, "packageManager": "yarn@1.22.22" } diff --git a/packages/editor/src/core/extensions/custom-image/components/image-block.tsx b/packages/editor/src/core/extensions/custom-image/components/image-block.tsx index 0cc38f5a4..5dfbad012 100644 --- a/packages/editor/src/core/extensions/custom-image/components/image-block.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/image-block.tsx @@ -3,7 +3,7 @@ import React, { useRef, useState, useCallback, useLayoutEffect, useEffect } from // plane utils import { cn } from "@plane/utils"; // extensions -import { CustoBaseImageNodeViewProps, ImageToolbarRoot } from "@/extensions/custom-image"; +import { CustomBaseImageNodeViewProps, ImageToolbarRoot } from "@/extensions/custom-image"; import { ImageUploadStatus } from "./upload-status"; const MIN_SIZE = 100; @@ -38,7 +38,7 @@ const ensurePixelString = (value: Pixel | TDefault | number | undefin return value; }; -type CustomImageBlockProps = CustoBaseImageNodeViewProps & { +type CustomImageBlockProps = CustomBaseImageNodeViewProps & { imageFromFileSystem: string | undefined; setFailedToLoadImage: (isError: boolean) => void; editorContainer: HTMLDivElement | null; diff --git a/packages/editor/src/core/extensions/custom-image/components/image-node.tsx b/packages/editor/src/core/extensions/custom-image/components/image-node.tsx index f8bfcf4a1..8dfe6974b 100644 --- a/packages/editor/src/core/extensions/custom-image/components/image-node.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/image-node.tsx @@ -7,7 +7,7 @@ import { CustomImageBlock, CustomImageUploader, ImageAttributes } from "@/extens // helpers import { getExtensionStorage } from "@/helpers/get-extension-storage"; -export type CustoBaseImageNodeViewProps = { +export type CustomBaseImageNodeViewProps = { getPos: () => number; editor: Editor; node: NodeViewProps["node"] & { @@ -17,7 +17,7 @@ export type CustoBaseImageNodeViewProps = { selected: boolean; }; -export type CustomImageNodeProps = NodeViewProps & CustoBaseImageNodeViewProps; +export type CustomImageNodeProps = NodeViewProps & CustomBaseImageNodeViewProps; export const CustomImageNode = (props: CustomImageNodeProps) => { const { getPos, editor, node, updateAttributes, selected } = props; diff --git a/packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx b/packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx index 5af4f556d..7a7f71f00 100644 --- a/packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx +++ b/packages/editor/src/core/extensions/custom-image/components/image-uploader.tsx @@ -6,12 +6,14 @@ import { cn } from "@plane/utils"; import { ACCEPTED_IMAGE_MIME_TYPES } from "@/constants/config"; import { CORE_EXTENSIONS } from "@/constants/extension"; // extensions -import { CustoBaseImageNodeViewProps, getImageComponentImageFileMap } from "@/extensions/custom-image"; +import { CustomBaseImageNodeViewProps, getImageComponentImageFileMap } from "@/extensions/custom-image"; +// helpers +import { EFileError } from "@/helpers/file"; +import { getExtensionStorage } from "@/helpers/get-extension-storage"; // hooks import { useUploader, useDropZone, uploadFirstFileAndInsertRemaining } from "@/hooks/use-file-upload"; -import { getExtensionStorage } from "@/helpers/get-extension-storage"; -type CustomImageUploaderProps = CustoBaseImageNodeViewProps & { +type CustomImageUploaderProps = CustomBaseImageNodeViewProps & { maxFileSize: number; loadImageFromFileSystem: (file: string) => void; failedToLoadImage: boolean; @@ -71,23 +73,39 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => { }, [imageComponentImageFileMap, imageEntityId, updateAttributes, getPos] ); + + const uploadImageEditorCommand = useCallback( + async (file: File) => await editor?.commands.uploadImage(imageEntityId ?? "", file), + [editor, imageEntityId] + ); + + const handleProgressStatus = useCallback( + (isUploading: boolean) => { + getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY).uploadInProgress = isUploading; + }, + [editor] + ); + // hooks const { isUploading: isImageBeingUploaded, uploadFile } = useUploader({ acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, // @ts-expect-error - TODO: fix typings, and don't remove await from here for now - editorCommand: async (file) => await editor?.commands.uploadImage(imageEntityId, file), - handleProgressStatus: (isUploading) => { - getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY).uploadInProgress = isUploading; - }, + editorCommand: uploadImageEditorCommand, + handleProgressStatus, loadFileFromFileSystem: loadImageFromFileSystem, maxFileSize, onUpload, }); + + const handleInvalidFile = useCallback((_error: EFileError, message: string) => { + alert(message); + }, []); + const { draggedInside, onDrop, onDragEnter, onDragLeave } = useDropZone({ acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, editor, maxFileSize, - onInvalidFile: (_error, message) => alert(message), + onInvalidFile: handleInvalidFile, pos: getPos(), type: "image", uploader: uploadFile, diff --git a/packages/editor/src/core/hooks/use-file-upload.ts b/packages/editor/src/core/hooks/use-file-upload.ts index e40c15913..51116fe52 100644 --- a/packages/editor/src/core/hooks/use-file-upload.ts +++ b/packages/editor/src/core/hooks/use-file-upload.ts @@ -74,7 +74,15 @@ export const useUploader = (args: TUploaderArgs) => { setIsUploading(false); } }, - [acceptedMimeTypes, editorCommand, handleProgressStatus, loadFileFromFileSystem, maxFileSize, onUpload] + [ + acceptedMimeTypes, + editorCommand, + handleProgressStatus, + loadFileFromFileSystem, + maxFileSize, + onInvalidFile, + onUpload, + ] ); return { isUploading, uploadFile };