diff --git a/packages/discord-types/src/common/messages/Message.d.ts b/packages/discord-types/src/common/messages/Message.d.ts index b347eecbd..0b71979f2 100644 --- a/packages/discord-types/src/common/messages/Message.d.ts +++ b/packages/discord-types/src/common/messages/Message.d.ts @@ -291,6 +291,8 @@ export interface MessageAttachment { content_type?: string; width?: number; height?: number; + title?: string; + description?: string; } export interface ReactionEmoji { diff --git a/src/equicordplugins/favouriteAnything/index.tsx b/src/equicordplugins/favouriteAnything/index.tsx index 9797c9b42..b9d094962 100644 --- a/src/equicordplugins/favouriteAnything/index.tsx +++ b/src/equicordplugins/favouriteAnything/index.tsx @@ -26,11 +26,12 @@ export default definePlugin({ name: "FavouriteAnything", description: "Favourite any image, video, or file attachment", authors: [Devs.nin0dev, EquicordDevs.davri], + tags: ["favorite"], managedStyle, patches: [ // EMBEDS { - find: "#{intl::SUPPRESS_ALL_EMBEDS}", + find: "this.renderInlineMediaEmbed", replacement: [ { // Wrap the embed component's render method in a custom context to avoid having to drill props diff --git a/src/equicordplugins/favouriteAnything/utils.ts b/src/equicordplugins/favouriteAnything/utils.ts index b90ea9653..b03aa347c 100644 --- a/src/equicordplugins/favouriteAnything/utils.ts +++ b/src/equicordplugins/favouriteAnything/utils.ts @@ -70,23 +70,27 @@ function defineItems>(def: Ite // Stringify returns a simple string representation used for thumbnail text and expression picker search. export const defs = defineItems({ [CustomItemFormat.ATTACHMENT]: defineItem({ - encode: ({ id, filename, size, url, content_type = "" }: MessageAttachment) => [ + encode: ({ id, filename, size, url, content_type = "", title, description }: MessageAttachment) => [ id, filename, size, new URL(url).pathname, - content_type + content_type, + title ?? null, + description ?? null ], - decode: ([id, filename, size, path, content_type]) => ({ + decode: ([id, filename, size, path, content_type, title, description]) => ({ id: id ?? "0", filename: filename ?? "UNKNOWN", size: +size! || 0, url: `${new URL(path!, `https://${window.GLOBAL_ENV.CDN_HOST}`)}`, proxy_url: `${new URL(path!, `https://${window.GLOBAL_ENV.MEDIA_PROXY_ENDPOINT}`)}`, content_type: content_type ?? "application/octet-stream", - spoiler: filename?.startsWith("SPOILER_") ?? false + spoiler: filename?.startsWith("SPOILER_") ?? false, + title: title ?? undefined, + description: description ?? undefined }), - stringify: ({ filename }) => filename + stringify: ({ title, filename }) => title?.trim() || filename }) // This could be expanded in the future with other item types (e.g. voice messages) }); @@ -149,23 +153,15 @@ async function fetchAttachment(attachment: MessageAttachment): Promise { } export async function sendAttachment(attachment: MessageAttachment, channel: Channel) { - const file = await fetchAttachment(attachment) - .catch(() => - Toasts.show({ - message: `Couldn't fetch ${attachment.filename}`, - id: Toasts.genId(), - type: Toasts.Type.FAILURE - }) - ); + const { filename, title, description } = attachment; + const file = await fetchAttachment(attachment).catch(() => + Toasts.show({ message: `Couldn't fetch ${filename}`, id: Toasts.genId(), type: Toasts.Type.FAILURE }) + ); if (!file) return; // Using promptToUpload instead of addFiles directly since it has file size checks with error popups await UploadHandler.promptToUpload([file], channel, DraftType.ChannelMessage).catch(() => - Toasts.show({ - message: `Couldn't upload ${attachment.filename}`, - id: Toasts.genId(), - type: Toasts.Type.FAILURE - }) + Toasts.show({ message: `Couldn't upload ${filename}`, id: Toasts.genId(), type: Toasts.Type.FAILURE }) ); const uploads = [...UploadAttachmentStore.getUploads(channel.id, DraftType.ChannelMessage)]; @@ -173,8 +169,13 @@ export async function sendAttachment(attachment: MessageAttachment, channel: Cha if (uploadIdx === -1) return; const reply = PendingReplyStore.getPendingReply(channel.id); + const [upload] = uploads.splice(uploadIdx); UploadManager.setUploads({ uploads, channelId: channel.id, draftType: DraftType.ChannelMessage }); + // Empty titles and descriptions are allowed + if (title != null) upload.filename = title; + if (description != null) upload.description = description; + FluxDispatcher.dispatch({ type: "DELETE_PENDING_REPLY", channelId: channel.id }); void sendMessage(channel.id, {}, false, {