Repository navigation
fix(app-shell): keep a language picked on the sign-in page when someone else last used the browser - #30397
Merged
Conversation
…change of owner (#30338) The sign-in page's language pick is written to the device slot, and SessionUserScope.adopt sweeps that slot when someone other than the browser's last owner signs in; the page then navigates away, so the next page-load booted in the browser language. The pick is now remembered for the page-load and written back after the sweep. objectui#10193's purge of what the previous owner left is unchanged. Claude-Session: https://claude.ai/code/session_01Utp6CZGT41gdDg2656as2b Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CZGT41gdDg2656as2b Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6CZGT41gdDg2656as2b Co-authored-by: Claude <noreply@anthropic.com>
Contributor
Author
|
domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG 维护者速读
席位核对 — ACCEPT · head 43bcd1f
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Bill · project thread
domain:ui#3 · os-bill · session_01Utp6CbPN5UYMnBaNJPJWfG
维护者速读
useUserLocale.ts里新增的keepSignedOutPickThroughOwnerChange,以及useLanguageSelection未登录分支。Refs #30338 (item: keep the sign-in choice)
Clause-②: no
Metadata-protocol: none
What changes
@object-ui/app-shell,useUserLocale.tsonly.useLanguageSelection, signed out, now remembers the picked language for this page-load (module scope, memory only) and installs one listener onsubscribeSessionOwnerChange.SessionUserScope.adoptdrops the previous owner's state (the event fires after the sweep), the listener writes the remembered pick back into the existingobjectui-localeslot. The next page-load boots from it like any choice.sys_userread forgets it, so it cannot reach a later owner.No new storage key, no new export from the package barrel, no request added.
Why
Measured on
origin/mainfdad1786, the card's premise does not hold:useLanguageResetOnOwnerChangeis not on the failing path. It runs insideuseSignedInUserLocale, which the console mounts only inAppContent(the/apps/:appName/*route), and the sign-in page is outside it. The drop is in the sign-in page-load itself:LocaleSwitcherswitch persistsobjectui-localethrough the i18n provider'slanguageChangedchoke point.signInsets the user;AuthProvidercallsSessionUserScope.adopt(B); the persisted pointer names A, sopurgePreviousUserClientStatesweeps every key outsideDEVICE_SCOPED_KEYS, the pick included.LoginPage's post-login effect leaves bywindow.location.assign. The next page-load has no choice and no seed, so it boots in the browser language. Its pointer already names B, so no owner change fires there.The card asked whether the previous person's residue and a pick made after they signed out can be told apart without a new stored marker. For keeping the pick, they can: the pick and the sweep happen in the same page-load, so the pick is known in memory. objectui#10193 ruling B is unchanged: with no pick since, the previous person's language is still swept (pinned below).
Acceptance notes
locale: nulland leaves the slot set, so saving the slot there would undo that choice on every boot. The seat routes the save half to its own card (await the existingsys_usersave before the sign-in page navigates), blocked by Mobile sign-in: a person who has to verify their email during the hand-off gets a mail link to 页面不存在, and the verify page drops the refusal time #30157, which holds the sign-in page files. A new stored marker was not adopted. The save half is Sign-in page: a language picked before signing in is not saved as the person's own preference when they have none (save after #30157) #30399.PLATFORM_LOCALESis a static platform table, not the deployment's list (the card's deployment offersvi, which neither the table nor the built-ins have), and moving the menu onto it is phase 4 of Platform locale table (ruling F of #29349): one list of 11 languages in spec, complete on every surface #29428, its own card. The fix does not need the list. Row 4 measures unchanged (below).Tests
New
packages/app-shell/src/hooks/__tests__/userLocaleSignInPick-30338.test.tsx, five cases: B picks then signs in (pick stored, A's seed swept); control with no pick (A's language swept, ruling B); the pick does not come back at a later owner change; a signed-in switch replaces it; the shell mounted with no navigation keeps it live and stored after the reset.vitest, the locale hook files and the LocaleSwitcher layout suite (merged head 1ec0fe4)
Ablation: useUserLocale.ts set to origin/main, new file run, then restored from HEAD (hash checked, git diff HEAD empty)
The two that stay green are the ruling-B control and the signed-in-switch guard, both expected to pass with or without the fix.
Type-check
@object-ui/app-shell'stype-checkrunstsc --noEmitandtsc -p tsconfig.test.json, so the new test file is type-checked.Verification
Local boot:
examples/app-showcaseobjectstack dev --seed-admin --fresh, console fromui/apps/consolevia vite, Playwright with browser languagezh-CN. A = the seeded admin, B = a second user. Each row is a fresh browser context; "signed out" is the auth sign-out call plus the session token and cookies removed (the owner pointer stays, as on a real sign-out). The before run swappeduseUserLocale.tstoorigin/mainand restored it from HEAD.sys_user.localeread back empty in every row before and after: the save half is not in this PR.Derived gates
On head
1ec0fe4c(after mergingorigin/main870ebce3),node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, each exit code captured before any pipe:dispatch-gates --ran: 35 derived famil(ies) accounted for, 35 run, 0 NOT-MEASURED. The type-check lanes, wide-population and roster families are CI's run.main was red at dispatch on
check:liveness(query/searchFields, #30367, fix in PR #30368, not landed at this merge); aLint UIred on that row is not this PR's.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses. (no formatter ran;pnpm lintis not run locally, it is CI's run)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed. (not touched)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code