You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[$250] Public Room - Public room does not display open after loging in as existing account #95445
An anonymous user viewing a public room already holds an (anonymous) auth token, so the app treats them as "authenticated". When they tap Pin, the action is gated by interceptAnonymousUser, which calls signOutAndRedirectToSignIn. For an anonymous user this branch just opens the sign-in modal without stashing the current room route:
if(isAnonymousUser()){if(!Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)){if(shouldResetToHome){Navigation.resetToHome();}Navigation.navigate(ROUTES.SIGN_IN_MODAL);// current /r/<id> route not saved}return;}
After credentials are entered, SignInModalunconditionally navigates to ROUTES.HOME, discarding the public room the user was viewing:
Navigation.dismissModal();Navigation.navigate(ROUTES.HOME);// hardcoded — public room is lost
Because the user was already "authenticated" (anonymous token), the deep-link route-restoration path in openReportFromDeepLink is never armed for this flow, so nothing re-navigates back to the room. Result: after login the user lands on Home instead of the public room.
What changes do you think we should make in order to solve the problem?
Preserve and restore the room route across the anonymous → authenticated transition:
When opening the sign-in modal for an anonymous user in signOutAndRedirectToSignIn, capture the currently-active route (the /r/<reportID> the user is on).
In SignInModal, after dismissModal(), navigate back to that saved route instead of the hardcoded ROUTES.HOME (fall back to HOME only when there was no prior route).
Investigation details, alternative considered, and related issues
Flow traced:
Anonymous user opens /r/<reportID> — holds an anonymous authToken, so useIsAuthenticated()/hasAuthToken() treat them as authenticated; openReportFromDeepLink early-returns without arming a post-login navigate.
Tap Pin → interceptAnonymousUser → signOutAndRedirectToSignIn() → opens SIGN_IN_MODAL, no route stored.
Enter credentials → session.authTokenType flips away from ANONYMOUS → SignInModal runs openApp(true), then on IS_LOADING_APP === false does dismissModal() + navigate(ROUTES.HOME).
App lands on Home; public room is not reopened.
Alternative considered: route the anonymous case through openReportFromDeepLink's waitForUserSignIn restoration instead of stashing the route in SignInModal. Both work; stashing the active route is the smaller, more localized change and doesn't depend on the deep-link handler being re-invoked (it isn't, on web).
Confidence: High — the hardcoded Navigation.navigate(ROUTES.HOME) combined with the un-stashed route deterministically explains the reported behavior on both web (Windows: Chrome) and Android.
Likely related open issues (same deep-link/anon login family — probably fix together or de-dupe):
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/95445) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
Please re-state the problem that we are trying to solve in this issue.
When an anonymous user opens a public room deep link (e.g. https://staging.new.expensify.com/r/1540486774487195), taps Pin on a message to trigger the sign-in modal, and then signs in with an existing account, the app lands on the default Home screen instead of restoring the public room the user was viewing before login. Expected: after login the public room should remain open at the same route.
What is the root cause of that problem?
There are two independent failure points that together prevent the public room from being restored after login.
Failure 1 — NavigationRoot never re-applies the deep-link path on auth transition.
The initialStateuseMemo in src/libs/Navigation/NavigationRoot.tsx (starting around line 129) is responsible for seeding the navigator's initial route. Two conditions inside it cause it to return undefined instead of the captured /r/{reportID} path:
(a) Line 139 early-returns undefined whenever account.isFromPublicDomain is truthy. The Applause tester's +odtesting@gmail.com address has a public-domain suffix, so this fires and short-circuits before any deep-link handling.
(b) Even without that, line 155's isSpecificDeepLink branch explicitly returns undefined for non-root deep links, so the /r/... route captured while the user was anonymous is never re-hydrated when authenticated flips from false to true and the navigator swaps from the Public screen stack to the Auth screen stack.
Failure 2 — SignInModal unconditionally navigates to Home after sign-in, overwriting any route restoration.
src/pages/signin/SignInModal.tsx contains a useEffect (lines 63–69) that fires once IS_LOADING_APP becomes false after a successful sign-in:
useEffect(()=>{if(!hasSignedInRef.current||isLoadingApp!==false){return;}Navigation.dismissModal();Navigation.navigate(ROUTES.HOME);// ← always navigates to Home},[isLoadingApp]);
Even if NavigationRoot's initialState were fixed to restore /r/{reportID}, this effect runs after openApp resolves and unconditionally replaces whatever route was set with ROUTES.HOME. For the SignInModal flow (anonymous user, deep-link open, pin-tap triggers sign-in), this is the direct cause of the regression.
What changes do you think we should make in order to solve the problem?
Change 1 — Fix SignInModal to preserve the public-room route.
In src/pages/signin/SignInModal.tsx, before calling Navigation.navigate(ROUTES.HOME), check whether the user arrived via a public-room deep link. If so, navigate to that report instead of Home:
useEffect(()=>{if(!hasSignedInRef.current||isLoadingApp!==false){return;}Navigation.dismissModal();constinitialUrl=useInitialURL();// already available via InitialURLContextProviderconstreportIDMatch=initialUrl?.match(/\/r\/(\d+)/);if(reportIDMatch){Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportIDMatch[1]));}else{Navigation.navigate(ROUTES.HOME);}},[isLoadingApp]);
The initial URL is the URL the anonymous user had open when the SignInModal appeared — useInitialURLState() from @components/InitialURLContextProvider already exposes it. Prefer that over getCurrentUrl() because the URL bar may have been replaced by the sign-in flow before this effect fires.
Change 2 — Fix NavigationRoot to re-apply the deep-link on the false → true auth transition.
In src/libs/Navigation/NavigationRoot.tsx around the initialState memo (lines 129–164), when authenticated becomes true and initialUrl is a public-report deep link (/r/{reportID} — matching ROUTES.REPORT_WITH_ID), return getAdaptedStateFromPath(path) instead of undefined, regardless of account.isFromPublicDomain.
Do not gate this restoration on isFromPublicDomain — that flag reflects the user's email domain, not the room's visibility, and public-domain users are the primary consumers of public-room links.
Add handling in the existing useEffect on [authenticated] (around line 198) to trigger a Navigation.navigate to the captured path on the false → true transition, so the deep link captured while anonymous survives the Public/Auth navigator swap.
Change 3 — Preserve the existing guard.
Keep the isTransitioning (TRANSITION_BETWEEN_APPS) guard at line 143 intact — that path is owned by LogOutPreviousUserPage and setUpPoliciesAndNavigate and must not be double-handled here.
What alternative solutions did you explore?
Patching only NavigationRoot.tsx without touching SignInModal.tsx would be insufficient: even with a correctly restored initialState, the SignInModal effect at lines 63–69 fires after openApp resolves and unconditionally calls Navigation.navigate(ROUTES.HOME), which overwrites any restored route. Both layers must be fixed together.
🚨 Edited by proposal-police: This proposal was edited at 2026-07-06 21:36:50 UTC.
Proposal
Please re-state the problem that we are trying to solve in this issue.
An anonymous user viewing a public room triggers an auth-gated action (pin), signs in with an existing account, and the app lands on Home/Inbox instead of showing the public room they were viewing. The room should stay open after login.
What is the root cause of that problem?
When the anonymous user taps pin, checkIfActionIsAllowed calls signOutAndRedirectToSignIn(), which for anonymous sessions just opens the sign-in RHP on top of the still-mounted public-room ReportScreen:
Once IS_LOADING_APP flips to false, a second effect dismisses the modal — which alone would reveal the public room underneath — and then unconditionally navigates to Home, replacing the room:
That Navigation.navigate(ROUTES.HOME) exists for exactly one cohort: brand-new accounts. It was added in PR #87257 ("Navigate to HOME after openApp to trigger onboarding for anonymous sign-in") because a plain modal dismissal (a POP) does not trigger the OnboardingGuard redirect. But for an existing account, NVP_ONBOARDING.hasCompletedGuidedSetupFlow is true, so the guard computes isOnboardingCompleted = true → shouldSkipOnboarding = true → ALLOW, and the navigation simply lands on Home with no benefit:
Structural cause: a navigation needed only by not-yet-onboarded users fires for every user. Regression history confirms it: PR #86390 fixed this exact symptom by removing this line (commit e235263d0) plus preserving fullscreen routes in the router guard handling, but it was CP-reverted by PR #90387 because the router change caused deploy blocker #90303 (dead back button on Concierge after onboarding). The revert restored the unconditional Home navigation and re-introduced this bug.
All anonymous entry points funnel into this one effect, so this single line explains every repro variant: pin/context-menu (BaseReportActionContextMenu.tsx), the "Sign in" button in AnonymousReportFooter.tsx, the sidebar SignInButton.tsx, and emoji reactions all call the same signOutAndRedirectToSignIn → same modal. SignInModal.tsx is a single shared file (no index.native split), which matches the cross-platform repro (Android app + Windows Chrome, narrow and wide layouts).
What changes do you think we should make in order to solve the problem?
In SignInModal.tsx, gate the Home navigation on onboarding not being completed, reusing the exact selector pattern already used for the same decision in NavigationRoot:
const[isOnboardingCompleted=true]=useOnyx(ONYXKEYS.NVP_ONBOARDING,{selector: hasCompletedGuidedSetupFlowSelector});// in the existing isLoadingApp effect:Navigation.dismissModal();if(!isOnboardingCompleted){Navigation.navigate(ROUTES.HOME);}
The flag is authoritative at decision time by the effect's own documented precondition: IS_LOADING_APP only flips to false after the OpenApp response is processed and NVP_ONBOARDING is loaded (comment at
// Wait for IS_LOADING_APP to become false after sign-in before dismissing the modal.
// openApp queues a request and IS_LOADING_APP only transitions to false once the response
// is processed and NVP_ONBOARDING is loaded. Dismissing at that point ensures OnboardingGuard
// evaluates with accurate data and properly redirects new users to onboarding.
). New users get byte-identical behavior (navigate → guard redirects to onboarding); existing users get the modal dismissed and the public room revealed underneath — no extra navigation at all. Regression safety in one sentence: the new-user path is unchanged, the router/guard code is untouched, and non-anonymous sign-out flows take the other branch of signOutAndRedirectToSignIn and never reach this effect.
Why the obvious one-line fix fails: simply deleting Navigation.navigate(ROUTES.HOME) is exactly what PR #86390 did — and it regresses new-user onboarding, the reason the line was added: Navigation.dismissModal() is a POP action, so without a subsequent navigate the OnboardingGuard never fires its REDIRECT and a new account signing up from a public room never sees the onboarding modal (the #85242/#87257 bug; an earlier attempt #85660 was also reverted). Equally, re-landing #86390's router-level route-preservation is not viable — it caused deploy blocker #90303 and was CP-reverted, so the fix must stay out of RootStackRouter's guard handling. Conditioning the navigation on the already-loaded onboarding NVP is the only variant that keeps both prior fixes intact.
What alternative solutions did you explore? (Optional)
Delete the navigate entirely — breaks new-user onboarding (see above); this was tried in #86390 and reverted.
Preserve fullscreen routes during the guard REDIRECT (#86390's router change) — caused deploy blocker #90303; must not be re-proposed as-is.
Mirror all of the guard's skip conditions (migrated users, invited/group members) instead of only isOnboardingCompleted — would also keep the room open for those cohorts, but duplicates guard logic in a component; those users behave exactly as today under my fix, so this can be a follow-up if desired.
Re-navigate to a stored last-visited path after Home — adds a visible navigation flicker and per-login work; gating removes the unnecessary navigation entirely instead of compensating for it.
🚨 Edited by proposal-police: This proposal was edited at 2026-07-06 21:43:01 UTC.
Proposal
Please re-state the problem that we are trying to solve in this issue.
Open a public room link while logged out, tap a message, and pin it. That triggers a sign-in prompt. After you log in with an existing account, you land on the inbox instead of the public room you were just looking at. The room you had open is gone, and nothing brings you back to it.
What is the root cause of that problem?
The problem is in src/pages/signin/SignInModal.tsx. When an anonymous user pins a message, interceptAnonymousUser (BaseReportActionContextMenu.tsx) calls Session.signOutAndRedirectToSignIn(), which pushes the SIGN_IN_MODAL RHP over the current /r/<id> route. This all happens in the same JS runtime, so the report screen stays mounted underneath. Once sign-in completes and IS_LOADING_APP flips to false, this effect runs (lines 61-68):
dismissModal() does the right thing and restores the public room the modal was opened over. But navigate(ROUTES.HOME) on the very next line immediately overrides that and sends the user to the inbox. The navigate(HOME) call only exists to re-trigger OnboardingGuard so that brand-new users get routed into onboarding. For an existing account isOnboardingCompleted is already true, so OnboardingGuard returns ALLOW, the HOME navigation goes through, and the user is stranded on the inbox with nothing restoring the room.
This line was reintroduced by PR #90387 (commit b2998cc, 2026-05-12), which reverted the earlier work that preserved the deep-linked report route. The router-level "preserve fullscreen routes during redirect" approach (PR #86390) has been reverted twice now (#86307, #90387), so that path is a known dead end.
What changes do you think we should make in order to solve the problem?
Guard the HOME navigation so it only fires for users who still need onboarding. Read the onboarding-completed flag and skip navigate(HOME) when onboarding is already done:
const[isOnboardingCompleted]=useOnyx(ONYXKEYS.NVP_ONBOARDING,{selector: hasCompletedGuidedSetupFlowSelector});
...
Navigation.dismissModal();// navigate(HOME) only exists to re-trigger OnboardingGuard for users who still need onboarding.if(!isOnboardingCompleted){Navigation.navigate(ROUTES.HOME);}
New users still get pushed to HOME and picked up by OnboardingGuard, while existing users keep the room that dismissModal() already restored. The change is contained to SignInModal.tsx, so the blast radius is just this flow. I'd also add a test here, since there's currently no coverage for SignInModal's navigation after sign-in (the related handleNavigationGuardRedirect.test.ts was removed by the #90387 revert). The test should assert existing users return to the report with no HOME navigation, and incomplete-onboarding users still route HOME into onboarding.
What alternative solutions did you explore? (Optional)
Restoring the router-level route-preservation fix would cover more cases, but it's been reverted twice for regressions, so I stayed away from it. Deleting navigate(HOME) outright is simpler, but it brings back the onboarding-not-appearing bug for new anonymous sign-ins, which is exactly why the line exists. Leaning on lastVisitedPath doesn't help either, since it only restores on a cold startup and this flow never reloads the page.
When a signed-out user opens a public room link like /r/1540486774487195, the report route is rendered. Tapping an action that requires authentication (pin) sends the user to SignInPage, which is registered at the root under NAVIGATORS.TAB_NAVIGATOR inside the public navigator:
After the user signs in with an existing account, the app swaps from the public navigator to the authenticated navigator and resets the navigation state. The report route the user was viewing is never treated as a route to restore, because isPublicScreenRoute only matches routes listed in PUBLIC_SCREENS_ROUTES, and the public room report route (/r/:reportID) is not one of them:
So when the auth transition happens, the navigator has no stored non-public route to return to, and it lands the user on the default authenticated screen instead of reopening the public room. The gap: the room route the user was actively viewing before sign-in is dropped during the public to authenticated navigator swap.
What changes do you think we should make in order to solve the problem?
Persist the report route the user was viewing before we push SignInPage, so it can be reused as an exitTo target once authentication completes. The public navigator swap happens after SignInPage (registered at TAB_NAVIGATOR) in PublicScreens.tsx:
Before navigating to sign-in from a public room, capture the current report route (for example the active /r/:reportID) into a stable location such as an Onyx key, following the same single-value pattern already used for room highlighting in Room.ts:
After the authenticated navigator mounts, read that stored route and navigate to it as the resolved exitTo target, then clear the stored value. This makes the app reopen the same public room the user had open, matching the expected result.
What alternative solutions did you explore? (Optional)
Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.
changed the title [-]Public Room - Public room does not display open after loging in as existing account[/-][+][$250] Public Room - Public room does not display open after loging in as existing account[/+]on Jul 6, 2026
This issue has not been updated in over 15 days. @abdulrahuman5196 eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
changed the title [-][HOLD for #92834] [$250] Public Room - Public room does not display open after loging in as existing account[/-][+][$250] Public Room - Public room does not display open after loging in as existing account[/+]on Sep 26, 2026
Activity
applause-bot commentedon Jul 6, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/1f3a5fd072f4036fd685dc39072a551a80028ae640c37c27b25febb3be059c63
MelvinBot commentedon Jul 6, 2026
Proposal
What is the root cause of that problem?
An anonymous user viewing a public room already holds an (anonymous) auth token, so the app treats them as "authenticated". When they tap Pin, the action is gated by
interceptAnonymousUser, which callssignOutAndRedirectToSignIn. For an anonymous user this branch just opens the sign-in modal without stashing the current room route:After credentials are entered,
SignInModalunconditionally navigates toROUTES.HOME, discarding the public room the user was viewing:Because the user was already "authenticated" (anonymous token), the deep-link route-restoration path in
openReportFromDeepLinkis never armed for this flow, so nothing re-navigates back to the room. Result: after login the user lands on Home instead of the public room.What changes do you think we should make in order to solve the problem?
Preserve and restore the room route across the anonymous → authenticated transition:
signOutAndRedirectToSignIn, capture the currently-active route (the/r/<reportID>the user is on).SignInModal, afterdismissModal(), navigate back to that saved route instead of the hardcodedROUTES.HOME(fall back toHOMEonly when there was no prior route).Investigation details, alternative considered, and related issues
Flow traced:
/r/<reportID>— holds an anonymous authToken, souseIsAuthenticated()/hasAuthToken()treat them as authenticated;openReportFromDeepLinkearly-returns without arming a post-login navigate.interceptAnonymousUser→signOutAndRedirectToSignIn()→ opensSIGN_IN_MODAL, no route stored.session.authTokenTypeflips away fromANONYMOUS→SignInModalrunsopenApp(true), then onIS_LOADING_APP === falsedoesdismissModal()+navigate(ROUTES.HOME).Alternative considered: route the anonymous case through
openReportFromDeepLink'swaitForUserSignInrestoration instead of stashing the route inSignInModal. Both work; stashing the active route is the smaller, more localized change and doesn't depend on the deep-link handler being re-invoked (it isn't, on web).Confidence: High — the hardcoded
Navigation.navigate(ROUTES.HOME)combined with the un-stashed route deterministically explains the reported behavior on both web (Windows: Chrome) and Android.Likely related open issues (same deep-link/anon login family — probably fix together or de-dupe):
Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/95445)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
aswin-s commentedon Jul 6, 2026
Please re-state the problem that we are trying to solve in this issue.
When an anonymous user opens a public room deep link (e.g.
https://staging.new.expensify.com/r/1540486774487195), taps Pin on a message to trigger the sign-in modal, and then signs in with an existing account, the app lands on the default Home screen instead of restoring the public room the user was viewing before login. Expected: after login the public room should remain open at the same route.What is the root cause of that problem?
There are two independent failure points that together prevent the public room from being restored after login.
Failure 1 — NavigationRoot never re-applies the deep-link path on auth transition.
The
initialStateuseMemoinsrc/libs/Navigation/NavigationRoot.tsx(starting around line 129) is responsible for seeding the navigator's initial route. Two conditions inside it cause it to returnundefinedinstead of the captured/r/{reportID}path:(a) Line 139 early-returns
undefinedwheneveraccount.isFromPublicDomainis truthy. The Applause tester's+odtesting@gmail.comaddress has a public-domain suffix, so this fires and short-circuits before any deep-link handling.(b) Even without that, line 155's
isSpecificDeepLinkbranch explicitly returnsundefinedfor non-root deep links, so the/r/...route captured while the user was anonymous is never re-hydrated whenauthenticatedflips fromfalsetotrueand the navigator swaps from the Public screen stack to the Auth screen stack.Failure 2 — SignInModal unconditionally navigates to Home after sign-in, overwriting any route restoration.
src/pages/signin/SignInModal.tsxcontains auseEffect(lines 63–69) that fires onceIS_LOADING_APPbecomesfalseafter a successful sign-in:Even if
NavigationRoot'sinitialStatewere fixed to restore/r/{reportID}, this effect runs afteropenAppresolves and unconditionally replaces whatever route was set withROUTES.HOME. For theSignInModalflow (anonymous user, deep-link open, pin-tap triggers sign-in), this is the direct cause of the regression.What changes do you think we should make in order to solve the problem?
Change 1 — Fix
SignInModalto preserve the public-room route.In
src/pages/signin/SignInModal.tsx, before callingNavigation.navigate(ROUTES.HOME), check whether the user arrived via a public-room deep link. If so, navigate to that report instead of Home:The initial URL is the URL the anonymous user had open when the
SignInModalappeared —useInitialURLState()from@components/InitialURLContextProvideralready exposes it. Prefer that overgetCurrentUrl()because the URL bar may have been replaced by the sign-in flow before this effect fires.Change 2 — Fix
NavigationRootto re-apply the deep-link on thefalse → trueauth transition.In
src/libs/Navigation/NavigationRoot.tsxaround theinitialStatememo (lines 129–164), whenauthenticatedbecomes true andinitialUrlis a public-report deep link (/r/{reportID}— matchingROUTES.REPORT_WITH_ID), returngetAdaptedStateFromPath(path)instead ofundefined, regardless ofaccount.isFromPublicDomain.Do not gate this restoration on
isFromPublicDomain— that flag reflects the user's email domain, not the room's visibility, and public-domain users are the primary consumers of public-room links.Add handling in the existing
useEffecton[authenticated](around line 198) to trigger aNavigation.navigateto the captured path on thefalse → truetransition, so the deep link captured while anonymous survives the Public/Auth navigator swap.Change 3 — Preserve the existing guard.
Keep the
isTransitioning(TRANSITION_BETWEEN_APPS) guard at line 143 intact — that path is owned byLogOutPreviousUserPageandsetUpPoliciesAndNavigateand must not be double-handled here.What alternative solutions did you explore?
Patching only
NavigationRoot.tsxwithout touchingSignInModal.tsxwould be insufficient: even with a correctly restoredinitialState, theSignInModaleffect at lines 63–69 fires afteropenAppresolves and unconditionally callsNavigation.navigate(ROUTES.HOME), which overwrites any restored route. Both layers must be fixed together.ahmdshrif commentedon Jul 6, 2026
🚨 Edited by proposal-police: This proposal was edited at 2026-07-06 21:36:50 UTC.
Proposal
Please re-state the problem that we are trying to solve in this issue.
An anonymous user viewing a public room triggers an auth-gated action (pin), signs in with an existing account, and the app lands on Home/Inbox instead of showing the public room they were viewing. The room should stay open after login.
What is the root cause of that problem?
When the anonymous user taps pin,
checkIfActionIsAllowedcallssignOutAndRedirectToSignIn(), which for anonymous sessions just opens the sign-in RHP on top of the still-mounted public-room ReportScreen:App/src/libs/actions/Session/index.ts
Lines 516 to 519 in 2a89475
App/src/libs/actions/Session/index.ts
Lines 357 to 364 in 2a89475
After sign-in succeeds,
SignInModalcallsopenApp(true)—shouldKeepPublicRooms = true— so the room's data is intentionally preserved:App/src/pages/signin/SignInModal.tsx
Lines 45 to 55 in 2a89475
App/src/libs/actions/App.ts
Line 435 in 2a89475
Once
IS_LOADING_APPflips tofalse, a second effect dismisses the modal — which alone would reveal the public room underneath — and then unconditionally navigates to Home, replacing the room:App/src/pages/signin/SignInModal.tsx
Lines 61 to 68 in 2a89475
That
Navigation.navigate(ROUTES.HOME)exists for exactly one cohort: brand-new accounts. It was added in PR#87257("Navigate to HOME after openApp to trigger onboarding for anonymous sign-in") because a plain modal dismissal (a POP) does not trigger theOnboardingGuardredirect. But for an existing account,NVP_ONBOARDING.hasCompletedGuidedSetupFlowistrue, so the guard computesisOnboardingCompleted = true→shouldSkipOnboarding = true→ALLOW, and the navigation simply lands on Home with no benefit:App/src/libs/Navigation/guards/OnboardingGuard.ts
Line 174 in 2a89475
App/src/libs/Navigation/guards/OnboardingGuard.ts
Lines 192 to 205 in 2a89475
Structural cause: a navigation needed only by not-yet-onboarded users fires for every user. Regression history confirms it: PR
#86390fixed this exact symptom by removing this line (commite235263d0) plus preserving fullscreen routes in the router guard handling, but it was CP-reverted by PR#90387because the router change caused deploy blocker#90303(dead back button on Concierge after onboarding). The revert restored the unconditional Home navigation and re-introduced this bug.All anonymous entry points funnel into this one effect, so this single line explains every repro variant: pin/context-menu (
BaseReportActionContextMenu.tsx), the "Sign in" button inAnonymousReportFooter.tsx, the sidebarSignInButton.tsx, and emoji reactions all call the samesignOutAndRedirectToSignIn→ same modal.SignInModal.tsxis a single shared file (noindex.nativesplit), which matches the cross-platform repro (Android app + Windows Chrome, narrow and wide layouts).What changes do you think we should make in order to solve the problem?
In
SignInModal.tsx, gate the Home navigation on onboarding not being completed, reusing the exact selector pattern already used for the same decision inNavigationRoot:App/src/libs/Navigation/NavigationRoot.tsx
Lines 123 to 125 in 2a89475
The flag is authoritative at decision time by the effect's own documented precondition:
IS_LOADING_APPonly flips tofalseafter the OpenApp response is processed andNVP_ONBOARDINGis loaded (comment atApp/src/pages/signin/SignInModal.tsx
Lines 57 to 60 in 2a89475
signOutAndRedirectToSignInand never reach this effect.Why the obvious one-line fix fails: simply deleting
Navigation.navigate(ROUTES.HOME)is exactly what PR#86390did — and it regresses new-user onboarding, the reason the line was added:Navigation.dismissModal()is a POP action, so without a subsequent navigate theOnboardingGuardnever fires its REDIRECT and a new account signing up from a public room never sees the onboarding modal (the#85242/#87257bug; an earlier attempt#85660was also reverted). Equally, re-landing#86390's router-level route-preservation is not viable — it caused deploy blocker#90303and was CP-reverted, so the fix must stay out ofRootStackRouter's guard handling. Conditioning the navigation on the already-loaded onboarding NVP is the only variant that keeps both prior fixes intact.What alternative solutions did you explore? (Optional)
#86390and reverted.#86390's router change) — caused deploy blocker#90303; must not be re-proposed as-is.isOnboardingCompleted— would also keep the room open for those cohorts, but duplicates guard logic in a component; those users behave exactly as today under my fix, so this can be a follow-up if desired.shivang-goliyan commentedon Jul 6, 2026
🚨 Edited by proposal-police: This proposal was edited at 2026-07-06 21:43:01 UTC.
Proposal
Please re-state the problem that we are trying to solve in this issue.
Open a public room link while logged out, tap a message, and pin it. That triggers a sign-in prompt. After you log in with an existing account, you land on the inbox instead of the public room you were just looking at. The room you had open is gone, and nothing brings you back to it.
What is the root cause of that problem?
The problem is in
src/pages/signin/SignInModal.tsx. When an anonymous user pins a message,interceptAnonymousUser(BaseReportActionContextMenu.tsx) callsSession.signOutAndRedirectToSignIn(), which pushes theSIGN_IN_MODALRHP over the current/r/<id>route. This all happens in the same JS runtime, so the report screen stays mounted underneath. Once sign-in completes andIS_LOADING_APPflips tofalse, this effect runs (lines 61-68):dismissModal()does the right thing and restores the public room the modal was opened over. Butnavigate(ROUTES.HOME)on the very next line immediately overrides that and sends the user to the inbox. Thenavigate(HOME)call only exists to re-triggerOnboardingGuardso that brand-new users get routed into onboarding. For an existing accountisOnboardingCompletedis already true, soOnboardingGuardreturnsALLOW, the HOME navigation goes through, and the user is stranded on the inbox with nothing restoring the room.This line was reintroduced by PR #90387 (commit
b2998cc, 2026-05-12), which reverted the earlier work that preserved the deep-linked report route. The router-level "preserve fullscreen routes during redirect" approach (PR #86390) has been reverted twice now (#86307, #90387), so that path is a known dead end.What changes do you think we should make in order to solve the problem?
Guard the HOME navigation so it only fires for users who still need onboarding. Read the onboarding-completed flag and skip
navigate(HOME)when onboarding is already done:New users still get pushed to HOME and picked up by
OnboardingGuard, while existing users keep the room thatdismissModal()already restored. The change is contained toSignInModal.tsx, so the blast radius is just this flow. I'd also add a test here, since there's currently no coverage for SignInModal's navigation after sign-in (the relatedhandleNavigationGuardRedirect.test.tswas removed by the #90387 revert). The test should assert existing users return to the report with no HOME navigation, and incomplete-onboarding users still route HOME into onboarding.What alternative solutions did you explore? (Optional)
Restoring the router-level route-preservation fix would cover more cases, but it's been reverted twice for regressions, so I stayed away from it. Deleting
navigate(HOME)outright is simpler, but it brings back the onboarding-not-appearing bug for new anonymous sign-ins, which is exactly why the line exists. Leaning onlastVisitedPathdoesn't help either, since it only restores on a cold startup and this flow never reloads the page.samranahm commentedon Jul 6, 2026
Proposal
What is the root cause of that problem?
When a signed-out user opens a public room link like
/r/1540486774487195, the report route is rendered. Tapping an action that requires authentication (pin) sends the user toSignInPage, which is registered at the root underNAVIGATORS.TAB_NAVIGATORinside the public navigator:App/src/libs/Navigation/AppNavigator/PublicScreens.tsx
Lines 27 to 92 in 2a89475
After the user signs in with an existing account, the app swaps from the public navigator to the authenticated navigator and resets the navigation state. The report route the user was viewing is never treated as a route to restore, because
isPublicScreenRouteonly matches routes listed inPUBLIC_SCREENS_ROUTES, and the public room report route (/r/:reportID) is not one of them:App/src/libs/isPublicScreenRoute.ts
Lines 3 to 8 in 2a89475
So when the auth transition happens, the navigator has no stored non-public route to return to, and it lands the user on the default authenticated screen instead of reopening the public room. The gap: the room route the user was actively viewing before sign-in is dropped during the public to authenticated navigator swap.
What changes do you think we should make in order to solve the problem?
SignInPage, so it can be reused as anexitTotarget once authentication completes. The public navigator swap happens afterSignInPage(registered atTAB_NAVIGATOR) inPublicScreens.tsx:App/src/libs/Navigation/AppNavigator/PublicScreens.tsx
Lines 27 to 92 in 2a89475
Before navigating to sign-in from a public room, capture the current report route (for example the active
/r/:reportID) into a stable location such as an Onyx key, following the same single-value pattern already used for room highlighting inRoom.ts:App/src/libs/actions/Policy/Room.ts
Lines 15 to 16 in 2a89475
exitTotarget, then clear the stored value. This makes the app reopen the same public room the user had open, matching the expected result.What alternative solutions did you explore? (Optional)
Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.
melvin-bot commentedon Jul 6, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @abdulrahuman5196 (
External)[-]Public Room - Public room does not display open after loging in as existing account[/-][+][$250] Public Room - Public room does not display open after loging in as existing account[/+]melvin-bot commentedon Jul 6, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022074245798692391418
34 remaining items
MelvinBot commentedon Jul 13, 2026
🤖 Done — swapped the
Dailylabel forWeekly.melvin-bot commentedon Aug 5, 2026
This issue has not been updated in over 15 days. @abdulrahuman5196 eroding to Monthly issue.
P.S. Is everyone reading this sure this is really a near-term priority? Be brave: if you disagree, go ahead and close it out. If someone disagrees, they'll reopen it, and if they don't: one less thing to do!
oqildev commentedon Aug 6, 2026
@abdulrahuman5196
It's not reproducible. Already fixed.
IMG_1123.MOV
samranahm commentedon Sep 24, 2026
@abdulrahuman5196 Should we close this issue, seems like no one is able to prodice this anymore.
abdulrahuman5196 commentedon Sep 26, 2026
@MelvinBot Remove the hold, the hold PR is merged
[-][HOLD for #92834] [$250] Public Room - Public room does not display open after loging in as existing account[/-][+][$250] Public Room - Public room does not display open after loging in as existing account[/+]MelvinBot commentedon Sep 26, 2026
🤖 Done. I removed the hold. The title is now:
I confirmed that fix: land new account on initially opened room was merged on 2026-07-17.
view run
abdulrahuman5196 commentedon Sep 26, 2026
Tested and its not repro anymore. Will ask in slack to close this issue.
melvin-bot commentedon Sep 26, 2026
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸