Skip to content

Redesign customize player page: two-pane layout + accurate commander tracking#66

Merged
Jshewmaker merged 33 commits into
mainfrom
claude/modest-tereshkova-b73eb3
Jun 27, 2026
Merged

Redesign customize player page: two-pane layout + accurate commander tracking#66
Jshewmaker merged 33 commits into
mainfrom
claude/modest-tereshkova-b73eb3

Conversation

@Jshewmaker

Copy link
Copy Markdown
Owner

Why

The trigger was a bug: on the customize-player page the soft keyboard appeared upside-down for players 3 & 4. Root cause — the whole page was wrapped in RotatedBox(quarterTurns: 2), but the OS keyboard can't be rotated. Rather than patch around an impossible constraint, we redesigned the screen around its real job: accurately capturing each player's commander setup so in-game commander-damage and color-identity tracking are trustworthy.

Design + plans live in docs/superpowers/.

What changed

Keyboard / orientation

  • Removed per-seat rotation from the customize page. The pod uses the iPad in natural landscape (host types or passes it around; typing is rare — setup only). Keyboard is now upright for everyone.

Accurate tracking (the north star)

  • New Player.background — a non-attacking second card (Background enchantment): contributes to color identity but never a commander-damage clock. Kept strictly separate from Player.partner (an attacking second commander = its own 21-damage clock).
  • commanderPairingFor(Commander) auto-detects pairing from Scryfall keywords/oracle text → none | partner | background. New Commander.keywords field (mapped from Scryfall) powers it.
  • Live "this game will track" preview: damage-clock count (1 for single/background, 2 for partner-type) + combined color-identity pips.
  • Invariant verified end-to-end (state → bloc → save → in-game tracker): a Background never produces a partner clock.

Reuse (regular-group friendly)

  • shared_preferences + CommanderLibraryRepository (device-local): recents (cap 20, dedup by oracleId) and favorites (star toggle). Interface is extensible to per-friend Firebase lists for the planned friends auto-sync.

Two-pane UI

  • Left: player identity (name, first-class friend link, chosen commander(s), tracking preview, save). Right: Favorites / Recent / Search picker with adaptive default tab and an auto-detected "add partner / add background" banner.
  • Hero banner shows partner or background as the second art. Removed three obsolete widgets.

Testing

  • flutter analyze: no new issues (pre-existing app_ui/gallery errors untouched).
  • Tests: root app 22/22, player_repository 17/17 — incl. pairing detection, model round-trips/backward-compat, recents/favorites storage, bloc behavior, and the background-vs-partner clock regression.
  • Backward compatible: existing persisted players/commanders deserialize with new fields defaulting to [] / null.

Follow-ups (non-blocking, noted in final review)

  • Localize the new picker/identity strings (incl. the background-mode search hint).
  • Offer the specific "Partner with " partner when detected.
  • A "change partner/background" affordance directly in the picker.
  • Manual on-device QA of the two-pane layout was not run in this environment.

🤖 Generated with Claude Code

Jshewmaker and others added 29 commits March 28, 2026 12:12
…ll list

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two-pane player sheet, accurate commander-damage tracking via typed
second card (partner vs background), device-local recents/favorites,
and removal of per-seat rotation to fix the upside-down keyboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Plan A: data foundation & accuracy (Commander.keywords, Player.background,
commanderPairingFor, save path). Plan B: device-local recents/favorites via
shared_preferences. Plan C: two-pane UI redesign + rotation removal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… flex

The left pane wraps PlayerIdentityPanel in a SingleChildScrollView, which
gives unbounded height. The panel's Column used a Spacer (flex child),
which can't expand under unbounded height — triggering a RenderFlex
assertion that cascaded into "not laid out" errors. Replace the Spacer
with fixed spacing and shrink-wrap the Column (mainAxisSize.min). Add a
widget regression test that pumps the panel inside an unbounded-height
scroll view.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Jshewmaker Jshewmaker force-pushed the claude/modest-tereshkova-b73eb3 branch from 9b718a0 to 330ff15 Compare June 26, 2026 18:55
Jshewmaker and others added 4 commits June 26, 2026 15:29
Scryfall's image CDN (cards.scryfall.io) now returns HTTP 400 for the
default Dart User-Agent ("Dart/<version> (dart:io)") that Flutter's
Image.network sends — breaking every commander image app-wide. Install a
global HttpOverrides at startup that gives dart:io's HttpClient (used by
NetworkImage) a descriptive User-Agent. Web-safe via conditional import
(no-op; the browser supplies its own UA). Verified: curl shows the Dart
agent -> 400 and a custom agent -> 200.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CommanderSearchBar now searches automatically once the query reaches 3
characters, debounced 350ms after the last keystroke so we don't fire a
request per character (and trip Scryfall rate limits). The search button
and the keyboard's search action still trigger an immediate query.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Jshewmaker Jshewmaker merged commit 2a4293a into main Jun 27, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant