diff --git a/react/features/app/index.js b/react/features/app/index.js index 5d564613e..44000a1a7 100644 --- a/react/features/app/index.js +++ b/react/features/app/index.js @@ -3,4 +3,5 @@ export * from './actionTypes'; export * from './components'; export * from './functions'; +import './middleware'; import './reducer'; diff --git a/react/features/app/middleware.js b/react/features/app/middleware.js new file mode 100644 index 000000000..f8786ffcb --- /dev/null +++ b/react/features/app/middleware.js @@ -0,0 +1,55 @@ +import { + CONNECTION_ESTABLISHED, + getURLWithoutParams +} from '../base/connection'; +import { MiddlewareRegistry } from '../base/redux'; + +MiddlewareRegistry.register(store => next => action => { + switch (action.type) { + case CONNECTION_ESTABLISHED: + return _connectionEstablished(store, next, action); + } + + return next(action); +}); + +/** + * Notifies the feature app that the action {@link CONNECTION_ESTABLISHED} is + * being dispatched within a specific Redux {@code store}. + * + * @param {Store} store - The Redux store in which the specified {@code action} + * is being dispatched. + * @param {Dispatch} next - The Redux {@code dispatch} function to dispatch the + * specified {@code action} to the specified {@code store}. + * @param {Action} action - The Redux action {@code CONNECTION_ESTABLISHED} + * which is being dispatched in the specified {@code store}. + * @private + * @returns {Object} The new state that is the result of the reduction of the + * specified {@code action}. + */ +function _connectionEstablished(store, next, action) { + const result = next(action); + + // In the Web app we explicitly do not want to display the hash and + // query/search URL params. Unfortunately, window.location and, more + // importantly, its params are used not only in jitsi-meet but also in + // lib-jitsi-meet. Consequenlty, the time to remove the params is + // determined by when no one needs them anymore. + const { history, location } = window; + + if (history + && location + && history.length + && typeof history.replaceState === 'function') { + const replacement = getURLWithoutParams(location); + + if (location !== replacement) { + history.replaceState( + history.state, + (document && document.title) || '', + replacement); + } + } + + return result; +} diff --git a/react/features/base/connection/functions.js b/react/features/base/connection/functions.js index 91667ee83..a188041a8 100644 --- a/react/features/base/connection/functions.js +++ b/react/features/base/connection/functions.js @@ -17,10 +17,29 @@ export function getInviteURL(stateOrGetState: Function | Object): ?string { let inviteURL; if (locationURL) { - const { host, pathname, protocol } = locationURL; - - inviteURL = `${protocol}//${host}${pathname}`; + inviteURL = getURLWithoutParams(locationURL).href; } return inviteURL; } + +/** + * Gets a {@link URL} without hash and query/search params from a specific + * {@code URL}. + * + * @param {URL} url - The {@code URL} which may have hash and query/search + * params. + * @returns {URL} + */ +export function getURLWithoutParams(url: URL): URL { + const { hash, search } = url; + + if ((hash && hash.length > 1) || (search && search.length > 1)) { + // eslint-disable-next-line no-param-reassign + url = new URL(url.href); + url.hash = ''; + url.search = ''; + } + + return url; +}