Skip to content

chore: sync fork with upstream (shop egg cards stay visible during the egg stage) - #45

Merged
cte13 merged 2 commits into
mainfrom
chore/sync-upstream-egg-shop
Sep 3, 2026
Merged

cte13 merged 2 commits into
mainfrom
chore/sync-upstream-egg-shop

Conversation

@cte13

@cte13 cte13 commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Sync

Catches the fork up with chattymin/PokeTokenBar@main (now at 56a3547).

Only one upstream commit was genuinely new — everything else in main..upstream/main was already applied by the squash-merged sync in #43, which breaks ancestry and makes those commits keep reappearing as "not merged". Verified by diffing content rather than trusting the commit list: the remaining upstream-only lines are all fork divergence (the iOS companion, the Antigravity refresh-token work from #44, statusText).

Fork follow-up

Upstream's change alters a display contract that this fork mirrors onto the phone, and the mirror does not break at compile time. phoneShopEntries fed PhoneShopEntry.canAfford from canBuyEgg, which folds hasActive into the balance check — so once eggs stayed in the list during the egg stage, the phone got a bare false and drew "Not enough tokens" on a wallet that covers the price.

  • canAfford now reports affordability only. A new optional lockedReason carries the pre-localized one-line state reason (eggShopLockedHint), nil when nothing blocks the purchase.
  • The iOS shop card renders that reason under a dimmed CTA and gives it priority over the balance label — the same priority as the Mac's EggCard.
  • lockedReason is optional so payloads from older Macs still decode. A non-optional field would throw during element decoding and drop the entire shop section to [].
  • docs/reference/defect-log.md records both classes: mirror payload fields must carry only what their name promises (a composite gate leaves the phone unable to pick a reason), and new phone payload fields need an optional + a legacy-decode test.

Verification

  • ./scripts/test-gate.sh — 1034 tests, 0 failures; logic-core line coverage 92.05% ≥ 75%.
  • xcodebuild -scheme PokeTokenBariOS — BUILD SUCCEEDED (the edited SwiftUI is outside swift build).
  • The replaced phone test was inverted to the new contract and checked by injection: restoring canAfford: companion.canBuyEgg(tier) fails it on all three tiers for both the affordability and the reason assertion.

🤖 Generated with Claude Code

https://claude.ai/code/session_012t7yGH4SM3icrTq2eGYG2R

chattymin and others added 2 commits September 2, 2026 20:03
…d buy button (chattymin#261)

During the egg stage the shop dropped all three egg cards, which read as
"the shop doesn't sell eggs" rather than "you can't buy one right now".
The purchase gate itself is intended and unchanged: a shop egg always
means "release the current Pokemon and reroll", so there is nothing to
reroll while incubating (canBuyEgg still requires an active Pokemon).

- shopEntries no longer filters eggs by hasActive; price-ascending merge
  order is unchanged.
- EggCard shows a disabled Buy button during the egg stage with a
  one-line reason underneath, localized in all seven languages. The
  state reason takes priority over the insufficient-balance label.
- The "eggs omitted when no active" test is replaced by one pinning the
  new contract: eggs stay visible, canBuyEgg/buyEgg stay blocked for
  every tier, and a blocked attempt does not touch the wallet.

Co-authored-by: p <p@local>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 56a3547)
…enough tokens"

Upstream chattymin#261 keeps the three shop egg cards visible during the egg stage
and disables only the buy button. The fork's phone mirror inherited the
visibility but not the reason: `PhoneShopEntry.canAfford` was fed
`canBuyEgg`, which folds `hasActive` into the balance check, so the phone
received a bare `false` and rendered "Not enough tokens" on a wallet that
covers the price.

- `canAfford` now reports affordability only; a new optional
  `lockedReason` carries the pre-localized one-line state reason
  (`eggShopLockedHint`), nil when nothing blocks it.
- The iOS shop card shows that reason under a dimmed CTA and gives it
  priority over the balance label, matching the Mac's EggCard.
- `lockedReason` is optional so payloads from older Macs still decode;
  a non-optional field would throw and drop the whole `shop` section.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012t7yGH4SM3icrTq2eGYG2R
@cte13
cte13 merged commit b111e7a into main Sep 3, 2026
@cte13
cte13 deleted the chore/sync-upstream-egg-shop branch September 3, 2026 03:24
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.

2 participants