jiti-meet/react/features/deep-linking/components/DeepLinkingMobilePage.web.tsx

242 lines
8.7 KiB
TypeScript

/* eslint-disable lines-around-comment */
import { Theme } from '@mui/material';
import React, { useCallback, useEffect, useMemo } from 'react';
import { WithTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { createDeepLinkingPageEvent } from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { IReduxState } from '../../app/types';
import { IDeeplinkingConfig, IDeeplinkingMobileConfig } from '../../base/config/configType';
import { isSupportedMobileBrowser } from '../../base/environment/environment';
import { translate } from '../../base/i18n/functions';
import Platform from '../../base/react/Platform.web';
import { withPixelLineHeight } from '../../base/styles/functions.web';
import Button from '../../base/ui/components/web/Button';
// @ts-ignore
import DialInSummary from '../../invite/components/dial-in-summary/web/DialInSummary';
import { openWebApp } from '../actions';
// @ts-ignore
import { _TNS } from '../constants';
// @ts-ignore
import { generateDeepLinkingURL } from '../functions';
const PADDINGS = {
topBottom: 24,
leftRight: 40
};
const useStyles = makeStyles()((theme: Theme) => {
return {
container: {
background: '#1E1E1E',
width: '100vw',
height: '100vh',
overflowX: 'hidden',
overflowY: 'auto',
justifyContent: 'center',
display: 'flex',
'& a': {
textDecoration: 'none'
}
},
contentPane: {
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
padding: `${PADDINGS.topBottom}px ${PADDINGS.leftRight}px`,
maxWidth: 410,
color: theme.palette.text01
},
launchingMeetingLabel: {
marginTop: 24,
textAlign: 'center',
marginBottom: 32,
...withPixelLineHeight(theme.typography.heading5)
},
roomNameLabel: {
...withPixelLineHeight(theme.typography.bodyLongRegularLarge)
},
joinMeetWrapper: {
marginTop: 24,
width: '100%'
},
labelDescription: {
textAlign: 'center',
marginTop: 16,
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
},
linkWrapper: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
marginTop: 8,
width: '100%'
},
linkLabel: {
color: theme.palette.link01,
...withPixelLineHeight(theme.typography.bodyLongBoldLarge)
},
supportedBrowserContent: {
marginTop: 16,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center'
},
labelOr: {
...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
},
separator: {
marginTop: '32px',
height: 1,
width: `calc(100% + ${2 * PADDINGS.leftRight}px)`,
background: theme.palette.ui03
}
};
});
const DeepLinkingMobilePage: React.FC<WithTranslation> = ({ t }) => {
const deeplinkingCfg = useSelector((state: IReduxState) =>
state['features/base/config']?.deeplinking || {} as IDeeplinkingConfig);
const { hideLogo } = deeplinkingCfg;
const deepLinkingUrl: string = useSelector(generateDeepLinkingURL);
const room = useSelector((state: IReduxState) => decodeURIComponent(state['features/base/conference'].room || ''));
const url = useSelector((state: IReduxState) => state['features/base/connection'] || {});
const dispatch = useDispatch();
const { classes: styles } = useStyles();
const generateDownloadURL = useCallback(() => {
const { downloadLink, dynamicLink, appScheme }
= (deeplinkingCfg?.[Platform.OS as keyof typeof deeplinkingCfg] || {}) as IDeeplinkingMobileConfig;
if (downloadLink && typeof dynamicLink === 'undefined') {
return downloadLink;
}
const {
apn,
appCode,
customDomain,
ibi,
isi
} = dynamicLink || {};
const domain = customDomain ?? `https://${appCode}.app.goo.gl`;
return `${domain}/?link=${
encodeURIComponent(window.location.href)}&apn=${
apn}&ibi=${
ibi}&isi=${
isi}&ius=${
appScheme}&efr=1`;
}, [ deeplinkingCfg ]);
const onDownloadApp = useCallback(() => {
sendAnalytics(
createDeepLinkingPageEvent(
'clicked', 'downloadAppButton', { isMobileBrowser: true }));
}, []);
const onLaunchWeb = useCallback(() => {
sendAnalytics(
createDeepLinkingPageEvent(
'clicked', 'launchWebButton', { isMobileBrowser: true }));
dispatch(openWebApp());
}, []);
const onOpenApp = useCallback(() => {
sendAnalytics(
createDeepLinkingPageEvent(
'clicked', 'openAppButton', { isMobileBrowser: true }));
}, []);
const onOpenLinkProperties = useMemo(() => {
const { downloadLink }
= (deeplinkingCfg?.[Platform.OS as keyof typeof deeplinkingCfg] || {}) as IDeeplinkingMobileConfig;
if (downloadLink) {
return {
// When opening a link to the download page, we want to let the
// OS itself handle intercepting and opening the appropriate
// app store. This avoids potential issues with browsers, such
// as iOS Chrome, not opening the store properly.
};
}
return {
// When falling back to another URL (Firebase) let the page be
// opened in a new window. This helps prevent the user getting
// trapped in an app-open-cycle where going back to the mobile
// browser re-triggers the app-open behavior.
target: '_blank',
rel: 'noopener noreferrer'
};
}, [ deeplinkingCfg ]);
useEffect(() => {
sendAnalytics(
createDeepLinkingPageEvent(
'displayed', 'DeepLinkingMobile', { isMobileBrowser: true }));
}, []);
return (
<div className = { styles.container }>
<div className = { styles.contentPane }>
{!hideLogo && (<img
alt = { t('welcomepage.logo.logoDeepLinking') }
src = 'images/logo-deep-linking-mobile.png' />
)}
<div className = { styles.launchingMeetingLabel }>{ t(`${_TNS}.launchMeetingLabel`) }</div>
<div className = ''>{room}</div>
<a
{ ...onOpenLinkProperties }
className = { styles.joinMeetWrapper }
href = { deepLinkingUrl }
onClick = { onOpenApp }
target = '_top'>
<Button
fullWidth = { true }
label = { t(`${_TNS}.joinInAppNew`) } />
</a>
<div className = { styles.labelDescription }>{ t(`${_TNS}.noMobileApp`) }</div>
<a
{ ...onOpenLinkProperties }
className = { styles.linkWrapper }
href = { generateDownloadURL() }
onClick = { onDownloadApp }
target = '_top'>
<div className = { styles.linkLabel }>{ t(`${_TNS}.downloadMobileApp`) }</div>
</a>
{isSupportedMobileBrowser() ? (
<div className = { styles.supportedBrowserContent }>
<div className = { styles.labelOr }>OR</div>
<a
className = { styles.linkWrapper }
onClick = { onLaunchWeb }
target = '_top'>
<div className = { styles.linkLabel }>{ t(`${_TNS}.joinInBrowser`) }</div>
</a>
</div>
) : (
<div className = { styles.labelDescription }>
{t(`${_TNS}.unsupportedBrowser`)}
</div>
)}
<div className = { styles.separator } />
<DialInSummary
className = 'deep-linking-dial-in'
clickableNumbers = { true }
room = { room }
url = { url } />
</div>
</div>
);
};
export default translate(DeepLinkingMobilePage);