From 36625c961fbc9dd1f95ecfc56b15901d0373f606 Mon Sep 17 00:00:00 2001 From: dodaa08 Date: Thu, 15 Jan 2026 21:30:29 +0530 Subject: [PATCH 1/4] fix: update file upload to use RC 8.x rooms.media API - Replace deprecated rooms.upload endpoint with new two-step process - Step 1: POST to rooms.media/:rid to upload file - Step 2: POST to rooms.mediaConfirm/:rid/:fileId to confirm with metadata - Fixes file upload 404 error on Rocket.Chat 8.x servers --- packages/api/src/EmbeddedChatApi.ts | 61 +++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/packages/api/src/EmbeddedChatApi.ts b/packages/api/src/EmbeddedChatApi.ts index f55f55d58..18c89085d 100644 --- a/packages/api/src/EmbeddedChatApi.ts +++ b/packages/api/src/EmbeddedChatApi.ts @@ -1046,26 +1046,55 @@ export default class EmbeddedChatApi { ) { try { const { userId, authToken } = (await this.auth.getCurrentUser()) || {}; - const form = new FormData(); - if (threadId) { - form.append("tmid", threadId); + if (!userId || !authToken) { + console.error("sendAttachment: User not authenticated"); + return; } + + // Step 1: Upload file to rooms.media endpoint (RC 8.x) + const form = new FormData(); form.append("file", file, fileName); - form.append( - "description", - fileDescription.length !== 0 ? fileDescription : "" + + const uploadResponse = await fetch( + `${this.host}/api/v1/rooms.media/${this.rid}`, + { + method: "POST", + body: form, + headers: { + "X-Auth-Token": authToken, + "X-User-Id": userId, + }, + } ); - const response = fetch(`${this.host}/api/v1/rooms.upload/${this.rid}`, { - method: "POST", - body: form, - headers: { - "X-Auth-Token": authToken, - "X-User-Id": userId, - }, - }).then((r) => r.json()); - return response; + + const uploadResult = await uploadResponse.json(); + + if (!uploadResult.success || !uploadResult.file?._id) { + console.error("sendAttachment: Upload failed", uploadResult); + return uploadResult; + } + + // Step 2: Confirm the upload with message details + const confirmResponse = await fetch( + `${this.host}/api/v1/rooms.mediaConfirm/${this.rid}/${uploadResult.file._id}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Auth-Token": authToken, + "X-User-Id": userId, + }, + body: JSON.stringify( + threadId + ? { msg: "", description: fileDescription || "", tmid: threadId } + : { msg: "", description: fileDescription || "" } + ), + } + ); + + return await confirmResponse.json(); } catch (err) { - console.log(err); + console.error("sendAttachment error:", err); } } From 15d0e63254ce45c17c4d714ed9ed5fb2f2b6cab2 Mon Sep 17 00:00:00 2001 From: dodaa08 Date: Sat, 17 Jan 2026 22:04:11 +0530 Subject: [PATCH 2/4] fix: reset file input after upload to allow re-selecting same file --- packages/react/src/views/ChatInput/ChatInput.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js index e753b689a..34cd8a7c3 100644 --- a/packages/react/src/views/ChatInput/ChatInput.js +++ b/packages/react/src/views/ChatInput/ChatInput.js @@ -120,9 +120,10 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => { ); const isLoginIn = useLoginStore((state) => state.isLoginIn); - const { toggle, setData } = useAttachmentWindowStore((state) => ({ + const { toggle, setData, data } = useAttachmentWindowStore((state) => ({ toggle: state.toggle, setData: state.setData, + data: state.data, })); const userInfo = { _id: userId, username, name }; @@ -184,6 +185,13 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => { } }, [deletedMessage]); + + useEffect(() => { + if (data === null && inputRef.current) { + inputRef.current.value = ''; + } + }, [data]); + const getMessageLink = async (id) => { const host = RCInstance.getHost(); const res = await RCInstance.channelInfo(); From 1a4923ffde1df31470cfb531b90be7fe16f634cc Mon Sep 17 00:00:00 2001 From: dodaa08 Date: Sat, 17 Jan 2026 22:10:18 +0530 Subject: [PATCH 3/4] style: fix prettier formatting --- packages/react/src/views/ChatInput/ChatInput.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js index 34cd8a7c3..df4d247da 100644 --- a/packages/react/src/views/ChatInput/ChatInput.js +++ b/packages/react/src/views/ChatInput/ChatInput.js @@ -185,7 +185,6 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => { } }, [deletedMessage]); - useEffect(() => { if (data === null && inputRef.current) { inputRef.current.value = ''; From 86aa1c9c816efaea2283e3c4f8d7832471a9d65a Mon Sep 17 00:00:00 2001 From: dodaa08 Date: Sat, 17 Jan 2026 22:22:56 +0530 Subject: [PATCH 4/4] fix: resolve variable shadowing in ChatInput.js --- packages/react/src/views/ChatInput/ChatInput.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/views/ChatInput/ChatInput.js b/packages/react/src/views/ChatInput/ChatInput.js index df4d247da..0bdebf322 100644 --- a/packages/react/src/views/ChatInput/ChatInput.js +++ b/packages/react/src/views/ChatInput/ChatInput.js @@ -148,7 +148,7 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => { RCInstance.auth.onAuthChange((user) => { if (user) { RCInstance.getCommandsList() - .then((data) => setCommands(data.commands || [])) + .then((response) => setCommands(response.commands || [])) .catch(console.error); RCInstance.getChannelMembers(isChannelPrivate)