Reported on glass: the "Controller-optimized UI" switch is there, turning it off does nothing — the console stays up.
The switch
pf_client_core::trust::Settings::extra is #[serde(flatten)], so the android.* console settings are top-level keys of the settings document, beside width and codec. There is no "extra" object — trust.rs's own settings_unknown_keys_survive_round_trip already asserts a serialized default contains no such key.
ConsoleJson wrote and read them nested under one. Serde put that whole object into the map under the literal key "extra", so:
no console row ever found android.gamepad_ui_enabled — each showed its compiled default, whatever the touch UI had stored;
the value the console saved came back to Kotlin as the one Kotlin had just sent, so applySettings saw no change, raised no onSettingsChange, and App never recomputed gamepadUiActive.
Hence a switch you can flip with nothing behind it.
It hit every Android-only row, not just this one: low latency, phone rumble, phone gyro, SC2 capture, DualSense capture, and the Show it mode picker. None of them round-tripped from the console.
A store written by the nesting build carries the dead wrapper; it is dropped on the next write rather than echoed for the life of the install.
Why nothing caught it
Both halves agreed on the same wrong nesting, so a write-then-read round-trip passes while the feature is broken — theRoundTripKeepsEveryAndroidRow in the new test still passes with the fix reverted. The other three cases assert the shape (android.… present at the top level, no "extra" wrapper, a console-shaped save read back) and all three fail without it.
The layer under the cards
Also reported: the layer behind every card, the one that reads as an outline, does not follow the card's corners.
That is theme::focus_halo. It grows the card's rect by 4 design units on every side but drew it with the card's own radius. A shape grown by d keeps its corners parallel to the original's only if its radius grows by d too — otherwise the two arcs stop sharing a centre. So the halo came out squarer than the card: clean along the edges, visibly off at the four corners.
Same rule applied to panel_highlight, which pulls in half a unit and kept the full radius. drop_shadow only offsets, so its geometry was already right, and the collections plate uses RRect::with_outset, which adjusts the radii itself.
Every card in the console goes through these two helpers — home tiles, library grid, coverflow, collections deck.
Verification
98 app unit tests green; the new ConsoleSettingsExtraTest fails 3 of 4 with the fix stashed.
cargo fmt --check -p pf-console-ui clean.
Native compiles for arm64-v8a, armeabi-v7a and x86_64 (:kit:cargoNdkRelease).
⏳On glass owed — nobody has yet watched the console actually drop to the touch UI, and the halo change is a visual call worth eyeballing.
Reported on glass: the "Controller-optimized UI" switch is there, turning it off does nothing — the console stays up.
## The switch
`pf_client_core::trust::Settings::extra` is `#[serde(flatten)]`, so the `android.*` console settings are **top-level** keys of the settings document, beside `width` and `codec`. There is no `"extra"` object — `trust.rs`'s own `settings_unknown_keys_survive_round_trip` already asserts a serialized default contains no such key.
`ConsoleJson` wrote and read them nested under one. Serde put that whole object into the map under the literal key `"extra"`, so:
- no console row ever found `android.gamepad_ui_enabled` — each showed its compiled default, whatever the touch UI had stored;
- the value the console saved came back to Kotlin as the one Kotlin had just sent, so `applySettings` saw no change, raised no `onSettingsChange`, and `App` never recomputed `gamepadUiActive`.
Hence a switch you can flip with nothing behind it.
It hit **every** Android-only row, not just this one: low latency, phone rumble, phone gyro, SC2 capture, DualSense capture, and the `Show it` mode picker. None of them round-tripped from the console.
A store written by the nesting build carries the dead wrapper; it is dropped on the next write rather than echoed for the life of the install.
### Why nothing caught it
Both halves agreed on the same wrong nesting, so a write-then-read round-trip passes while the feature is broken — `theRoundTripKeepsEveryAndroidRow` in the new test still passes with the fix reverted. The other three cases assert the **shape** (`android.…` present at the top level, no `"extra"` wrapper, a console-shaped save read back) and all three fail without it.
## The layer under the cards
Also reported: the layer behind every card, the one that reads as an outline, does not follow the card's corners.
That is `theme::focus_halo`. It grows the card's rect by 4 design units on every side but drew it with the card's *own* radius. A shape grown by `d` keeps its corners parallel to the original's only if its radius grows by `d` too — otherwise the two arcs stop sharing a centre. So the halo came out squarer than the card: clean along the edges, visibly off at the four corners.
Same rule applied to `panel_highlight`, which pulls in half a unit and kept the full radius. `drop_shadow` only offsets, so its geometry was already right, and the collections plate uses `RRect::with_outset`, which adjusts the radii itself.
Every card in the console goes through these two helpers — home tiles, library grid, coverflow, collections deck.
## Verification
- 98 app unit tests green; the new `ConsoleSettingsExtraTest` fails 3 of 4 with the fix stashed.
- `cargo fmt --check -p pf-console-ui` clean.
- Native compiles for arm64-v8a, armeabi-v7a and x86_64 (`:kit:cargoNdkRelease`).
⏳ **On glass owed** — nobody has yet watched the console actually drop to the touch UI, and the halo change is a visual call worth eyeballing.
Turning "Controller-optimized UI" off in the console did nothing: the console
stayed up, because the setting never left the console.
`trust::Settings::extra` is `#[serde(flatten)]`, so the `android.*` keys are
TOP-LEVEL keys of the settings document, beside `width` and `codec`.
`ConsoleJson` wrote and read them nested under an `"extra"` object instead.
Serde put that whole object into the map under the literal key `"extra"`, so
no console row ever found `android.gamepad_ui_enabled` — the row showed its
own default, and the value the console saved came back to Kotlin as the one
Kotlin had just sent. `applySettings` then saw no change, raised no callback,
and `App` never recomputed `gamepadUiActive`.
Every Android-only row rode the same broken path: low latency, phone
rumble/gyro, SC2 and DualSense capture, and the console-UI mode picker.
A store written by the nesting build carries the dead wrapper; it is dropped
on the next write rather than echoed for the life of the install.
The new test pins the shape from both sides. A round-trip alone could not have
caught this — both halves agreed on the same wrong nesting, which is exactly
how it survived review.
The focus halo grows the card's rect by 4 design units on every side but drew
it with the card's own corner radius. A shape grown by `d` keeps its corners
parallel to the original's only if its radius grows by `d` too — otherwise the
two arcs stop sharing a centre. So the halo came out squarer than the card it
sits under: clean along the edges, visibly misaligned at the four corners,
where it read as a badly drawn outline rather than as light spilling out.
Same rule applied to `panel_highlight`, which pulls in half a unit and kept the
full radius. `drop_shadow` only offsets, so its geometry was already right, and
the collections plate uses `RRect::with_outset`, which adjusts the radii itself.
Every card in the console goes through these two helpers — the home tiles, the
library grid, the coverflow, the collections deck.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Reported on glass: the "Controller-optimized UI" switch is there, turning it off does nothing — the console stays up.
The switch
pf_client_core::trust::Settings::extrais#[serde(flatten)], so theandroid.*console settings are top-level keys of the settings document, besidewidthandcodec. There is no"extra"object —trust.rs's ownsettings_unknown_keys_survive_round_tripalready asserts a serialized default contains no such key.ConsoleJsonwrote and read them nested under one. Serde put that whole object into the map under the literal key"extra", so:android.gamepad_ui_enabled— each showed its compiled default, whatever the touch UI had stored;applySettingssaw no change, raised noonSettingsChange, andAppnever recomputedgamepadUiActive.Hence a switch you can flip with nothing behind it.
It hit every Android-only row, not just this one: low latency, phone rumble, phone gyro, SC2 capture, DualSense capture, and the
Show itmode picker. None of them round-tripped from the console.A store written by the nesting build carries the dead wrapper; it is dropped on the next write rather than echoed for the life of the install.
Why nothing caught it
Both halves agreed on the same wrong nesting, so a write-then-read round-trip passes while the feature is broken —
theRoundTripKeepsEveryAndroidRowin the new test still passes with the fix reverted. The other three cases assert the shape (android.…present at the top level, no"extra"wrapper, a console-shaped save read back) and all three fail without it.The layer under the cards
Also reported: the layer behind every card, the one that reads as an outline, does not follow the card's corners.
That is
theme::focus_halo. It grows the card's rect by 4 design units on every side but drew it with the card's own radius. A shape grown bydkeeps its corners parallel to the original's only if its radius grows bydtoo — otherwise the two arcs stop sharing a centre. So the halo came out squarer than the card: clean along the edges, visibly off at the four corners.Same rule applied to
panel_highlight, which pulls in half a unit and kept the full radius.drop_shadowonly offsets, so its geometry was already right, and the collections plate usesRRect::with_outset, which adjusts the radii itself.Every card in the console goes through these two helpers — home tiles, library grid, coverflow, collections deck.
Verification
ConsoleSettingsExtraTestfails 3 of 4 with the fix stashed.cargo fmt --check -p pf-console-uiclean.:kit:cargoNdkRelease).⏳ On glass owed — nobody has yet watched the console actually drop to the touch UI, and the halo change is a visual call worth eyeballing.