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
This commit is contained in:
Aaryan Khandelwal
2025-05-28 19:03:14 +05:30
committed by GitHub
parent 26b62c4a70
commit 141cb17e8a
5 changed files with 41 additions and 14 deletions

View File

@@ -30,7 +30,8 @@
"nanoid": "3.3.8", "nanoid": "3.3.8",
"esbuild": "0.25.0", "esbuild": "0.25.0",
"@babel/helpers": "7.26.10", "@babel/helpers": "7.26.10",
"@babel/runtime": "7.26.10" "@babel/runtime": "7.26.10",
"chokidar": "3.6.0"
}, },
"packageManager": "yarn@1.22.22" "packageManager": "yarn@1.22.22"
} }

View File

@@ -3,7 +3,7 @@ import React, { useRef, useState, useCallback, useLayoutEffect, useEffect } from
// plane utils // plane utils
import { cn } from "@plane/utils"; import { cn } from "@plane/utils";
// extensions // extensions
import { CustoBaseImageNodeViewProps, ImageToolbarRoot } from "@/extensions/custom-image"; import { CustomBaseImageNodeViewProps, ImageToolbarRoot } from "@/extensions/custom-image";
import { ImageUploadStatus } from "./upload-status"; import { ImageUploadStatus } from "./upload-status";
const MIN_SIZE = 100; const MIN_SIZE = 100;
@@ -38,7 +38,7 @@ const ensurePixelString = <TDefault,>(value: Pixel | TDefault | number | undefin
return value; return value;
}; };
type CustomImageBlockProps = CustoBaseImageNodeViewProps & { type CustomImageBlockProps = CustomBaseImageNodeViewProps & {
imageFromFileSystem: string | undefined; imageFromFileSystem: string | undefined;
setFailedToLoadImage: (isError: boolean) => void; setFailedToLoadImage: (isError: boolean) => void;
editorContainer: HTMLDivElement | null; editorContainer: HTMLDivElement | null;

View File

@@ -7,7 +7,7 @@ import { CustomImageBlock, CustomImageUploader, ImageAttributes } from "@/extens
// helpers // helpers
import { getExtensionStorage } from "@/helpers/get-extension-storage"; import { getExtensionStorage } from "@/helpers/get-extension-storage";
export type CustoBaseImageNodeViewProps = { export type CustomBaseImageNodeViewProps = {
getPos: () => number; getPos: () => number;
editor: Editor; editor: Editor;
node: NodeViewProps["node"] & { node: NodeViewProps["node"] & {
@@ -17,7 +17,7 @@ export type CustoBaseImageNodeViewProps = {
selected: boolean; selected: boolean;
}; };
export type CustomImageNodeProps = NodeViewProps & CustoBaseImageNodeViewProps; export type CustomImageNodeProps = NodeViewProps & CustomBaseImageNodeViewProps;
export const CustomImageNode = (props: CustomImageNodeProps) => { export const CustomImageNode = (props: CustomImageNodeProps) => {
const { getPos, editor, node, updateAttributes, selected } = props; const { getPos, editor, node, updateAttributes, selected } = props;

View File

@@ -6,12 +6,14 @@ import { cn } from "@plane/utils";
import { ACCEPTED_IMAGE_MIME_TYPES } from "@/constants/config"; import { ACCEPTED_IMAGE_MIME_TYPES } from "@/constants/config";
import { CORE_EXTENSIONS } from "@/constants/extension"; import { CORE_EXTENSIONS } from "@/constants/extension";
// extensions // 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 // hooks
import { useUploader, useDropZone, uploadFirstFileAndInsertRemaining } from "@/hooks/use-file-upload"; import { useUploader, useDropZone, uploadFirstFileAndInsertRemaining } from "@/hooks/use-file-upload";
import { getExtensionStorage } from "@/helpers/get-extension-storage";
type CustomImageUploaderProps = CustoBaseImageNodeViewProps & { type CustomImageUploaderProps = CustomBaseImageNodeViewProps & {
maxFileSize: number; maxFileSize: number;
loadImageFromFileSystem: (file: string) => void; loadImageFromFileSystem: (file: string) => void;
failedToLoadImage: boolean; failedToLoadImage: boolean;
@@ -71,23 +73,39 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => {
}, },
[imageComponentImageFileMap, imageEntityId, updateAttributes, getPos] [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 // hooks
const { isUploading: isImageBeingUploaded, uploadFile } = useUploader({ const { isUploading: isImageBeingUploaded, uploadFile } = useUploader({
acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES,
// @ts-expect-error - TODO: fix typings, and don't remove await from here for now // @ts-expect-error - TODO: fix typings, and don't remove await from here for now
editorCommand: async (file) => await editor?.commands.uploadImage(imageEntityId, file), editorCommand: uploadImageEditorCommand,
handleProgressStatus: (isUploading) => { handleProgressStatus,
getExtensionStorage(editor, CORE_EXTENSIONS.UTILITY).uploadInProgress = isUploading;
},
loadFileFromFileSystem: loadImageFromFileSystem, loadFileFromFileSystem: loadImageFromFileSystem,
maxFileSize, maxFileSize,
onUpload, onUpload,
}); });
const handleInvalidFile = useCallback((_error: EFileError, message: string) => {
alert(message);
}, []);
const { draggedInside, onDrop, onDragEnter, onDragLeave } = useDropZone({ const { draggedInside, onDrop, onDragEnter, onDragLeave } = useDropZone({
acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES,
editor, editor,
maxFileSize, maxFileSize,
onInvalidFile: (_error, message) => alert(message), onInvalidFile: handleInvalidFile,
pos: getPos(), pos: getPos(),
type: "image", type: "image",
uploader: uploadFile, uploader: uploadFile,

View File

@@ -74,7 +74,15 @@ export const useUploader = (args: TUploaderArgs) => {
setIsUploading(false); setIsUploading(false);
} }
}, },
[acceptedMimeTypes, editorCommand, handleProgressStatus, loadFileFromFileSystem, maxFileSize, onUpload] [
acceptedMimeTypes,
editorCommand,
handleProgressStatus,
loadFileFromFileSystem,
maxFileSize,
onInvalidFile,
onUpload,
]
); );
return { isUploading, uploadFile }; return { isUploading, uploadFile };