From f4e4008be1380de07378af524a7ddc068ea3a61e Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 11 Oct 2024 10:02:09 -0300 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20(create-file-upload.ts):=20impr?= =?UTF-8?q?ove=20file=20upload=20functionality=20by=20adding=20cleanup=20l?= =?UTF-8?q?ogic=20and=20handling=20edge=20cases=20for=20resolving=20file?= =?UTF-8?q?=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/helpers/create-file-upload.ts | 61 ++++++++++++------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/src/frontend/src/helpers/create-file-upload.ts b/src/frontend/src/helpers/create-file-upload.ts index b11363ce53b..b1b1d9b0a87 100644 --- a/src/frontend/src/helpers/create-file-upload.ts +++ b/src/frontend/src/helpers/create-file-upload.ts @@ -1,35 +1,54 @@ -export async function createFileUpload(props?: { +export function createFileUpload(props?: { accept?: string; multiple?: boolean; }): Promise { - let lock = false; return new Promise((resolve) => { const input = document.createElement("input"); input.type = "file"; input.accept = props?.accept ?? ".json"; input.multiple = props?.multiple ?? true; input.style.display = "none"; - // add a change event listener to the file input - input.onchange = async (e: Event) => { - lock = true; - resolve(Array.from((e.target as HTMLInputElement).files!)); - document.body.removeChild(input); + + let isResolved = false; + + const cleanup = () => { + if (input && input.parentNode) { + input.parentNode.removeChild(input); + } + window.removeEventListener("focus", handleFocus); }; - window.addEventListener( - "focus", - () => { - setTimeout(() => { - if (!lock) { - resolve([]); - document.body.removeChild(input); - } - }, 300); - }, - { once: true }, - ); - // add the input element to the body to ensure it is part of the DOM + + const handleChange = (e: Event) => { + if (!isResolved) { + isResolved = true; + const files = Array.from((e.target as HTMLInputElement).files!); + cleanup(); + resolve(files); + } + }; + + const handleFocus = () => { + setTimeout(() => { + if (!isResolved) { + isResolved = true; + cleanup(); + resolve([]); + } + }, 300); + }; + + input.addEventListener("change", handleChange); + window.addEventListener("focus", handleFocus); + document.body.appendChild(input); - // trigger the file input click event to open the file dialog input.click(); + + setTimeout(() => { + if (!isResolved) { + isResolved = true; + cleanup(); + resolve([]); + } + }, 60000); }); } From 15138d9727c566a258262c34f9095eb3d54bd3a1 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 11 Oct 2024 10:24:34 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20(create-file-upload.ts):=20f?= =?UTF-8?q?ix=20removing=20input=20element=20from=20the=20DOM=20by=20check?= =?UTF-8?q?ing=20if=20it=20is=20contained=20in=20the=20document=20body=20b?= =?UTF-8?q?efore=20removal=20=F0=9F=92=A1=20(create-file-upload.ts):=20add?= =?UTF-8?q?=20a=20comment=20to=20clarify=20the=20purpose=20of=20the=20setT?= =?UTF-8?q?imeout=20function=20for=20a=20fallback=20timeout=20of=201=20min?= =?UTF-8?q?ute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/helpers/create-file-upload.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/helpers/create-file-upload.ts b/src/frontend/src/helpers/create-file-upload.ts index b1b1d9b0a87..fba3af86f5a 100644 --- a/src/frontend/src/helpers/create-file-upload.ts +++ b/src/frontend/src/helpers/create-file-upload.ts @@ -12,8 +12,8 @@ export function createFileUpload(props?: { let isResolved = false; const cleanup = () => { - if (input && input.parentNode) { - input.parentNode.removeChild(input); + if (input && document.body.contains(input)) { + document.body.removeChild(input); } window.removeEventListener("focus", handleFocus); }; @@ -43,12 +43,13 @@ export function createFileUpload(props?: { document.body.appendChild(input); input.click(); + // Fallback timeout to ensure resolution setTimeout(() => { if (!isResolved) { isResolved = true; cleanup(); resolve([]); } - }, 60000); + }, 60000); // 1 minute timeout }); } From 3ad4334da190d6828fba8fd4b4575e178ba4be13 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 11 Oct 2024 10:26:22 -0300 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=A8=20(create-file-upload.ts):=20chan?= =?UTF-8?q?ge=20createFileUpload=20function=20to=20be=20asynchronous=20to?= =?UTF-8?q?=20support=20Promise=20return=20type=20for=20better=20handling?= =?UTF-8?q?=20of=20file=20upload=20operations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/helpers/create-file-upload.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/helpers/create-file-upload.ts b/src/frontend/src/helpers/create-file-upload.ts index fba3af86f5a..1645d3d99d9 100644 --- a/src/frontend/src/helpers/create-file-upload.ts +++ b/src/frontend/src/helpers/create-file-upload.ts @@ -1,4 +1,4 @@ -export function createFileUpload(props?: { +export async function createFileUpload(props?: { accept?: string; multiple?: boolean; }): Promise { From c0b2c11535550dbd5da2c417a1460bbfec61ced3 Mon Sep 17 00:00:00 2001 From: cristhianzl Date: Fri, 11 Oct 2024 10:27:51 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=9D=20(create-file-upload.ts):=20i?= =?UTF-8?q?mprove=20error=20handling=20when=20removing=20input=20element?= =?UTF-8?q?=20from=20the=20DOM=20=F0=9F=93=9D=20(create-file-upload.ts):?= =?UTF-8?q?=20remove=20unnecessary=20comment=20about=20timeout=20value=20i?= =?UTF-8?q?n=20the=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/helpers/create-file-upload.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/helpers/create-file-upload.ts b/src/frontend/src/helpers/create-file-upload.ts index 1645d3d99d9..19671675630 100644 --- a/src/frontend/src/helpers/create-file-upload.ts +++ b/src/frontend/src/helpers/create-file-upload.ts @@ -12,8 +12,13 @@ export async function createFileUpload(props?: { let isResolved = false; const cleanup = () => { + // Check if the input element still exists in the DOM before attempting to remove it if (input && document.body.contains(input)) { - document.body.removeChild(input); + try { + document.body.removeChild(input); + } catch (error) { + console.warn("Error removing input element:", error); + } } window.removeEventListener("focus", handleFocus); }; @@ -50,6 +55,6 @@ export async function createFileUpload(props?: { cleanup(); resolve([]); } - }, 60000); // 1 minute timeout + }, 60000); }); }