-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
index.website.tsx
103 lines (89 loc) · 4.51 KB
/
index.website.tsx
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
import Str from 'expensify-common/lib/str';
import {useEffect, useRef, useState} from 'react';
import * as Browser from '@libs/Browser';
import Navigation from '@libs/Navigation/Navigation';
import navigationRef from '@libs/Navigation/navigationRef';
import shouldPreventDeeplinkPrompt from '@libs/Navigation/shouldPreventDeeplinkPrompt';
import * as App from '@userActions/App';
import * as Session from '@userActions/Session';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type DeeplinkWrapperProps from './types';
function isMacOSWeb(): boolean {
return !Browser.isMobile() && typeof navigator === 'object' && typeof navigator.userAgent === 'string' && /Mac/i.test(navigator.userAgent) && !/Electron/i.test(navigator.userAgent);
}
function promptToOpenInDesktopApp() {
// If the current url path is /transition..., meaning it was opened from oldDot, during this transition period:
// 1. The user session may not exist, because sign-in has not been completed yet.
// 2. There may be non-idempotent operations (e.g. create a new workspace), which obviously should not be executed again in the desktop app.
// So we need to wait until after sign-in and navigation are complete before starting the deeplink redirect.
if (Str.startsWith(window.location.pathname, Str.normalizeUrl(ROUTES.TRANSITION_BETWEEN_APPS))) {
App.beginDeepLinkRedirectAfterTransition();
} else {
// Match any magic link (/v/<account id>/<6 digit code>)
const isMagicLink = CONST.REGEX.ROUTES.VALIDATE_LOGIN.test(window.location.pathname);
App.beginDeepLinkRedirect(!isMagicLink);
}
}
function DeeplinkWrapper({children, isAuthenticated, autoAuthState}: DeeplinkWrapperProps) {
const [currentScreen, setCurrentScreen] = useState<string | undefined>();
const [hasShownPrompt, setHasShownPrompt] = useState(false);
const removeListener = useRef<() => void>();
useEffect(() => {
// If we've shown the prompt and still have a listener registered,
// remove the listener and reset its ref to undefined
if (hasShownPrompt && removeListener.current !== undefined) {
removeListener.current();
removeListener.current = undefined;
}
if (isAuthenticated === false) {
setHasShownPrompt(false);
Navigation.isNavigationReady().then(() => {
// Get initial route
const initialRoute = navigationRef.current?.getCurrentRoute();
setCurrentScreen(initialRoute?.name);
removeListener.current = navigationRef.current?.addListener('state', (event) => {
setCurrentScreen(Navigation.getRouteNameFromStateEvent(event));
});
});
}
}, [hasShownPrompt, isAuthenticated]);
useEffect(() => {
// According to the design, we don't support unlink in Desktop app https://github.com/Expensify/App/issues/19681#issuecomment-1610353099
const routeRegex = new RegExp(CONST.REGEX.ROUTES.UNLINK_LOGIN);
const isUnsupportedDeeplinkRoute = routeRegex.test(window.location.pathname);
// Making a few checks to exit early before checking authentication status
if (
!isMacOSWeb() ||
isUnsupportedDeeplinkRoute ||
hasShownPrompt ||
CONFIG.ENVIRONMENT === CONST.ENVIRONMENT.DEV ||
autoAuthState === CONST.AUTO_AUTH_STATE.NOT_STARTED ||
Session.isAnonymousUser()
) {
return;
}
// We want to show the prompt immediately if the user is already authenticated.
// Otherwise, we want to wait until the navigation state is set up
// and we know the user is on a screen that supports deeplinks.
if (isAuthenticated) {
promptToOpenInDesktopApp();
setHasShownPrompt(true);
} else {
// Navigation state is not set up yet, we're unsure if we should show the deep link prompt or not
if (currentScreen === undefined || isAuthenticated === false) {
return;
}
const preventPrompt = shouldPreventDeeplinkPrompt(currentScreen);
if (preventPrompt === true) {
return;
}
promptToOpenInDesktopApp();
setHasShownPrompt(true);
}
}, [currentScreen, hasShownPrompt, isAuthenticated, autoAuthState]);
return children;
}
DeeplinkWrapper.displayName = 'DeeplinkWrapper';
export default DeeplinkWrapper;