Skip to content

fix: admin default theme not applied for new users; force LTR on login inputs#689

Open
xhzeem wants to merge 1 commit into
bulwarkmail:mainfrom
xhzeem:fix/admin-default-theme-race
Open

fix: admin default theme not applied for new users; force LTR on login inputs#689
xhzeem wants to merge 1 commit into
bulwarkmail:mainfrom
xhzeem:fix/admin-default-theme-race

Conversation

@xhzeem

@xhzeem xhzeem commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Two separate bugs found while testing the RTL/Arabic work in #661 / #664.

1. Admin-configured default theme never reached new user sessions

initializeTheme() (stores/theme-store.ts) determines the effective theme synchronously on mount, including a fallback to usePolicyStore.getState().policy.themePolicy?.defaultThemeId. But /api/admin/policy is only fetched after /api/config resolves (hooks/use-config.ts, explicitly commented "non-blocking") — a minimum of two chained network round-trips. A brand-new user's theme init (pure sync/localStorage) always wins that race, so the policy-default branch always sees an empty policy and falls back to activeThemeId: null — which then gets persisted, making the miss permanent instead of self-correcting on the next reload. New accounts were stuck on the built-in look regardless of what the admin configured as default.

Fix: added a themeChoiceMade flag (persisted) to distinguish "user explicitly picked Default" from "never decided yet" — both currently look identical as activeThemeId === null. Added a one-shot subscription to the policy store that retroactively applies themePolicy.defaultThemeId once policy actually loads, but only when the user hasn't made their own choice (neither before boot nor in the interim while waiting for policy).

2. Login inputs right-aligned in RTL locales

The JMAP endpoint, username, password, and TOTP inputs on the login page (plus the admin password input) inherit dir="rtl" from <html> when an RTL locale (ar/he/fa) is active, right-aligning fields that must always read left-to-right regardless of UI language — same category of bug as #664, just not covered there since it's plain dir inheritance rather than bidi character mirroring. Set dir="ltr" explicitly on each.

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run — same result as a clean main (one pre-existing, unrelated failure: the newly-merged ca locale is missing email_composer.toolbar.* keys added in a later commit than when Catalan was added — reproduces identically on main, not touched by this PR)
  • Manual verification: fresh account against a server with themePolicy.defaultThemeId set boots into that theme; login fields stay LTR in ar/he/fa

…inputs

Two independent RTL/theming bugs:

1. Admin-configured default theme (themePolicy.defaultThemeId) never
   reached new user sessions. initializeTheme() (stores/theme-store.ts)
   reads the policy store synchronously on mount, but /api/admin/policy
   is only fetched after /api/config resolves (hooks/use-config.ts,
   explicitly "non-blocking") - a minimum of two chained network round
   trips. A brand-new user's synchronous theme init always finished
   first, so the default-theme branch always saw an empty policy and
   fell back to activeThemeId: null - which then got persisted, making
   the miss permanent instead of self-correcting on reload.

   Added a themeChoiceMade flag (persisted) to distinguish "user
   explicitly picked Default" from "never decided yet," and a one-shot
   subscription to the policy store that retroactively applies
   themePolicy.defaultThemeId once it loads, but only if the user
   hasn't made their own choice (initially or since boot).

2. Login inputs (JMAP endpoint, username, password, TOTP, admin
   password) inherited dir="rtl" from <html> in RTL locales, right-
   aligning credential fields that must always read LTR. Set dir="ltr"
   explicitly on each.
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