,
-
- /**
- * Used to obtain translations.
- */
- t: Function
-};
-
-/**
- * React component representing the deep linking page.
- *
- * @class DeepLinkingDesktopPage
- */
-class DeepLinkingDesktopPage extends Component
{
- /**
- * Initializes a new {@code DeepLinkingDesktopPage} instance.
- *
- * @param {Object} props - The read-only React {@code Component} props with
- * which the new instance is to be initialized.
- */
- constructor(props: P) {
- super(props);
-
- // Bind event handlers so they are only bound once per instance.
- this._onLaunchWeb = this._onLaunchWeb.bind(this);
- this._onTryAgain = this._onTryAgain.bind(this);
- }
-
- /**
- * Implements the Component's componentDidMount method.
- *
- * @inheritdoc
- */
- componentDidMount() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'displayed', 'DeepLinkingDesktop', { isMobileBrowser: false }));
- }
-
- /**
- * Renders the component.
- *
- * @returns {ReactElement}
- */
- render() {
- const { t, _deeplinkingCfg: { desktop = {}, hideLogo, showImage } } = this.props;
- const { appName } = desktop;
- const rightColumnStyle
- = showImage ? null : { width: '100%' };
-
- return (
-
- // Enabling light theme because of the color of the buttons.
-
-
-
- {
- hideLogo
- ? null
- :
- }
-
-
- {
- showImage
- ?
: null
- }
-
-
-
- {
- t(`${_TNS}.title`,
- { app: appName })
- }
-
-
- {
- t(
- `${_TNS}.${isSupportedBrowser()
- ? 'description'
- : 'descriptionWithoutWeb'}`,
- { app: appName }
- )
- }
-
-
-
- {
- isSupportedBrowser()
- &&
- }
-
-
-
-
-
-
- );
- }
-
- _onTryAgain: () => void;
-
- /**
- * Handles try again button clicks.
- *
- * @returns {void}
- */
- _onTryAgain() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'clicked', 'tryAgainButton', { isMobileBrowser: false }));
- this.props.dispatch(openDesktopApp());
- }
-
- _onLaunchWeb: () => void;
-
- /**
- * Handles launch web button clicks.
- *
- * @returns {void}
- */
- _onLaunchWeb() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'clicked', 'launchWebButton', { isMobileBrowser: false }));
- this.props.dispatch(openWebApp());
- }
-}
-
-/**
- * Maps (parts of) the Redux state to the associated props for the
- * {@code DeepLinkingDesktopPage} component.
- *
- * @param {Object} state - The Redux state.
- * @private
- * @returns {Props}
- */
-function _mapStateToProps(state) {
- return {
- _deeplinkingCfg: state['features/base/config'].deeplinking || {}
- };
-}
-
-export default translate(connect(_mapStateToProps)(DeepLinkingDesktopPage));
diff --git a/react/features/deep-linking/components/DeepLinkingDesktopPage.web.tsx b/react/features/deep-linking/components/DeepLinkingDesktopPage.web.tsx
new file mode 100644
index 000000000..31d50650c
--- /dev/null
+++ b/react/features/deep-linking/components/DeepLinkingDesktopPage.web.tsx
@@ -0,0 +1,159 @@
+import { Theme } from '@mui/material';
+import React, { useCallback, useEffect } 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 } from '../../base/config/configType';
+import { getLegalUrls } from '../../base/config/functions.any';
+import { isSupportedBrowser } from '../../base/environment/environment';
+import { translate, translateToHTML } from '../../base/i18n/functions';
+import { withPixelLineHeight } from '../../base/styles/functions.web';
+import Button from '../../base/ui/components/web/Button';
+import { BUTTON_TYPES } from '../../base/ui/constants.any';
+import {
+ openDesktopApp,
+ openWebApp
+} from '../actions';
+import { _TNS } from '../constants';
+
+const useStyles = makeStyles()((theme: Theme) => {
+ return {
+ container: {
+ background: '#1E1E1E',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: '100%',
+ height: '100%',
+ display: 'flex'
+ },
+ contentPane: {
+ display: 'flex',
+ flexDirection: 'column',
+ background: theme.palette.ui01,
+ border: `1px solid ${theme.palette.ui03}`,
+ padding: 40,
+ borderRadius: 16,
+ maxWidth: 410,
+ color: theme.palette.text01
+ },
+ logo: {
+ marginBottom: 32
+ },
+ launchingMeetingLabel: {
+ marginBottom: 16,
+ ...withPixelLineHeight(theme.typography.heading4)
+ },
+ roomName: {
+ marginBottom: 32,
+ ...withPixelLineHeight(theme.typography.heading5)
+ },
+ descriptionLabel: {
+ marginBottom: 32,
+ ...withPixelLineHeight(theme.typography.bodyLongRegular)
+ },
+ buttonsContainer: {
+ display: 'flex',
+ justifyContent: 'flex-start',
+ '& > *:not(:last-child)': {
+ marginRight: 16
+ }
+ },
+ separator: {
+ marginTop: 40,
+ height: 1,
+ maxWidth: 390,
+ background: theme.palette.ui03
+ },
+ label: {
+ marginTop: 40,
+ ...withPixelLineHeight(theme.typography.labelRegular),
+ color: theme.palette.text02,
+ '& a': {
+ color: theme.palette.link01
+ }
+ }
+ };
+});
+
+const DeepLinkingDesktopPage: React.FC = ({ t }) => {
+ const dispatch = useDispatch();
+ const room = useSelector((state: IReduxState) => decodeURIComponent(state['features/base/conference'].room || ''));
+ const deeplinkingCfg = useSelector((state: IReduxState) =>
+ state['features/base/config']?.deeplinking || {} as IDeeplinkingConfig);
+
+ const legalUrls = useSelector(getLegalUrls);
+
+ const { hideLogo, desktop } = deeplinkingCfg;
+
+ const { classes: styles } = useStyles();
+ const onLaunchWeb = useCallback(() => {
+ sendAnalytics(
+ createDeepLinkingPageEvent(
+ 'clicked', 'launchWebButton', { isMobileBrowser: false }));
+ dispatch(openWebApp());
+ }, []);
+ const onTryAgain = useCallback(() => {
+ sendAnalytics(
+ createDeepLinkingPageEvent(
+ 'clicked', 'tryAgainButton', { isMobileBrowser: false }));
+ dispatch(openDesktopApp());
+ }, []);
+
+ useEffect(() => {
+ sendAnalytics(
+ createDeepLinkingPageEvent(
+ 'displayed', 'DeepLinkingDesktop', { isMobileBrowser: false }));
+ }, []);
+
+ return (
+
+
+
+ {
+ !hideLogo
+ &&
+ }
+
+
+ {
+ t(`${_TNS}.titleNew`)
+ }
+
+
{ room }
+
+ {
+ isSupportedBrowser()
+ ? translateToHTML(t, `${_TNS}.descriptionNew`, { app: desktop?.appName })
+ : t(`${_TNS}.descriptionWithoutWeb`, { app: desktop?.appName })
+ }
+
+
+
+ { isSupportedBrowser() && (
+
+ )}
+
+
+
+
{translateToHTML(t, 'deepLinking.termsAndConditions', {
+ termsAndConditionsLink: legalUrls.terms
+ })}
+
+
+
+ );
+};
+
+export default translate(DeepLinkingDesktopPage);
diff --git a/react/features/deep-linking/components/DeepLinkingMobilePage.web.js b/react/features/deep-linking/components/DeepLinkingMobilePage.web.js
deleted file mode 100644
index e4a810238..000000000
--- a/react/features/deep-linking/components/DeepLinkingMobilePage.web.js
+++ /dev/null
@@ -1,299 +0,0 @@
-// @flow
-
-import React, { Component } from 'react';
-import type { Dispatch } from 'redux';
-
-import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
-import { IDeeplinkingConfig, IDeeplinkingMobileConfig } from '../../base/config/configType';
-import { isSupportedMobileBrowser } from '../../base/environment';
-import { translate } from '../../base/i18n';
-import { Platform } from '../../base/react';
-import { connect } from '../../base/redux';
-import { DialInSummary } from '../../invite';
-import { openWebApp } from '../actions';
-import { _TNS } from '../constants';
-import { generateDeepLinkingURL } from '../functions';
-import { renderPromotionalFooter } from '../renderPromotionalFooter';
-
-/**
- * The namespace of the CSS styles of DeepLinkingMobilePage.
- *
- * @private
- * @type {string}
- */
-const _SNS = 'deep-linking-mobile';
-
-/**
- * The type of the React {@code Component} props of
- * {@link DeepLinkingMobilePage}.
- */
-type Props = {
-
- /**
- * The deeplinking config.
- */
- _deeplinkingCfg: IDeeplinkingConfig,
-
- /**
- * Application mobile deeplinking config.
- */
- _mobileConfig: IDeeplinkingMobileConfig,
-
- /**
- * The deeplinking url.
- */
- _deepLinkingUrl: string,
-
- /**
- * The name of the conference attempting to being joined.
- */
- _room: string,
-
- /**
- * The page current url.
- */
- _url: URL,
-
- /**
- * Used to dispatch actions from the buttons.
- */
- dispatch: Dispatch,
-
- /**
- * The function to translate human-readable text.
- */
- t: Function
-};
-
-/**
- * React component representing mobile browser page.
- *
- * @class DeepLinkingMobilePage
- */
-class DeepLinkingMobilePage extends Component {
- /**
- * Initializes a new {@code DeepLinkingMobilePage} instance.
- *
- * @param {Object} props - The read-only React {@code Component} props with
- * which the new instance is to be initialized.
- */
- constructor(props: Props) {
- super(props);
-
- // Bind event handlers so they are only bound once per instance.
- this._onDownloadApp = this._onDownloadApp.bind(this);
- this._onLaunchWeb = this._onLaunchWeb.bind(this);
- this._onOpenApp = this._onOpenApp.bind(this);
- }
-
- /**
- * Implements the Component's componentDidMount method.
- *
- * @inheritdoc
- */
- componentDidMount() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'displayed', 'DeepLinkingMobile', { isMobileBrowser: true }));
- }
-
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- const {
- _deeplinkingCfg: { hideLogo },
- _mobileConfig: { downloadLink, appName },
- _room,
- t,
- _url,
- _deepLinkingUrl
- } = this.props;
- const downloadButtonClassName
- = `${_SNS}__button ${_SNS}__button_primary`;
-
-
- const onOpenLinkProperties = downloadLink
- ? {
- // 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.
- }
- : {
- // 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'
- };
-
- return (
-
-
- {
- hideLogo
- ? null
- :
- }
-
-
-
- );
- }
-
- /**
- * Generates the URL for downloading the app.
- *
- * @private
- * @returns {string} - The URL for downloading the app.
- */
- _generateDownloadURL() {
- const { _mobileConfig: { downloadLink, dynamicLink, appScheme } } = this.props;
-
- 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`;
- }
-
- _onDownloadApp: () => void;
-
- /**
- * Handles download app button clicks.
- *
- * @private
- * @returns {void}
- */
- _onDownloadApp() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'clicked', 'downloadAppButton', { isMobileBrowser: true }));
- }
-
- _onLaunchWeb: () => void;
-
- /**
- * Handles launch web button clicks.
- *
- * @returns {void}
- */
- _onLaunchWeb() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'clicked', 'launchWebButton', { isMobileBrowser: true }));
- this.props.dispatch(openWebApp());
- }
-
- _onOpenApp: () => void;
-
- /**
- * Handles open app button clicks.
- *
- * @private
- * @returns {void}
- */
- _onOpenApp() {
- sendAnalytics(
- createDeepLinkingPageEvent(
- 'clicked', 'openAppButton', { isMobileBrowser: true }));
- }
-}
-
-/**
- * Maps (parts of) the Redux state to the associated props for the
- * {@code DeepLinkingMobilePage} component.
- *
- * @param {Object} state - The Redux state.
- * @private
- * @returns {Props}
- */
-function _mapStateToProps(state) {
- const { locationURL = {} } = state['features/base/connection'];
- const { deeplinking } = state['features/base/config'];
- const mobileConfig = deeplinking?.[Platform.OS] || {};
-
- return {
- _deeplinkingCfg: deeplinking || {},
- _mobileConfig: mobileConfig,
- _room: decodeURIComponent(state['features/base/conference'].room),
- _url: locationURL,
- _deepLinkingUrl: generateDeepLinkingURL(state)
- };
-}
-
-export default translate(connect(_mapStateToProps)(DeepLinkingMobilePage));
diff --git a/react/features/deep-linking/components/DeepLinkingMobilePage.web.tsx b/react/features/deep-linking/components/DeepLinkingMobilePage.web.tsx
new file mode 100644
index 000000000..5c00bb2b4
--- /dev/null
+++ b/react/features/deep-linking/components/DeepLinkingMobilePage.web.tsx
@@ -0,0 +1,241 @@
+/* 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 = ({ 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 (
+
+
+ {!hideLogo && (
+ )}
+
+
{ t(`${_TNS}.launchMeetingLabel`) }
+
{room}
+
+
+
+
{ t(`${_TNS}.noMobileApp`) }
+
+ { t(`${_TNS}.downloadMobileApp`) }
+
+ {isSupportedMobileBrowser() ? (
+
+ ) : (
+
+ {t(`${_TNS}.unsupportedBrowser`)}
+
+ )}
+
+
+
+
+ );
+};
+
+export default translate(DeepLinkingMobilePage);
diff --git a/react/features/deep-linking/renderPromotionalFooter.js b/react/features/deep-linking/renderPromotionalFooter.js
deleted file mode 100644
index 733de78f4..000000000
--- a/react/features/deep-linking/renderPromotionalFooter.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// @flow
-/**
- * Method used in order to render a custom promotional footer.
- *
- * @returns {HTMLElement}
- */
-export function renderPromotionalFooter() {
- return null;
-}
diff --git a/react/features/invite/components/dial-in-summary/web/ConferenceID.js b/react/features/invite/components/dial-in-summary/web/ConferenceID.js
deleted file mode 100644
index 328957919..000000000
--- a/react/features/invite/components/dial-in-summary/web/ConferenceID.js
+++ /dev/null
@@ -1,60 +0,0 @@
-// @flow
-
-import React, { Component } from 'react';
-
-import { translate } from '../../../../base/i18n';
-import { _formatConferenceIDPin } from '../../../_utils';
-
-/**
- * The type of the React {@code Component} props of {@link ConferenceID}.
- */
-type Props = {
-
- /**
- * The conference ID for dialing in.
- */
- conferenceID: number,
-
- /**
- * The name of the conference.
- */
- conferenceName: ?string,
-
- /**
- * Invoked to obtain translated strings.
- */
- t: Function
-};
-
-/**
- * Displays a conference ID used as a pin for dialing into a conference.
- *
- * @augments Component
- */
-class ConferenceID extends Component {
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- const { conferenceID, conferenceName, t } = this.props;
-
- return (
-
-
- { conferenceName }
-
-
- { t('info.dialANumber') }
-
-
- { `${t('info.dialInConferenceID')} ${_formatConferenceIDPin(conferenceID)}` }
-
-
- );
- }
-}
-
-export default translate(ConferenceID);
diff --git a/react/features/invite/components/dial-in-summary/web/ConferenceID.tsx b/react/features/invite/components/dial-in-summary/web/ConferenceID.tsx
new file mode 100644
index 000000000..136fddd70
--- /dev/null
+++ b/react/features/invite/components/dial-in-summary/web/ConferenceID.tsx
@@ -0,0 +1,77 @@
+/* eslint-disable lines-around-comment */
+import { Theme } from '@mui/material';
+import React from 'react';
+import { WithTranslation } from 'react-i18next';
+import { makeStyles } from 'tss-react/mui';
+
+import { translate } from '../../../../base/i18n/functions';
+import { withPixelLineHeight } from '../../../../base/styles/functions.web';
+// @ts-ignore
+import { _formatConferenceIDPin } from '../../../_utils';
+
+
+interface IProps extends WithTranslation {
+
+ /**
+ * The conference id.
+ */
+ conferenceID?: string | number;
+
+ /**
+ * The conference name.
+ */
+ conferenceName: string;
+}
+
+const useStyles = makeStyles()((theme: Theme) => {
+ return {
+ container: {
+ marginTop: 32,
+ maxWidth: 310,
+ padding: '16px 12px',
+ background: theme.palette.ui02,
+ textAlign: 'center',
+ display: 'flex',
+ flexDirection: 'column',
+ borderRadius: 6
+ },
+ confNameLabel: {
+ ...withPixelLineHeight(theme.typography.heading6),
+ marginBottom: 18,
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis'
+ },
+ descriptionLabel: {
+ ...withPixelLineHeight(theme.typography.bodyShortRegularLarge),
+ marginBottom: 18
+ },
+ separator: {
+ width: '100%',
+ height: 1,
+ background: theme.palette.ui04,
+ marginBottom: 18
+ },
+ pinLabel: {
+ ...withPixelLineHeight(theme.typography.heading6)
+ }
+ };
+});
+
+const ConferenceID: React.FC = ({ conferenceID, t }) => {
+ const { classes: styles } = useStyles();
+
+ return (
+
+
+ To join the meeting via phone, dial one of these numbers and then enter the pin
+
+
+
+ { `${t('info.dialInConferenceID')} ${_formatConferenceIDPin(conferenceID ?? '')}` }
+
+
+ );
+};
+
+export default translate(ConferenceID);
diff --git a/react/features/invite/components/dial-in-summary/web/DialInSummary.js b/react/features/invite/components/dial-in-summary/web/DialInSummary.js
index 64865af46..5549ace25 100644
--- a/react/features/invite/components/dial-in-summary/web/DialInSummary.js
+++ b/react/features/invite/components/dial-in-summary/web/DialInSummary.js
@@ -1,8 +1,13 @@
// @flow
+
+import { Theme } from '@mui/material';
+import { withStyles } from '@mui/styles';
+import clsx from 'clsx';
import React, { Component } from 'react';
import { translate } from '../../../../base/i18n';
+import { withPixelLineHeight } from '../../../../base/styles/functions.web';
import { getDialInConferenceID, getDialInNumbers } from '../../../_utils';
import ConferenceID from './ConferenceID';
@@ -20,6 +25,11 @@ type Props = {
*/
className: string,
+ /**
+ * An object containing the CSS classes.
+ */
+ classes: any;
+
/**
* Whether or not numbers should include links with the telephone protocol.
*/
@@ -30,6 +40,16 @@ type Props = {
*/
room: string,
+ /**
+ * Whether the dial in summary container is scrollable.
+ */
+ scrollable: Boolean,
+
+ /**
+ * Whether the room name should show as title.
+ */
+ showTitle?: boolean,
+
/**
* The url where we were loaded.
*/
@@ -72,6 +92,26 @@ type State = {
numbersEnabled: ?boolean
}
+const styles = (theme: Theme) => {
+ return {
+ hasNumbers: {
+ alignItems: 'center',
+ display: 'flex',
+ flexDirection: 'column',
+ background: '#1E1E1E',
+ color: theme.palette.text01
+ },
+ scrollable: {
+ height: '100vh',
+ overflowY: 'scroll'
+ },
+ roomName: {
+ margin: '40px auto 8px',
+ ...withPixelLineHeight(theme.typography.heading5)
+ }
+ };
+};
+
/**
* Displays a page listing numbers for dialing into a conference and pin to
* the a specific conference.
@@ -136,24 +176,27 @@ class DialInSummary extends Component {
let contents;
const { conferenceID, error, loading, numbersEnabled } = this.state;
+ const { classes, showTitle, room, clickableNumbers, scrollable, t } = this.props;
if (loading) {
contents = '';
} else if (numbersEnabled === false) {
- contents = this.props.t('info.dialInNotSupported');
+ contents = t('info.dialInNotSupported');
} else if (error) {
contents = error;
} else {
- className = 'has-numbers';
+ className = clsx(classes.hasNumbers, scrollable && classes.scrollable);
contents = [
conferenceID
- ?
- : null,
+ ? <>
+ { showTitle && { room }
}
+
+ > : null,
@@ -161,7 +204,7 @@ class DialInSummary extends Component {
}
return (
-
+
{ contents }
);
@@ -272,4 +315,4 @@ class DialInSummary extends Component
{
}
}
-export default translate(DialInSummary);
+export default translate(withStyles(styles)(DialInSummary));
diff --git a/react/features/invite/components/dial-in-summary/web/DialInSummaryApp.js b/react/features/invite/components/dial-in-summary/web/DialInSummaryApp.js
new file mode 100644
index 000000000..2339059de
--- /dev/null
+++ b/react/features/invite/components/dial-in-summary/web/DialInSummaryApp.js
@@ -0,0 +1,80 @@
+// @flow
+
+import { AtlasKitThemeProvider } from '@atlaskit/theme';
+import React from 'react';
+
+import { BaseApp } from '../../../../base/app';
+import { isMobileBrowser } from '../../../../base/environment/utils';
+import GlobalStyles from '../../../../base/ui/components/GlobalStyles.web';
+import JitsiThemeProvider from '../../../../base/ui/components/JitsiThemeProvider.web';
+import { parseURLParams } from '../../../../base/util';
+import { DIAL_IN_INFO_PAGE_PATH_NAME } from '../../../constants';
+import NoRoomError from '../../dial-in-info-page/NoRoomError.web';
+
+import DialInSummary from './DialInSummary';
+
+/**
+ * Wrapper application for prejoin.
+ *
+ * @augments BaseApp
+ */
+export default class DialInSummaryApp extends BaseApp {
+ /**
+ * The deferred for the initialisation {{promise, resolve, reject}}.
+ */
+ _init: Object;
+
+ /**
+ * Navigates to {@link Prejoin} upon mount.
+ *
+ * @returns {void}
+ */
+ async componentDidMount() {
+ await super.componentDidMount();
+
+ const { room } = parseURLParams(window.location, true, 'search');
+ const { href } = window.location;
+ const ix = href.indexOf(DIAL_IN_INFO_PAGE_PATH_NAME);
+ const url = (ix > 0 ? href.substring(0, ix) : href) + room;
+
+ super._navigate({
+ component: () => (<>
+ {room
+ ?
+ : }
+ >)
+ });
+ }
+
+ /**
+ * Overrides the parent method to inject {@link AtlasKitThemeProvider} as
+ * the top most component.
+ *
+ * @override
+ */
+ _createMainElement(component, props) {
+ return (
+
+
+
+ {super._createMainElement(component, props)}
+
+
+ );
+ }
+
+ /**
+ * Renders the platform specific dialog container.
+ *
+ * @returns {React$Element}
+ */
+ _renderDialogContainer() {
+ return null;
+ }
+}
diff --git a/react/features/invite/components/dial-in-summary/web/NumbersList.js b/react/features/invite/components/dial-in-summary/web/NumbersList.js
deleted file mode 100644
index c87e2fc91..000000000
--- a/react/features/invite/components/dial-in-summary/web/NumbersList.js
+++ /dev/null
@@ -1,244 +0,0 @@
-// @flow
-
-import React, { Component } from 'react';
-
-import { translate } from '../../../../base/i18n';
-import { Icon, IconPhoneRinging } from '../../../../base/icons';
-
-type Props = {
-
- /**
- * Whether or not numbers should include links with the telephone protocol.
- */
- clickableNumbers: boolean,
-
- /**
- * The conference ID for dialing in.
- */
- conferenceID: number,
-
- /**
- * The phone numbers to display. Can be an array of number Objects or an
- * object with countries as keys and an array of numbers as values.
- */
- numbers: { [string]: Array } | Array