(feature) - Add support for custom DID numbers page url

This commit is contained in:
horymury 2021-02-24 11:37:14 +02:00 committed by GitHub
parent d22792c9e3
commit 79bb98dab3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 143 deletions

View File

@ -58,6 +58,14 @@ const DEFAULT_STATE = {
*/ */
defaultBranding: true, defaultBranding: true,
/**
* Url for a custom page for DID numbers list.
*
* @public
* @type {string}
*/
didPageUrl: '',
/** /**
* The custom invite domain. * The custom invite domain.
* *
@ -101,6 +109,7 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
backgroundColor, backgroundColor,
backgroundImageUrl, backgroundImageUrl,
defaultBranding, defaultBranding,
didPageUrl,
inviteDomain, inviteDomain,
logoClickUrl, logoClickUrl,
logoImageUrl logoImageUrl
@ -110,6 +119,7 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
backgroundColor, backgroundColor,
backgroundImageUrl, backgroundImageUrl,
defaultBranding, defaultBranding,
didPageUrl,
inviteDomain, inviteDomain,
logoClickUrl, logoClickUrl,
logoImageUrl, logoImageUrl,

View File

@ -1,14 +1,12 @@
// @flow // @flow
import React, { useState, useEffect } from 'react'; import React, { useEffect } from 'react';
import { createInviteDialogEvent, sendAnalytics } from '../../../../analytics'; import { createInviteDialogEvent, sendAnalytics } from '../../../../analytics';
import { getRoomName } from '../../../../base/conference';
import { getInviteURL } from '../../../../base/connection'; import { getInviteURL } from '../../../../base/connection';
import { Dialog } from '../../../../base/dialog'; import { Dialog } from '../../../../base/dialog';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
import { getLocalParticipant } from '../../../../base/participants';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import { isVpaasMeeting } from '../../../../billing-counter/functions'; import { isVpaasMeeting } from '../../../../billing-counter/functions';
import EmbedMeetingTrigger from '../../../../embed-meeting/components/EmbedMeetingTrigger'; import EmbedMeetingTrigger from '../../../../embed-meeting/components/EmbedMeetingTrigger';
@ -26,11 +24,6 @@ declare var interfaceConfig: Object;
type Props = { type Props = {
/**
* The name of the current conference. Used as part of inviting users.
*/
_conferenceName: string,
/** /**
* The object representing the dialIn feature. * The object representing the dialIn feature.
*/ */
@ -41,6 +34,11 @@ type Props = {
*/ */
_embedMeetingVisible: boolean, _embedMeetingVisible: boolean,
/**
* The meeting invitation text.
*/
_invitationText: string,
/** /**
* Whether or not invite contacts should be visible. * Whether or not invite contacts should be visible.
*/ */
@ -57,14 +55,9 @@ type Props = {
_liveStreamViewURL: string, _liveStreamViewURL: string,
/** /**
* The redux representation of the local participant. * The default phone number.
*/ */
_localParticipantName: ?string, _phoneNumber: ?string,
/**
* The current location url of the conference.
*/
_locationUrl: Object,
/** /**
* Invoked to obtain translated strings. * Invoked to obtain translated strings.
@ -83,17 +76,15 @@ type Props = {
* @returns {React$Element<any>} * @returns {React$Element<any>}
*/ */
function AddPeopleDialog({ function AddPeopleDialog({
_conferenceName,
_dialIn, _dialIn,
_embedMeetingVisible, _embedMeetingVisible,
_invitationText,
_inviteContactsVisible, _inviteContactsVisible,
_inviteUrl, _inviteUrl,
_liveStreamViewURL, _liveStreamViewURL,
_localParticipantName, _phoneNumber,
_locationUrl,
t, t,
updateNumbers }: Props) { updateNumbers }: Props) {
const [ phoneNumber, setPhoneNumber ] = useState(undefined);
/** /**
* Updates the dial-in numbers. * Updates the dial-in numbers.
@ -119,27 +110,6 @@ function AddPeopleDialog({
}; };
}, []); }, []);
/**
* Updates the phone number in the state once the dial-in numbers are fetched.
*
* @returns {void}
*/
useEffect(() => {
if (!phoneNumber && _dialIn && _dialIn.numbers) {
setPhoneNumber(_getDefaultPhoneNumber(_dialIn.numbers));
}
}, [ _dialIn ]);
const invite = getInviteText({
_conferenceName,
_localParticipantName,
_inviteUrl,
_locationUrl,
_dialIn,
_liveStreamViewURL,
phoneNumber,
t
});
const inviteSubject = t('addPeople.inviteMoreMailSubject', { const inviteSubject = t('addPeople.inviteMoreMailSubject', {
appName: interfaceConfig.APP_NAME appName: interfaceConfig.APP_NAME
}); });
@ -156,7 +126,7 @@ function AddPeopleDialog({
<CopyMeetingLinkSection url = { _inviteUrl } /> <CopyMeetingLinkSection url = { _inviteUrl } />
<InviteByEmailSection <InviteByEmailSection
inviteSubject = { inviteSubject } inviteSubject = { inviteSubject }
inviteText = { invite } /> inviteText = { _invitationText } />
{ _embedMeetingVisible && <EmbedMeetingTrigger /> } { _embedMeetingVisible && <EmbedMeetingTrigger /> }
<div className = 'invite-more-dialog separator' /> <div className = 'invite-more-dialog separator' />
{ {
@ -165,11 +135,7 @@ function AddPeopleDialog({
} }
{ {
_dialIn.numbers _dialIn.numbers
&& <DialInSection && <DialInSection phoneNumber = { _phoneNumber } />
conferenceName = { _conferenceName }
dialIn = { _dialIn }
locationUrl = { _locationUrl }
phoneNumber = { phoneNumber } />
} }
</div> </div>
</Dialog> </Dialog>
@ -181,29 +147,32 @@ function AddPeopleDialog({
* {@code AddPeopleDialog} component. * {@code AddPeopleDialog} component.
* *
* @param {Object} state - The Redux state. * @param {Object} state - The Redux state.
* @param {Object} ownProps - The properties explicitly passed to the component.
* @private * @private
* @returns {Props} * @returns {Props}
*/ */
function mapStateToProps(state) { function mapStateToProps(state, ownProps) {
const localParticipant = getLocalParticipant(state);
const currentLiveStreamingSession const currentLiveStreamingSession
= getActiveSession(state, JitsiRecordingConstants.mode.STREAM); = getActiveSession(state, JitsiRecordingConstants.mode.STREAM);
const { iAmRecorder } = state['features/base/config']; const { iAmRecorder } = state['features/base/config'];
const addPeopleEnabled = isAddPeopleEnabled(state); const addPeopleEnabled = isAddPeopleEnabled(state);
const dialOutEnabled = isDialOutEnabled(state); const dialOutEnabled = isDialOutEnabled(state);
const hideInviteContacts = iAmRecorder || (!addPeopleEnabled && !dialOutEnabled); const hideInviteContacts = iAmRecorder || (!addPeopleEnabled && !dialOutEnabled);
const dialIn = state['features/invite'];
const phoneNumber = dialIn && dialIn.numbers ? _getDefaultPhoneNumber(dialIn.numbers) : undefined;
return { return {
_conferenceName: getRoomName(state), _dialIn: dialIn,
_dialIn: state['features/invite'],
_embedMeetingVisible: !isVpaasMeeting(state), _embedMeetingVisible: !isVpaasMeeting(state),
_invitationText: getInviteText({ state,
phoneNumber,
t: ownProps.t }),
_inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts, _inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts,
_inviteUrl: getInviteURL(state), _inviteUrl: getInviteURL(state),
_liveStreamViewURL: _liveStreamViewURL:
currentLiveStreamingSession currentLiveStreamingSession
&& currentLiveStreamingSession.liveStreamViewURL, && currentLiveStreamingSession.liveStreamViewURL,
_localParticipantName: localParticipant?.name, _phoneNumber: phoneNumber
_locationUrl: state['features/base/connection'].locationURL
}; };
} }

View File

@ -3,26 +3,22 @@
import React from 'react'; import React from 'react';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { connect } from '../../../../base/redux';
import { getDialInfoPageURL } from '../../../functions'; import { getDialInfoPageURL } from '../../../functions';
import DialInNumber from './DialInNumber'; import DialInNumber from './DialInNumber';
type Props = { type Props = {
/**
* The name of the current conference. Used as part of inviting users.
*/
conferenceName: string,
/** /**
* The object representing the dialIn feature. * The object representing the dialIn feature.
*/ */
dialIn: Object, _dialIn: Object,
/** /**
* The current location url of the conference. * The url of the page containing the dial-in numbers list.
*/ */
locationUrl: Object, _dialInfoPageUrl: string,
/** /**
* The phone number to dial to begin the process of dialing into a * The phone number to dial to begin the process of dialing into a
@ -45,25 +41,19 @@ type Props = {
* @returns {null|ReactElement} * @returns {null|ReactElement}
*/ */
function DialInSection({ function DialInSection({
conferenceName, _dialIn,
dialIn, _dialInfoPageUrl,
locationUrl,
phoneNumber, phoneNumber,
t t
}: Props) { }: Props) {
return ( return (
<div className = 'invite-more-dialog dial-in-display'> <div className = 'invite-more-dialog dial-in-display'>
<DialInNumber <DialInNumber
conferenceID = { dialIn.conferenceID } conferenceID = { _dialIn.conferenceID }
phoneNumber = { phoneNumber } /> phoneNumber = { phoneNumber } />
<a <a
className = 'more-numbers' className = 'more-numbers'
href = { href = { _dialInfoPageUrl }
getDialInfoPageURL(
conferenceName,
locationUrl
)
}
rel = 'noopener noreferrer' rel = 'noopener noreferrer'
target = '_blank'> target = '_blank'>
{ t('info.moreNumbers') } { t('info.moreNumbers') }
@ -72,4 +62,20 @@ function DialInSection({
); );
} }
export default translate(DialInSection);
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code DialInLink} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function _mapStateToProps(state) {
return {
_dialIn: state['features/invite'],
_dialInfoPageUrl: getDialInfoPageURL(state)
};
}
export default translate(connect(_mapStateToProps)(DialInSection));

View File

@ -1,7 +1,11 @@
// @flow // @flow
import { getActiveSession } from '../../features/recording/functions';
import { getRoomName } from '../base/conference';
import { getInviteURL } from '../base/connection';
import { i18next } from '../base/i18n'; import { i18next } from '../base/i18n';
import { isLocalParticipantModerator } from '../base/participants'; import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants';
import { toState } from '../base/redux'; import { toState } from '../base/redux';
import { doGetJSON, parseURIString } from '../base/util'; import { doGetJSON, parseURIString } from '../base/util';
import { isVpaasMeeting } from '../billing-counter/functions'; import { isVpaasMeeting } from '../billing-counter/functions';
@ -239,43 +243,44 @@ export function getInviteResultsForQuery(
* @returns {string} * @returns {string}
*/ */
export function getInviteText({ export function getInviteText({
_conferenceName, state,
_localParticipantName,
_inviteUrl,
_locationUrl,
_dialIn,
_liveStreamViewURL,
phoneNumber, phoneNumber,
t t
}: Object) { }: Object) {
const inviteURL = _decodeRoomURI(_inviteUrl); const dialIn = state['features/invite'];
const inviteUrl = getInviteURL(state);
const currentLiveStreamingSession = getActiveSession(state, JitsiRecordingConstants.mode.STREAM);
const liveStreamViewURL
= currentLiveStreamingSession
&& currentLiveStreamingSession.liveStreamViewURL;
const localParticipant = getLocalParticipant(state);
const localParticipantName = localParticipant?.name;
let invite = _localParticipantName const inviteURL = _decodeRoomURI(inviteUrl);
? t('info.inviteURLFirstPartPersonal', { name: _localParticipantName })
let invite = localParticipantName
? t('info.inviteURLFirstPartPersonal', { name: localParticipantName })
: t('info.inviteURLFirstPartGeneral'); : t('info.inviteURLFirstPartGeneral');
invite += t('info.inviteURLSecondPart', { invite += t('info.inviteURLSecondPart', {
url: inviteURL url: inviteURL
}); });
if (_liveStreamViewURL) { if (liveStreamViewURL) {
const liveStream = t('info.inviteLiveStream', { const liveStream = t('info.inviteLiveStream', {
url: _liveStreamViewURL url: liveStreamViewURL
}); });
invite = `${invite}\n${liveStream}`; invite = `${invite}\n${liveStream}`;
} }
if (shouldDisplayDialIn(_dialIn)) { if (shouldDisplayDialIn(dialIn)) {
const dial = t('info.invitePhone', { const dial = t('info.invitePhone', {
number: phoneNumber, number: phoneNumber,
conferenceID: _dialIn.conferenceID conferenceID: dialIn.conferenceID
}); });
const moreNumbers = t('info.invitePhoneAlternatives', { const moreNumbers = t('info.invitePhoneAlternatives', {
url: getDialInfoPageURL( url: getDialInfoPageURL(state),
_conferenceName,
_locationUrl
),
silentUrl: `${inviteURL}#config.startSilent=true` silentUrl: `${inviteURL}#config.startSilent=true`
}); });
@ -514,9 +519,7 @@ export function getShareInfoText(
.catch(error => .catch(error =>
logger.error('Error fetching numbers or conferenceID', error)) logger.error('Error fetching numbers or conferenceID', error))
.then(defaultDialInNumber => { .then(defaultDialInNumber => {
let dialInfoPageUrl = getDialInfoPageURL( let dialInfoPageUrl = getDialInfoPageURL(state);
room,
state['features/base/connection'].locationURL);
if (useHtml) { if (useHtml) {
dialInfoPageUrl dialInfoPageUrl
@ -537,28 +540,19 @@ export function getShareInfoText(
/** /**
* Generates the URL for the static dial in info page. * Generates the URL for the static dial in info page.
* *
* @param {string} conferenceName - The conference name. * @param {Object} state - The state from the Redux store.
* @param {Object} locationURL - The current location URL, the object coming
* from state ['features/base/connection'].locationURL.
* @returns {string} * @returns {string}
*/ */
export function getDialInfoPageURL( export function getDialInfoPageURL(state: Object) {
conferenceName: string, const { didPageUrl } = state['features/dynamic-branding'];
locationURL: Object) { const conferenceName = getRoomName(state);
const origin = locationURL.origin; const { locationURL } = state['features/base/connection'];
const pathParts = locationURL.pathname.split('/'); const { href } = locationURL;
const room = _decodeRoomURI(conferenceName);
pathParts.length = pathParts.length - 1; const url = didPageUrl || `${href.substring(0, href.lastIndexOf('/'))}/static/dialInInfo.html`;
const newPath = pathParts.reduce((accumulator, currentValue) => { return `${url}?room=${room}`;
if (currentValue) {
return `${accumulator}/${currentValue}`;
}
return accumulator;
}, '');
return `${origin}${newPath}/static/dialInInfo.html?room=${_decodeRoomURI(conferenceName)}`;
} }
/** /**

View File

@ -11,22 +11,16 @@ import { getDialInfoPageURL, shouldDisplayDialIn } from '../../invite';
*/ */
type Props = { type Props = {
/**
* The name of the current conference.
*/
_room: string,
/**
* The current location url of the conference.
*/
_locationURL: string,
/** /**
* The redux state representing the dial-in numbers feature. * The redux state representing the dial-in numbers feature.
*/ */
_dialIn: Object, _dialIn: Object,
/**
* The url of the page containing the dial-in numbers list.
*/
_dialInfoPageUrl: string,
/** /**
* Invoked to obtain translated strings. * Invoked to obtain translated strings.
*/ */
@ -47,7 +41,7 @@ class DialInLink extends Component<Props> {
* @returns {ReactElement} * @returns {ReactElement}
*/ */
render() { render() {
const { _room, _locationURL, _dialIn, t } = this.props; const { _dialIn, _dialInfoPageUrl, t } = this.props;
if (!shouldDisplayDialIn(_dialIn)) { if (!shouldDisplayDialIn(_dialIn)) {
return null; return null;
@ -56,12 +50,7 @@ class DialInLink extends Component<Props> {
return ( return (
<div>{t('toolbar.noAudioSignalDialInDesc')}&nbsp; <div>{t('toolbar.noAudioSignalDialInDesc')}&nbsp;
<a <a
href = { href = { _dialInfoPageUrl }
getDialInfoPageURL(
_room,
_locationURL
)
}
rel = 'noopener noreferrer' rel = 'noopener noreferrer'
target = '_blank'> target = '_blank'>
{t('toolbar.noAudioSignalDialInLinkDesc')} {t('toolbar.noAudioSignalDialInLinkDesc')}
@ -77,18 +66,12 @@ class DialInLink extends Component<Props> {
* *
* @param {Object} state - The Redux state. * @param {Object} state - The Redux state.
* @private * @private
* @returns {{ * @returns {Props}
* _room: string, */
* _locationURL: string,
* _dialIn: Object,
* }}
*/
function _mapStateToProps(state) { function _mapStateToProps(state) {
return { return {
_room: state['features/base/conference'].room, _dialIn: state['features/invite'],
_locationURL: state['features/base/connection'].locationURL, _dialInfoPageUrl: getDialInfoPageURL(state)
_dialIn: state['features/invite']
}; };
} }

View File

@ -4,7 +4,6 @@ declare var JitsiMeetJS: Object;
import uuid from 'uuid'; import uuid from 'uuid';
import { getRoomName } from '../base/conference';
import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions'; import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions';
import { createLocalTrack } from '../base/lib-jitsi-meet'; import { createLocalTrack } from '../base/lib-jitsi-meet';
import { import {
@ -262,10 +261,7 @@ export function makePrecallTest(conferenceOptions: Object) {
*/ */
export function openDialInPage() { export function openDialInPage() {
return function(dispatch: Function, getState: Function) { return function(dispatch: Function, getState: Function) {
const state = getState(); const dialInPage = getDialInfoPageURL(getState());
const locationURL = state['features/base/connection'].locationURL;
const roomName = getRoomName(state);
const dialInPage = getDialInfoPageURL(roomName, locationURL);
openURLInBrowser(dialInPage, true); openURLInBrowser(dialInPage, true);
}; };