diff --git a/react/features/app/components/AbstractApp.js b/react/features/app/components/AbstractApp.js index ea1235854..353cacbc5 100644 --- a/react/features/app/components/AbstractApp.js +++ b/react/features/app/components/AbstractApp.js @@ -8,10 +8,7 @@ import { compose, createStore } from 'redux'; import Thunk from 'redux-thunk'; import { i18next } from '../../base/i18n'; -import { - localParticipantJoined, - localParticipantLeft -} from '../../base/participants'; +import { localParticipantLeft } from '../../base/participants'; import { Fragment, RouteRegistry } from '../../base/react'; import { MiddlewareRegistry, ReducerRegistry } from '../../base/redux'; import { SoundCollection } from '../../base/sounds'; @@ -126,24 +123,10 @@ export class AbstractApp extends Component { */ componentWillMount() { this._init.then(() => { - const { dispatch, getState } = this._getStore(); + const { dispatch } = this._getStore(); dispatch(appWillMount(this)); - // FIXME I believe it makes more sense for a middleware to dispatch - // localParticipantJoined on APP_WILL_MOUNT because the order of - // actions is important, not the call site. Moreover, we've got - // localParticipant business logic in the React Component - // (i.e. UI) AbstractApp now. - - const settings = getState()['features/base/settings']; - const localParticipant = { - avatarID: settings.avatarID, - avatarURL: settings.avatarURL, - email: settings.email, - name: settings.displayName - }; - // We set the initialized state here and not in the contructor to // make sure that {@code componentWillMount} gets invoked before // the app tries to render the actual app content. @@ -151,8 +134,6 @@ export class AbstractApp extends Component { appAsyncInitialized: true }); - dispatch(localParticipantJoined(localParticipant)); - // If a URL was explicitly specified to this React Component, // then open it; otherwise, use a default. this._openURL(toURLString(this.props.url) || this._getDefaultURL()); diff --git a/react/features/base/participants/middleware.js b/react/features/base/participants/middleware.js index ae1732b37..ac447095c 100644 --- a/react/features/base/participants/middleware.js +++ b/react/features/base/participants/middleware.js @@ -12,6 +12,7 @@ import { playSound, registerSound, unregisterSound } from '../sounds'; import { localParticipantIdChanged, + localParticipantJoined, participantUpdated } from './actions'; import { @@ -56,7 +57,8 @@ MiddlewareRegistry.register(store => next => action => { switch (action.type) { case APP_WILL_MOUNT: _registerSounds(store); - break; + + return _localParticipantJoined(store, next, action); case APP_WILL_UNMOUNT: _unregisterSounds(store); break; @@ -174,6 +176,33 @@ MiddlewareRegistry.register(store => next => action => { return next(action); }); +/** + * Initializes the local participant and signals that it joined. + * + * @private + * @param {Store} store - The Redux store. + * @param {Dispatch} next - The redux dispatch function to dispatch the + * specified action to the specified store. + * @param {Action} action - The redux action which is being dispatched + * in the specified store. + * @private + * @returns {Object} The value returned by {@code next(action)}. + */ +function _localParticipantJoined({ getState, dispatch }, next, action) { + const result = next(action); + const settings = getState()['features/base/settings']; + const localParticipant = { + avatarID: settings.avatarID, + avatarURL: settings.avatarURL, + email: settings.email, + name: settings.displayName + }; + + dispatch(localParticipantJoined(localParticipant)); + + return result; +} + /** * Plays sounds when participants join/leave conference. *