diff --git a/src/frontend/src/controllers/API/queries/files/index.ts b/src/frontend/src/controllers/API/queries/files/index.ts index 54d5f7070c1..62533f72f8f 100644 --- a/src/frontend/src/controllers/API/queries/files/index.ts +++ b/src/frontend/src/controllers/API/queries/files/index.ts @@ -1,3 +1,4 @@ +export * from "./use-download-files"; export * from "./use-get-download-images"; export * from "./use-get-profile-pictures"; export * from "./use-post-upload-file"; diff --git a/src/frontend/src/controllers/API/queries/files/use-download-files.ts b/src/frontend/src/controllers/API/queries/files/use-download-files.ts new file mode 100644 index 00000000000..051f76532d1 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/files/use-download-files.ts @@ -0,0 +1,45 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { + useMutationFunctionType, + useQueryFunctionType, +} from "../../../../types/api"; +import { api } from "../../api"; +import { getURL } from "../../helpers/constants"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface DownloadImagesQueryParams { + path: string; + filename: string; +} + +export const useGetDownloadFileMutation: useMutationFunctionType< + DownloadImagesQueryParams +> = (params, options) => { + const { mutate } = UseRequestProcessor(); + + const getDownloadImagesFn = async () => { + if (!params) return; + // need to use fetch because axios convert blob data to string, and this convertion can corrupt the file + const response = await fetch(`${getURL("FILES")}/download/${params.path}`); + const blob = await response.blob(); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.setAttribute("download", params.filename); // Set the filename + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + URL.revokeObjectURL(url); + return {}; + }; + + const queryResult = mutate( + ["useGetDownloadFileMutation", params.path], + getDownloadImagesFn, + options, + ); + + return queryResult; +}; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx index e6b4509d052..3a3467b62b9 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/components/fileCardWrapper/index.tsx @@ -24,12 +24,7 @@ export default function FileCardWrapper({ {formatFileName(name, 50)} - + ); } diff --git a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx index 17708aa3f89..704d9934c0b 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/index.tsx @@ -1,3 +1,4 @@ +import { useGetDownloadFileMutation } from "@/controllers/API/queries/files"; import { useState } from "react"; import { ForwardedIconComponent } from "../../../../../components/genericIconComponent"; import { BACKEND_URL, BASE_URL_API } from "../../../../../constants/constants"; @@ -6,18 +7,20 @@ import { fileCardPropsType } from "../../../../../types/components"; import formatFileName from "../filePreviewChat/utils/format-file-name"; import DownloadButton from "./components/downloadButton/downloadButton"; import getClasses from "./utils/get-classes"; -import handleDownload from "./utils/handle-download"; const imgTypes = new Set(["png", "jpg", "jpeg", "gif", "webp", "image"]); export default function FileCard({ fileName, - content, + path, fileType, showFile = true, }: fileCardPropsType): JSX.Element | undefined { const [isHovered, setIsHovered] = useState(false); - const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId); + const { mutate } = useGetDownloadFileMutation({ + filename: fileName, + path: path, + }); function handleMouseEnter(): void { setIsHovered(true); } @@ -27,7 +30,7 @@ export default function FileCard({ const fileWrapperClasses = getClasses(isHovered); - const imgSrc = `${BASE_URL_API}files/images/${content}`; + const imgSrc = `${BASE_URL_API}files/images/${path}`; if (showFile) { if (imgTypes.has(fileType)) { @@ -46,7 +49,7 @@ export default function FileCard({ /> handleDownload({ fileName, content })} + handleDownload={() => mutate(undefined)} /> @@ -56,7 +59,7 @@ export default function FileCard({ return (
handleDownload({ fileName, content })} + onClick={() => mutate(undefined)} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > @@ -69,7 +72,7 @@ export default function FileCard({
handleDownload({ fileName, content })} + handleDownload={() => mutate(undefined)} /> ); diff --git a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx b/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx deleted file mode 100644 index 53a9cf7705f..00000000000 --- a/src/frontend/src/modals/IOModal/components/chatView/fileComponent/utils/handle-download.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { - BACKEND_URL, - BASE_URL_API, -} from "../../../../../../constants/constants"; - -let isDownloading = false; - -export default async function handleDownload({ - fileName, - content, -}: { - fileName: string; - content: string; -}): Promise { - if (isDownloading) return; - - try { - isDownloading = true; - - const response = await fetch(`${BASE_URL_API}files/download/${content}`); - if (!response.ok) { - throw new Error("Network response was not ok"); - } - - const blob = await response.blob(); - const url = URL.createObjectURL(blob); - - const link = document.createElement("a"); - link.href = url; - link.setAttribute("download", fileName); // Set the filename - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - URL.revokeObjectURL(url); // Clean up the URL object - } catch (error) { - console.error("Failed to download file:", error); - } finally { - isDownloading = false; - } -} diff --git a/src/frontend/src/modals/IOModal/components/chatView/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/index.tsx index 5e0b2d4fd3d..fd6bb270a97 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/index.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/index.tsx @@ -80,7 +80,6 @@ export default function ChatView({ const is_ai = sender === "Machine" || sender === null || sender === undefined; - return { isSend: !is_ai, message, diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index 632b24d1bfc..ddd5a2a48e9 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -617,7 +617,7 @@ export interface Props { export type fileCardPropsType = { fileName: string; - content: string; + path: string; fileType: string; showFile?: boolean; };