-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy pathAuthScreensInitHandler.tsx
More file actions
152 lines (135 loc) · 7 KB
/
AuthScreensInitHandler.tsx
File metadata and controls
152 lines (135 loc) · 7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import {hasSeenTourSelector} from '@selectors/Onboarding';
import {useEffect, useRef} from 'react';
import {useInitialURLActions, useInitialURLState} from '@components/InitialURLContextProvider';
import useHasActiveAdminPolicies from '@hooks/useHasActiveAdminPolicies';
import useOnyx from '@hooks/useOnyx';
import {init, isClientTheLeader} from '@libs/ActiveClientManager';
import Log from '@libs/Log';
import getCurrentUrl from '@libs/Navigation/currentUrl';
import Navigation from '@libs/Navigation/Navigation';
import NetworkConnection from '@libs/NetworkConnection';
import Pusher from '@libs/Pusher';
import PusherConnectionManager from '@libs/PusherConnectionManager';
import {getReportIDFromLink} from '@libs/ReportUtils';
import * as SessionUtils from '@libs/SessionUtils';
import {endSpan, getSpan, startSpan} from '@libs/telemetry/activeSpans';
import {getSearchParamFromUrl} from '@libs/Url';
import * as App from '@userActions/App';
import * as Download from '@userActions/Download';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
import * as User from '@userActions/User';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
function initializePusher(conciergeReportID: string | undefined, currentUserAccountID?: number) {
return Pusher.init({
appKey: CONFIG.PUSHER.APP_KEY,
cluster: CONFIG.PUSHER.CLUSTER,
authEndpoint: `${CONFIG.EXPENSIFY.DEFAULT_API_ROOT}api/AuthenticatePusher?`,
}).then(() => {
User.subscribeToUserEvents(currentUserAccountID ?? CONST.DEFAULT_NUMBER_ID, conciergeReportID);
});
}
/**
* Component that does not render anything and owns mount-only initialization logic, network reconnect,
* and all Onyx subscriptions that are only consumed during initialization.
*
* Extracted from AuthScreens to isolate useOnyx subscriptions:
* - SESSION, NVP_INTRO_SELECTED, NVP_ACTIVE_POLICY_ID,
* NVP_ONBOARDING (tour selector), ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT (x2),
* IS_LOADING_APP
*/
function AuthScreensInitHandler() {
const currentUrl = getCurrentUrl();
const delegatorEmail = getSearchParamFromUrl(currentUrl, 'delegatorEmail');
const {initialURL, isAuthenticatedAtStartup} = useInitialURLState();
const {setIsAuthenticatedAtStartup} = useInitialURLActions();
const hasActiveAdminPolicies = useHasActiveAdminPolicies();
const [session] = useOnyx(ONYXKEYS.SESSION);
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const [betas] = useOnyx(ONYXKEYS.BETAS);
const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT);
const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
const [lastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT);
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
const [conciergeReportID, conciergeReportIDMetadata] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
const lastUpdateIDAppliedToClientRef = useRef(lastUpdateIDAppliedToClient);
const isLoadingAppRef = useRef(isLoadingApp);
lastUpdateIDAppliedToClientRef.current = lastUpdateIDAppliedToClient;
isLoadingAppRef.current = isLoadingApp;
const handleNetworkReconnect = () => {
if (isLoadingAppRef.current) {
App.openApp();
} else {
Log.info('[handleNetworkReconnect] Sending ReconnectApp');
App.reconnectApp(lastUpdateIDAppliedToClientRef.current);
}
};
useEffect(() => {
if (!Navigation.isActiveRoute(ROUTES.SIGN_IN_MODAL)) {
return;
}
if (isLoadingOnyxValue(conciergeReportIDMetadata)) {
return;
}
// This means sign in in RHP was successful, so we can subscribe to user events
initializePusher(conciergeReportID, session?.accountID);
}, [session?.accountID, conciergeReportID, conciergeReportIDMetadata]);
useEffect(() => {
const isLoggingInAsNewUser = !!session?.email && SessionUtils.isLoggingInAsNewUser(currentUrl, session.email);
// Sign out the current user if we're transitioning with a different user
const isTransitioning = currentUrl.includes(ROUTES.TRANSITION_BETWEEN_APPS);
const isSupportalTransition = currentUrl.includes('authTokenType=support');
if (isLoggingInAsNewUser && isTransitioning) {
Session.signOutAndRedirectToSignIn(false, isSupportalTransition);
return;
}
NetworkConnection.listenForReconnect();
NetworkConnection.onReconnect(() => handleNetworkReconnect());
// Pusher initialization span
startSpan(CONST.TELEMETRY.SPAN_NAVIGATION.PUSHER_INIT, {
name: CONST.TELEMETRY.SPAN_NAVIGATION.PUSHER_INIT,
op: CONST.TELEMETRY.SPAN_NAVIGATION.PUSHER_INIT,
parentSpan: getSpan(CONST.TELEMETRY.SPAN_BOOTSPLASH.ROOT),
});
PusherConnectionManager.init();
initializePusher(conciergeReportID, session?.accountID).finally(() => {
endSpan(CONST.TELEMETRY.SPAN_NAVIGATION.PUSHER_INIT);
});
// Sometimes when we transition from old dot to new dot, the client is not the leader
// so we need to initialize the client again
if (!isClientTheLeader() && isTransitioning) {
init();
}
// If we are on this screen then we are "logged in", but the user might not have "just logged in". They could be reopening the app
// or returning from background. If so, we'll assume they have some app data already and we can call reconnectApp() instead of openApp().
// Delegator connect() is handled by DelegatorConnectGate.
if (delegatorEmail) {
// connect() handled by DelegatorConnectGate
} else if (SessionUtils.didUserLogInDuringSession()) {
const reportID = getReportIDFromLink(initialURL ?? null);
if (reportID && !isAuthenticatedAtStartup) {
Report.openReport({reportID, introSelected, betas});
// Don't want to call `openReport` again when logging out and then logging in
setIsAuthenticatedAtStartup(true);
}
App.openApp();
} else {
Log.info('[AuthScreens] Sending ReconnectApp');
App.reconnectApp(initialLastUpdateIDAppliedToClient);
}
App.setUpPoliciesAndNavigate(session, introSelected, activePolicyID, isSelfTourViewed, hasActiveAdminPolicies);
Download.clearDownloads();
return () => {
Session.cleanupSession();
};
// Rule disabled because this effect is only for component did mount & will component unmount lifecycle event
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return null;
}
export default AuthScreensInitHandler;