Skip to content

Commit 5d4c0d8

Browse files
committed
fix: navigate to Concierge chat after login from deep link on web
1 parent 54345c4 commit 5d4c0d8

16 files changed

Lines changed: 74 additions & 652 deletions

src/DeepLinkHandler.tsx

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ import {openReportFromDeepLink} from './libs/actions/Link';
1212
import * as Report from './libs/actions/Report';
1313
import {hasAuthToken, isAnonymousUser} from './libs/actions/Session';
1414
import Log from './libs/Log';
15-
import normalizePath from './libs/Navigation/helpers/normalizePath';
16-
import {setPendingConciergeDeepLink, setPendingHomeDeepLinkIfNoPendingConcierge} from './libs/PendingConciergeDeepLink';
1715
import {getReportIDFromLink} from './libs/ReportUtils';
1816
import {endSpan} from './libs/telemetry/activeSpans';
1917
import {hasSecureLinkKey} from './libs/Url';
2018
import ONYXKEYS from './ONYXKEYS';
21-
import ROUTES from './ROUTES';
2219
import {hasSeenTourSelector} from './selectors/Onboarding';
2320
import isLoadingOnyxValue from './types/utils/isLoadingOnyxValue';
2421

@@ -27,36 +24,6 @@ type DeepLinkHandlerProps = {
2724
onInitialUrl: (url: Route | null) => void;
2825
};
2926

30-
function getNormalizedCurrentPath() {
31-
if (typeof window === 'undefined') {
32-
return '';
33-
}
34-
35-
return normalizePath(window.location.pathname).replace(/\/$/, '') || '/';
36-
}
37-
38-
function getNormalizedPathFromURL(url: string) {
39-
let path = url;
40-
41-
try {
42-
const parsedURL = new URL(url);
43-
path = parsedURL.protocol === 'http:' || parsedURL.protocol === 'https:' ? parsedURL.pathname : `${parsedURL.host}${parsedURL.pathname}`;
44-
} catch {
45-
// If URL parsing fails, treat the value as a route path.
46-
}
47-
48-
return normalizePath(path).replace(/\/$/, '') || '/';
49-
}
50-
51-
function isCurrentPathConcierge() {
52-
return getNormalizedCurrentPath() === normalizePath(ROUTES.CONCIERGE);
53-
}
54-
55-
function isCurrentPathRootOrOnboarding() {
56-
const normalizedPath = getNormalizedCurrentPath();
57-
return normalizedPath === '/' || normalizedPath === normalizePath(ROUTES.ONBOARDING_ROOT.route) || normalizedPath.startsWith(`${normalizePath(ROUTES.ONBOARDING_ROOT.route)}/`);
58-
}
59-
6027
/**
6128
* Component that does not render anything but isolates the COLLECTION.REPORT Onyx subscription
6229
* from the root Expensify component to prevent cascading re-renders of the
@@ -130,10 +97,6 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
13097
initialUrlProcessed.current = true;
13198
onInitialUrl(url as Route);
13299

133-
if (!isCurrentlyAuthenticated && isCurrentPathConcierge() && (!url || getNormalizedPathFromURL(url) !== normalizePath(ROUTES.CONCIERGE))) {
134-
setPendingConciergeDeepLink();
135-
}
136-
137100
if (url) {
138101
if (conciergeReportID === undefined) {
139102
Log.info('[Deep link] conciergeReportID is undefined when processing initial URL', false, {url});
@@ -144,10 +107,6 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
144107
openReportFromDeepLink(url, allReports, isCurrentlyAuthenticated, conciergeReportID, introSelected, isSelfTourViewed, betas);
145108
trackPendingPublicRoomFromDeepLink(url, isCurrentlyAuthenticated);
146109
} else {
147-
if (!isCurrentlyAuthenticated && isCurrentPathRootOrOnboarding()) {
148-
// A missing initial URL at root/onboarding can happen during startup, so don't override a stored /concierge intent.
149-
setPendingHomeDeepLinkIfNoPendingConcierge();
150-
}
151110
Report.doneCheckingPublicRoom();
152111
}
153112

src/hooks/useAutoCreateSubmitWorkspace.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Log from '@libs/Log';
2-
import {navigateToPendingDeepLinkAfterOnboarding, navigateToSubmitWorkspaceAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
2+
import {navigateToSubmitWorkspaceAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
33
import {createDisplayName} from '@libs/PersonalDetailsUtils';
44
import {canEditWorkspaceSettings, isGroupPolicy, isSubmitPolicy} from '@libs/PolicyUtils';
55

@@ -88,7 +88,6 @@ function useAutoCreateSubmitWorkspace() {
8888
hasActiveAdminPolicies,
8989
})
9090
: {adminsChatReportID: onboardingAdminsChatReportID, policyID: onboardingPolicyID};
91-
let didNavigateToPendingDeepLink = false;
9291

9392
if (shouldCompleteOnboarding) {
9493
try {
@@ -102,9 +101,6 @@ function useAutoCreateSubmitWorkspace() {
102101
introSelected,
103102
isSelfTourViewed,
104103
conciergeChat,
105-
onBeforeOnboardingModalUnmount: () => {
106-
didNavigateToPendingDeepLink = navigateToPendingDeepLinkAfterOnboarding(conciergeReportID);
107-
},
108104
});
109105
} catch (error) {
110106
// Swallow onboarding completion failures so a network error doesn't block workspace
@@ -126,12 +122,7 @@ function useAutoCreateSubmitWorkspace() {
126122
policyIDForNavigation = existingSubmitPolicyID;
127123
}
128124

129-
if (didNavigateToPendingDeepLink) {
130-
return;
131-
}
132-
133-
// Pass conciergeReportID so true onboarding completion can honor a pending /concierge intent after refresh.
134-
navigateToSubmitWorkspaceAfterOnboardingWithMicrotaskQueue(policyIDForNavigation, shouldUseNarrowLayout, conciergeReportID, shouldCompleteOnboarding);
125+
navigateToSubmitWorkspaceAfterOnboardingWithMicrotaskQueue(policyIDForNavigation, shouldUseNarrowLayout);
135126
},
136127
[
137128
currentUserEmail,
@@ -153,7 +144,6 @@ function useAutoCreateSubmitWorkspace() {
153144
hasActiveAdminPolicies,
154145
shouldUseNarrowLayout,
155146
conciergeChat,
156-
conciergeReportID,
157147
],
158148
);
159149

src/hooks/useAutoCreateTrackWorkspace.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import isSidePanelReportSupported from '@components/SidePanel/isSidePanelReportSupported';
22

33
import Log from '@libs/Log';
4-
import {navigateAfterOnboardingWithMicrotaskQueue, navigateToPendingDeepLinkAfterOnboarding} from '@libs/navigateAfterOnboarding';
4+
import {navigateAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
55
import {isTrackOnboardingChoice} from '@libs/OnboardingUtils';
66
import {createDisplayName} from '@libs/PersonalDetailsUtils';
77
import {isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
@@ -102,7 +102,6 @@ function useAutoCreateTrackWorkspace() {
102102
// On mobile, hardcode trackExpensesWithConcierge since the web flow already works
103103
// with the CompleteGuidedSetup response and side panel isn't supported on native.
104104
let rhpVariant: OnboardingRHPVariant | undefined = isSidePanelReportSupported ? undefined : CONST.ONBOARDING_RHP_VARIANT.TRACK_EXPENSES_WITH_CONCIERGE;
105-
let didNavigateToPendingDeepLink = false;
106105
try {
107106
const response = await completeOnboarding({
108107
engagementChoice,
@@ -117,9 +116,6 @@ function useAutoCreateTrackWorkspace() {
117116
isSelfTourViewed,
118117
conciergeChat,
119118
selfDMReport,
120-
onBeforeOnboardingModalUnmount: () => {
121-
didNavigateToPendingDeepLink = navigateToPendingDeepLinkAfterOnboarding(conciergeChatReportID);
122-
},
123119
});
124120

125121
if (isSidePanelReportSupported) {
@@ -137,18 +133,16 @@ function useAutoCreateTrackWorkspace() {
137133
setOnboardingAdminsChatReportID();
138134
setOnboardingPolicyID();
139135

140-
if (!didNavigateToPendingDeepLink) {
141-
navigateAfterOnboardingWithMicrotaskQueue(
142-
shouldUseNarrowLayout,
143-
isBetaEnabled(CONST.BETAS.DEFAULT_ROOMS),
144-
conciergeChatReportID,
145-
reportNameValuePairs,
146-
newPolicyID,
147-
mergedAccountConciergeReportID,
148-
false,
149-
{variantOverride: rhpVariant},
150-
);
151-
}
136+
navigateAfterOnboardingWithMicrotaskQueue(
137+
shouldUseNarrowLayout,
138+
isBetaEnabled(CONST.BETAS.DEFAULT_ROOMS),
139+
conciergeChatReportID,
140+
reportNameValuePairs,
141+
newPolicyID,
142+
mergedAccountConciergeReportID,
143+
false,
144+
{variantOverride: rhpVariant},
145+
);
152146
}
153147
},
154148
[

src/hooks/useCompleteOnboarding.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {completeOnboarding, extractRHPVariantFromResponse} from '@libs/actions/R
55
import {setOnboardingAdminsChatReportID, setOnboardingPolicyID} from '@libs/actions/Welcome';
66
import type {OnboardingFeatureMapItem} from '@libs/actions/Welcome/OnboardingFeatures';
77
import Log from '@libs/Log';
8-
import {navigateAfterOnboardingWithMicrotaskQueue, navigateToPendingDeepLinkAfterOnboarding} from '@libs/navigateAfterOnboarding';
8+
import {navigateAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
99
import TransitionTracker from '@libs/Navigation/TransitionTracker';
1010
import {isGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
1111

@@ -72,7 +72,6 @@ function useCompleteOnboarding() {
7272
const isAccountingEnabled = featuresMap.some((feature) => feature.id === CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED && feature.enabled);
7373
const resolvedIntegration = isAccountingEnabled ? userReportedIntegration : undefined;
7474
const email = currentUserPersonalDetails.email ?? '';
75-
let didNavigateToPendingDeepLink = false;
7675

7776
const {adminsChatReportID, policyID} = shouldCreateWorkspace
7877
? createWorkspace({
@@ -119,9 +118,6 @@ function useCompleteOnboarding() {
119118
isSelfTourViewed,
120119
conciergeChat,
121120
adminsChatReport,
122-
onBeforeOnboardingModalUnmount: () => {
123-
didNavigateToPendingDeepLink = navigateToPendingDeepLinkAfterOnboarding(conciergeReportID);
124-
},
125121
});
126122
const rhpVariant = isSidePanelReportSupported ? extractRHPVariantFromResponse(response) : undefined;
127123

@@ -133,11 +129,6 @@ function useCompleteOnboarding() {
133129
waitForUpcomingTransition: true,
134130
});
135131

136-
if (didNavigateToPendingDeepLink) {
137-
setIsLoading(false);
138-
return;
139-
}
140-
141132
navigateAfterOnboardingWithMicrotaskQueue(
142133
isSmallScreenWidth,
143134
isBetaEnabled(CONST.BETAS.DEFAULT_ROOMS),

src/libs/Navigation/linkingConfig/subscribe.ts

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import {hasAuthToken} from '@libs/actions/Session';
22
import continuePlaidOAuth from '@libs/continuePlaidOAuth';
3-
import normalizePath from '@libs/Navigation/helpers/normalizePath';
43
import navigationRef from '@libs/Navigation/navigationRef';
54
import type {RootNavigatorParamList} from '@libs/Navigation/types';
6-
import {updatePendingConciergeDeepLinkForRoute} from '@libs/PendingConciergeDeepLink';
75

86
import CONST from '@src/CONST';
97
import ROUTES from '@src/ROUTES';
@@ -13,8 +11,6 @@ import type {LinkingOptions} from '@react-navigation/native';
1311
import {findFocusedRoute} from '@react-navigation/native';
1412
import {Linking} from 'react-native';
1513

16-
import prefixes from './prefixes';
17-
1814
/**
1915
* Rules for dropping a deep link that would re-navigate to a screen the user is already on.
2016
*/
@@ -33,40 +29,8 @@ const skipRules: ReadonlyArray<{urlMatcher: RegExp; focusedScreens: readonly str
3329
},
3430
];
3531

36-
function isInternalAppURL(url: string) {
37-
if (url.startsWith('/') || prefixes.some((prefix) => url.startsWith(prefix))) {
38-
return true;
39-
}
40-
41-
try {
42-
return typeof window !== 'undefined' && new URL(url).origin === window.location.origin;
43-
} catch {
44-
return false;
45-
}
46-
}
47-
48-
function getNormalizedPathFromURL(url: string) {
49-
let path = url;
50-
51-
try {
52-
const parsedURL = new URL(url);
53-
path = parsedURL.protocol === 'http:' || parsedURL.protocol === 'https:' || parsedURL.pathname ? parsedURL.pathname : parsedURL.host;
54-
} catch {
55-
// If URL parsing fails, treat the value as a route path.
56-
}
57-
58-
return (normalizePath(path).replace(/\/$/, '') || '/').toLowerCase();
59-
}
60-
61-
const subscribe: NonNullable<LinkingOptions<RootNavigatorParamList>['subscribe']> = (listener) => {
32+
const subscribe: LinkingOptions<RootNavigatorParamList>['subscribe'] = (listener) => {
6233
const subscription = Linking.addEventListener('url', ({url}: {url: string}) => {
63-
const isAuthenticated = hasAuthToken();
64-
const normalizedPath = getNormalizedPathFromURL(url);
65-
const route = normalizedPath === '/' ? '' : normalizedPath.slice(1);
66-
if (!isAuthenticated && isInternalAppURL(url)) {
67-
updatePendingConciergeDeepLinkForRoute(route, isAuthenticated);
68-
}
69-
7034
// Skip deep links to screens where the user is already focused.
7135
const skipRule = skipRules.find(({urlMatcher}) => urlMatcher.test(url));
7236
if (skipRule) {
@@ -91,7 +55,7 @@ const subscribe: NonNullable<LinkingOptions<RootNavigatorParamList>['subscribe']
9155
// which lives in AuthScreens and is not mounted while PublicScreens is showing. Dispatching it here
9256
// throws "NAVIGATE ... was not handled by any navigator". openReportFromDeepLink() already opens the
9357
// public room as an anonymous user and handles navigation, so defer to it instead. See #92672.
94-
if (!isAuthenticated && url.includes(`/${ROUTES.REPORT}/`)) {
58+
if (!hasAuthToken() && url.includes(`/${ROUTES.REPORT}/`)) {
9559
return;
9660
}
9761
listener(url);

0 commit comments

Comments
 (0)