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

308 lines
9.3 KiB
JavaScript

// @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<any>,
/**
* The function to translate human-readable text.
*/
t: Function
};
/**
* React component representing mobile browser page.
*
* @class DeepLinkingMobilePage
*/
class DeepLinkingMobilePage extends Component<Props> {
/**
* 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, showImage },
_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 (
<div className = { _SNS }>
<div className = 'header'>
{
hideLogo
? null
: <img
alt = { t('welcomepage.logo.logoDeepLinking') }
className = 'logo'
src = 'images/logo-deep-linking.png' />
}
</div>
<div className = { `${_SNS}__body` }>
{
showImage
? <img
alt = { t('welcomepage.logo.logoDeepLinking') }
className = 'image'
src = 'images/deep-linking-image.png' />
: null
}
<p className = { `${_SNS}__text` }>
{ t(`${_TNS}.appNotInstalled`, { app: appName }) }
</p>
<p className = { `${_SNS}__text` }>
{ t(`${_TNS}.ifHaveApp`) }
</p>
<a
{ ...onOpenLinkProperties }
className = { `${_SNS}__href` }
href = { _deepLinkingUrl }
onClick = { this._onOpenApp }
target = '_top'>
<button className = { `${_SNS}__button ${_SNS}__button_primary` }>
{ t(`${_TNS}.joinInApp`) }
</button>
</a>
<p className = { `${_SNS}__text` }>
{ t(`${_TNS}.ifDoNotHaveApp`) }
</p>
<a
{ ...onOpenLinkProperties }
href = { this._generateDownloadURL() }
onClick = { this._onDownloadApp }
target = '_top'>
<button className = { downloadButtonClassName }>
{ t(`${_TNS}.downloadApp`) }
</button>
</a>
{
isSupportedMobileBrowser()
? (
<a
onClick = { this._onLaunchWeb }
target = '_top'>
<button className = { downloadButtonClassName }>
{ t(`${_TNS}.launchWebButton`) }
</button>
</a>
) : (
<b>
{ t(`${_TNS}.unsupportedBrowser`) }
</b>
)
}
{ renderPromotionalFooter() }
<DialInSummary
className = 'deep-linking-dial-in'
clickableNumbers = { true }
room = { _room }
url = { _url } />
</div>
</div>
);
}
/**
* 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));