Skip to content

fix(ui): SessionPicker honors wallet currency instead of hardcoded ¥ (#312)#357

Merged
esengine merged 1 commit intomainfrom
fix-312-session-picker-currency
May 7, 2026
Merged

fix(ui): SessionPicker honors wallet currency instead of hardcoded ¥ (#312)#357
esengine merged 1 commit intomainfrom
fix-312-session-picker-currency

Conversation

@esengine
Copy link
Copy Markdown
Owner

@esengine esengine commented May 7, 2026

Closes #312

Summary

Same bug shape as the StatusRow / UsageCard / StatsPanel set fixed under #272 — SessionPicker still hardcoded ¥ and ran USD → CNY itself, so USD-wallet users saw ¥X.XX in the session list picker.

The wallet currency in this codebase isn't persisted in config — it comes from a live balance fetch. The pre-mount picker (chat.tsx) doesn't have that yet. So the fix has two layers:

  • Stored fallback: SessionMeta gains balanceCurrency?: string. Every turn's cost-save in App.tsx writes it alongside totalCostUsd. Rows fall back to their own stored currency when no live prop is in scope.
  • Live prop: SessionPicker accepts walletCurrency. The in-app picker (/sessions) gets walletCurrencyRef.current. Prop wins over per-row stored value.

Cost rendering routes through the shared formatCost(usd, currency, digits) helper instead of the inline ¥${...}.

Test plan

  • tests/ui-session-picker-currency.test.tsx — 4 cases: USD prop, CNY prop, no-prop + USD meta, no-prop + no meta (legacy default ¥)
  • npx vitest run — 165/165 test files, 2423 tests pass

…312)

Same bug shape as the StatusRow / UsageCard / StatsPanel set that #272
already fixed — `SessionPicker` was still doing
`¥${totalCostUsd * USD_TO_CNY}` so USD-wallet users saw ¥-formatted
costs in the session list.

- `SessionMeta` gains `balanceCurrency?: string`. App.tsx writes the
  live wallet currency alongside `totalCostUsd` on each turn save, so
  every persisted session knows what currency its cost is denominated
  in.
- `SessionPicker` accepts a `walletCurrency` prop and falls back to
  each row's `meta.balanceCurrency`. Prop wins (live value > stored).
  In-app picker (`/sessions`) gets the live ref from App; pre-mount
  picker in `chat.tsx` doesn't have a balance fetched yet, so it
  relies on the stored per-session value.
- Cost rendering routes through the shared `formatCost()` helper that
  the rest of the cost UI already uses.
- Regression test asserts USD wallet → `$0.05`, CNY wallet → `¥0.36`,
  no-prop + stored-USD → `$0.05`, neither → unchanged `¥0.36`.
@esengine esengine merged commit 1805b0c into main May 7, 2026
3 checks passed
@esengine esengine deleted the fix-312-session-picker-currency branch May 7, 2026 05:22
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.

SessionPicker shows ¥ for USD wallets

1 participant