Make the download card visible, and the events arrive at all

Two separate faults, both hiding the same feature.

The events never reached the shell. They were emitted from inside
WebKit's download delegate, which runs on the main thread, and delivering
an event means running JavaScript in a webview - which cannot happen from
in there. They are now emitted from a spawned task, like every other
event in the app that works.

And the card was drawn over the page, where it could never be seen: an
app's webview is a native view painted above everything the shell draws,
so a card over the page is a card behind the page. It now lives in the
nav, which is the shell's own - full detail when the nav is open, just
the state icon on the rail.

Verified end to end on a Gmail attachment: requested, named, saved, and
shown as "Downloaded" with a Show button that reveals it.
This commit is contained in:
2026-09-02 11:07:22 +02:00
parent 04b731cf37
commit 36506718c2
6 changed files with 136 additions and 80 deletions
@@ -346,9 +346,19 @@ every time.
## Downloads
The webview saves a file perfectly well and mentions it to nobody, which makes a download
indistinguishable from a click that did nothing. So each one is announced in the corner as
indistinguishable from a click that did nothing. So each one is announced **in the nav** as
it saves, and offers to show the finished file in the Finder.
In the nav, and not floating over the page, because that is where this was first put and
where it could never be seen: an app's webview is a native view painted above everything
the shell draws, so a card over the page is a card *behind* the page. The nav is the
shell's own.
The events reaching the shell at all took a second fix. They are emitted from a spawned
task rather than from the download callback directly — that callback runs on the main
thread inside WebKit's download delegate, and delivering an event means running JavaScript
in a webview, which cannot happen from in there. Emitted directly they were simply lost.
Two things the API does not give, and how each is handled:
- **No progress.** `DownloadEvent` reports a start and a finish and nothing between — no