Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

DeepLinkingMobilePage.web.tsx 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* eslint-disable lines-around-comment */
  2. import { Theme } from '@mui/material';
  3. import React, { useCallback, useEffect, useMemo } from 'react';
  4. import { WithTranslation } from 'react-i18next';
  5. import { useDispatch, useSelector } from 'react-redux';
  6. import { makeStyles } from 'tss-react/mui';
  7. import { createDeepLinkingPageEvent } from '../../analytics/AnalyticsEvents';
  8. import { sendAnalytics } from '../../analytics/functions';
  9. import { IReduxState } from '../../app/types';
  10. import { IDeeplinkingConfig, IDeeplinkingMobileConfig } from '../../base/config/configType';
  11. import { isSupportedMobileBrowser } from '../../base/environment/environment';
  12. import { translate } from '../../base/i18n/functions';
  13. import Platform from '../../base/react/Platform.web';
  14. import { withPixelLineHeight } from '../../base/styles/functions.web';
  15. import Button from '../../base/ui/components/web/Button';
  16. import DialInSummary from '../../invite/components/dial-in-summary/web/DialInSummary';
  17. import { openWebApp } from '../actions';
  18. import { _TNS } from '../constants';
  19. import { generateDeepLinkingURL } from '../functions';
  20. const PADDINGS = {
  21. topBottom: 24,
  22. leftRight: 40
  23. };
  24. const useStyles = makeStyles()((theme: Theme) => {
  25. return {
  26. container: {
  27. background: '#1E1E1E',
  28. width: '100vw',
  29. height: '100dvh',
  30. overflowX: 'hidden',
  31. overflowY: 'auto',
  32. justifyContent: 'center',
  33. display: 'flex',
  34. '& a': {
  35. textDecoration: 'none'
  36. }
  37. },
  38. contentPane: {
  39. display: 'flex',
  40. alignItems: 'center',
  41. flexDirection: 'column',
  42. padding: `${PADDINGS.topBottom}px ${PADDINGS.leftRight}px`,
  43. maxWidth: 410,
  44. color: theme.palette.text01
  45. },
  46. launchingMeetingLabel: {
  47. marginTop: 24,
  48. textAlign: 'center',
  49. marginBottom: 32,
  50. ...withPixelLineHeight(theme.typography.heading5)
  51. },
  52. roomNameLabel: {
  53. ...withPixelLineHeight(theme.typography.bodyLongRegularLarge)
  54. },
  55. joinMeetWrapper: {
  56. marginTop: 24,
  57. width: '100%'
  58. },
  59. labelDescription: {
  60. textAlign: 'center',
  61. marginTop: 16,
  62. ...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
  63. },
  64. linkWrapper: {
  65. display: 'flex',
  66. justifyContent: 'center',
  67. alignItems: 'center',
  68. marginTop: 8,
  69. width: '100%'
  70. },
  71. linkLabel: {
  72. color: theme.palette.link01,
  73. ...withPixelLineHeight(theme.typography.bodyLongBoldLarge)
  74. },
  75. supportedBrowserContent: {
  76. marginTop: 16,
  77. display: 'flex',
  78. flexDirection: 'column',
  79. alignItems: 'center',
  80. justifyContent: 'center'
  81. },
  82. labelOr: {
  83. ...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
  84. },
  85. separator: {
  86. marginTop: '32px',
  87. height: 1,
  88. width: `calc(100% + ${2 * PADDINGS.leftRight}px)`,
  89. background: theme.palette.ui03
  90. }
  91. };
  92. });
  93. const DeepLinkingMobilePage: React.FC<WithTranslation> = ({ t }) => {
  94. const deeplinkingCfg = useSelector((state: IReduxState) =>
  95. state['features/base/config']?.deeplinking || {} as IDeeplinkingConfig);
  96. const { hideLogo } = deeplinkingCfg;
  97. const deepLinkingUrl: string = useSelector(generateDeepLinkingURL);
  98. const room = useSelector((state: IReduxState) => decodeURIComponent(state['features/base/conference'].room || ''));
  99. const url = useSelector((state: IReduxState) => state['features/base/connection'] || {});
  100. const dispatch = useDispatch();
  101. const { classes: styles } = useStyles();
  102. const generateDownloadURL = useCallback(() => {
  103. const { downloadLink }
  104. = (deeplinkingCfg?.[Platform.OS as keyof typeof deeplinkingCfg] || {}) as IDeeplinkingMobileConfig;
  105. return downloadLink;
  106. }, [ deeplinkingCfg ]);
  107. const onDownloadApp = useCallback(() => {
  108. sendAnalytics(
  109. createDeepLinkingPageEvent(
  110. 'clicked', 'downloadAppButton', { isMobileBrowser: true }));
  111. }, []);
  112. const onLaunchWeb = useCallback(() => {
  113. sendAnalytics(
  114. createDeepLinkingPageEvent(
  115. 'clicked', 'launchWebButton', { isMobileBrowser: true }));
  116. dispatch(openWebApp());
  117. }, []);
  118. const onOpenApp = useCallback(() => {
  119. sendAnalytics(
  120. createDeepLinkingPageEvent(
  121. 'clicked', 'openAppButton', { isMobileBrowser: true }));
  122. }, []);
  123. const onOpenLinkProperties = useMemo(() => {
  124. const { downloadLink }
  125. = (deeplinkingCfg?.[Platform.OS as keyof typeof deeplinkingCfg] || {}) as IDeeplinkingMobileConfig;
  126. if (downloadLink) {
  127. return {
  128. // When opening a link to the download page, we want to let the
  129. // OS itself handle intercepting and opening the appropriate
  130. // app store. This avoids potential issues with browsers, such
  131. // as iOS Chrome, not opening the store properly.
  132. };
  133. }
  134. return {
  135. // When falling back to another URL (Firebase) let the page be
  136. // opened in a new window. This helps prevent the user getting
  137. // trapped in an app-open-cycle where going back to the mobile
  138. // browser re-triggers the app-open behavior.
  139. target: '_blank',
  140. rel: 'noopener noreferrer'
  141. };
  142. }, [ deeplinkingCfg ]);
  143. useEffect(() => {
  144. sendAnalytics(
  145. createDeepLinkingPageEvent(
  146. 'displayed', 'DeepLinkingMobile', { isMobileBrowser: true }));
  147. }, []);
  148. return (
  149. <div className = { styles.container }>
  150. <div className = { styles.contentPane }>
  151. {!hideLogo && (<img
  152. alt = { t('welcomepage.logo.logoDeepLinking') }
  153. src = 'images/logo-deep-linking-mobile.png' />
  154. )}
  155. <div className = { styles.launchingMeetingLabel }>{ t(`${_TNS}.launchMeetingLabel`) }</div>
  156. <div className = ''>{room}</div>
  157. <a
  158. { ...onOpenLinkProperties }
  159. className = { styles.joinMeetWrapper }
  160. href = { deepLinkingUrl }
  161. onClick = { onOpenApp }
  162. target = '_top'>
  163. <Button
  164. fullWidth = { true }
  165. label = { t(`${_TNS}.joinInAppNew`) } />
  166. </a>
  167. <div className = { styles.labelDescription }>{ t(`${_TNS}.noMobileApp`) }</div>
  168. <a
  169. { ...onOpenLinkProperties }
  170. className = { styles.linkWrapper }
  171. href = { generateDownloadURL() }
  172. onClick = { onDownloadApp }
  173. target = '_top'>
  174. <div className = { styles.linkLabel }>{ t(`${_TNS}.downloadMobileApp`) }</div>
  175. </a>
  176. {isSupportedMobileBrowser() ? (
  177. <div className = { styles.supportedBrowserContent }>
  178. <div className = { styles.labelOr }>{ t(`${_TNS}.or`) }</div>
  179. <a
  180. className = { styles.linkWrapper }
  181. onClick = { onLaunchWeb }
  182. target = '_top'>
  183. <div className = { styles.linkLabel }>{ t(`${_TNS}.joinInBrowser`) }</div>
  184. </a>
  185. </div>
  186. ) : (
  187. <div className = { styles.labelDescription }>
  188. {t(`${_TNS}.unsupportedBrowser`)}
  189. </div>
  190. )}
  191. <div className = { styles.separator } />
  192. <DialInSummary
  193. className = 'deep-linking-dial-in'
  194. clickableNumbers = { true }
  195. hideError = { true }
  196. room = { room }
  197. url = { url } />
  198. </div>
  199. </div>
  200. );
  201. };
  202. export default translate(DeepLinkingMobilePage);