Browse Source

feat(reload): Preserve local track mute state.

master
Hristo Terezov 4 years ago
parent
commit
d388a7bd3c

+ 1
- 1
connection_optimization/do_external_connect.js View File

1
 /* global config, createConnectionExternally */
1
 /* global config, createConnectionExternally */
2
 
2
 
3
 import getRoomName from '../react/features/base/config/getRoomName';
3
 import getRoomName from '../react/features/base/config/getRoomName';
4
-import parseURLParams from '../react/features/base/config/parseURLParams';
4
+import { parseURLParams } from '../react/features/base/util/parseURLParams';
5
 
5
 
6
 /**
6
 /**
7
  * Implements external connect using createConnectionExternally function defined
7
  * Implements external connect using createConnectionExternally function defined

+ 3
- 3
modules/API/constants.js View File

1
-// XXX The function parseURLParams is exported by the feature base/config (as
1
+// XXX The function parseURLParams is exported by the feature base/util (as
2
 // defined in the terminology of react/). However, this file is (very likely)
2
 // defined in the terminology of react/). However, this file is (very likely)
3
 // bundled in external_api in addition to app.bundle and, consequently, it is
3
 // bundled in external_api in addition to app.bundle and, consequently, it is
4
 // best to import as little as possible here (rather than the whole feature
4
 // best to import as little as possible here (rather than the whole feature
5
-// base/config) in order to minimize the amount of source code bundled into
5
+// base/util) in order to minimize the amount of source code bundled into
6
 // multiple bundles.
6
 // multiple bundles.
7
-import parseURLParams from '../../react/features/base/config/parseURLParams';
7
+import { parseURLParams } from '../../react/features/base/util/parseURLParams';
8
 
8
 
9
 /**
9
 /**
10
  * JitsiMeetExternalAPI id - unique for a webpage.
10
  * JitsiMeetExternalAPI id - unique for a webpage.

+ 38
- 8
react/features/app/actions.js View File

13
 } from '../base/config';
13
 } from '../base/config';
14
 import { connect, disconnect, setLocationURL } from '../base/connection';
14
 import { connect, disconnect, setLocationURL } from '../base/connection';
15
 import { loadConfig } from '../base/lib-jitsi-meet';
15
 import { loadConfig } from '../base/lib-jitsi-meet';
16
-import { createDesiredLocalTracks } from '../base/tracks';
16
+import { MEDIA_TYPE } from '../base/media';
17
+import { toState } from '../base/redux';
18
+import { createDesiredLocalTracks, isLocalVideoTrackMuted, isLocalTrackMuted } from '../base/tracks';
17
 import {
19
 import {
20
+    addHashParamsToURL,
18
     getBackendSafeRoomName,
21
     getBackendSafeRoomName,
19
     getLocationContextRoot,
22
     getLocationContextRoot,
20
     parseURIString,
23
     parseURIString,
191
     return (dispatch: Dispatch<Function>, getState: Function) => {
194
     return (dispatch: Dispatch<Function>, getState: Function) => {
192
         dispatch(setFatalError(undefined));
195
         dispatch(setFatalError(undefined));
193
 
196
 
194
-        const { locationURL } = getState()['features/base/connection'];
197
+        const state = getState();
198
+        const { locationURL } = state['features/base/connection'];
199
+
200
+        // Preserve the local tracks muted state after the reload.
201
+        const newURL = addTrackStateToURL(locationURL, state);
195
 
202
 
196
         logger.info(`Reloading the conference using URL: ${locationURL}`);
203
         logger.info(`Reloading the conference using URL: ${locationURL}`);
197
 
204
 
198
         if (navigator.product === 'ReactNative') {
205
         if (navigator.product === 'ReactNative') {
199
-            dispatch(appNavigate(toURLString(locationURL)));
206
+            dispatch(appNavigate(toURLString(newURL)));
200
         } else {
207
         } else {
201
             dispatch(reloadWithStoredParams());
208
             dispatch(reloadWithStoredParams());
202
         }
209
         }
203
     };
210
     };
204
 }
211
 }
205
 
212
 
213
+/**
214
+ * Adds the current track state to the passed URL.
215
+ *
216
+ * @param {URL} url - The URL that will be modified.
217
+ * @param {Function|Object} stateful - The redux store or {@code getState} function.
218
+ * @returns {URL} - Returns the modified URL.
219
+ */
220
+function addTrackStateToURL(url, stateful) {
221
+    const state = toState(stateful);
222
+    const tracks = state['features/base/tracks'];
223
+    const isVideoMuted = isLocalVideoTrackMuted(tracks);
224
+    const isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);
225
+
226
+    return addHashParamsToURL(new URL(url), { // use new URL object in order to not pollute the passed parameter.
227
+        'config.startWithAudioMuted': isAudioMuted,
228
+        'config.startWithVideoMuted': isVideoMuted
229
+    });
230
+
231
+}
232
+
206
 /**
233
 /**
207
  * Reloads the page by restoring the original URL.
234
  * Reloads the page by restoring the original URL.
208
  *
235
  *
210
  */
237
  */
211
 export function reloadWithStoredParams() {
238
 export function reloadWithStoredParams() {
212
     return (dispatch: Dispatch<any>, getState: Function) => {
239
     return (dispatch: Dispatch<any>, getState: Function) => {
213
-        const { locationURL } = getState()['features/base/connection'];
240
+        const state = getState();
241
+        const { locationURL } = state['features/base/connection'];
242
+
243
+        // Preserve the local tracks muted states.
244
+        const newURL = addTrackStateToURL(locationURL, state);
214
         const windowLocation = window.location;
245
         const windowLocation = window.location;
215
         const oldSearchString = windowLocation.search;
246
         const oldSearchString = windowLocation.search;
216
 
247
 
217
-        windowLocation.replace(locationURL.toString());
248
+        windowLocation.replace(newURL.toString());
218
 
249
 
219
-        if (window.self !== window.top
220
-            && locationURL.search === oldSearchString) {
250
+        if (newURL.search === oldSearchString) {
221
             // NOTE: Assuming that only the hash or search part of the URL will
251
             // NOTE: Assuming that only the hash or search part of the URL will
222
             // be changed!
252
             // be changed!
223
-            // location.reload will not trigger redirect/reload for iframe when
253
+            // location.replace will not trigger redirect/reload when
224
             // only the hash params are changed. That's why we need to call
254
             // only the hash params are changed. That's why we need to call
225
             // reload in addition to replace.
255
             // reload in addition to replace.
226
             windowLocation.reload();
256
             windowLocation.reload();

+ 3
- 4
react/features/base/config/functions.any.js View File

6
 import CONFIG_WHITELIST from './configWhitelist';
6
 import CONFIG_WHITELIST from './configWhitelist';
7
 import { _CONFIG_STORE_PREFIX } from './constants';
7
 import { _CONFIG_STORE_PREFIX } from './constants';
8
 import INTERFACE_CONFIG_WHITELIST from './interfaceConfigWhitelist';
8
 import INTERFACE_CONFIG_WHITELIST from './interfaceConfigWhitelist';
9
-import parseURLParams from './parseURLParams';
9
+import { parseURLParams } from '../util';
10
 import logger from './logger';
10
 import logger from './logger';
11
 
11
 
12
-// XXX The functions getRoomName and parseURLParams are split out of
13
-// functions.js because they are bundled in both app.bundle and
12
+// XXX The function getRoomName is split out of
13
+// functions.js because it is bundled in both app.bundle and
14
 // do_external_connect, webpack 1 does not support tree shaking, and we don't
14
 // do_external_connect, webpack 1 does not support tree shaking, and we don't
15
 // want all functions to be bundled in do_external_connect.
15
 // want all functions to be bundled in do_external_connect.
16
 export { default as getRoomName } from './getRoomName';
16
 export { default as getRoomName } from './getRoomName';
17
-export { parseURLParams };
18
 
17
 
19
 /**
18
 /**
20
  * Create a "fake" configuration object for the given base URL. This is used in case the config
19
  * Create a "fake" configuration object for the given base URL. This is used in case the config

+ 1
- 1
react/features/base/devices/functions.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
-import { parseURLParams } from '../config';
3
+import { parseURLParams } from '../util';
4
 import JitsiMeetJS from '../lib-jitsi-meet';
4
 import JitsiMeetJS from '../lib-jitsi-meet';
5
 import { updateSettings } from '../settings';
5
 import { updateSettings } from '../settings';
6
 
6
 

+ 1
- 1
react/features/base/jwt/functions.js View File

1
 /* @flow */
1
 /* @flow */
2
 
2
 
3
-import { parseURLParams } from '../config';
3
+import { parseURLParams } from '../util';
4
 
4
 
5
 /**
5
 /**
6
  * Retrieves the JSON Web Token (JWT), if any, defined by a specific
6
  * Retrieves the JSON Web Token (JWT), if any, defined by a specific

+ 2
- 1
react/features/base/settings/functions.any.js View File

1
 // @flow
1
 // @flow
2
-import { CONFIG_WHITELIST, parseURLParams } from '../config';
2
+import { CONFIG_WHITELIST } from '../config';
3
 import { toState } from '../redux';
3
 import { toState } from '../redux';
4
+import { parseURLParams } from '../util';
4
 
5
 
5
 import { DEFAULT_SERVER_URL } from './constants';
6
 import { DEFAULT_SERVER_URL } from './constants';
6
 
7
 

+ 1
- 1
react/features/base/settings/middleware.js View File

3
 
3
 
4
 import { APP_WILL_MOUNT } from '../app';
4
 import { APP_WILL_MOUNT } from '../app';
5
 import { setAudioOnly } from '../audio-only';
5
 import { setAudioOnly } from '../audio-only';
6
-import parseURLParams from '../config/parseURLParams'; // minimize imports to avoid circular imports
6
+import { parseURLParams } from '../util';
7
 import { SET_LOCATION_URL } from '../connection/actionTypes'; // minimize imports to avoid circular imports
7
 import { SET_LOCATION_URL } from '../connection/actionTypes'; // minimize imports to avoid circular imports
8
 import { getLocalParticipant, participantUpdated } from '../participants';
8
 import { getLocalParticipant, participantUpdated } from '../participants';
9
 import { MiddlewareRegistry } from '../redux';
9
 import { MiddlewareRegistry } from '../redux';

+ 1
- 0
react/features/base/util/index.js View File

3
 export * from './loadScript';
3
 export * from './loadScript';
4
 export * from './openURLInBrowser';
4
 export * from './openURLInBrowser';
5
 export * from './uri';
5
 export * from './uri';
6
+export * from './parseURLParams';

react/features/base/config/parseURLParams.js → react/features/base/util/parseURLParams.js View File

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

+ 22
- 0
react/features/base/util/uri.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { parseURLParams } from './parseURLParams';
3
 import { normalizeNFKC } from './strings';
4
 import { normalizeNFKC } from './strings';
4
 
5
 
5
 /**
6
 /**
551
 
552
 
552
     return url.toString() || undefined;
553
     return url.toString() || undefined;
553
 }
554
 }
555
+
556
+/**
557
+ * Adds hash params to URL.
558
+ *
559
+ * @param {URL} url - The URL.
560
+ * @param {Object} hashParamsToAdd - A map with the parameters to be set.
561
+ * @returns {URL} - The new URL.
562
+ */
563
+export function addHashParamsToURL(url: URL, hashParamsToAdd: Object = {}) {
564
+    const params = parseURLParams(url);
565
+    const urlParamsArray = _objectToURLParamsArray({
566
+        ...params,
567
+        ...hashParamsToAdd
568
+    });
569
+
570
+    if (urlParamsArray.length) {
571
+        url.hash = `#${urlParamsArray.join('&')}`;
572
+    }
573
+
574
+    return url;
575
+}

+ 1
- 2
react/features/calendar-sync/web/microsoftCalendar.js View File

6
 
6
 
7
 import { createDeferred } from '../../../../modules/util/helpers';
7
 import { createDeferred } from '../../../../modules/util/helpers';
8
 
8
 
9
-import parseURLParams from '../../base/config/parseURLParams';
10
-import { parseStandardURIString } from '../../base/util';
9
+import { parseStandardURIString, parseURLParams } from '../../base/util';
11
 import { getShareInfoText } from '../../invite';
10
 import { getShareInfoText } from '../../invite';
12
 
11
 
13
 import { setCalendarAPIAuthState } from '../actions';
12
 import { setCalendarAPIAuthState } from '../actions';

+ 2
- 2
react/features/dropbox/functions.web.js View File

2
 
2
 
3
 import { Dropbox } from 'dropbox';
3
 import { Dropbox } from 'dropbox';
4
 
4
 
5
-import { parseURLParams } from '../base/config';
6
 import {
5
 import {
7
     getJitsiMeetGlobalNS,
6
     getJitsiMeetGlobalNS,
8
-    parseStandardURIString
7
+    parseStandardURIString,
8
+    parseURLParams
9
 } from '../base/util';
9
 } from '../base/util';
10
 
10
 
11
 /**
11
 /**

+ 1
- 1
react/features/invite/components/dial-in-info-page/DialInInfoApp.web.js View File

2
 import ReactDOM from 'react-dom';
2
 import ReactDOM from 'react-dom';
3
 import { I18nextProvider } from 'react-i18next';
3
 import { I18nextProvider } from 'react-i18next';
4
 
4
 
5
-import parseURLParams from '../../../base/config/parseURLParams';
6
 import { i18next } from '../../../base/i18n';
5
 import { i18next } from '../../../base/i18n';
7
 import { isMobileBrowser } from '../../../base/environment/utils';
6
 import { isMobileBrowser } from '../../../base/environment/utils';
7
+import { parseURLParams } from '../../../base/util/parseURLParams';
8
 import { DialInSummary } from '../dial-in-summary';
8
 import { DialInSummary } from '../dial-in-summary';
9
 
9
 
10
 import NoRoomError from './NoRoomError';
10
 import NoRoomError from './NoRoomError';

+ 1
- 1
react/features/settings/components/web/DeviceSelectionPopup.js View File

20
     setVideoInputDevice
20
     setVideoInputDevice
21
 } from '../../../../../modules/API/external/functions';
21
 } from '../../../../../modules/API/external/functions';
22
 
22
 
23
-import parseURLParams from '../../../base/config/parseURLParams';
24
 import DialogWithTabs from '../../../base/dialog/components/web/DialogWithTabs';
23
 import DialogWithTabs from '../../../base/dialog/components/web/DialogWithTabs';
24
+import { parseURLParams } from '../../../base/util/parseURLParams';
25
 import DeviceSelection from '../../../device-selection/components/DeviceSelection';
25
 import DeviceSelection from '../../../device-selection/components/DeviceSelection';
26
 
26
 
27
 /**
27
 /**

Loading…
Cancel
Save