72 lines
2.8 KiB
TypeScript
72 lines
2.8 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> {
|
|
imageUpload: {
|
|
uploadImage: () => ReturnType;
|
|
};
|
|
}
|
|
}
|
|
|
|
export const ImageUpload = Extension.create({
|
|
name: 'imageUpload',
|
|
|
|
addCommands() {
|
|
return {
|
|
uploadImage: () => ({ editor }) => {
|
|
const taskId = activeTaskId();
|
|
const noteId = activeNoteId();
|
|
|
|
if (!taskId && !noteId) {
|
|
toast.error("Cannot upload image outside of a task or note.");
|
|
return false;
|
|
}
|
|
|
|
const input = document.createElement("input");
|
|
input.type = "file";
|
|
input.accept = "image/*,.heic,.heif";
|
|
input.onchange = async () => {
|
|
if (input.files?.length) {
|
|
const originalFile = input.files[0];
|
|
toast.promise(
|
|
(async () => {
|
|
const webpFile = await convertImageToWebpFile(originalFile);
|
|
if (taskId) {
|
|
return uploadTaskAttachment(taskId, webpFile);
|
|
} else {
|
|
return uploadNoteAttachment(noteId!, webpFile);
|
|
}
|
|
})(),
|
|
{
|
|
loading: "Processing & uploading image...",
|
|
success: ({ url, filename }) => {
|
|
// Insert image
|
|
editor.chain()
|
|
.focus()
|
|
// @ts-ignore
|
|
.setImage({ src: url, filename })
|
|
.run();
|
|
|
|
// Manually force a new paragraph at the end so the user can keep typing
|
|
editor.chain()
|
|
.focus('end')
|
|
.insertContent('<p></p>')
|
|
.run();
|
|
|
|
return "Image uploaded.";
|
|
},
|
|
error: "Failed to upload image."
|
|
}
|
|
);
|
|
}
|
|
};
|
|
input.click();
|
|
return true;
|
|
},
|
|
};
|
|
},
|
|
});
|