import { Extension } from '@tiptap/core'; import { activeTaskId, uploadTaskAttachment, activeNoteId, uploadNoteAttachment } from "@/store"; import { convertImageToWebpFile } from "@/lib/utils"; import { toast } from "solid-sonner"; declare module '@tiptap/core' { interface Commands { mediaUpload: { uploadMedia: () => ReturnType; }; } } export const MediaUpload = Extension.create({ name: 'mediaUpload', addCommands() { return { uploadMedia: () => ({ editor }) => { const taskId = activeTaskId(); const noteId = activeNoteId(); if (!taskId && !noteId) { toast.error("Cannot upload media outside of a task or note."); return false; } const input = document.createElement("input"); input.type = "file"; input.onchange = async () => { if (input.files?.length) { const originalFile = input.files[0]; const isImage = originalFile.type.startsWith('image/'); const isVideo = originalFile.type.startsWith('video/'); toast.promise( (async () => { let fileToUpload = originalFile; if (isImage && !originalFile.type.includes('svg') && !originalFile.type.includes('gif')) { fileToUpload = await convertImageToWebpFile(originalFile); } if (taskId) { return uploadTaskAttachment(taskId, fileToUpload); } else { return uploadNoteAttachment(noteId!, fileToUpload); } })(), { loading: "Processing & uploading media...", success: ({ url, filename }) => { if (isImage) { // @ts-ignore editor.chain().focus().setImage({ src: url, filename }).run(); } else if (isVideo) { editor.chain().focus().setVideo({ src: url, filename }).run(); } else { editor.chain().focus().insertFileAttachment({ src: url, filename, filesize: originalFile.size.toString() }).run(); } // Manually force a new paragraph at the end so the user can keep typing editor.chain() .focus('end') .insertContent('

') .run(); return "Media uploaded."; }, error: "Failed to upload media." } ); } }; input.click(); return true; }, }; }, });