From 545696166d620fc7bb9f415caa21581140d622d6 Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Tue, 9 Jun 2026 16:12:03 +0500
Subject: [PATCH 1/6] fix: keep public room in LHN for anonymous users

An anonymous session can only access public rooms, whose notification
preference defaults to `hidden`. Previously a public room only survived
the LHN filter while it was the focused report, so opening a thread inside
the room (which steals focus) dropped the room from the Inbox, leaving the
anon user unable to return to it.

Add an override in `shouldDisplayReportInLHN` so a public room stays in the
LHN for anonymous users regardless of focus, mirroring how ReportUtils
already gates anon-only public-room behaviour (e.g. canLeaveChat).

Fixes #92672

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/libs/SidebarUtils.ts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 8f28be104bd6..ec49bcfc3680 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -31,6 +31,7 @@ import {Str} from 'expensify-common';
 
 import type {OptionData} from './ReportUtils';
 
+import {isAnonymousUser} from './actions/Session';
 import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
 import {formatList} from './Localize';
 import {
@@ -196,6 +197,7 @@ import {
     isOneOnOneChat,
     isOneTransactionThread,
     isPolicyExpenseChat,
+    isPublicRoom,
     isSelfDM,
     isSystemChat as isSystemChatUtil,
     isTaskReport,
@@ -343,6 +345,10 @@ function shouldDisplayReportInLHN({
         !!draftComment ||
         hasErrorsOtherThanFailedReceipt ||
         isFocused ||
+        // An anonymous user can only access public rooms, and such a room's notification preference
+        // defaults to `hidden`. Without this, opening a thread inside the room (which steals focus)
+        // drops the room from the LHN, leaving the anon user unable to return to it. See #92672.
+        (isPublicRoom(report) && isAnonymousUser()) ||
         isSystemChat ||
         !!report.isPinned ||
         // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing

From c54e7e212202feb06f456d013667339c9bb3f47b Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Fri, 12 Jun 2026 16:18:49 +0500
Subject: [PATCH 2/6] fix: keep public room in LHN for anonymous users on cold
 start

---
 src/DeepLinkHandler.tsx                       | 35 ++++++++++++++++++-
 .../Navigation/linkingConfig/subscribe.ts     |  8 +++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/src/DeepLinkHandler.tsx b/src/DeepLinkHandler.tsx
index a97974d2cd15..a81e85d5aac8 100644
--- a/src/DeepLinkHandler.tsx
+++ b/src/DeepLinkHandler.tsx
@@ -10,8 +10,9 @@ import useIsAuthenticated from './hooks/useIsAuthenticated';
 import useOnyx from './hooks/useOnyx';
 import {openReportFromDeepLink} from './libs/actions/Link';
 import * as Report from './libs/actions/Report';
-import {hasAuthToken} from './libs/actions/Session';
+import {hasAuthToken, isAnonymousUser} from './libs/actions/Session';
 import Log from './libs/Log';
+import {getReportIDFromLink} from './libs/ReportUtils';
 import {endSpan} from './libs/telemetry/activeSpans';
 import ONYXKEYS from './ONYXKEYS';
 import {hasSeenTourSelector} from './selectors/Onboarding';
@@ -30,8 +31,11 @@ type DeepLinkHandlerProps = {
 function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
     const linkingChangeListener = useRef<NativeEventSubscription | null>(null);
     const initialUrlProcessed = useRef(false);
+    const pendingPublicRoomReportID = useRef('');
+    const hasRefetchedPublicRoom = useRef(false);
 
     const [allReports, allReportsMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
+    const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
     const [, sessionMetadata] = useOnyx(ONYXKEYS.SESSION);
     const [conciergeReportID, conciergeReportIDMetadata] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
     const [introSelected, introSelectedMetadata] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
@@ -89,6 +93,11 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
                         Log.info('[Deep link] introSelected is undefined when processing initial URL', false, {url});
                     }
                     openReportFromDeepLink(url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, isSelfTourViewed, betas);
+                    const deepLinkReportID = getReportIDFromLink(url);
+                    if (deepLinkReportID && !isCurrentlyAuthenticated) {
+                        pendingPublicRoomReportID.current = deepLinkReportID;
+                        hasRefetchedPublicRoom.current = false;
+                    }
                 } else {
                     Report.doneCheckingPublicRoom();
                 }
@@ -116,6 +125,11 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
             }
             const isCurrentlyAuthenticated = hasAuthToken();
             openReportFromDeepLink(state.url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, isSelfTourViewed, betas);
+            const deepLinkReportID = getReportIDFromLink(state.url);
+            if (deepLinkReportID && !isCurrentlyAuthenticated) {
+                pendingPublicRoomReportID.current = deepLinkReportID;
+                hasRefetchedPublicRoom.current = false;
+            }
         });
 
         return () => {
@@ -149,6 +163,25 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
         Report.doneCheckingPublicRoom();
     }, [isAuthenticated]);
 
+    // An anonymous user opening a public room via a cold deep link loads the room (OpenReport), but the
+    // OpenApp that follows anonymous session creation drops it from Onyx, so it never reaches the LHN.
+    // Once OpenApp settles, re-fetch the room if it went missing so it shows up in the LHN. See #92672.
+    useEffect(() => {
+        const reportID = pendingPublicRoomReportID.current;
+        if (!reportID || isLoadingApp || !isAnonymousUser()) {
+            return;
+        }
+        if (allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]?.reportID) {
+            hasRefetchedPublicRoom.current = false;
+            return;
+        }
+        if (hasRefetchedPublicRoom.current) {
+            return;
+        }
+        hasRefetchedPublicRoom.current = true;
+        Report.openReport({reportID, introSelected, betas});
+    }, [isLoadingApp, allReports, introSelected, betas]);
+
     return null;
 }
 
diff --git a/src/libs/Navigation/linkingConfig/subscribe.ts b/src/libs/Navigation/linkingConfig/subscribe.ts
index d1407a0cdba2..85f77ed3f41b 100644
--- a/src/libs/Navigation/linkingConfig/subscribe.ts
+++ b/src/libs/Navigation/linkingConfig/subscribe.ts
@@ -1,3 +1,4 @@
+import {hasAuthToken} from '@libs/actions/Session';
 import continuePlaidOAuth from '@libs/continuePlaidOAuth';
 import navigationRef from '@libs/Navigation/navigationRef';
 import type {RootNavigatorParamList} from '@libs/Navigation/types';
@@ -34,6 +35,13 @@ const subscribe: LinkingOptions<RootNavigatorParamList>['subscribe'] = (listener
             continuePlaidOAuth(url);
             return;
         }
+        // For an unauthenticated session, a report deep link (`/r/<reportID>`) targets the Report screen,
+        // which lives in AuthScreens and is not mounted while PublicScreens is showing. Dispatching it here
+        // throws "NAVIGATE ... was not handled by any navigator". openReportFromDeepLink() already opens the
+        // public room as an anonymous user and handles navigation, so defer to it instead. See #92672.
+        if (!hasAuthToken() && url.includes(`/${ROUTES.REPORT}/`)) {
+            return;
+        }
         listener(url);
     });
     return () => subscription.remove();

From 17b02bc7423aa4081318828cc910c0e3edba685d Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Sat, 13 Jun 2026 14:25:36 +0500
Subject: [PATCH 3/6] test: add unit tests for anonymous public room LHN
 visibility and deep link refetch

---
 tests/unit/DeepLinkHandlerTest.tsx | 117 +++++++++++++++++++++++++++++
 tests/unit/SidebarUtilsTest.ts     | 109 +++++++++++++++++++++++++++
 2 files changed, 226 insertions(+)
 create mode 100644 tests/unit/DeepLinkHandlerTest.tsx

diff --git a/tests/unit/DeepLinkHandlerTest.tsx b/tests/unit/DeepLinkHandlerTest.tsx
new file mode 100644
index 000000000000..2aad57b5179c
--- /dev/null
+++ b/tests/unit/DeepLinkHandlerTest.tsx
@@ -0,0 +1,117 @@
+import {act, render} from '@testing-library/react-native';
+import {Linking} from 'react-native';
+import Onyx from 'react-native-onyx';
+import type * as Link from '@libs/actions/Link';
+import * as Report from '@libs/actions/Report';
+import CONST from '@src/CONST';
+import DeepLinkHandler from '@src/DeepLinkHandler';
+import ONYXKEYS from '@src/ONYXKEYS';
+import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct';
+
+jest.mock('@libs/actions/Link', () => ({
+    ...jest.requireActual<typeof Link>('@libs/actions/Link'),
+    openReportFromDeepLink: jest.fn(),
+}));
+
+jest.mock('@libs/actions/Report', () => ({
+    ...jest.requireActual<typeof Report>('@libs/actions/Report'),
+    openReport: jest.fn(),
+    doneCheckingPublicRoom: jest.fn(),
+}));
+
+const PUBLIC_ROOM_ID = '987654321';
+const DEFAULT_URL = 'https://new.expensify.com/';
+
+describe('DeepLinkHandler', () => {
+    beforeAll(() => {
+        Onyx.init({keys: ONYXKEYS});
+    });
+
+    beforeEach(async () => {
+        await act(async () => {
+            await Onyx.clear();
+        });
+        jest.clearAllMocks();
+        Linking.setInitialURL(DEFAULT_URL);
+    });
+
+    it('re-fetches a public room that is missing from Onyx after OpenApp settles for an anonymous user (#92672)', async () => {
+        // An anonymous session has no authToken, so hasAuthToken() is false and isAnonymousUser() is true.
+        await act(async () => {
+            await Onyx.multiSet({
+                [ONYXKEYS.SESSION]: {authTokenType: CONST.AUTH_TOKEN_TYPES.ANONYMOUS},
+                [ONYXKEYS.IS_LOADING_APP]: true,
+                [ONYXKEYS.CONCIERGE_REPORT_ID]: '',
+                [ONYXKEYS.NVP_INTRO_SELECTED]: {},
+                [ONYXKEYS.BETAS]: [],
+            });
+        });
+
+        // Cold deep link straight into the public room.
+        Linking.setInitialURL(`new-expensify://r/${PUBLIC_ROOM_ID}`);
+
+        render(<DeepLinkHandler onInitialUrl={jest.fn()} />);
+        await waitForBatchedUpdatesWithAct();
+
+        // While OpenApp is still loading, we should not refetch yet.
+        expect(Report.openReport).not.toHaveBeenCalled();
+
+        // OpenApp settles but the public room is still absent from Onyx -> refetch it so it reaches the LHN.
+        await act(async () => {
+            await Onyx.merge(ONYXKEYS.IS_LOADING_APP, false);
+        });
+        await waitForBatchedUpdatesWithAct();
+
+        expect(Report.openReport).toHaveBeenCalledWith(expect.objectContaining({reportID: PUBLIC_ROOM_ID}));
+    });
+
+    it('does not refetch when the public room is already present in Onyx', async () => {
+        await act(async () => {
+            await Onyx.multiSet({
+                [ONYXKEYS.SESSION]: {authTokenType: CONST.AUTH_TOKEN_TYPES.ANONYMOUS},
+                [ONYXKEYS.IS_LOADING_APP]: true,
+                [ONYXKEYS.CONCIERGE_REPORT_ID]: '',
+                [ONYXKEYS.NVP_INTRO_SELECTED]: {},
+                [ONYXKEYS.BETAS]: [],
+                [`${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}`]: {reportID: PUBLIC_ROOM_ID},
+            });
+        });
+
+        Linking.setInitialURL(`new-expensify://r/${PUBLIC_ROOM_ID}`);
+
+        render(<DeepLinkHandler onInitialUrl={jest.fn()} />);
+        await waitForBatchedUpdatesWithAct();
+
+        await act(async () => {
+            await Onyx.merge(ONYXKEYS.IS_LOADING_APP, false);
+        });
+        await waitForBatchedUpdatesWithAct();
+
+        expect(Report.openReport).not.toHaveBeenCalled();
+    });
+
+    it('does not refetch for an authenticated user', async () => {
+        await act(async () => {
+            await Onyx.multiSet({
+                // An authToken means hasAuthToken() is true, so the deep link is not tracked as a pending public room.
+                [ONYXKEYS.SESSION]: {authToken: 'token', accountID: 1},
+                [ONYXKEYS.IS_LOADING_APP]: true,
+                [ONYXKEYS.CONCIERGE_REPORT_ID]: '',
+                [ONYXKEYS.NVP_INTRO_SELECTED]: {},
+                [ONYXKEYS.BETAS]: [],
+            });
+        });
+
+        Linking.setInitialURL(`new-expensify://r/${PUBLIC_ROOM_ID}`);
+
+        render(<DeepLinkHandler onInitialUrl={jest.fn()} />);
+        await waitForBatchedUpdatesWithAct();
+
+        await act(async () => {
+            await Onyx.merge(ONYXKEYS.IS_LOADING_APP, false);
+        });
+        await waitForBatchedUpdatesWithAct();
+
+        expect(Report.openReport).not.toHaveBeenCalled();
+    });
+});
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index f18474089139..1a397e540690 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1110,6 +1110,115 @@ describe('SidebarUtils', () => {
             expect(result).toBeDefined();
             expect(typeof result.shouldDisplay).toBe('boolean');
         });
+
+        describe('anonymous user public room (#92672)', () => {
+            const PUBLIC_ROOM_ID = '92672';
+            const OTHER_FOCUSED_REPORT_ID = '92673';
+
+            // The room has no notification preference for the current user, so `isHiddenForCurrentUser`
+            // treats it as `hidden` - exactly the state an anonymous user lands in for a public room.
+            const buildPublicRoom = (visibility: Report['visibility']): Report => ({
+                reportID: PUBLIC_ROOM_ID,
+                type: CONST.REPORT.TYPE.CHAT,
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
+                visibility,
+                reportName: '#publicroom',
+                policyID: '1',
+                lastMessageText: 'hello',
+                lastVisibleActionCreated: DateUtils.getDBTime(),
+                participants: {},
+            });
+
+            it('keeps a hidden public room in the LHN when it is not the focused report', async () => {
+                const report = buildPublicRoom(CONST.REPORT.VISIBILITY.PUBLIC);
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reports: OnyxCollection<Report> = {[reportKey]: report};
+
+                await act(async () => {
+                    await Onyx.multiSet({
+                        [ONYXKEYS.SESSION]: {authTokenType: CONST.AUTH_TOKEN_TYPES.ANONYMOUS},
+                        [reportKey]: report,
+                    });
+                });
+                await waitForBatchedUpdates();
+
+                const result = SidebarUtils.shouldDisplayReportInLHN({
+                    report,
+                    reports,
+                    currentReportId: OTHER_FOCUSED_REPORT_ID,
+                    isInFocusMode: false,
+                    betas: [],
+                    transactionViolations: {},
+                    draftComment: undefined,
+                    transactions: {},
+                    isOffline: false,
+                    currentUserLogin: CURRENT_USER_LOGIN,
+                    currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
+                });
+
+                expect(result.shouldDisplay).toBe(true);
+            });
+
+            it('drops the same hidden public room for an authenticated (non-anonymous) user', async () => {
+                const report = buildPublicRoom(CONST.REPORT.VISIBILITY.PUBLIC);
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reports: OnyxCollection<Report> = {[reportKey]: report};
+
+                await act(async () => {
+                    await Onyx.multiSet({
+                        [ONYXKEYS.SESSION]: {accountID: CURRENT_USER_ACCOUNT_ID, email: CURRENT_USER_LOGIN},
+                        [reportKey]: report,
+                    });
+                });
+                await waitForBatchedUpdates();
+
+                const result = SidebarUtils.shouldDisplayReportInLHN({
+                    report,
+                    reports,
+                    currentReportId: OTHER_FOCUSED_REPORT_ID,
+                    isInFocusMode: false,
+                    betas: [],
+                    transactionViolations: {},
+                    draftComment: undefined,
+                    transactions: {},
+                    isOffline: false,
+                    currentUserLogin: CURRENT_USER_LOGIN,
+                    currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
+                });
+
+                expect(result.shouldDisplay).toBe(false);
+            });
+
+            it('does not apply the override to a non-public hidden room for an anonymous user', async () => {
+                const report = buildPublicRoom(undefined);
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reports: OnyxCollection<Report> = {[reportKey]: report};
+
+                await act(async () => {
+                    await Onyx.multiSet({
+                        [ONYXKEYS.SESSION]: {authTokenType: CONST.AUTH_TOKEN_TYPES.ANONYMOUS},
+                        [reportKey]: report,
+                    });
+                });
+                await waitForBatchedUpdates();
+
+                const result = SidebarUtils.shouldDisplayReportInLHN({
+                    report,
+                    reports,
+                    currentReportId: OTHER_FOCUSED_REPORT_ID,
+                    isInFocusMode: false,
+                    betas: [],
+                    transactionViolations: {},
+                    draftComment: undefined,
+                    transactions: {},
+                    isOffline: false,
+                    currentUserLogin: CURRENT_USER_LOGIN,
+                    currentUserAccountID: CURRENT_USER_ACCOUNT_ID,
+                });
+
+                expect(result.shouldDisplay).toBe(false);
+            });
+        });
     });
 
     describe('getWelcomeMessage', () => {

From 89e00a6babd9f788ac156cdf5836ef6146da5a29 Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Sat, 13 Jun 2026 16:29:34 +0500
Subject: [PATCH 4/6] fix spellcheck and typecheck CI failures in public room
 tests

---
 cspell.json                        | 3 ++-
 tests/unit/DeepLinkHandlerTest.tsx | 2 +-
 tests/unit/SidebarUtilsTest.ts     | 8 ++++----
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/cspell.json b/cspell.json
index fc11acf9656e..ab21181d0608 100644
--- a/cspell.json
+++ b/cspell.json
@@ -1045,7 +1045,8 @@
         "Prefetch",
         "Prefetcher",
         "knip",
-        "lottiefiles"
+        "lottiefiles",
+        "Refetched"
     ],
     "ignorePaths": [
         ".gitignore",
diff --git a/tests/unit/DeepLinkHandlerTest.tsx b/tests/unit/DeepLinkHandlerTest.tsx
index 2aad57b5179c..2ecf5b34dea9 100644
--- a/tests/unit/DeepLinkHandlerTest.tsx
+++ b/tests/unit/DeepLinkHandlerTest.tsx
@@ -73,7 +73,7 @@ describe('DeepLinkHandler', () => {
                 [ONYXKEYS.CONCIERGE_REPORT_ID]: '',
                 [ONYXKEYS.NVP_INTRO_SELECTED]: {},
                 [ONYXKEYS.BETAS]: [],
-                [`${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}`]: {reportID: PUBLIC_ROOM_ID},
+                [`${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}` as const]: {reportID: PUBLIC_ROOM_ID},
             });
         });
 
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 1a397e540690..b72d5ad45102 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1122,7 +1122,7 @@ describe('SidebarUtils', () => {
                 type: CONST.REPORT.TYPE.CHAT,
                 chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
                 visibility,
-                reportName: '#publicroom',
+                reportName: '#public-room',
                 policyID: '1',
                 lastMessageText: 'hello',
                 lastVisibleActionCreated: DateUtils.getDBTime(),
@@ -1131,7 +1131,7 @@ describe('SidebarUtils', () => {
 
             it('keeps a hidden public room in the LHN when it is not the focused report', async () => {
                 const report = buildPublicRoom(CONST.REPORT.VISIBILITY.PUBLIC);
-                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}` as const;
                 const reports: OnyxCollection<Report> = {[reportKey]: report};
 
                 await act(async () => {
@@ -1161,7 +1161,7 @@ describe('SidebarUtils', () => {
 
             it('drops the same hidden public room for an authenticated (non-anonymous) user', async () => {
                 const report = buildPublicRoom(CONST.REPORT.VISIBILITY.PUBLIC);
-                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}` as const;
                 const reports: OnyxCollection<Report> = {[reportKey]: report};
 
                 await act(async () => {
@@ -1191,7 +1191,7 @@ describe('SidebarUtils', () => {
 
             it('does not apply the override to a non-public hidden room for an anonymous user', async () => {
                 const report = buildPublicRoom(undefined);
-                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${report.reportID}` as const;
+                const reportKey = `${ONYXKEYS.COLLECTION.REPORT}${PUBLIC_ROOM_ID}` as const;
                 const reports: OnyxCollection<Report> = {[reportKey]: report};
 
                 await act(async () => {

From aba48a93368119abb0b3b7a8f6695cb5a1fd378e Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Sun, 21 Jun 2026 14:09:25 +0500
Subject: [PATCH 5/6] Extract pending public room helper and clear ref after
 refetch

---
 src/DeepLinkHandler.tsx | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/DeepLinkHandler.tsx b/src/DeepLinkHandler.tsx
index a81e85d5aac8..8c7ebbdb80a3 100644
--- a/src/DeepLinkHandler.tsx
+++ b/src/DeepLinkHandler.tsx
@@ -1,6 +1,6 @@
 import type {NativeEventSubscription} from 'react-native';
 
-import {useEffect, useRef} from 'react';
+import {useCallback, useEffect, useRef} from 'react';
 import {Linking} from 'react-native';
 
 import type {Route} from './ROUTES';
@@ -43,6 +43,17 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
     const [betas, betasMetadata] = useOnyx(ONYXKEYS.BETAS);
     const isAuthenticated = useIsAuthenticated();
 
+    // An anonymous deep link into a public room needs to be re-fetched after OpenApp settles (see the effect
+    // below). Track the pending reportID so both the initial-URL and the url-change paths stay in sync.
+    const trackPendingPublicRoomFromDeepLink = useCallback((url: string, isCurrentlyAuthenticated: boolean) => {
+        const deepLinkReportID = getReportIDFromLink(url);
+        if (!deepLinkReportID || isCurrentlyAuthenticated) {
+            return;
+        }
+        pendingPublicRoomReportID.current = deepLinkReportID;
+        hasRefetchedPublicRoom.current = false;
+    }, []);
+
     useEffect(() => {
         if (isLoadingOnyxValue(allReportsMetadata, sessionMetadata, conciergeReportIDMetadata, introSelectedMetadata, isSelfTourViewedMetadata, betasMetadata)) {
             return;
@@ -93,11 +104,7 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
                         Log.info('[Deep link] introSelected is undefined when processing initial URL', false, {url});
                     }
                     openReportFromDeepLink(url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, isSelfTourViewed, betas);
-                    const deepLinkReportID = getReportIDFromLink(url);
-                    if (deepLinkReportID && !isCurrentlyAuthenticated) {
-                        pendingPublicRoomReportID.current = deepLinkReportID;
-                        hasRefetchedPublicRoom.current = false;
-                    }
+                    trackPendingPublicRoomFromDeepLink(url, isCurrentlyAuthenticated);
                 } else {
                     Report.doneCheckingPublicRoom();
                 }
@@ -125,11 +132,7 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
             }
             const isCurrentlyAuthenticated = hasAuthToken();
             openReportFromDeepLink(state.url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, isSelfTourViewed, betas);
-            const deepLinkReportID = getReportIDFromLink(state.url);
-            if (deepLinkReportID && !isCurrentlyAuthenticated) {
-                pendingPublicRoomReportID.current = deepLinkReportID;
-                hasRefetchedPublicRoom.current = false;
-            }
+            trackPendingPublicRoomFromDeepLink(state.url, isCurrentlyAuthenticated);
         });
 
         return () => {
@@ -171,7 +174,9 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
         if (!reportID || isLoadingApp || !isAnonymousUser()) {
             return;
         }
+        // The room made it into Onyx, so the cold-start race is over - stop tracking it.
         if (allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]?.reportID) {
+            pendingPublicRoomReportID.current = '';
             hasRefetchedPublicRoom.current = false;
             return;
         }

From e43c5adca5e84d979d2fb2e15c545e7578e950d1 Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Fri, 3 Jul 2026 16:13:11 +0500
Subject: [PATCH 6/6] Format DeepLinkHandlerTest with oxfmt

---
 tests/unit/DeepLinkHandlerTest.tsx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tests/unit/DeepLinkHandlerTest.tsx b/tests/unit/DeepLinkHandlerTest.tsx
index 2ecf5b34dea9..77ab38769ca5 100644
--- a/tests/unit/DeepLinkHandlerTest.tsx
+++ b/tests/unit/DeepLinkHandlerTest.tsx
@@ -1,11 +1,15 @@
 import {act, render} from '@testing-library/react-native';
-import {Linking} from 'react-native';
-import Onyx from 'react-native-onyx';
+
 import type * as Link from '@libs/actions/Link';
 import * as Report from '@libs/actions/Report';
+
 import CONST from '@src/CONST';
 import DeepLinkHandler from '@src/DeepLinkHandler';
 import ONYXKEYS from '@src/ONYXKEYS';
+
+import {Linking} from 'react-native';
+import Onyx from 'react-native-onyx';
+
 import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct';
 
 jest.mock('@libs/actions/Link', () => ({
