From fae253ec3576d2222456e2a071636568daf0727a Mon Sep 17 00:00:00 2001 From: Gregor MacLennan Date: Thu, 17 Sep 2026 10:11:19 +0100 Subject: [PATCH] fix(ui): say the downloaded file is incomplete when an export fails Browsers that report failed downloads discard the file, but iOS Safari keeps whatever was flushed, so the error now names the progress reached and tells the user to delete the file. --- e2e/app.test.ts | 6 +++--- src/main.ts | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/e2e/app.test.ts b/e2e/app.test.ts index 7fc2ab9..a36347d 100644 --- a/e2e/app.test.ts +++ b/e2e/app.test.ts @@ -188,9 +188,9 @@ describeEngines((engine) => { await page.click("#cancel"); await page.waitForSelector('[data-message="error"]'); - expect(await page.textContent('[data-message="error"]')).toContain( - "cancelled", - ); + const message = await page.textContent('[data-message="error"]'); + expect(message).toContain("cancelled"); + expect(message).toContain("incomplete"); await page.waitForSelector('[role="progressbar"]', { state: "detached" }); await page.waitForSelector("#export:not([disabled])"); }); diff --git a/src/main.ts b/src/main.ts index 70b2594..7143fc0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -158,7 +158,14 @@ function start(app: HTMLElement) { form.message = null; }, SAVED_MESSAGE_MS); } catch (err) { - form.message = { kind: "error", text: describe(err) }; + // The download had already started, and iOS keeps whatever was flushed. + const reached = Math.round(form.progress * 100); + form.message = { + kind: "error", + text: + `${describe(err)} (stopped at ${reached}%). ` + + "Any file that was downloaded is incomplete — delete it and try again.", + }; } finally { form.exporting = false; form.progress = 0;