From df94685c9682c0653d6e10c8211af5be3822f86d Mon Sep 17 00:00:00 2001 From: Timothy Cardoza Date: Thu, 12 Mar 2026 17:23:28 -0500 Subject: [PATCH] cleanup (broken files) --- src/lib/extensions/file-upload.ts | 5 ++-- src/lib/extensions/image-upload.ts | 4 +-- src/lib/extensions/image.ts | 44 ++++++++++++++++-------------- src/lib/extensions/video-upload.ts | 4 +-- src/lib/extensions/video.ts | 38 +++++++++++++++++--------- src/store/index.ts | 17 +++++++----- 6 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/lib/extensions/file-upload.ts b/src/lib/extensions/file-upload.ts index 676ca66..bd7a1d3 100644 --- a/src/lib/extensions/file-upload.ts +++ b/src/lib/extensions/file-upload.ts @@ -32,7 +32,6 @@ export const FileUpload = Extension.create({ input.onchange = async () => { if (input.files?.length) { const file = input.files[0]; - const filename = file.name; const filesize = file.size.toString(); toast.promise( @@ -45,11 +44,11 @@ export const FileUpload = Extension.create({ })(), { loading: "Uploading file...", - success: (url) => { + success: ({ url, filename: pbFilename }) => { // Insert file attchment UI card editor.chain() .focus() - .insertFileAttachment({ src: url, filename, filesize }) + .insertFileAttachment({ src: url, filename: pbFilename, filesize }) .run(); // Manually force a new paragraph at the end so the user can keep typing diff --git a/src/lib/extensions/image-upload.ts b/src/lib/extensions/image-upload.ts index 5c06f21..e2ccd3e 100644 --- a/src/lib/extensions/image-upload.ts +++ b/src/lib/extensions/image-upload.ts @@ -42,11 +42,11 @@ export const ImageUpload = Extension.create({ })(), { loading: "Processing & uploading image...", - success: (url) => { + success: ({ url, filename }) => { // Insert image editor.chain() .focus() - .setImage({ src: url }) + .setImage({ src: url, filename }) .run(); // Manually force a new paragraph at the end so the user can keep typing diff --git a/src/lib/extensions/image.ts b/src/lib/extensions/image.ts index d9db95b..59aeb3e 100644 --- a/src/lib/extensions/image.ts +++ b/src/lib/extensions/image.ts @@ -7,27 +7,19 @@ export const CustomImage = Image.extend({ selectable: true, draggable: true, - addKeyboardShortcuts() { + addAttributes() { return { - Backspace: () => { - const { selection } = this.editor.state; - if (!selection.empty) { - const selectedNode = this.editor.state.doc.nodeAt(selection.from); - if (selectedNode?.type.name === this.name) { - return true; // Prevent default deletion if image is selected - } - } - return false; + ...this.parent?.(), + src: { + default: null, }, - Delete: () => { - const { selection } = this.editor.state; - if (!selection.empty) { - const selectedNode = this.editor.state.doc.nodeAt(selection.from); - if (selectedNode?.type.name === this.name) { - return true; // Prevent default deletion if image is selected - } - } - return false; + filename: { + default: null, + parseHTML: element => element.getAttribute('data-filename'), + renderHTML: attributes => { + if (!attributes.filename) return {}; + return { 'data-filename': attributes.filename }; + }, }, }; }, @@ -43,7 +35,11 @@ export const CustomImage = Image.extend({ const img = document.createElement('img'); Object.entries(node.attrs).forEach(([key, value]) => { if (value !== null && value !== undefined) { - img.setAttribute(key, value); + if (key === 'filename') { + img.setAttribute('data-filename', value); + } else { + img.setAttribute(key, value); + } } }); img.classList.add('rounded-lg', 'border', 'border-border', 'max-w-full', 'h-auto', 'cursor-default'); @@ -79,3 +75,11 @@ export const CustomImage = Image.extend({ }; }, }); + +declare module '@tiptap/core' { + interface Commands { + image: { + setImage: (options: { src: string, alt?: string, title?: string, filename?: string }) => ReturnType; + }; + } +} diff --git a/src/lib/extensions/video-upload.ts b/src/lib/extensions/video-upload.ts index ab2e28a..cad060a 100644 --- a/src/lib/extensions/video-upload.ts +++ b/src/lib/extensions/video-upload.ts @@ -41,11 +41,11 @@ export const VideoUpload = Extension.create({ })(), { loading: "Uploading video...", - success: (url) => { + success: ({ url, filename }) => { // Insert video editor.chain() .focus() - .setVideo({ src: url }) + .setVideo({ src: url, filename }) .run(); // Manually force a new paragraph at the end so the user can keep typing diff --git a/src/lib/extensions/video.ts b/src/lib/extensions/video.ts index d5e84fb..756a455 100644 --- a/src/lib/extensions/video.ts +++ b/src/lib/extensions/video.ts @@ -27,6 +27,25 @@ export const Video = Node.create({ src: { default: null, }, + filename: { + default: null, + parseHTML: element => element.getAttribute('data-filename'), + renderHTML: attributes => { + if (!attributes.filename) return {}; + return { 'data-filename': attributes.filename }; + }, + }, + }; + }, + + addCommands() { + return { + setVideo: (options: { src: string, filename?: string }) => ({ commands }) => { + return commands.insertContent({ + type: this.name, + attrs: options, + }); + }, }; }, @@ -76,7 +95,11 @@ export const Video = Node.create({ const video = document.createElement('video'); Object.entries(node.attrs).forEach(([key, value]) => { if (value !== null && value !== undefined) { - video.setAttribute(key, value); + if (key === 'filename') { + video.setAttribute('data-filename', value); + } else { + video.setAttribute(key, value); + } } }); // Apply default attributes if not present @@ -115,23 +138,12 @@ export const Video = Node.create({ }; }; }, - - addCommands() { - return { - setVideo: (options: { src: string }) => ({ commands }) => { - return commands.insertContent({ - type: this.name, - attrs: options, - }); - }, - }; - }, }); declare module '@tiptap/core' { interface Commands { video: { - setVideo: (options: { src: string }) => ReturnType; + setVideo: (options: { src: string, filename?: string }) => ReturnType; }; } } diff --git a/src/store/index.ts b/src/store/index.ts index 926e348..5e89168 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -576,19 +576,19 @@ const mapRecordToTask = (r: any): Task => { }; }; -export const uploadTaskAttachment = async (taskId: string, file: File): Promise => { +export const uploadTaskAttachment = async (taskId: string, file: File): Promise<{ url: string, filename: string }> => { try { const formData = new FormData(); formData.append('attachments+', file); const record = await pb.collection(TASGRID_COLLECTION).update(taskId, formData); - // Return the URL for the newly uploaded file. PocketBase appends new files to the array. - // We need to find the specific filename that was just uploaded to get its URL. - // Since we don't know the exact generated filename, we can return the URL of the last file in the array. if (record.attachments && record.attachments.length > 0) { const latestFilename = record.attachments[record.attachments.length - 1]; - return pb.files.getURL(record, latestFilename); + return { + url: pb.files.getURL(record, latestFilename), + filename: latestFilename + }; } throw new Error("File uploaded but no attachment returned"); @@ -599,7 +599,7 @@ export const uploadTaskAttachment = async (taskId: string, file: File): Promise< } }; -export const uploadNoteAttachment = async (noteId: string, file: File): Promise => { +export const uploadNoteAttachment = async (noteId: string, file: File): Promise<{ url: string, filename: string }> => { try { const formData = new FormData(); formData.append('attachments+', file); @@ -608,7 +608,10 @@ export const uploadNoteAttachment = async (noteId: string, file: File): Promise< if (record.attachments && record.attachments.length > 0) { const latestFilename = record.attachments[record.attachments.length - 1]; - return pb.files.getURL(record, latestFilename); + return { + url: pb.files.getURL(record, latestFilename), + filename: latestFilename + }; } throw new Error("File uploaded but no attachment returned");