Adds new format of phoneList service and re-design dial in numbers page. (#3903)
* Adds new format of phoneList service and re-design dial in numbers page. Adds flags and country names (with translations) for the numbers if using the new format. * Fixes tests and fixes get default number. * Updates swagger with new format. * Moves html back yo table. Fixes displaying on mobile and also the tel: URI generation. The tel: URI is tested on Android and iOS and seems to work (Android was not interpreting 'p', but both seems to like ','). * Fixes a wrong return statement. * Small fixes.
This commit is contained in:
parent
d7eea8abbc
commit
ea4d49f2a0
|
@ -28,7 +28,7 @@
|
|||
max-width: 40em;
|
||||
padding: 35px 0 40px 0;
|
||||
text-align: center;
|
||||
width: 75%;
|
||||
width: 90%;
|
||||
|
||||
a:active {
|
||||
text-decoration: none;
|
||||
|
@ -46,7 +46,7 @@
|
|||
|
||||
&__text,
|
||||
.deep-linking-dial-in {
|
||||
font-size: 1.2em;
|
||||
font-size: 1em;
|
||||
line-height: em(29px, 21px);
|
||||
margin-bottom: 0.65em;
|
||||
|
||||
|
@ -59,6 +59,26 @@
|
|||
font-size: em(21, 18);
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.dial-in-conference-id {
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
.dial-in-conference-description {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.toll-free-list {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.numbers-list {
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
&__href {
|
||||
|
|
|
@ -124,29 +124,75 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dial-in-numbers-list {
|
||||
margin-top: 20px;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 5px;
|
||||
|
||||
thead {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
border-bottom: 1px solid #d1dbe8;
|
||||
}
|
||||
|
||||
.flag {
|
||||
border-bottom-style: none;
|
||||
width: 30px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.country {
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
padding: 0 20px 0 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.numbers-list {
|
||||
list-style: none;
|
||||
padding: 0 20px 0 0;
|
||||
}
|
||||
|
||||
.toll-free-list {
|
||||
font-weight: bold;
|
||||
list-style: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.dial-in-page {
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 24px;
|
||||
font-size: 12px;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
padding: 25px;
|
||||
position: absolute;
|
||||
transform: translateY(-50%);
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
|
||||
.dial-in-numbers-list {
|
||||
font-size: 24px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.dial-in-conference-id {
|
||||
text-align: center;
|
||||
min-width: 200px;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.dial-in-conference-name,
|
||||
.dial-in-conference-pin {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.dial-in-conference-description {
|
||||
margin: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,22 @@
|
|||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
LANGUAGES := $(shell node -p "Object.keys(require('./lang/languages.json')).join(' ')")
|
||||
COUNTRIES_DIR := node_modules/i18n-iso-countries/langs
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
# we skip making Makefile exists for updating browserify modules when developing
|
||||
override_dh_auto_build:
|
||||
|
||||
override_dh_install:
|
||||
override_dh_install: $(LANGUAGES)
|
||||
dh_installdirs
|
||||
dh_install -X/config.js -X/package.json
|
||||
|
||||
$(LANGUAGES):
|
||||
if [ -f $(COUNTRIES_DIR)/$@.json ] ; \
|
||||
then \
|
||||
dh_install -pjitsi-meet-web $(COUNTRIES_DIR)/$@.json usr/share/jitsi-meet/lang/; \
|
||||
mv debian/jitsi-meet-web/usr/share/jitsi-meet/lang/$@.json debian/jitsi-meet-web/usr/share/jitsi-meet/lang/countries-$@.json; \
|
||||
fi;
|
||||
|
|
|
@ -128,19 +128,23 @@ definitions:
|
|||
description: "Full JID for the conference OR boolean false if no conference was found (search by ID)"
|
||||
|
||||
PhoneNumberList:
|
||||
type: "object"
|
||||
properties:
|
||||
numbersEnabled:
|
||||
type: "boolean"
|
||||
description: "Control flag for Jitsi Meet user interface. Must be set to true for Jitsi Meet to display phone-in UI elements"
|
||||
numbers:
|
||||
description: "List of dial in numbers for the conference."
|
||||
type: "array"
|
||||
items:
|
||||
type: "object"
|
||||
description: "Keys are Country Names, each value is an array of phone numbers"
|
||||
additionalProperties:
|
||||
type: "array"
|
||||
items:
|
||||
properties:
|
||||
countryCode:
|
||||
type: "string"
|
||||
format: "phone"
|
||||
description: "ISO 3166-1 country code. Alpha-2 supported."
|
||||
default:
|
||||
type: "boolean"
|
||||
description: "Whether this number is the default one to show. Optional."
|
||||
formattedNumber:
|
||||
type: "string"
|
||||
description: "The formatted telephone number to show."
|
||||
tollFree:
|
||||
type: "boolean"
|
||||
description: "Whether the number is toll free number."
|
||||
|
||||
externalDocs:
|
||||
description: "Find out more about the Jitsi Cloud API"
|
||||
|
|
|
@ -344,10 +344,11 @@
|
|||
"cancelPassword": "Cancel password",
|
||||
"conferenceURL": "Link:",
|
||||
"country": "Country",
|
||||
"dialANumber": "To join your meeting, dial one of these numbers and then enter this PIN: __conferenceID__#",
|
||||
"dialANumber": "To join your meeting, dial one of these numbers and then enter the pin.",
|
||||
"dialInConferenceID": "PIN:",
|
||||
"dialInNotSupported": "Sorry, dialing in is currently not suppported.",
|
||||
"dialInNotSupported": "Sorry, dialing in is currently not supported.",
|
||||
"dialInNumber": "Dial-in:",
|
||||
"dialInTollFree": "Toll Free",
|
||||
"genericError": "Whoops, something went wrong.",
|
||||
"inviteLiveStream": "To view the live stream of this meeting, click this link: __url__",
|
||||
"invitePhone": "To join by phone, dial __number__ and enter this PIN: __conferenceID__#",
|
||||
|
|
|
@ -7494,6 +7494,11 @@
|
|||
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
|
||||
"dev": true
|
||||
},
|
||||
"i18n-iso-countries": {
|
||||
"version": "3.7.8",
|
||||
"resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-3.7.8.tgz",
|
||||
"integrity": "sha512-NkT3lRiw7D4kKtSAVjVdHCvGlc2UOe0ALKa9IfEx0LkEDf0q3YgjP/veVk0d/OZ7yqUNzV8aJP4lJc6RPj++Gw=="
|
||||
},
|
||||
"i18next": {
|
||||
"version": "8.4.3",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-8.4.3.tgz",
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"@webcomponents/url": "0.7.1",
|
||||
"amplitude-js": "4.5.2",
|
||||
"dropbox": "4.0.9",
|
||||
"i18n-iso-countries": "3.7.8",
|
||||
"i18next": "8.4.3",
|
||||
"i18next-browser-languagedetector": "2.0.0",
|
||||
"i18next-xhr-backend": "1.4.2",
|
||||
|
|
|
@ -13,7 +13,7 @@ import { translate as reactI18nextTranslate } from 'react-i18next';
|
|||
export function translate(component, options = { wait: true }) {
|
||||
// Use the default list of namespaces.
|
||||
return (
|
||||
reactI18nextTranslate([ 'main', 'languages' ], options)(
|
||||
reactI18nextTranslate([ 'main', 'languages', 'countries' ], options)(
|
||||
component));
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import i18next from 'i18next';
|
||||
import I18nextXHRBackend from 'i18next-xhr-backend';
|
||||
|
||||
import COUNTRIES_RESOURCES from 'i18n-iso-countries/langs/en.json';
|
||||
import LANGUAGES_RESOURCES from '../../../../lang/languages.json';
|
||||
import MAIN_RESOURCES from '../../../../lang/main.json';
|
||||
|
||||
|
@ -51,7 +52,7 @@ const options = {
|
|||
load: 'unspecific',
|
||||
ns: {
|
||||
defaultNs: 'main',
|
||||
namespaces: [ 'main', 'languages' ]
|
||||
namespaces: [ 'main', 'languages', 'countries' ]
|
||||
},
|
||||
resGetPath: 'lang/__ns__-__lng__.json',
|
||||
useDataAttrOptions: true
|
||||
|
@ -68,6 +69,12 @@ i18next
|
|||
.init(options);
|
||||
|
||||
// Add default language which is preloaded from the source code.
|
||||
i18next.addResourceBundle(
|
||||
DEFAULT_LANGUAGE,
|
||||
'countries',
|
||||
COUNTRIES_RESOURCES,
|
||||
/* deep */ true,
|
||||
/* overwrite */ true);
|
||||
i18next.addResourceBundle(
|
||||
DEFAULT_LANGUAGE,
|
||||
'languages',
|
||||
|
|
|
@ -14,6 +14,11 @@ type Props = {
|
|||
*/
|
||||
conferenceID: number,
|
||||
|
||||
/**
|
||||
* The name of the conference.
|
||||
*/
|
||||
conferenceName: ?string,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
|
@ -33,11 +38,19 @@ class ConferenceID extends Component<Props> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { conferenceID, t } = this.props;
|
||||
const { conferenceID, conferenceName, t } = this.props;
|
||||
|
||||
return (
|
||||
<div className = 'dial-in-conference-id'>
|
||||
{ t('info.dialANumber', { conferenceID }) }
|
||||
<div className = 'dial-in-conference-name'>
|
||||
{ conferenceName }
|
||||
</div>
|
||||
<div className = 'dial-in-conference-description'>
|
||||
{ t('info.dialANumber') }
|
||||
</div>
|
||||
<div className = 'dial-in-conference-pin'>
|
||||
{ `${t('info.dialInConferenceID')} ${conferenceID}` }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -56,9 +56,9 @@ type State = {
|
|||
loading: boolean,
|
||||
|
||||
/**
|
||||
* The dial-in numbers. entered by the local participant.
|
||||
* The dial-in numbers to be displayed.
|
||||
*/
|
||||
numbers: ?Array<Object>,
|
||||
numbers: ?Array<Object> | ?Object,
|
||||
|
||||
/**
|
||||
* Whether or not dial-in is allowed.
|
||||
|
@ -143,6 +143,7 @@ class DialInSummary extends Component<Props, State> {
|
|||
conferenceID
|
||||
? <ConferenceID
|
||||
conferenceID = { conferenceID }
|
||||
conferenceName = { this.props.room }
|
||||
key = 'conferenceID' />
|
||||
: null,
|
||||
<NumbersList
|
||||
|
@ -238,17 +239,22 @@ class DialInSummary extends Component<Props, State> {
|
|||
* Callback invoked when fetching dial-in numbers succeeds. Sets the
|
||||
* internal to show the numbers.
|
||||
*
|
||||
* @param {Object} response - The response from fetching dial-in numbers.
|
||||
* @param {Array|Object} response - The response from fetching
|
||||
* dial-in numbers.
|
||||
* @param {Array|Object} response.numbers - The dial-in numbers.
|
||||
* @param {boolean} reponse.numbersEnabled - Whether or not dial-in is
|
||||
* enabled.
|
||||
* @param {boolean} response.numbersEnabled - Whether or not dial-in is
|
||||
* enabled, old syntax that is deprecated.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onGetNumbersSuccess({ numbers, numbersEnabled }) {
|
||||
_onGetNumbersSuccess(
|
||||
response: Array<Object> | { numbersEnabled?: boolean }) {
|
||||
|
||||
this.setState({
|
||||
numbersEnabled,
|
||||
numbers
|
||||
numbersEnabled:
|
||||
Array.isArray(response)
|
||||
? response.length > 0 : response.numbersEnabled,
|
||||
numbers: response
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ type Props = {
|
|||
conferenceID: number,
|
||||
|
||||
/**
|
||||
* The phone numbers to display. Can be an array of numbers or an object
|
||||
* with countries as keys and an array of numbers as values.
|
||||
* 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<string> } | Array<string>,
|
||||
numbers: { [string]: Array<string> } | Array<Object>,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
|
@ -41,92 +41,165 @@ class NumbersList extends Component<Props> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { numbers, t } = this.props;
|
||||
const { numbers } = this.props;
|
||||
|
||||
return (
|
||||
<table className = 'dial-in-numbers-list'>
|
||||
<thead>
|
||||
<tr>
|
||||
{ Array.isArray(numbers)
|
||||
? null
|
||||
: <th>{ t('info.country') }</th> }
|
||||
<th>{ t('info.numbers') }</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className = 'dial-in-numbers-body'>
|
||||
{ Array.isArray(numbers)
|
||||
? numbers.map(this._renderNumberRow)
|
||||
: this._renderWithCountries(numbers) }
|
||||
</tbody>
|
||||
</table>);
|
||||
return this._renderWithCountries(numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders rows of countries and associated phone numbers.
|
||||
*
|
||||
* @param {Object} numbersMapping - An object with country names as keys
|
||||
* and values as arrays of phone numbers.
|
||||
* @param {Object|Array<Object>} numbersMapping - An object with country
|
||||
* names as keys and values as arrays of phone numbers.
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
*/
|
||||
_renderWithCountries(numbersMapping: Object) {
|
||||
const rows = [];
|
||||
_renderWithCountries(
|
||||
numbersMapping: { numbers: Array<string> } | Array<Object>) {
|
||||
const { t } = this.props;
|
||||
let hasFlags = false, numbers;
|
||||
|
||||
for (const [ country, numbers ] of Object.entries(numbersMapping)) {
|
||||
if (!Array.isArray(numbers)) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(numbersMapping)) {
|
||||
hasFlags = true;
|
||||
numbers = numbersMapping.reduce(
|
||||
(resultNumbers, number) => {
|
||||
const countryName
|
||||
= t(`countries:countries.${number.countryCode}`);
|
||||
|
||||
const formattedNumbers = numbers.map(number => {
|
||||
if (typeof number === 'string') {
|
||||
return this._renderNumberDiv(number);
|
||||
if (resultNumbers[countryName]) {
|
||||
resultNumbers[countryName].push(number);
|
||||
} else {
|
||||
resultNumbers[countryName] = [ number ];
|
||||
}
|
||||
|
||||
return resultNumbers;
|
||||
}, {});
|
||||
} else {
|
||||
numbers = {};
|
||||
|
||||
for (const [ country, numbersArray ]
|
||||
of Object.entries(numbersMapping.numbers)) {
|
||||
|
||||
if (Array.isArray(numbersArray)) {
|
||||
/* eslint-disable arrow-body-style */
|
||||
const formattedNumbers = numbersArray.map(number => ({
|
||||
formattedNumber: number
|
||||
}));
|
||||
/* eslint-enable arrow-body-style */
|
||||
|
||||
numbers[country] = formattedNumbers;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
rows.push(
|
||||
<tr key = { country }>
|
||||
<td>{ country }</td>
|
||||
<td className = 'dial-in-numbers'>{ formattedNumbers }</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
const rows = [];
|
||||
|
||||
Object.keys(numbers).forEach((countryName: string) => {
|
||||
const numbersArray = numbers[countryName];
|
||||
|
||||
rows.push(
|
||||
<tr
|
||||
className = 'number-group'
|
||||
key = { countryName }>
|
||||
{ this._renderFlag(numbersArray[0].countryCode) }
|
||||
<td className = 'country' >{ countryName }</td>
|
||||
<td className = 'numbers-list-column'>
|
||||
{ this._renderNumbersList(numbersArray) }
|
||||
</td>
|
||||
<td className = 'toll-free-list-column' >
|
||||
{ this._renderNumbersTollFreeList(numbersArray) }
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Renders a table row for a phone number.
|
||||
*
|
||||
* @param {string} number - The phone number to display.
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
*/
|
||||
_renderNumberRow(number) {
|
||||
return (
|
||||
<tr key = { number }>
|
||||
<td className = 'dial-in-number'>
|
||||
{ this._renderNumberLink(number) }
|
||||
</td>
|
||||
</tr>
|
||||
<table className = 'dial-in-numbers-list'>
|
||||
<thead>
|
||||
<tr>
|
||||
{ hasFlags ? <th /> : null}
|
||||
<th>{ t('info.country') }</th>
|
||||
<th>{ t('info.numbers') }</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className = 'dial-in-numbers-body'>
|
||||
{ rows }
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a div container for a phone number.
|
||||
*
|
||||
* @param {string} number - The phone number to display.
|
||||
* @param {string} countryCode - The phone number to display.
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderFlag(countryCode) {
|
||||
const OFFSET = 127397;
|
||||
|
||||
if (countryCode) {
|
||||
// ensure country code is all caps
|
||||
const cc = countryCode.toUpperCase();
|
||||
|
||||
// return the emoji flag corresponding to country_code or null
|
||||
const countryFlag = /^[A-Z]{2}$/.test(cc)
|
||||
? String.fromCodePoint(...[ ...cc ]
|
||||
.map(c => c.charCodeAt() + OFFSET))
|
||||
: null;
|
||||
|
||||
return <td className = 'flag'>{ countryFlag }</td>;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a div container for a phone number.
|
||||
*
|
||||
* @param {Array} numbers - The phone number to display.
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
*/
|
||||
_renderNumberDiv(number) {
|
||||
return (
|
||||
<div
|
||||
_renderNumbersList(numbers) {
|
||||
const numbersListItems = numbers.map(number =>
|
||||
(<li
|
||||
className = 'dial-in-number'
|
||||
key = { number }>
|
||||
{ this._renderNumberLink(number) }
|
||||
</div>
|
||||
key = { number.formattedNumber }>
|
||||
{ this._renderNumberLink(number.formattedNumber) }
|
||||
</li>));
|
||||
|
||||
return (
|
||||
<ul className = 'numbers-list'>
|
||||
{ numbersListItems }
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders list with a toll free text on the position where there is a
|
||||
* number marked as toll free.
|
||||
*
|
||||
* @param {Array} numbers - The phone number that are displayed.
|
||||
* @private
|
||||
* @returns {ReactElement[]}
|
||||
*/
|
||||
_renderNumbersTollFreeList(numbers) {
|
||||
const { t } = this.props;
|
||||
|
||||
const tollNumbersListItems = numbers.map(number =>
|
||||
(<li
|
||||
className = 'toll-free'
|
||||
key = { number.formattedNumber }>
|
||||
{ number.tollFree ? t('info.dialInTollFree') : '' }
|
||||
</li>));
|
||||
|
||||
return (
|
||||
<ul className = 'toll-free-list'>
|
||||
{ tollNumbersListItems }
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -141,9 +214,12 @@ class NumbersList extends Component<Props> {
|
|||
*/
|
||||
_renderNumberLink(number) {
|
||||
if (this.props.clickableNumbers) {
|
||||
// Url encode # to %23, Android phone was cutting the # after
|
||||
// clicking it.
|
||||
// Seems that using ',' and '%23' works on iOS and Android.
|
||||
return (
|
||||
<a
|
||||
href = { `tel:${number}p${this.props.conferenceID}#` }
|
||||
href = { `tel:${number},${this.props.conferenceID}%23` }
|
||||
key = { number } >
|
||||
{ number }
|
||||
</a>
|
||||
|
|
|
@ -121,9 +121,7 @@ class InfoDialog extends Component<Props, State> {
|
|||
let phoneNumber = state.phoneNumber;
|
||||
|
||||
if (!state.phoneNumber && props.dialIn.numbers) {
|
||||
const { defaultCountry, numbers } = props.dialIn;
|
||||
|
||||
phoneNumber = _getDefaultPhoneNumber(numbers, defaultCountry);
|
||||
phoneNumber = _getDefaultPhoneNumber(props.dialIn);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -157,11 +155,9 @@ class InfoDialog extends Component<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
const { defaultCountry, numbers } = props.dialIn;
|
||||
|
||||
if (numbers) {
|
||||
if (props.dialIn && props.dialIn.numbers) {
|
||||
this.state.phoneNumber
|
||||
= _getDefaultPhoneNumber(numbers, defaultCountry);
|
||||
= _getDefaultPhoneNumber(props.dialIn.numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,13 +54,14 @@ export function getDialInConferenceID(
|
|||
/**
|
||||
* Sends a GET request for phone numbers used to dial into a conference.
|
||||
*
|
||||
* @param {string} url - The service that returns confernce dial-in numbers.
|
||||
* @param {string} url - The service that returns conference dial-in numbers.
|
||||
* @param {string} roomName - The conference name to find the associated
|
||||
* conference ID.
|
||||
* @param {string} mucURL - In which MUC the conference exists.
|
||||
* @returns {Promise} - The promise created by the request. The returned numbers
|
||||
* may be an array of numbers or an object with countries as keys and arrays of
|
||||
* phone number strings.
|
||||
* may be an array of Objects containing numbers, with keys countryCode,
|
||||
* tollFree, formattedNumber or an object with countries as keys and arrays of
|
||||
* phone number strings, as the second one should not be used and is deprecated.
|
||||
*/
|
||||
export function getDialInNumbers(
|
||||
url: string,
|
||||
|
@ -432,7 +433,7 @@ export function getShareInfoText(
|
|||
numbersPromise = Promise.all([
|
||||
getDialInNumbers(dialInNumbersUrl, room, mucURL),
|
||||
getDialInConferenceID(dialInConfCodeUrl, room, mucURL)
|
||||
]).then(([ { defaultCountry, numbers }, {
|
||||
]).then(([ numbers, {
|
||||
conference, id, message } ]) => {
|
||||
|
||||
if (!conference || !id) {
|
||||
|
@ -440,7 +441,6 @@ export function getShareInfoText(
|
|||
}
|
||||
|
||||
return {
|
||||
defaultCountry,
|
||||
numbers,
|
||||
conferenceID: id
|
||||
};
|
||||
|
@ -448,9 +448,8 @@ export function getShareInfoText(
|
|||
}
|
||||
|
||||
return numbersPromise.then(
|
||||
({ conferenceID, defaultCountry, numbers }) => {
|
||||
const phoneNumber
|
||||
= _getDefaultPhoneNumber(numbers, defaultCountry) || '';
|
||||
({ conferenceID, numbers }) => {
|
||||
const phoneNumber = _getDefaultPhoneNumber(numbers) || '';
|
||||
|
||||
return `${
|
||||
i18next.t('info.dialInNumber')} ${
|
||||
|
@ -513,27 +512,47 @@ export function getDialInfoPageURL(
|
|||
*
|
||||
* @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'): ?string {
|
||||
dialInNumbers: Object): ?string {
|
||||
const defValueForDefaultCountry = '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];
|
||||
// new syntax follows
|
||||
// find the default country inside dialInNumbers, US one
|
||||
// or return the first one
|
||||
let defaultNumber = dialInNumbers.find(number => number.default);
|
||||
|
||||
if (!defaultNumber) {
|
||||
defaultNumber = dialInNumbers.find(({ countryCode }) =>
|
||||
countryCode === defValueForDefaultCountry);
|
||||
}
|
||||
|
||||
if (defaultNumber) {
|
||||
return defaultNumber.formattedNumber;
|
||||
}
|
||||
|
||||
return dialInNumbers.length > 0
|
||||
? dialInNumbers[0].formattedNumber : null;
|
||||
}
|
||||
|
||||
const {
|
||||
defaultCountry = defValueForDefaultCountry,
|
||||
numbers } = dialInNumbers;
|
||||
|
||||
if (numbers && Object.keys(numbers).length > 0) {
|
||||
// deprecated and will be removed
|
||||
const defaultNumbers = numbers[defaultCountry];
|
||||
|
||||
if (defaultNumbers) {
|
||||
return defaultNumbers[0];
|
||||
}
|
||||
|
||||
const firstRegion = Object.keys(dialInNumbers)[0];
|
||||
const firstRegion = Object.keys(numbers)[0];
|
||||
|
||||
return firstRegion && firstRegion[0];
|
||||
return firstRegion && numbers[firstRegion][0];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -10,6 +10,8 @@ import {
|
|||
UPDATE_DIAL_IN_NUMBERS_SUCCESS
|
||||
} from './actionTypes';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
/**
|
||||
* The indicator which determines whether (the) {@code CalleeInfo} is
|
||||
|
@ -54,17 +56,24 @@ ReducerRegistry.register('features/invite', (state = DEFAULT_STATE, action) => {
|
|||
};
|
||||
|
||||
case UPDATE_DIAL_IN_NUMBERS_SUCCESS: {
|
||||
const {
|
||||
defaultCountry,
|
||||
numbers,
|
||||
numbersEnabled
|
||||
} = action.dialInNumbers;
|
||||
if (Array.isArray(action.dialInNumbers)) {
|
||||
return {
|
||||
...state,
|
||||
conferenceID: action.conferenceID,
|
||||
numbers: action.dialInNumbers,
|
||||
numbersEnabled: true
|
||||
};
|
||||
}
|
||||
|
||||
// this is the old format which is deprecated
|
||||
logger.warn('Using deprecated API for retrieving phone numbers');
|
||||
|
||||
const { numbersEnabled } = action.dialInNumbers;
|
||||
|
||||
return {
|
||||
...state,
|
||||
conferenceID: action.conferenceID,
|
||||
defaultCountry,
|
||||
numbers,
|
||||
numbers: action.dialInNumbers,
|
||||
numbersEnabled
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue