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:
parent
1d128e027a
commit
7674e90d4d
|
@ -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":
|
||||
{
|
||||
|
|
|
@ -329,36 +329,35 @@ 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 */);
|
||||
|
||||
|
||||
const client = Client.init({
|
||||
authProvider: done => done(null, token)
|
||||
});
|
||||
|
||||
return client
|
||||
.api(`/me/events/${id}`)
|
||||
.get()
|
||||
.then(description => {
|
||||
const body = description.body;
|
||||
|
||||
if (description.bodyPreview) {
|
||||
body.content = `${description.bodyPreview}<br><br>`;
|
||||
}
|
||||
|
||||
// replace all new lines from the text with html <br>
|
||||
// to make it pretty
|
||||
body.content += text.split('\n').join('<br>');
|
||||
return getShareInfoText(getState(), location, true/* use html */)
|
||||
.then(text => {
|
||||
const client = Client.init({
|
||||
authProvider: done => done(null, token)
|
||||
});
|
||||
|
||||
return client
|
||||
.api(`/me/calendar/events/${id}`)
|
||||
.patch({
|
||||
body,
|
||||
location: {
|
||||
'displayName': location
|
||||
.api(`/me/events/${id}`)
|
||||
.get()
|
||||
.then(description => {
|
||||
const body = description.body;
|
||||
|
||||
if (description.bodyPreview) {
|
||||
body.content
|
||||
= `${description.bodyPreview}<br><br>`;
|
||||
}
|
||||
|
||||
// replace all new lines from the text with html
|
||||
// <br> to make it pretty
|
||||
body.content += text.split('\n').join('<br>');
|
||||
|
||||
return client
|
||||
.api(`/me/calendar/events/${id}`)
|
||||
.patch({
|
||||
body,
|
||||
location: {
|
||||
'displayName': location
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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 (useHtml) {
|
||||
dialInfoPageUrl
|
||||
= `<a href="${dialInfoPageUrl}">${dialInfoPageUrl}</a>`;
|
||||
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
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
infoText += i18next.t('share.dialInfoText', { dialInfoPageUrl });
|
||||
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', {
|
||||
defaultDialInNumber,
|
||||
dialInfoPageUrl });
|
||||
|
||||
return infoText;
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,36 +32,35 @@ 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);
|
||||
const title = `${getName()} Conference`;
|
||||
const onFulfilled
|
||||
= (shared: boolean) => dispatch(endShareRoom(roomURL, shared));
|
||||
function _shareRoom(roomURL: string, { dispatch, getState }) {
|
||||
getShareInfoText(getState(), roomURL)
|
||||
.then(message => {
|
||||
const title = `${getName()} Conference`;
|
||||
const onFulfilled
|
||||
= (shared: boolean) => dispatch(endShareRoom(roomURL, shared));
|
||||
|
||||
Share.share(
|
||||
/* content */ {
|
||||
message,
|
||||
title
|
||||
},
|
||||
/* options */ {
|
||||
dialogTitle: title, // Android
|
||||
subject: title // iOS
|
||||
})
|
||||
.then(
|
||||
/* onFulfilled */ value => {
|
||||
onFulfilled(value.action === Share.sharedAction);
|
||||
},
|
||||
/* onRejected */ reason => {
|
||||
logger.error(
|
||||
`Failed to share conference/room URL ${roomURL}:`,
|
||||
reason);
|
||||
onFulfilled(false);
|
||||
});
|
||||
Share.share(
|
||||
/* content */ {
|
||||
message,
|
||||
title
|
||||
},
|
||||
/* options */ {
|
||||
dialogTitle: title, // Android
|
||||
subject: title // iOS
|
||||
})
|
||||
.then(
|
||||
/* onFulfilled */ value => {
|
||||
onFulfilled(value.action === Share.sharedAction);
|
||||
},
|
||||
/* onRejected */ reason => {
|
||||
logger.error(
|
||||
`Failed to share conference/room URL ${roomURL}:`,
|
||||
reason);
|
||||
onFulfilled(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue