Преглед изворни кода

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.
master
Дамян Минков пре 7 година
родитељ
комит
7674e90d4d
No account linked to committer's email address

+ 1
- 1
lang/main.json Прегледај датотеку

@@ -430,7 +430,7 @@
430 430
     "share":
431 431
     {
432 432
         "mainText": "Click the following link to join the meeting:\n__roomUrl__",
433
-        "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__"
433
+        "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__"
434 434
     },
435 435
     "connection":
436 436
     {

+ 26
- 27
react/features/calendar-sync/web/microsoftCalendar.js Прегледај датотеку

@@ -329,36 +329,35 @@ export const microsoftCalendarApi = {
329 329
                 return Promise.reject('Not authorized, please sign in!');
330 330
             }
331 331
 
332
-            const { dialInNumbersUrl } = getState()['features/base/config'];
333
-            const text = getShareInfoText(
334
-                location, dialInNumbersUrl !== undefined, true/* use html */);
335
-
336
-
337
-            const client = Client.init({
338
-                authProvider: done => done(null, token)
339
-            });
340
-
341
-            return client
342
-                .api(`/me/events/${id}`)
343
-                .get()
344
-                .then(description => {
345
-                    const body = description.body;
346
-
347
-                    if (description.bodyPreview) {
348
-                        body.content = `${description.bodyPreview}<br><br>`;
349
-                    }
350
-
351
-                    // replace all new lines from the text with html <br>
352
-                    // to make it pretty
353
-                    body.content += text.split('\n').join('<br>');
332
+            return getShareInfoText(getState(), location, true/* use html */)
333
+                .then(text => {
334
+                    const client = Client.init({
335
+                        authProvider: done => done(null, token)
336
+                    });
354 337
 
355 338
                     return client
356
-                        .api(`/me/calendar/events/${id}`)
357
-                        .patch({
358
-                            body,
359
-                            location: {
360
-                                'displayName': location
339
+                        .api(`/me/events/${id}`)
340
+                        .get()
341
+                        .then(description => {
342
+                            const body = description.body;
343
+
344
+                            if (description.bodyPreview) {
345
+                                body.content
346
+                                    = `${description.bodyPreview}<br><br>`;
361 347
                             }
348
+
349
+                            // replace all new lines from the text with html
350
+                            // <br> to make it pretty
351
+                            body.content += text.split('\n').join('<br>');
352
+
353
+                            return client
354
+                                .api(`/me/calendar/events/${id}`)
355
+                                .patch({
356
+                                    body,
357
+                                    location: {
358
+                                        'displayName': location
359
+                                    }
360
+                                });
362 361
                         });
363 362
                 });
364 363
         };

+ 3
- 8
react/features/google-api/actions.js Прегледај датотеку

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

+ 2
- 3
react/features/invite/components/dial-in-info-page/DialInInfoApp.web.js Прегледај датотеку

@@ -10,8 +10,7 @@ import { DialInSummary } from '../dial-in-summary';
10 10
 import NoRoomError from './NoRoomError';
11 11
 
12 12
 document.addEventListener('DOMContentLoaded', () => {
13
-    const params = parseURLParams(window.location, true, 'search');
14
-    const { room } = params;
13
+    const { room } = parseURLParams(window.location, true, 'search');
15 14
 
16 15
     ReactDOM.render(
17 16
         <I18nextProvider i18n = { i18next }>
@@ -19,7 +18,7 @@ document.addEventListener('DOMContentLoaded', () => {
19 18
                 ? <DialInSummary
20 19
                     className = 'dial-in-page'
21 20
                     clickableNumbers = { false }
22
-                    room = { params.room } />
21
+                    room = { room } />
23 22
                 : <NoRoomError className = 'dial-in-page' /> }
24 23
         </I18nextProvider>,
25 24
         document.getElementById('react')

+ 12
- 34
react/features/invite/components/info-dialog/InfoDialog.web.js Прегледај датотеку

@@ -7,7 +7,7 @@ import { getInviteURL } from '../../../base/connection';
7 7
 import { translate } from '../../../base/i18n';
8 8
 import { isLocalParticipantModerator } from '../../../base/participants';
9 9
 
10
-import { getDialInfoPageURL } from '../../functions';
10
+import { _getDefaultPhoneNumber, getDialInfoPageURL } from '../../functions';
11 11
 import DialInNumber from './DialInNumber';
12 12
 import PasswordForm from './PasswordForm';
13 13
 
@@ -49,6 +49,11 @@ class InfoDialog extends Component {
49 49
          */
50 50
         _inviteURL: PropTypes.string,
51 51
 
52
+        /**
53
+         * The current location url of the conference.
54
+         */
55
+        _locationURL: PropTypes.object,
56
+
52 57
         /**
53 58
          * The value for how the conference is locked (or undefined if not
54 59
          * locked) as defined by room-lock constants.
@@ -118,7 +123,7 @@ class InfoDialog extends Component {
118 123
 
119 124
         if (numbers) {
120 125
             this.state.phoneNumber
121
-                = this._getDefaultPhoneNumber(numbers, defaultCountry);
126
+                = _getDefaultPhoneNumber(numbers, defaultCountry);
122 127
         }
123 128
 
124 129
         /**
@@ -157,8 +162,7 @@ class InfoDialog extends Component {
157 162
             const { defaultCountry, numbers } = nextProps.dialIn;
158 163
 
159 164
             this.setState({
160
-                phoneNumber:
161
-                    this._getDefaultPhoneNumber(numbers, defaultCountry)
165
+                phoneNumber: _getDefaultPhoneNumber(numbers, defaultCountry)
162 166
             });
163 167
         }
164 168
     }
@@ -231,35 +235,6 @@ class InfoDialog extends Component {
231 235
         );
232 236
     }
233 237
 
234
-    /**
235
-     * Sets the internal state of which dial-in number to display.
236
-     *
237
-     * @param {Array<string>|Object} dialInNumbers - The array or object of
238
-     * numbers to choose a number from.
239
-     * @param {string} defaultCountry - The country code for the country
240
-     * whose phone number should display.
241
-     * @private
242
-     * @returns {string|null}
243
-     */
244
-    _getDefaultPhoneNumber(dialInNumbers, defaultCountry = 'US') {
245
-        if (Array.isArray(dialInNumbers)) {
246
-            // Dumbly return the first number if an array.
247
-            return dialInNumbers[0];
248
-        } else if (Object.keys(dialInNumbers).length > 0) {
249
-            const defaultNumbers = dialInNumbers[defaultCountry];
250
-
251
-            if (defaultNumbers) {
252
-                return defaultNumbers[0];
253
-            }
254
-
255
-            const firstRegion = Object.keys(dialInNumbers)[0];
256
-
257
-            return firstRegion && firstRegion[0];
258
-        }
259
-
260
-        return null;
261
-    }
262
-
263 238
     /**
264 239
      * Generates the URL for the static dial in info page.
265 240
      *
@@ -268,7 +243,8 @@ class InfoDialog extends Component {
268 243
      */
269 244
     _getDialInfoPageURL() {
270 245
         return getDialInfoPageURL(
271
-            encodeURIComponent(this.props._conferenceName));
246
+            encodeURIComponent(this.props._conferenceName),
247
+            this.props._locationURL);
272 248
     }
273 249
 
274 250
     /**
@@ -525,6 +501,7 @@ class InfoDialog extends Component {
525 501
  *     _conference: Object,
526 502
  *     _conferenceName: string,
527 503
  *     _inviteURL: string,
504
+ *     _locationURL: string,
528 505
  *     _locked: string,
529 506
  *     _password: string
530 507
  * }}
@@ -542,6 +519,7 @@ function _mapStateToProps(state) {
542 519
         _conference: conference,
543 520
         _conferenceName: room,
544 521
         _inviteURL: getInviteURL(state),
522
+        _locationURL: state['features/base/connection'].locationURL,
545 523
         _locked: locked,
546 524
         _password: password
547 525
     };

+ 107
- 14
react/features/invite/functions.js Прегледај датотеку

@@ -403,15 +403,16 @@ export function searchDirectory( // eslint-disable-line max-params
403 403
  * Returns descriptive text that can be used to invite participants to a meeting
404 404
  * (share via mobile or use it for calendar event description).
405 405
  *
406
+ * @param {Object} state - The current state.
406 407
  * @param {string} inviteUrl - The conference/location URL.
407
- * @param {boolean} includeDialInfo - Whether to include or not the dialing
408
- * information link.
409 408
  * @param {boolean} useHtml - Whether to return html text.
410
- * @returns {string}
409
+ * @returns {Promise<string>} A {@code Promise} resolving with a
410
+ * descriptive text that can be used to invite participants to a meeting.
411 411
  */
412 412
 export function getShareInfoText(
413
-        inviteUrl: string, includeDialInfo: boolean, useHtml: ?boolean) {
413
+        state: Object, inviteUrl: string, useHtml: ?boolean): Promise<string> {
414 414
     let roomUrl = inviteUrl;
415
+    const includeDialInfo = state['features/base/config'] !== undefined;
415 416
 
416 417
     if (useHtml) {
417 418
         roomUrl = `<a href="${roomUrl}">${roomUrl}</a>`;
@@ -421,29 +422,90 @@ export function getShareInfoText(
421 422
 
422 423
     if (includeDialInfo) {
423 424
         const { room } = parseURIString(inviteUrl);
424
-        let dialInfoPageUrl = getDialInfoPageURL(room);
425
+        let numbersPromise;
426
+
427
+        if (state['features/invite'].numbers
428
+            && state['features/invite'].conferenceID) {
429
+            numbersPromise = Promise.resolve(state['features/invite']);
430
+        } else {
431
+            // we are requesting numbers and conferenceId directly
432
+            // not using updateDialInNumbers, because custom room
433
+            // is specified and we do not want to store the data
434
+            // in the state
435
+            const { dialInConfCodeUrl, dialInNumbersUrl, hosts }
436
+                = state['features/base/config'];
437
+            const mucURL = hosts && hosts.muc;
438
+
439
+            if (!dialInConfCodeUrl || !dialInNumbersUrl || !mucURL) {
440
+                // URLs for fetching dial in numbers not defined
441
+                return Promise.reject();
442
+            }
443
+
444
+            numbersPromise = Promise.all([
445
+                getDialInNumbers(dialInNumbersUrl),
446
+                getDialInConferenceID(dialInConfCodeUrl, room, mucURL)
447
+            ]).then(([ { defaultCountry, numbers }, {
448
+                conference, id, message } ]) => {
425 449
 
426
-        if (useHtml) {
427
-            dialInfoPageUrl
428
-                = `<a href="${dialInfoPageUrl}">${dialInfoPageUrl}</a>`;
450
+                if (!conference || !id) {
451
+                    return Promise.reject(message);
452
+                }
453
+
454
+                return {
455
+                    defaultCountry,
456
+                    numbers,
457
+                    conferenceID: id
458
+                };
459
+            });
429 460
         }
430 461
 
431
-        infoText += i18next.t('share.dialInfoText', { dialInfoPageUrl });
462
+        return numbersPromise.then(
463
+            ({ conferenceID, defaultCountry, numbers }) => {
464
+                const phoneNumber
465
+                    = _getDefaultPhoneNumber(numbers, defaultCountry) || '';
466
+
467
+                return `${
468
+                    i18next.t('info.dialInNumber')} ${
469
+                    phoneNumber} ${
470
+                    i18next.t('info.dialInConferenceID')} ${
471
+                    conferenceID}#\n\n`;
472
+            })
473
+            .catch(error =>
474
+                logger.error('Error fetching numbers or conferenceID', error))
475
+            .then(defaultDialInNumber => {
476
+                let dialInfoPageUrl = getDialInfoPageURL(
477
+                    room,
478
+                    state['features/base/connection'].locationURL);
479
+
480
+                if (useHtml) {
481
+                    dialInfoPageUrl
482
+                        = `<a href="${dialInfoPageUrl}">${dialInfoPageUrl}</a>`;
483
+                }
484
+
485
+                infoText += i18next.t('share.dialInfoText', {
486
+                    defaultDialInNumber,
487
+                    dialInfoPageUrl });
488
+
489
+                return infoText;
490
+            });
432 491
     }
433 492
 
434
-    return infoText;
493
+    return Promise.resolve(infoText);
435 494
 }
436 495
 
437 496
 /**
438 497
  * Generates the URL for the static dial in info page.
439 498
  *
440 499
  * @param {string} conferenceName - The conference name.
441
- * @private
500
+ * @param {Object} locationURL - The current location URL, the object coming
501
+ * from state ['features/base/connection'].locationURL.
442 502
  * @returns {string}
443 503
  */
444
-export function getDialInfoPageURL(conferenceName: string) {
445
-    const origin = window.location.origin;
446
-    const pathParts = window.location.pathname.split('/');
504
+export function getDialInfoPageURL(
505
+        conferenceName: string,
506
+        locationURL: Object) {
507
+    const origin = locationURL.origin;
508
+    const pathParts = locationURL.pathname.split('/');
447 509
 
448 510
     pathParts.length = pathParts.length - 1;
449 511
 
@@ -457,3 +519,34 @@ export function getDialInfoPageURL(conferenceName: string) {
457 519
 
458 520
     return `${origin}${newPath}/static/dialInInfo.html?room=${conferenceName}`;
459 521
 }
522
+
523
+/**
524
+ * Sets the internal state of which dial-in number to display.
525
+ *
526
+ * @param {Array<string>|Object} dialInNumbers - The array or object of
527
+ * numbers to choose a number from.
528
+ * @param {string} defaultCountry - The country code for the country
529
+ * whose phone number should display.
530
+ * @private
531
+ * @returns {string|null}
532
+ */
533
+export function _getDefaultPhoneNumber(
534
+        dialInNumbers: Object,
535
+        defaultCountry: string = 'US') {
536
+    if (Array.isArray(dialInNumbers)) {
537
+        // Dumbly return the first number if an array.
538
+        return dialInNumbers[0];
539
+    } else if (Object.keys(dialInNumbers).length > 0) {
540
+        const defaultNumbers = dialInNumbers[defaultCountry];
541
+
542
+        if (defaultNumbers) {
543
+            return defaultNumbers[0];
544
+        }
545
+
546
+        const firstRegion = Object.keys(dialInNumbers)[0];
547
+
548
+        return firstRegion && firstRegion[0];
549
+    }
550
+
551
+    return null;
552
+}

+ 1
- 3
react/features/share-room/actions.js Прегледај датотеку

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

+ 28
- 29
react/features/share-room/middleware.js Прегледај датотеку

@@ -21,7 +21,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
21 21
 MiddlewareRegistry.register(store => next => action => {
22 22
     switch (action.type) {
23 23
     case BEGIN_SHARE_ROOM:
24
-        _shareRoom(action.roomURL, action.includeDialInfo, store.dispatch);
24
+        _shareRoom(action.roomURL, store);
25 25
         break;
26 26
     }
27 27
 
@@ -32,36 +32,35 @@ MiddlewareRegistry.register(store => next => action => {
32 32
  * Open the native sheet for sharing a specific conference/room URL.
33 33
  *
34 34
  * @param {string} roomURL - The URL of the conference/room to be shared.
35
- * @param {boolean} includeDialInfo - Whether to include or not the dialing
36
- * information link.
37
- * @param {Dispatch} dispatch - The Redux dispatch function.
35
+ * @param {Store} store - Redux store.
38 36
  * @private
39 37
  * @returns {void}
40 38
  */
41
-function _shareRoom(
42
-        roomURL: string, includeDialInfo: boolean, dispatch: Function) {
43
-    const message = getShareInfoText(roomURL, includeDialInfo);
44
-    const title = `${getName()} Conference`;
45
-    const onFulfilled
46
-        = (shared: boolean) => dispatch(endShareRoom(roomURL, shared));
39
+function _shareRoom(roomURL: string, { dispatch, getState }) {
40
+    getShareInfoText(getState(), roomURL)
41
+        .then(message => {
42
+            const title = `${getName()} Conference`;
43
+            const onFulfilled
44
+                = (shared: boolean) => dispatch(endShareRoom(roomURL, shared));
47 45
 
48
-    Share.share(
49
-        /* content */ {
50
-            message,
51
-            title
52
-        },
53
-        /* options */ {
54
-            dialogTitle: title, // Android
55
-            subject: title // iOS
56
-        })
57
-        .then(
58
-            /* onFulfilled */ value => {
59
-                onFulfilled(value.action === Share.sharedAction);
60
-            },
61
-            /* onRejected */ reason => {
62
-                logger.error(
63
-                    `Failed to share conference/room URL ${roomURL}:`,
64
-                    reason);
65
-                onFulfilled(false);
66
-            });
46
+            Share.share(
47
+                /* content */ {
48
+                    message,
49
+                    title
50
+                },
51
+                /* options */ {
52
+                    dialogTitle: title, // Android
53
+                    subject: title // iOS
54
+                })
55
+                .then(
56
+                    /* onFulfilled */ value => {
57
+                        onFulfilled(value.action === Share.sharedAction);
58
+                    },
59
+                    /* onRejected */ reason => {
60
+                        logger.error(
61
+                            `Failed to share conference/room URL ${roomURL}:`,
62
+                            reason);
63
+                        onFulfilled(false);
64
+                    });
65
+        });
67 66
 }

Loading…
Откажи
Сачувај