80 lines
3.4 KiB
TypeScript
80 lines
3.4 KiB
TypeScript
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<ReturnType> {
|
|
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('<p></p>')
|
|
.run();
|
|
|
|
return "Media uploaded.";
|
|
},
|
|
error: "Failed to upload media."
|
|
}
|
|
);
|
|
}
|
|
};
|
|
input.click();
|
|
return true;
|
|
},
|
|
};
|
|
},
|
|
});
|