Skip to content

Fix usage panel sizing and localization - #95

Draft
zenghuizhu69-hub wants to merge 7 commits into
aqua5230:mainfrom
zenghuizhu69-hub:agent/fix-usage-panel-layout-i18n
Draft

Fix usage panel sizing and localization#95
zenghuizhu69-hub wants to merge 7 commits into
aqua5230:mainfrom
zenghuizhu69-hub:agent/fix-usage-panel-layout-i18n

Conversation

@zenghuizhu69-hub

Copy link
Copy Markdown

What changed

  • add Yesterday project usage and footer totals across the Windows and macOS panel payloads
  • prefer the general Codex weekly rate-limit record instead of model-specific limits
  • make Windows panel height react to initial layout, font loading, project-range changes, and later DOM resizing
  • preserve the full Codex title when the panel switch button moves into its header
  • add a persisted Language menu with Auto, Simplified Chinese, Traditional Chinese, English, Japanese, and Korean
  • make Windows Auto language detection ignore inherited POSIX LANG values and follow the Windows UI language
  • prevent stale refresh workers from overwriting a newly selected language
  • clamp dynamic height against the monitor that contains the panel

Why

The panel could open at a stale height because it measured before WebView2 layout stabilized, and project-range updates bypassed the measurement path. The Codex heading was the only flexible item in an overcrowded header, so it collapsed to a single character. Windows language selection was startup-only and could be incorrectly forced to English by LANG=C.UTF-8. Codex weekly usage could also select a model-specific reset window instead of the general account limit.

User impact

The tray panel now fits its visible content without repeated button clicks, keeps the Codex name readable, exposes a persistent language selector, displays yesterday's totals, and reports the intended Codex weekly allowance.

Validation

  • 178 passed, 1 skipped across Windows-safe dynamic-height, language, tray, i18n, menubar-state, and Codex-loader tests
  • git diff --check
  • the skipped test imports the macOS-only objc dependency and is not runnable on Windows

@aqua5230

Copy link
Copy Markdown
Owner

Automated review (Codex)

The patch introduces localization and installer regressions, and the new "yesterday" view can become stale across midnight. The single-instance activation protocol also has a silent-failure race.

[P2] Preserve LANG detection on non-Windows platformsusage_lang.py:67-70
For normal detect_lang() calls, this drops LANG on every platform, not only Windows. On Linux, a locale such as LANG=ja_JP.UTF-8 now falls through to the macOS detector and returns English because Foundation is unavailable; macOS LANG overrides also regress. Exclude LANG only when sys.platform == "win32".

[P2] Quote the Run-key commandinstaller/windows/usage.iss:51
When {app} contains spaces (a custom installation directory or user profile path), Windows parses this unquoted Run value as an executable ending at the first space, so autostart fails or invokes the wrong path. Store the executable path with embedded command-line quotes.

[P2] Invalidate "yesterday" rows at the date boundarywintray.py:980
When the tray stays running across local midnight without any history file changing, projects still comes from _cached_projects, whose invalidation key only contains file metadata. This keeps showing the previous "yesterday" bucket until another entry is written or the app restarts, while the footer is recalculated for the new date. Include the local date in the cache key, or recompute calendar buckets each refresh.

[P3] Handle a missing activation eventwintray.py:1573-1574
If a second process observes the mutex after the first process creates it but before CreateEventW runs, OpenEventW returns null; the same happens when the existing instance predates this event protocol. The second process then exits silently without activating anything. Retry briefly, or retain a fallback when the event cannot be opened.


Generated with Codex CLI, dispatched via Claude Code.

@aqua5230

Copy link
Copy Markdown
Owner

Heads-up: a large Windows change is landing in main (#96)

Thanks for the work here, and sorry for the timing — I want to flag this early so you don't rebase into a surprise.

#96 is a broad Windows pass that touches many of the same files as this PR. It is not yet merged, but it is likely to land before this one. This PR already shows CONFLICTING against main independently of #96, so a rebase was going to be needed regardless; I'd rather tell you what's coming than have you do it twice.

Files changed on both sides

wintray.py · tests/test_wintray.py · scripts/build_windows.ps1 · assets/usage.ico · assets/panels/panel_core.js · panels/payload.py · i18n.json · tests/test_panels.py

wintray.py is the heaviest overlap. #96 restructures it substantially: the tray and panel menus are no longer two hand-written lists but render from a shared descriptor model in a new wintray_menu.py, and the tray right-click menu is reduced to Reset Panel Position + Quit (everything else moved into the panel menu). The Win32 geometry code was also reworked to stay in pywebview logical coordinates and to marshal all window mutation onto the UI thread.

What is now redundant

What is genuinely unique and worth keeping

The Inno Setup installer (installer/windows/usage.iss + scripts/build_windows_installer.ps1). #96 does not touch this at all, and the project currently only ships a portable zip. This is the most valuable part of this PR and it has almost no overlap.

Suggestion: consider splitting the installer into its own PR off current main. It would be reviewable and mergeable on its own without waiting on any of the above, and it avoids carrying the conflicted files along with it.

Still open from the earlier review

The four findings in the previous comment have not been addressed yet. The first one in particular is worth fixing wherever this work ends up landing:

  • usage_lang.py — the LANG exclusion applies on every platform, not just Windows, so LANG=ja_JP.UTF-8 on Linux now falls through to the macOS detector and returns English. Gate it on sys.platform == "win32".
  • The Run-key quoting, the "yesterday" cache not invalidating at the date boundary, and the missing-activation-event race are the other three.

Happy to help sort out the rebase once #96 is in — just say the word.

@aqua5230

Copy link
Copy Markdown
Owner

Update: #96 has now merged

Quick status update, and an amendment to what I said last time.

#96 landed in main on Aug 13. This PR now conflicts more heavily than before — wintray.py in particular, where the tray and panel menus are now rendered from a shared descriptor model in wintray_menu.py rather than two hand-written lists, and the refresh worker is a single queue-driven loop instead of the old non-blocking-lock model.

One correction to my earlier comment

I said the dynamic panel height work was superseded. That was only half right:

  • Monitor clamping — yes, superseded. main now derives the work area from the monitor the panel is actually on.
  • Re-measuring on initial layout, font load, project-range change, and later DOM resizenot superseded. main still measures once after usageApplyState. This part of your PR is genuinely new and worth keeping.

Where things stand, per file

  • Installer (installer/windows/usage.iss, scripts/build_windows_installer.ps1) — still the most valuable part, still zero overlap with Windows: P1 修正、原生功能整合與 macOS 功能對齊 #96. Please open this as its own PR off current main; it can be reviewed and merged on its own. Two small things when you do: quote the Run-key command so paths with spaces work, and the three user-visible strings (Create a desktop shortcut, Start Usage when I sign in to Windows, Launch Usage) are hardcoded English — every user-facing string in this project goes through i18n.
  • Yesterday view, height re-measure triggers, Codex header title — new and wanted, but they need to be rebased onto current main.
  • Language menu and the refresh-worker language race — these have to be rewritten against wintray_menu.py and the new refresh queue. The current patches no longer apply.
  • codex_loader.py — I checked this against real session data: limit_id is codex in essentially every record, and the rare alternative carries no numbers at all. Your change is a safe improvement, but note this loader is shared with macOS, so it needs a cross-platform regression test before it lands.
  • usage_lang.py — I've fixed this in main myself, since it was a live Windows bug independent of this PR. Note your version gated on env is None, which drops LANG on every platform, not just Windows; the fix in main gates on sys.platform == "win32". Thanks for surfacing it.
  • assets/usage.ico — superseded by Windows: P1 修正、原生功能整合與 macOS 功能對齊 #96, which added its own icon plus scripts/make_ico.py.

I don't want this to sit indefinitely. If I don't hear from you within a week, I'll land the pieces above myself with attribution to you and close this PR — no hard feelings either way, and the installer is still yours to open whenever you like.

aqua5230 added a commit that referenced this pull request Aug 13, 2026
Git Bash / MSYS 會塞一個 LANG 進環境變數(通常是 en_US.UTF-8),
不代表使用者的系統語言,卻蓋掉了 GetUserDefaultUILanguage 的結果。
Windows 上只保留 USAGE_LANG 與 TT_LANG 這兩個顯式覆寫,其他平台不變。

問題由 PR #95 (zenghuizhu69-hub) 指出;該 PR 的修法以 env is None 為
條件,會連帶讓 Linux/macOS 也不再尊重 LANG,故改以平台判斷實作。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

3 participants