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 7a7f71f00d..17c9f81773 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 @@ -86,6 +86,10 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => { [editor] ); + const handleInvalidFile = useCallback((_error: EFileError, _file: File, message: string) => { + alert(message); + }, []); + // hooks const { isUploading: isImageBeingUploaded, uploadFile } = useUploader({ acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, @@ -94,18 +98,12 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => { handleProgressStatus, loadFileFromFileSystem: loadImageFromFileSystem, maxFileSize, + onInvalidFile: handleInvalidFile, onUpload, }); - const handleInvalidFile = useCallback((_error: EFileError, message: string) => { - alert(message); - }, []); - const { draggedInside, onDrop, onDragEnter, onDragLeave } = useDropZone({ - acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, editor, - maxFileSize, - onInvalidFile: handleInvalidFile, pos: getPos(), type: "image", uploader: uploadFile, @@ -140,11 +138,8 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => { return; } await uploadFirstFileAndInsertRemaining({ - acceptedMimeTypes: ACCEPTED_IMAGE_MIME_TYPES, editor, filesList, - maxFileSize, - onInvalidFile: (_error, message) => alert(message), 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 51116fe52b..dce48cca5f 100644 --- a/packages/editor/src/core/hooks/use-file-upload.ts +++ b/packages/editor/src/core/hooks/use-file-upload.ts @@ -9,11 +9,11 @@ import { TEditorCommands } from "@/types"; type TUploaderArgs = { acceptedMimeTypes: string[]; - editorCommand: (file: File) => Promise; + editorCommand: (file: File) => Promise; handleProgressStatus?: (isUploading: boolean) => void; loadFileFromFileSystem?: (file: string) => void; maxFileSize: number; - onInvalidFile: (error: EFileError, message: string) => void; + onInvalidFile: (error: EFileError, file: File, message: string) => void; onUpload: (url: string, file: File) => void; }; @@ -38,7 +38,7 @@ export const useUploader = (args: TUploaderArgs) => { acceptedMimeTypes, file, maxFileSize, - onError: onInvalidFile, + onError: (error, message) => onInvalidFile(error, file, message), }); if (!isValid) { handleProgressStatus?.(false); @@ -60,7 +60,7 @@ export const useUploader = (args: TUploaderArgs) => { }; reader.readAsDataURL(file); } - const url: string = await editorCommand(file); + const url = await editorCommand(file); if (!url) { throw new Error("Something went wrong while uploading the file."); @@ -89,17 +89,14 @@ export const useUploader = (args: TUploaderArgs) => { }; type TDropzoneArgs = { - acceptedMimeTypes: string[]; editor: Editor; - maxFileSize: number; - onInvalidFile: (error: EFileError, message: string) => void; pos: number; type: Extract; uploader: (file: File) => Promise; }; export const useDropZone = (args: TDropzoneArgs) => { - const { acceptedMimeTypes, editor, maxFileSize, onInvalidFile, pos, type, uploader } = args; + const { editor, pos, type, uploader } = args; // states const [isDragging, setIsDragging] = useState(false); const [draggedInside, setDraggedInside] = useState(false); @@ -126,22 +123,21 @@ export const useDropZone = (args: TDropzoneArgs) => { async (e: DragEvent) => { e.preventDefault(); setDraggedInside(false); - if (e.dataTransfer.files.length === 0 || !editor.isEditable) { + const filesList = e.dataTransfer.files; + + if (filesList.length === 0 || !editor.isEditable) { return; } - const filesList = e.dataTransfer.files; + await uploadFirstFileAndInsertRemaining({ - acceptedMimeTypes, editor, filesList, - maxFileSize, - onInvalidFile, pos, type, uploader, }); }, - [acceptedMimeTypes, editor, maxFileSize, onInvalidFile, pos, type, uploader] + [editor, pos, type, uploader] ); const onDragEnter = useCallback(() => setDraggedInside(true), []); const onDragLeave = useCallback(() => setDraggedInside(false), []); @@ -156,11 +152,8 @@ export const useDropZone = (args: TDropzoneArgs) => { }; type TMultipleFileArgs = { - acceptedMimeTypes: string[]; editor: Editor; filesList: FileList; - maxFileSize: number; - onInvalidFile: (error: EFileError, message: string) => void; pos: number; type: Extract; uploader: (file: File) => Promise; @@ -168,35 +161,18 @@ type TMultipleFileArgs = { // Upload the first file and insert the remaining ones for uploading multiple files export const uploadFirstFileAndInsertRemaining = async (args: TMultipleFileArgs) => { - const { acceptedMimeTypes, editor, filesList, maxFileSize, onInvalidFile, pos, type, uploader } = args; - const filteredFiles: File[] = []; - for (let i = 0; i < filesList.length; i += 1) { - const file = filesList.item(i); - if ( - file && - isFileValid({ - acceptedMimeTypes, - file, - maxFileSize, - onError: onInvalidFile, - }) - ) { - filteredFiles.push(file); - } - } - if (filteredFiles.length !== filesList.length) { - console.warn("Some files were invalid and have been ignored."); - } - if (filteredFiles.length === 0) { + const { editor, filesList, pos, type, uploader } = args; + const filesArray = Array.from(filesList); + if (filesArray.length === 0) { console.error("No files found to upload."); return; } // Upload the first file - const firstFile = filteredFiles[0]; + const firstFile = filesArray[0]; uploader(firstFile); // Insert the remaining files - const remainingFiles = filteredFiles.slice(1); + const remainingFiles = filesArray.slice(1); if (remainingFiles.length > 0) { const docSize = editor.state.doc.content.size; const posOfNextFileToBeInserted = Math.min(pos + 1, docSize); diff --git a/packages/editor/src/core/plugins/file/delete.ts b/packages/editor/src/core/plugins/file/delete.ts index b77841c229..ac69b18194 100644 --- a/packages/editor/src/core/plugins/file/delete.ts +++ b/packages/editor/src/core/plugins/file/delete.ts @@ -1,5 +1,7 @@ import { Editor } from "@tiptap/core"; import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state"; +// constants +import { CORE_EDITOR_META } from "@/constants/meta"; // plane editor imports import { NODE_FILE_MAP } from "@/plane-editor/constants/utility"; // types @@ -32,7 +34,7 @@ export const TrackFileDeletionPlugin = (editor: Editor, deleteHandler: TFileHand transactions.forEach((transaction) => { // if the transaction has meta of skipFileDeletion set to true, then return (like while clearing the editor content programmatically) - if (transaction.getMeta("skipFileDeletion")) return; + if (transaction.getMeta(CORE_EDITOR_META.SKIP_FILE_DELETION)) return; const removedFiles: TFileNode[] = [];