From dd84097b6d3611f6aeefbf01f5156f68e8f71021 Mon Sep 17 00:00:00 2001 From: bflatastic Date: Thu, 15 Oct 2026 19:04:16 +0700 Subject: [PATCH] #368: revoke a download's object URL after a delay Revoking it right after the click can cancel the download in some browsers; it now goes 40 s later on a timer. --- apps/figcraft-web/src/web.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/figcraft-web/src/web.rs b/apps/figcraft-web/src/web.rs index 43ec2cf2..8cadb013 100644 --- a/apps/figcraft-web/src/web.rs +++ b/apps/figcraft-web/src/web.rs @@ -131,7 +131,8 @@ impl Services for WebServices { } fn download(name: &str, bytes: &[u8]) -> Result<(), wasm_bindgen::JsValue> { - let document = web_sys::window().and_then(|w| w.document()).ok_or("no document")?; + let window = web_sys::window().ok_or("no window")?; + let document = window.document().ok_or("no document")?; let body = document.body().ok_or("no body")?; let parts = js_sys::Array::of1(&js_sys::Uint8Array::from(bytes)); let blob = web_sys::Blob::new_with_u8_array_sequence_and_options(&parts, &{ @@ -146,5 +147,14 @@ fn download(name: &str, bytes: &[u8]) -> Result<(), wasm_bindgen::JsValue> { body.append_child(&a)?; a.click(); a.remove(); - web_sys::Url::revoke_object_url(&url) + // Revoked later, not at once: some browsers cancel a download whose URL goes before it starts. + let revoke = wasm_bindgen::closure::Closure::once_into_js(move || { + let _ = web_sys::Url::revoke_object_url(&url); + }); + // Without the timer the URL just stays until the page closes. + let _ = window.set_timeout_with_callback_and_timeout_and_arguments_0(revoke.unchecked_ref(), REVOKE_DOWNLOAD_MS); + Ok(()) } + +/// How long a download's object URL is kept (milliseconds). +const REVOKE_DOWNLOAD_MS: i32 = 40_000;