feat(dev): ask the phone instead of looking at it
The device tier could only take a screenshot and read what Go chose to log, and a screenshot cannot tell a dropped CSS declaration from a missing asset. This adds the third thing: the page's own answer, from the engine that is really rendering it. `make android-screenshot` grabs the screen, `make android-inspect` forwards the WebView's devtools socket, and `make android-eval EXPR=...` evaluates in the real page. Four details are load-bearing. Only a `debuggable` build opens that socket, so the debug build type takes `applicationIdSuffix ".dev"` and installs *beside* the release app -- the two carry different signing certificates, and Android's only remedy for a changed certificate is an uninstall, which takes the user's library with it. Playwright cannot drive a WebView (`connectOverCDP` calls `Browser.setDownloadBehavior`, which it answers "Browser context management is not supported"), so the eval is raw CDP over Node's built-in WebSocket. The socket name carries the pid, so it is resolved per launch rather than written down. And `exec-out`, not `shell`, for the screenshot: a pty translates LF and corrupts the PNG. What it immediately established is why it was worth having. The phone renders in Chrome 113 at 424x439 CSS px -- two years behind every browser the other tiers use, with no Popover API and no relaxed CSS nesting -- so a spec passing at that viewport says nothing about the device, and two conclusions drawn from version numbers alone were wrong. Both are corrected in NOTES.md and the plan.
This commit is contained in:
@@ -3138,3 +3138,73 @@ cover the history behaviour, on Chromium locally and WebKit in CI.
|
||||
Not verified: the insets themselves, which need the next APK on the
|
||||
owner's phone. What to look for is one thing — the transport and the tab
|
||||
bar clear of the gesture bar, and the header clear of the status bar.
|
||||
|
||||
## The phone is a Chrome 113 WebView, and that reframes everything (2026-08-17)
|
||||
|
||||
The device is reachable over adb now, so the tier can be *asked* rather
|
||||
than reported on. `make android-inspect` + `make android-eval` are that:
|
||||
a debug build (`applicationIdSuffix ".dev"`, so it installs **beside**
|
||||
the release app rather than needing the uninstall that would take the
|
||||
library with it) opens `webview_devtools_remote_<pid>`, and raw CDP over
|
||||
Node's built-in WebSocket evaluates in the real page. **Playwright
|
||||
cannot do this** — `connectOverCDP` calls `Browser.setDownloadBehavior`
|
||||
and a WebView answers "Browser context management is not supported",
|
||||
killing the connection before the first evaluate.
|
||||
|
||||
Measured on the device (Light Phone III, TLP301):
|
||||
|
||||
| fact | value |
|
||||
| --- | --- |
|
||||
| Android | 14, SDK 34 |
|
||||
| screen | 1080x1240, density 408 |
|
||||
| WebView viewport | **424 x 439 CSS px**, DPR 2.55 |
|
||||
| WebView engine | **Chrome 113.0.5672.136** (mid-2023) |
|
||||
|
||||
**The first correction: the insets commit does not explain the report.**
|
||||
Edge-to-edge is forced for apps *running on* Android 15, and this phone
|
||||
is Android 14 — the screenshot shows the app correctly inset, with the
|
||||
status bar and the gesture bar outside it. `applyWindowInsets()` is
|
||||
right and stays (the next phone, or one OS update, is Android 15), but
|
||||
it is **pre-emptive, not the fix for "the controls are off screen"**.
|
||||
That was an inference from a version number, and the device disagreed.
|
||||
|
||||
**The second correction: the black `fill` proves nothing.** A wa-icon on
|
||||
the device has the right `color` (#ffd43b) and an `<svg>` in its shadow
|
||||
root, and `getComputedStyle(svg).fill` is black — but that is the *svg
|
||||
root*, and every vendored Font Awesome path carries
|
||||
`fill="currentColor"` itself, so the root's fill is irrelevant. Measuring
|
||||
the wrong node produced a diagnosis-shaped result. `__yjIconMisses` is
|
||||
empty, so no name is unbundled either. Why the icons do not appear in the
|
||||
screenshot is **still open**.
|
||||
|
||||
**What the engine version does explain, and what to check next.**
|
||||
Chrome 113 has `:has()`, `color-mix()` and `dialog.showModal()`, and
|
||||
lacks three things this app's dependencies use:
|
||||
|
||||
- **Relaxed CSS nesting** (Chrome 120): a nested rule starting with a
|
||||
bare element selector is dropped. `.x { svg { ... } }` parses to
|
||||
nothing; `.x { & svg { ... } }` parses. Any Web Awesome or app
|
||||
stylesheet written the modern way silently loses declarations here,
|
||||
and dropped declarations are exactly the failure that looks like
|
||||
"rendered but wrong".
|
||||
- **The Popover API** (Chrome 114). Web Awesome's popup calls
|
||||
`showPopover?.()` — optional, so nothing throws — but also sets
|
||||
`popover="manual"`, which on 113 is an unknown attribute doing
|
||||
nothing. Every context menu, dropdown and the whole menu keyboard
|
||||
model rides on that, so it is the first thing to test with a library
|
||||
present.
|
||||
- `light-dark()` and relative colour syntax (`rgb(from ...)`).
|
||||
|
||||
**The lesson for the tier: a device is an engine, not just a screen.**
|
||||
Every browser tier here runs a current Chromium or WebKit, and the phone
|
||||
that will actually run this app is two years behind — so "it renders at
|
||||
424x439 in Chromium" (checked, the transport is on screen) says nothing
|
||||
about whether it renders on the phone. The e2e tier cannot be fixed by
|
||||
resizing; the missing signal is version, and CDP against the device is
|
||||
the only place to get it.
|
||||
|
||||
Verified by execution: every number in the table, the four feature
|
||||
probes, and that the hardware back button no longer kills the app (the
|
||||
`.dev` build carries the history fix; pid survived a BACK press).
|
||||
Unverified: what happened to the icons and the transport controls, which
|
||||
is where this resumes.
|
||||
|
||||
@@ -360,9 +360,14 @@ awaiting the next APK for confirmation (`NOTES.md`, same date):
|
||||
`webView.canGoBack()`; the frontend had never used `history`. A
|
||||
navigation is a history entry now, and `navStack` is gone rather than
|
||||
kept beside it.
|
||||
- **The transport was under the gesture bar.** `targetSdk 35` is
|
||||
edge-to-edge by force; `applyWindowInsets()` in `MainActivity` pads
|
||||
by `systemBars | displayCutout | ime`.
|
||||
- **The transport was under the gesture bar** — or so the version
|
||||
number said. `applyWindowInsets()` in `MainActivity` is right and
|
||||
stays, but the phone is **Android 14**, where the system still insets
|
||||
the window: the fix is pre-emptive and the symptom has another cause.
|
||||
Still open, along with icons that do not appear at all. The phone's
|
||||
WebView is **Chrome 113**, which is the lead (no Popover API, no
|
||||
relaxed CSS nesting), and `make android-inspect` / `android-eval` are
|
||||
how it gets asked.
|
||||
|
||||
The standing item is unchanged in kind: **B3 (tag writing) and the
|
||||
permission flow still need a device**, and so does confirming these two.
|
||||
|
||||
Reference in New Issue
Block a user