feat(explore): refuse 0.6 GB on someone's mobile data
Plan 016 B4. The catalog artifact is about 0.6 GB and the app fetched it with no awareness of the connection: on a desktop that is a minute of bandwidth, on a phone it can be a month's allowance. It is now skipped on a cellular connection unless `AllowMeteredCatalogDownload` is on, with the toggle in Settings' Search Index section, where the text explaining what the catalog is already lives. The file layout is dictated by the cgo rule rather than by taste. `explore` is imported by `cmd/indexbuild`, which builds with CGO_ENABLED=0 and must not link Wails, so `netpolicy.go` holds the policy and the JSON parsing -- tested on every platform -- and the single platform call is a closure injected from `app.go`, which already names `application` legitimately. Three rules in it are load-bearing. An unknown answer is not a metered one: only mobile answers at all, and treating silence as metered would have disabled the download for every desktop user in the world. Cellular is the only signal available, because the runtime reports `wifi|cellular|ethernet|none` and no metered flag -- so a metered Wi-Fi cannot be detected and is not refused, which is documented rather than implied. And the gate runs before the first status write, so declining is a no-op instead of a job in the indicator and an error tier to dismiss. Two corrections to the plan while implementing it: the portable API is `application.Mobile.NetworkJSON()`, not `application.Android`'s, which exists only under the `android` build tag; and the permission is read at the moment a download would start, so enabling it takes effect on the next attempt rather than the next launch.
This commit is contained in:
@@ -3301,3 +3301,34 @@ answering for the *old* bundle — it reported the desktop layout at 424 px
|
||||
until the page was reopened. And wireless adb dropped twice more mid-
|
||||
session when the screen slept; USB for anything longer than a few
|
||||
probes.
|
||||
|
||||
## The catalog download now asks about the connection (2026-08-17)
|
||||
|
||||
Plan 016 B4. ~0.6 GB had no network awareness at all; it is skipped on a
|
||||
cellular connection unless the user says otherwise
|
||||
(`AllowMeteredCatalogDownload`, default false, toggle in Settings' Search
|
||||
Index section).
|
||||
|
||||
**The shape is dictated by the cgo rule, not by taste.** `explore` is
|
||||
imported by `cmd/indexbuild`, which builds with `CGO_ENABLED=0` and must
|
||||
not link Wails, so `netpolicy.go` holds the policy and the JSON parsing —
|
||||
tested on every platform — while the one platform call is a closure
|
||||
injected from `app.go`, where naming `application` is already legitimate.
|
||||
|
||||
Four things measured or corrected in the doing:
|
||||
|
||||
- **The portable name is `application.Mobile`, not `application.Android`**
|
||||
(which the plan and `CLAUDE.md` both named). `Android` exists only
|
||||
under the `android` build tag; `Mobile`'s desktop implementation is a
|
||||
stub whose `NetworkJSON()` returns `""`.
|
||||
- **The runtime reports no metered flag.** `{"connected":bool,
|
||||
"type":"wifi|cellular|ethernet|none"}` is all there is, so cellular is
|
||||
the signal and a metered *Wi-Fi* — a phone hotspot, a hotel — cannot be
|
||||
detected. Android itself knows (`NET_CAPABILITY_NOT_METERED`) and the
|
||||
runtime does not pass it on. Documented gap, not an oversight.
|
||||
- **An unknown answer must not read as metered.** Every desktop answers
|
||||
`""`, so the obvious defensive default would have disabled the catalog
|
||||
download for every desktop user in the world.
|
||||
- **The gate belongs before the first status write.** Declining is a
|
||||
no-op — no job in the indicator, no error tier to dismiss — which is
|
||||
what makes the refusal safe to have on by default.
|
||||
|
||||
@@ -347,8 +347,18 @@ done.**
|
||||
viewport would have: saved *desktop* column widths reached the phone
|
||||
through an id-keyed store and gave the duration column 55% of the row.
|
||||
|
||||
**B2 is complete.** What is left in this plan is B3 (tag writing, which
|
||||
needs a device), B4 (the catalog download on a metered connection), and
|
||||
**B2 and B4 are complete.** B4 is `backend/explore/netpolicy.go`: the
|
||||
catalog download is skipped on a cellular connection unless
|
||||
`AllowMeteredCatalogDownload` is on, with the toggle in Settings' Search
|
||||
Index section. The policy and the JSON parsing are in `explore` (tested
|
||||
on every platform) and only the platform call is injected from `app.go`,
|
||||
because `cmd/indexbuild` imports `explore` and must not link Wails. Two
|
||||
things the plan got slightly wrong: the portable API is
|
||||
`application.Mobile.NetworkJSON()` rather than `Android`'s, and it
|
||||
reports no metered flag — so cellular is the signal and a metered Wi-Fi
|
||||
cannot be seen.
|
||||
|
||||
What is left in this plan is B3 (tag writing, which needs a device) and
|
||||
the standing question of the Light Phone's Chrome 113 — which so far has
|
||||
cost nothing: menus, dialogs and long-press all work on it.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user