feat(gamepad-ui): profiles integration — pinned cards, pin management, settings section on all three gamepad UIs #42

Merged
enricobuehler merged 4 commits from worktree-gamepad-ui-profiles into main 2026-08-04 18:12:41 +00:00
Owner

Closes the gamepad-UI half of the client settings profiles design (client-settings-profiles.md §5.2a, §5.4) across all three gamepad UI implementations. Profiles stay desktop-authored; the gamepad surfaces render pinned cards, connect with them, and — new — manage pins.

Console (Linux/Windows, pf-console-ui + session binary) — 63a4f583

Previously had no profiles integration at all.

  • Pinned cards: the service thread expands each saved host into its primary tile followed by one card per KnownHost::pinned_profiles entry (resolved against the catalog, dedup + dangling-drop via resolved_pins). Card subtitle = profile name, tinted with the profile accent. Primary tiles show the bound default profile chip after the address.
  • Connect-with-profile: ConnectIntent/OverlayAction::Launch carry an optional one-off profile id fed to trust::effective_settings — the same resolver --connect --profile uses; dangling ids fall back to defaults without blocking the connect. Wake-then-connect from a pinned card keeps the profile.
  • Pin management: Settings gains a trailing Profiles section (one row per profile, live "Pinned to N hosts" counts, desktop-app explainer; inert "No profiles yet" placeholder when the catalog is empty). Activating opens a pin-to-hosts screen; toggles ride ConsoleCmd::SetPin to the binary, which persists pinned_profiles (append = card order; never touches the default binding; idempotent).
  • ConsoleEntry::Library boxes its HostRow (clippy large_enum_variant once the row learned its profile chips).

This is the Decky contract: pins created here land in KnownHost.pinned_profiles, which the CLI already resolves into its hosts JSON, and punktfunk-session --connect --profile already exists — the redesigned Decky panel renders pinned cards with no plugin-side work.

Apple (80b4eccf)

Pinned cards + connect were already in from WP5; this adds the missing management: GamepadSettingsView gains the same Profiles section with an in-place pin-to-hosts picker driving HostStore.setPinned. On tvOS this is the only possible pin surface — and since tvOS ships no profile editor and the catalog is a per-device App Group, the tvOS strings honestly say creation isn't available on Apple TV instead of pointing at a UI that doesn't exist there.

Android (857d7d7b, ff560236)

Pinned cards + unpin were already in from WP6; pin-add was touch-only. GamepadSettingsScreen gains the Profiles section plus a console-styled, remote-navigable GamepadPinHostsDialog writing KnownHost.pinnedProfileIds. Strings branch on isTvDevice: a TV names the actual on-device route (turn off Controller-optimized UI → standard interface, which unlike tvOS does contain the editor); phones keep "the touch interface".

Verification

  • Rust: cargo clippy --all-targets --locked -D warnings on pf-console-ui / punktfunk-client-session / pf-presenter + cargo test -p pf-console-ui (47 passed, incl. new tests for pinned-card connect intent, the settings section, and SetPin emission) — Linux amd64 container; cargo fmt --all clean.
  • Apple: swift build clean (macOS pass over the shared gamepad views; required rebuilding the stale local xcframework — gitignored, not in this diff); SharedFoundationTests 22/22 + 4 related suites green.
  • Android: :app:compileDebugKotlin green; KnownHostStoreTest + ProfilesTest green.

Owed / not covered: on-glass passes on all three surfaces (Deck console visuals, tvOS focus engine, Android TV remote); tvOS-conditional #if lines are typecheck-unverified (macOS build doesn't compile them). tvOS will realistically show the empty-catalog placeholder until a profile sync/import path exists — worth a design-doc note.

Closes the gamepad-UI half of the client settings profiles design (`client-settings-profiles.md` §5.2a, §5.4) across all three gamepad UI implementations. Profiles stay desktop-authored; the gamepad surfaces render pinned cards, connect with them, and — new — manage pins. ## Console (Linux/Windows, `pf-console-ui` + session binary) — `63a4f583` Previously had no profiles integration at all. - **Pinned cards**: the service thread expands each saved host into its primary tile followed by one card per `KnownHost::pinned_profiles` entry (resolved against the catalog, dedup + dangling-drop via `resolved_pins`). Card subtitle = profile name, tinted with the profile accent. Primary tiles show the bound default profile chip after the address. - **Connect-with-profile**: `ConnectIntent`/`OverlayAction::Launch` carry an optional one-off profile id fed to `trust::effective_settings` — the same resolver `--connect --profile` uses; dangling ids fall back to defaults without blocking the connect. Wake-then-connect from a pinned card keeps the profile. - **Pin management**: Settings gains a trailing **Profiles** section (one row per profile, live "Pinned to N hosts" counts, desktop-app explainer; inert "No profiles yet" placeholder when the catalog is empty). Activating opens a pin-to-hosts screen; toggles ride `ConsoleCmd::SetPin` to the binary, which persists `pinned_profiles` (append = card order; never touches the default binding; idempotent). - `ConsoleEntry::Library` boxes its `HostRow` (clippy `large_enum_variant` once the row learned its profile chips). **This is the Decky contract**: pins created here land in `KnownHost.pinned_profiles`, which the CLI already resolves into its hosts JSON, and `punktfunk-session --connect --profile` already exists — the redesigned Decky panel renders pinned cards with no plugin-side work. ## Apple (`80b4eccf`) Pinned cards + connect were already in from WP5; this adds the missing management: `GamepadSettingsView` gains the same Profiles section with an in-place pin-to-hosts picker driving `HostStore.setPinned`. On tvOS this is the only possible pin surface — and since tvOS ships no profile editor and the catalog is a per-device App Group, the tvOS strings honestly say creation isn't available on Apple TV instead of pointing at a UI that doesn't exist there. ## Android (`857d7d7b`, `ff560236`) Pinned cards + unpin were already in from WP6; pin-add was touch-only. `GamepadSettingsScreen` gains the Profiles section plus a console-styled, remote-navigable `GamepadPinHostsDialog` writing `KnownHost.pinnedProfileIds`. Strings branch on `isTvDevice`: a TV names the actual on-device route (turn off Controller-optimized UI → standard interface, which unlike tvOS does contain the editor); phones keep "the touch interface". ## Verification - Rust: `cargo clippy --all-targets --locked -D warnings` on `pf-console-ui` / `punktfunk-client-session` / `pf-presenter` + `cargo test -p pf-console-ui` (47 passed, incl. new tests for pinned-card connect intent, the settings section, and SetPin emission) — Linux amd64 container; `cargo fmt --all` clean. - Apple: `swift build` clean (macOS pass over the shared gamepad views; required rebuilding the stale local xcframework — gitignored, not in this diff); `SharedFoundationTests` 22/22 + 4 related suites green. - Android: `:app:compileDebugKotlin` green; `KnownHostStoreTest` + `ProfilesTest` green. **Owed / not covered**: on-glass passes on all three surfaces (Deck console visuals, tvOS focus engine, Android TV remote); tvOS-conditional `#if` lines are typecheck-unverified (macOS build doesn't compile them). tvOS will realistically show the empty-catalog placeholder until a profile sync/import path exists — worth a design-doc note.
enricobuehler added 4 commits 2026-08-04 18:05:09 +00:00
The Skia console now renders a pinned profile card after its host's primary
tile (KnownHost::pinned_profiles resolved by the service thread), connects
with that profile as a one-off via the existing effective_settings resolver,
and shows the bound default profile on the primary tile. The settings screen
gains a trailing Profiles section — one row per catalog profile with a live
pin count — whose activation opens a pin-to-hosts screen; toggles ride the
new ConsoleCmd::SetPin to the binary, which persists pinned_profiles (the
same field the CLI resolves for Decky's host list). Profiles themselves stay
desktop-authored (design client-settings-profiles.md §5.2a, §5.4).
GamepadSettingsView gains a trailing Profiles section (one row per catalog
profile, live pinned-to-N-hosts counts) and an in-place pin-to-hosts picker
driving HostStore.setPinned — the first pin management reachable from the
controller-first UI, and on tvOS the only possible one. tvOS wording drops
the 'create them in the standard interface' promise (no profile editor
exists there); other platforms keep it. Pinned-card rendering and the
connect path were already in from WP5 and stay untouched.
GamepadSettingsScreen gains the trailing Profiles section (per-profile rows
with live pin counts, touch-interface explainer) and a console-styled
GamepadPinHostsDialog — controller- and TV-remote-navigable pin management
writing KnownHost.pinnedProfileIds through the existing store path. Pin-add
was previously touch-only; pinned-card rendering and unpin stay as they
were.
fix(android/gamepad): TV wording points at the Controller-optimized UI toggle
apple / swift (pull_request) Successful in 1m18s
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 1m30s
ci / docs-site (pull_request) Successful in 1m20s
ci / web (pull_request) Successful in 1m37s
android / android (pull_request) Successful in 5m22s
windows / build (aarch64-pc-windows-msvc) (pull_request) Successful in 1m6s
windows / build (x86_64-pc-windows-msvc) (pull_request) Successful in 1m55s
ci / rust (pull_request) Successful in 8m35s
ff5602361f
'Created and edited in the touch interface' is dead advice on a TV box — no
touch to reach it with. Unlike tvOS the editor DOES exist on-device (same
APK), behind this screen's own Controller-optimized UI toggle, so on TV the
Profiles strings now name that route instead.
enricobuehler merged commit 454fa2e0cb into main 2026-08-04 18:12:41 +00:00
enricobuehler deleted branch worktree-gamepad-ui-profiles 2026-08-04 18:12:42 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unom/punktfunk#42