Adds dial in default number and pin to the text for calendar/share. (#3421)

* Adds dial in default number and pin to the text for calendar/share.

* Handles fail to fetch numbers or conference id.
This commit is contained in:
Дамян Минков 2018-09-07 17:48:58 -05:00 committed by GitHub
parent 1d128e027a
commit 7674e90d4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 180 additions and 119 deletions

View File

@ -430,7 +430,7 @@
"share":
{
"mainText": "Click the following link to join the meeting:\n__roomUrl__",
"dialInfoText": "\n\n=====\n\nJust want to dial in on your phone?\n\nClick this link to see the dial in phone numbers for this meetings\n__dialInfoPageUrl__"
"dialInfoText": "\n\n=====\n\nJust want to dial in on your phone?\n\n__defaultDialInNumber__Click this link to see the dial in phone numbers for this meeting\n__dialInfoPageUrl__"
},
"connection":
{

View File

@ -329,11 +329,8 @@ export const microsoftCalendarApi = {
return Promise.reject('Not authorized, please sign in!');
}
const { dialInNumbersUrl } = getState()['features/base/config'];
const text = getShareInfoText(
location, dialInNumbersUrl !== undefined, true/* use html */);
return getShareInfoText(getState(), location, true/* use html */)
.then(text => {
const client = Client.init({
authProvider: done => done(null, token)
});
@ -345,11 +342,12 @@ export const microsoftCalendarApi = {
const body = description.body;
if (description.bodyPreview) {
body.content = `${description.bodyPreview}<br><br>`;
body.content
= `${description.bodyPreview}<br><br>`;
}
// replace all new lines from the text with html <br>
// to make it pretty
// replace all new lines from the text with html
// <br> to make it pretty
body.content += text.split('\n').join('<br>');
return client
@ -361,6 +359,7 @@ export const microsoftCalendarApi = {
}
});
});
});
};
}
};

View File

@ -211,13 +211,8 @@ export function updateProfile() {
*/
export function updateCalendarEvent(
id: string, calendarId: string, location: string) {
return (dispatch: Dispatch<*>, getState: Function) => {
const { dialInNumbersUrl } = getState()['features/base/config'];
const text = getShareInfoText(location, dialInNumbersUrl !== undefined);
return googleApi.get()
.then(() =>
return (dispatch: Dispatch<*>, getState: Function) =>
getShareInfoText(getState(), location)
.then(text =>
googleApi._updateCalendarEntry(id, calendarId, location, text));
};
}

View File

@ -10,8 +10,7 @@ import { DialInSummary } from '../dial-in-summary';
import NoRoomError from './NoRoomError';
document.addEventListener('DOMContentLoaded', () => {
const params = parseURLParams(window.location, true, 'search');
const { room } = params;
const { room } = parseURLParams(window.location, true, 'search');
ReactDOM.render(
<I18nextProvider i18n = { i18next }>
@ -19,7 +18,7 @@ document.addEventListener('DOMContentLoaded', () => {
? <DialInSummary
className = 'dial-in-page'
clickableNumbers = { false }
room = { params.room } />
room = { room } />
: <NoRoomError className = 'dial-in-page' /> }
</I18nextProvider>,
document.getElementById('react')

View File

@ -7,7 +7,7 @@ import { getInviteURL } from '../../../base/connection';
import { translate } from '../../../base/i18n';
import { isLocalParticipantModerator } from '../../../base/participants';
import { getDialInfoPageURL } from '../../functions';
import { _getDefaultPhoneNumber, getDialInfoPageURL } from '../../functions';
import DialInNumber from './DialInNumber';
import PasswordForm from './PasswordForm';
@ -49,6 +49,11 @@ class InfoDialog extends Component {
*/
_inviteURL: PropTypes.string,
/**
* The current location url of the conference.
*/
_locationURL: PropTypes.object,
/**
* The value for how the conference is locked (or undefined if not
* locked) as defined by room-lock constants.
@ -118,7 +123,7 @@ class InfoDialog extends Component {
if (numbers) {
this.state.phoneNumber
= this._getDefaultPhoneNumber(numbers, defaultCountry);
= _getDefaultPhoneNumber(numbers, defaultCountry);
}
/**
@ -157,8 +162,7 @@ class InfoDialog extends Component {
const { defaultCountry, numbers } = nextProps.dialIn;
this.setState({
phoneNumber:
this._getDefaultPhoneNumber(numbers, defaultCountry)
phoneNumber: _getDefaultPhoneNumber(numbers, defaultCountry)
});
}
}
@ -231,35 +235,6 @@ class InfoDialog extends Component {
);
}
/**
* Sets the internal state of which dial-in number to display.
*
* @param {Array<string>|Object} dialInNumbers - The array or object of
* numbers to choose a number from.
* @param {string} defaultCountry - The country code for the country
* whose phone number should display.
* @private
* @returns {string|null}
*/
_getDefaultPhoneNumber(dialInNumbers, defaultCountry = 'US') {
if (Array.isArray(dialInNumbers)) {
// Dumbly return the first number if an array.
return dialInNumbers[0];
} else if (Object.keys(dialInNumbers).length > 0) {
const defaultNumbers = dialInNumbers[defaultCountry];
if (defaultNumbers) {
return defaultNumbers[0];
}
const firstRegion = Object.keys(dialInNumbers)[0];
return firstRegion && firstRegion[0];
}
return null;
}
/**
* Generates the URL for the static dial in info page.
*
@ -268,7 +243,8 @@ class InfoDialog extends Component {
*/
_getDialInfoPageURL() {
return getDialInfoPageURL(
encodeURIComponent(this.props._conferenceName));
encodeURIComponent(this.props._conferenceName),
this.props._locationURL);
}
/**
@ -525,6 +501,7 @@ class InfoDialog extends Component {
* _conference: Object,
* _conferenceName: string,
* _inviteURL: string,
* _locationURL: string,
* _locked: string,
* _password: string
* }}
@ -542,6 +519,7 @@ function _mapStateToProps(state) {
_conference: conference,
_conferenceName: room,
_inviteURL: getInviteURL(state),
_locationURL: state['features/base/connection'].locationURL,
_locked: locked,
_password: password
};

View File

@ -403,15 +403,16 @@ export function searchDirectory( // eslint-disable-line max-params
* Returns descriptive text that can be used to invite participants to a meeting
* (share via mobile or use it for calendar event description).
*
* @param {Object} state - The current state.
* @param {string} inviteUrl - The conference/location URL.
* @param {boolean} includeDialInfo - Whether to include or not the dialing
* information link.
* @param {boolean} useHtml - Whether to return html text.
* @returns {string}
* @returns {Promise<string>} A {@code Promise} resolving with a
* descriptive text that can be used to invite participants to a meeting.
*/
export function getShareInfoText(
inviteUrl: string, includeDialInfo: boolean, useHtml: ?boolean) {
state: Object, inviteUrl: string, useHtml: ?boolean): Promise<string> {
let roomUrl = inviteUrl;
const includeDialInfo = state['features/base/config'] !== undefined;
if (useHtml) {
roomUrl = `<a href="${roomUrl}">${roomUrl}</a>`;
@ -421,29 +422,90 @@ export function getShareInfoText(
if (includeDialInfo) {
const { room } = parseURIString(inviteUrl);
let dialInfoPageUrl = getDialInfoPageURL(room);
let numbersPromise;
if (state['features/invite'].numbers
&& state['features/invite'].conferenceID) {
numbersPromise = Promise.resolve(state['features/invite']);
} else {
// we are requesting numbers and conferenceId directly
// not using updateDialInNumbers, because custom room
// is specified and we do not want to store the data
// in the state
const { dialInConfCodeUrl, dialInNumbersUrl, hosts }
= state['features/base/config'];
const mucURL = hosts && hosts.muc;
if (!dialInConfCodeUrl || !dialInNumbersUrl || !mucURL) {
// URLs for fetching dial in numbers not defined
return Promise.reject();
}
numbersPromise = Promise.all([
getDialInNumbers(dialInNumbersUrl),
getDialInConferenceID(dialInConfCodeUrl, room, mucURL)
]).then(([ { defaultCountry, numbers }, {
conference, id, message } ]) => {
if (!conference || !id) {
return Promise.reject(message);
}
return {
defaultCountry,
numbers,
conferenceID: id
};
});
}
return numbersPromise.then(
({ conferenceID, defaultCountry, numbers }) => {
const phoneNumber
= _getDefaultPhoneNumber(numbers, defaultCountry) || '';
return `${
i18next.t('info.dialInNumber')} ${
phoneNumber} ${
i18next.t('info.dialInConferenceID')} ${
conferenceID}#\n\n`;
})
.catch(error =>
logger.error('Error fetching numbers or conferenceID', error))
.then(defaultDialInNumber => {
let dialInfoPageUrl = getDialInfoPageURL(
room,
state['features/base/connection'].locationURL);
if (useHtml) {
dialInfoPageUrl
= `<a href="${dialInfoPageUrl}">${dialInfoPageUrl}</a>`;
}
infoText += i18next.t('share.dialInfoText', { dialInfoPageUrl });
}
infoText += i18next.t('share.dialInfoText', {
defaultDialInNumber,
dialInfoPageUrl });
return infoText;
});
}
return Promise.resolve(infoText);
}
/**
* Generates the URL for the static dial in info page.
*
* @param {string} conferenceName - The conference name.
* @private
* @param {Object} locationURL - The current location URL, the object coming
* from state ['features/base/connection'].locationURL.
* @returns {string}
*/
export function getDialInfoPageURL(conferenceName: string) {
const origin = window.location.origin;
const pathParts = window.location.pathname.split('/');
export function getDialInfoPageURL(
conferenceName: string,
locationURL: Object) {
const origin = locationURL.origin;
const pathParts = locationURL.pathname.split('/');
pathParts.length = pathParts.length - 1;
@ -457,3 +519,34 @@ export function getDialInfoPageURL(conferenceName: string) {
return `${origin}${newPath}/static/dialInInfo.html?room=${conferenceName}`;
}
/**
* Sets the internal state of which dial-in number to display.
*
* @param {Array<string>|Object} dialInNumbers - The array or object of
* numbers to choose a number from.
* @param {string} defaultCountry - The country code for the country
* whose phone number should display.
* @private
* @returns {string|null}
*/
export function _getDefaultPhoneNumber(
dialInNumbers: Object,
defaultCountry: string = 'US') {
if (Array.isArray(dialInNumbers)) {
// Dumbly return the first number if an array.
return dialInNumbers[0];
} else if (Object.keys(dialInNumbers).length > 0) {
const defaultNumbers = dialInNumbers[defaultCountry];
if (defaultNumbers) {
return defaultNumbers[0];
}
const firstRegion = Object.keys(dialInNumbers)[0];
return firstRegion && firstRegion[0];
}
return null;
}

View File

@ -19,9 +19,7 @@ export function beginShareRoom(roomURL: ?string): Function {
}
roomURL && dispatch({
type: BEGIN_SHARE_ROOM,
roomURL,
includeDialInfo: getState()['features/base/config']
.dialInNumbersUrl !== undefined
roomURL
});
};
}

View File

@ -21,7 +21,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case BEGIN_SHARE_ROOM:
_shareRoom(action.roomURL, action.includeDialInfo, store.dispatch);
_shareRoom(action.roomURL, store);
break;
}
@ -32,15 +32,13 @@ MiddlewareRegistry.register(store => next => action => {
* Open the native sheet for sharing a specific conference/room URL.
*
* @param {string} roomURL - The URL of the conference/room to be shared.
* @param {boolean} includeDialInfo - Whether to include or not the dialing
* information link.
* @param {Dispatch} dispatch - The Redux dispatch function.
* @param {Store} store - Redux store.
* @private
* @returns {void}
*/
function _shareRoom(
roomURL: string, includeDialInfo: boolean, dispatch: Function) {
const message = getShareInfoText(roomURL, includeDialInfo);
function _shareRoom(roomURL: string, { dispatch, getState }) {
getShareInfoText(getState(), roomURL)
.then(message => {
const title = `${getName()} Conference`;
const onFulfilled
= (shared: boolean) => dispatch(endShareRoom(roomURL, shared));
@ -64,4 +62,5 @@ function _shareRoom(
reason);
onFulfilled(false);
});
});
}