diff --git a/src/components/Hack/HackActions.tsx b/src/components/Hack/HackActions.tsx index 866719e..1a14202 100644 --- a/src/components/Hack/HackActions.tsx +++ b/src/components/Hack/HackActions.tsx @@ -93,6 +93,35 @@ const HackActions: React.FC = ({ } }, [termsAgreed, patchUrl, patchBlob, file, baseRomId, isLinked, hasPermission, hasCached, status]); + React.useEffect(() => { + const fetchPatchBlob = async () => { + if (!patchUrl) return; + + // Defer fetch to attempt to avoid "Failed to fetch" errors + setTimeout(async () => { + const res = await fetch(patchUrl); + if (!res.ok) throw new Error("Failed to fetch patch"); + const blob = await res.blob(); + setPatchBlob(blob); + }, 50); + }; + + if (patchUrl) { + fetchPatchBlob(); + } + }, [patchUrl]); + + React.useEffect(() => { + if (patchBlob) { + const romReady = !!file || (isLinked(baseRomId) && (hasPermission(baseRomId) || hasCached(baseRomId))); + if (romReady) { + setStatus("ready"); + } else { + setStatus("idle"); + } + } + }, [patchBlob, file, baseRomId, isLinked, hasPermission, hasCached, status]); + async function onSelectFile(e: React.ChangeEvent) { const f = e.target.files?.[0] ?? null; setFile(f); @@ -120,29 +149,18 @@ const HackActions: React.FC = ({ setStatus("downloading"); // Fetch signed URL from server - const result = await getSignedPatchUrl(hackSlug); - if (!result.ok) { - setError(result.error); - setStatus("idle"); - return; - } + // Defer fetch to attempt to avoid "Failed to fetch" errors + setTimeout(async () => { + const result = await getSignedPatchUrl(hackSlug); + if (!result.ok) { + setError(result.error); + setStatus("idle"); + return; + } - setPatchUrl(result.url); - setTermsAgreed(true); - - // Download patch blob - const res = await fetch(result.url); - if (!res.ok) throw new Error("Failed to fetch patch"); - const blob = await res.blob(); - setPatchBlob(blob); - - // Update status based on ROM readiness - const romReady = !!file || (isLinked(baseRomId) && (hasPermission(baseRomId) || hasCached(baseRomId))); - if (romReady) { - setStatus("ready"); - } else { - setStatus("idle"); - } + setPatchUrl(result.url); + setTermsAgreed(true); + }, 50); } catch (e: any) { setError(e?.message || "Failed to fetch patch URL"); setStatus("idle"); @@ -186,6 +204,8 @@ const HackActions: React.FC = ({ (async () => { let blob = patchBlob; if (!blob) { + // Should likely never happen, but just in case + console.log('Blob missing, fetching from URL'); const resp = await fetch(patchUrl); if (!resp.ok) throw new Error("Failed to fetch patch"); blob = await resp.blob();