瀏覽代碼

[RN] Converge with Web's ExternalAPI a bit

Web's ExternalAPI accepts an object with properties as one of its
constructor arguments and from which it generated a URL. Mobile's
JitsiMeetView.loadURLObject is supposed to accept pretty much the same
object.
j8
Lyubo Marinov 7 年之前
父節點
當前提交
e542af28a2

+ 8
- 54
modules/API/external/external_api.js 查看文件

@@ -1,5 +1,6 @@
1 1
 import EventEmitter from 'events';
2 2
 
3
+import { urlObjectToString } from '../../../react/features/base/util';
3 4
 import {
4 5
     PostMessageTransportBackend,
5 6
     Transport
@@ -58,28 +59,6 @@ function changeParticipantNumber(APIInstance, number) {
58 59
     APIInstance._numberOfParticipants += number;
59 60
 }
60 61
 
61
-/**
62
- * Generates array with URL params based on the passed config object that will
63
- * be used for the Jitsi Meet URL generation.
64
- *
65
- * @param {Object} config - The config object.
66
- * @returns {Array<string>} The array with URL param strings.
67
- */
68
-function configToURLParamsArray(config = {}) {
69
-    const params = [];
70
-
71
-    for (const key in config) { // eslint-disable-line guard-for-in
72
-        try {
73
-            params.push(
74
-                `${key}=${encodeURIComponent(JSON.stringify(config[key]))}`);
75
-        } catch (e) {
76
-            console.warn(`Error encoding ${key}: ${e}`);
77
-        }
78
-    }
79
-
80
-    return params;
81
-}
82
-
83 62
 /**
84 63
  * Generates the URL for the iframe.
85 64
  *
@@ -92,42 +71,17 @@ function configToURLParamsArray(config = {}) {
92 71
  * configuration options defined in interface_config.js to be overridden.
93 72
  * @param {string} [options.jwt] - The JWT token if needed by jitsi-meet for
94 73
  * authentication.
95
- * @param {boolean} [options.noSsl] - If the value is true https won't be used.
74
+ * @param {boolean} [options.noSSL] - If the value is true https won't be used.
96 75
  * @param {string} [options.roomName] - The name of the room to join.
97 76
  * @returns {string} The URL.
98 77
  */
99 78
 function generateURL(domain, options = {}) {
100
-    const {
101
-        configOverwrite,
102
-        interfaceConfigOverwrite,
103
-        jwt,
104
-        noSSL,
105
-        roomName
106
-    } = options;
107
-
108
-    let url = `${noSSL ? 'http' : 'https'}://${domain}/${roomName || ''}`;
109
-
110
-    if (jwt) {
111
-        url += `?jwt=${jwt}`;
112
-    }
113
-
114
-    url += `#jitsi_meet_external_api_id=${id}`;
115
-
116
-    const configURLParams = configToURLParamsArray(configOverwrite);
117
-
118
-    if (configURLParams.length) {
119
-        url += `&config.${configURLParams.join('&config.')}`;
120
-    }
121
-
122
-    const interfaceConfigURLParams
123
-        = configToURLParamsArray(interfaceConfigOverwrite);
124
-
125
-    if (interfaceConfigURLParams.length) {
126
-        url += `&interfaceConfig.${
127
-            interfaceConfigURLParams.join('&interfaceConfig.')}`;
128
-    }
129
-
130
-    return url;
79
+    return urlObjectToString({
80
+        ...options,
81
+        url:
82
+            `${options.noSSL ? 'http' : 'https'}://${domain
83
+                }/#jitsi_meet_external_api_id=${id}`
84
+    });
131 85
 }
132 86
 
133 87
 /**

+ 5
- 15
react/features/app/actions.js 查看文件

@@ -90,17 +90,7 @@ function _appNavigateToMandatoryLocation(
90 90
      * @returns {void}
91 91
      */
92 92
     function dispatchSetLocationURL() {
93
-        dispatch(
94
-            setLocationURL(
95
-                new URL(
96
-                    (newLocation.protocol || 'https:')
97
-
98
-                        // TODO userinfo
99
-
100
-                        + newLocation.host
101
-                        + (newLocation.pathname || '/')
102
-                        + newLocation.search
103
-                        + newLocation.hash)));
93
+        dispatch(setLocationURL(new URL(newLocation.toString())));
104 94
     }
105 95
 
106 96
     /**
@@ -147,9 +137,7 @@ function _appNavigateToOptionalLocation(
147 137
         }
148 138
     }
149 139
 
150
-    if (!location.protocol) {
151
-        location.protocol = 'https:';
152
-    }
140
+    location.protocol || (location.protocol = 'https:');
153 141
 
154 142
     _appNavigateToMandatoryLocation(dispatch, getState, location);
155 143
 }
@@ -213,5 +201,7 @@ function _loadConfig(location: Object) {
213 201
 
214 202
     // TDOO userinfo
215 203
 
216
-    return loadConfig(protocol + location.host + (location.contextRoot || '/'));
204
+    return (
205
+        loadConfig(
206
+            `${protocol}//${location.host}${location.contextRoot || '/'}`));
217 207
 }

+ 6
- 5
react/features/base/config/parseURLParams.js 查看文件

@@ -1,13 +1,14 @@
1 1
 /* @flow */
2 2
 
3 3
 /**
4
- * Parses the parameters from the URL and returns them as a JS object.
4
+ * Parses the query/search or fragment/hash parameters out of a specific URL and
5
+ * returns them as a JS object.
5 6
  *
6 7
  * @param {string} url - The URL to parse.
7
- * @param {boolean} dontParse - If false or undefined some transformations
8
- * (for parsing the value as JSON) are going to be executed.
9
- * @param {string} source - Values - "hash"/"search" if "search" the parameters
10
- * will parsed from location.search otherwise from location.hash.
8
+ * @param {boolean} dontParse - If falsy, some transformations (for parsing the
9
+ * value as JSON) will be executed.
10
+ * @param {string} source - If {@code 'search'}, the parameters will parsed out
11
+ * of {@code url.search}; otherwise, out of {@code url.hash}.
11 12
  * @returns {Object}
12 13
  */
13 14
 export default function parseURLParams(

+ 152
- 13
react/features/base/util/uri.js 查看文件

@@ -1,5 +1,3 @@
1
-/* @flow */
2
-
3 1
 /**
4 2
  * The {@link RegExp} pattern of the authority of a URI.
5 3
  *
@@ -127,6 +125,30 @@ export function getLocationContextRoot(location: Object) {
127 125
             : pathname.substring(0, contextRootEndIndex + 1));
128 126
 }
129 127
 
128
+/**
129
+ * Constructs a new {@code Array} with URL parameter {@code String}s out of a
130
+ * specific {@code Object}.
131
+ *
132
+ * @param {Object} obj - The {@code Object} to turn into URL parameter
133
+ * {@code String}s.
134
+ * @returns {Array<string>} The {@code Array} with URL parameter {@code String}s
135
+ * constructed out of the specified {@code obj}.
136
+ */
137
+function _objectToURLParamsArray(obj = {}) {
138
+    const params = [];
139
+
140
+    for (const key in obj) { // eslint-disable-line guard-for-in
141
+        try {
142
+            params.push(
143
+                `${key}=${encodeURIComponent(JSON.stringify(obj[key]))}`);
144
+        } catch (e) {
145
+            console.warn(`Error encoding ${key}: ${e}`);
146
+        }
147
+    }
148
+
149
+    return params;
150
+}
151
+
130 152
 /**
131 153
  * Parses a specific URI string into an object with the well-known properties of
132 154
  * the {@link Location} and/or {@link URL} interfaces implemented by Web
@@ -147,7 +169,9 @@ export function getLocationContextRoot(location: Object) {
147 169
 export function parseStandardURIString(str: string) {
148 170
     /* eslint-disable no-param-reassign */
149 171
 
150
-    const obj = {};
172
+    const obj = {
173
+        toString: _standardURIToString
174
+    };
151 175
 
152 176
     let regex;
153 177
     let match;
@@ -200,9 +224,7 @@ export function parseStandardURIString(str: string) {
200 224
         str = str.substring(regex.lastIndex);
201 225
     }
202 226
     if (pathname) {
203
-        if (!pathname.startsWith('/')) {
204
-            pathname = `/${pathname}`;
205
-        }
227
+        pathname.startsWith('/') || (pathname = `/${pathname}`);
206 228
     } else {
207 229
         pathname = '/';
208 230
     }
@@ -263,6 +285,32 @@ export function parseURIString(uri: ?string) {
263 285
     return obj;
264 286
 }
265 287
 
288
+/**
289
+ * Implements {@code href} and {@code toString} for the {@code Object} returned
290
+ * by {@link #parseStandardURIString}.
291
+ *
292
+ * @param {Object} [thiz] - An {@code Object} returned by
293
+ * {@code #parseStandardURIString} if any; otherwise, it is presumed that the
294
+ * function is invoked on such an instance.
295
+ * @returns {string}
296
+ */
297
+function _standardURIToString(thiz: ?Object) {
298
+    // eslint-disable-next-line no-invalid-this
299
+    const { hash, host, pathname, protocol, search } = thiz || this;
300
+    let str = '';
301
+
302
+    protocol && (str += protocol);
303
+
304
+    // TODO userinfo
305
+
306
+    host && (str += `//${host}`);
307
+    str += pathname || '/';
308
+    search && (str += search);
309
+    hash && (str += hash);
310
+
311
+    return str;
312
+}
313
+
266 314
 /**
267 315
  * Attempts to return a {@code String} representation of a specific
268 316
  * {@code Object} which is supposed to represent a URL. Obviously, if a
@@ -285,7 +333,7 @@ export function toURLString(obj: ?(string | Object)): ?string {
285 333
             if (obj instanceof URL) {
286 334
                 str = obj.href;
287 335
             } else {
288
-                str = _urlObjectToString(obj);
336
+                str = urlObjectToString(obj);
289 337
             }
290 338
         }
291 339
         break;
@@ -303,12 +351,103 @@ export function toURLString(obj: ?(string | Object)): ?string {
303 351
  * {@code Object} similar to the one accepted by the constructor
304 352
  * of Web's ExternalAPI.
305 353
  *
306
- * @param {Object} obj - The URL to return a {@code String} representation of.
354
+ * @param {Object} o - The URL to return a {@code String} representation of.
307 355
  * @returns {string} - A {@code String} representation of the specified
308
- * {@code obj}.
356
+ * {@code Object}.
309 357
  */
310
-function _urlObjectToString({ url }: Object): ?string {
311
-    // TODO Support properties other than url. Support (pretty much) all
312
-    // properties accepted by the constructor of Web's ExternalAPI.
313
-    return url;
358
+export function urlObjectToString(o: Object): ?string {
359
+    const url = parseStandardURIString(o.url || '');
360
+
361
+    // protocol
362
+    if (!url.protocol) {
363
+        let protocol = o.protocol || o.scheme;
364
+
365
+        if (protocol) {
366
+            // Protocol is supposed to be the scheme and the final ':'. Anyway,
367
+            // do not make a fuss if the final ':' is not there.
368
+            protocol.endsWith(':') || (protocol += ':');
369
+            url.protocol = protocol;
370
+        }
371
+    }
372
+
373
+    // authority & pathname
374
+    let { pathname } = url;
375
+
376
+    if (!url.host) {
377
+        // Web's ExternalAPI domain
378
+        //
379
+        // It may be host/hostname and pathname with the latter denoting the
380
+        // tenant.
381
+        const { host, hostname, pathname: contextRoot, port }
382
+            = parseStandardURIString(o.domain || o.host || o.hostname);
383
+
384
+        // authority
385
+        if (host) {
386
+            url.host = host;
387
+            url.hostname = hostname;
388
+            url.port = port;
389
+        }
390
+
391
+        // pathname
392
+        pathname === '/' && contextRoot !== '/' && (pathname = contextRoot);
393
+    }
394
+
395
+    // pathname
396
+
397
+    // Web's ExternalAPI roomName
398
+    const room = o.roomName || o.room;
399
+
400
+    if (room
401
+            && (url.pathname.endsWith('/')
402
+                || !url.pathname.endsWith(`/${room}`))) {
403
+        pathname.endsWith('/') || (pathname += '/');
404
+        pathname += room;
405
+    }
406
+
407
+    url.pathname = pathname;
408
+
409
+    // query/search
410
+
411
+    // Web's ExternalAPI jwt
412
+    const { jwt } = o;
413
+
414
+    if (jwt) {
415
+        let { search } = url;
416
+
417
+        if (search.indexOf('?jwt=') === -1 && search.indexOf('&jwt=') === -1) {
418
+            search.startsWith('?') || (search = `?${search}`);
419
+            search.length === 1 || (search += '&');
420
+            search += `jwt=${jwt}`;
421
+
422
+            url.search = search;
423
+        }
424
+    }
425
+
426
+    // fragment/hash
427
+
428
+    let { hash } = url;
429
+
430
+    for (const configName of [ 'config', 'interfaceConfig' ]) {
431
+        const urlParamsArray
432
+            = _objectToURLParamsArray(
433
+                o[`${configName}Overwrite`]
434
+                    || o[configName]
435
+                    || o[`${configName}Override`]);
436
+
437
+        if (urlParamsArray.length) {
438
+            let urlParamsString
439
+                = `${configName}.${urlParamsArray.join(`&${configName}.`)}`;
440
+
441
+            if (hash.length) {
442
+                urlParamsString = `&${urlParamsString}`;
443
+            } else {
444
+                hash = '#';
445
+            }
446
+            hash += urlParamsString;
447
+        }
448
+    }
449
+
450
+    url.hash = hash;
451
+
452
+    return url.toString() || undefined;
314 453
 }

Loading…
取消
儲存