Fix toolbar's mute buttons when starting muted
The toolbar's mute buttons depict respective features/base/media states. However, (un)muting is practically carried out by features/base/tracks. When the mobile app enters a conference configured to invite the joining participant to mute themselves, the tracks would be muted but the toolbar's mute buttons would not reflect that.
This commit is contained in:
parent
f271eb4610
commit
4997ae79e3
|
@ -34,7 +34,7 @@ export function disposeLib() {
|
|||
*/
|
||||
export function initLib() {
|
||||
return (dispatch, getState) => {
|
||||
const config = getState()['features/base/lib'].config;
|
||||
const config = getState()['features/base/lib-jitsi-meet'].config;
|
||||
|
||||
if (!config) {
|
||||
throw new Error('Cannot initialize lib-jitsi-meet without config');
|
||||
|
|
|
@ -19,26 +19,23 @@ import { SET_CONFIG } from './actionTypes';
|
|||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
case PARTICIPANT_LEFT:
|
||||
if (action.participant.local) {
|
||||
store.dispatch(disposeLib());
|
||||
}
|
||||
action.participant.local && store.dispatch(disposeLib());
|
||||
break;
|
||||
|
||||
case SET_CONFIG: {
|
||||
const { dispatch, getState } = store;
|
||||
const libInitialized = getState()['features/base/lib'].initialized;
|
||||
const initialized
|
||||
= getState()['features/base/lib-jitsi-meet'].initialized;
|
||||
|
||||
// XXX If we already have config, that means new config is coming, which
|
||||
// means that we should dispose instance of lib initialized with
|
||||
// previous config first.
|
||||
// TODO Currently 'disposeLib' actually does not dispose lib-jitsi-meet.
|
||||
// This functionality should be implemented.
|
||||
const promise = libInitialized
|
||||
? dispatch(disposeLib())
|
||||
: Promise.resolve();
|
||||
const promise
|
||||
= initialized ? dispatch(disposeLib()) : Promise.resolve();
|
||||
|
||||
promise
|
||||
.then(dispatch(initLib()));
|
||||
promise.then(dispatch(initLib()));
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* Initial state of 'features/base/lib'.
|
||||
* Initial state of 'features/base/lib-jitsi-meet'.
|
||||
*
|
||||
* @type {{
|
||||
* initializationError: null,
|
||||
|
@ -31,7 +31,7 @@ const INITIAL_STATE = {
|
|||
};
|
||||
|
||||
ReducerRegistry.register(
|
||||
'features/base/lib',
|
||||
'features/base/lib-jitsi-meet',
|
||||
(state = INITIAL_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case LIB_DISPOSED:
|
||||
|
|
|
@ -42,15 +42,10 @@ function resetInitialMediaState(store) {
|
|||
const { dispatch, getState } = store;
|
||||
const state = getState()['features/base/media'];
|
||||
|
||||
if (state.audio.muted) {
|
||||
dispatch(audioMutedChanged(false));
|
||||
}
|
||||
if (state.video.facingMode !== CAMERA_FACING_MODE.USER) {
|
||||
dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
|
||||
}
|
||||
if (state.video.muted) {
|
||||
dispatch(videoMutedChanged(false));
|
||||
}
|
||||
state.audio.muted && dispatch(audioMutedChanged(false));
|
||||
(state.video.facingMode !== CAMERA_FACING_MODE.USER)
|
||||
&& dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
|
||||
state.video.muted && dispatch(videoMutedChanged(false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -72,14 +72,18 @@ export function getTracksByMediaType(tracks, mediaType) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Mute or unmute local track if any.
|
||||
* Mutes or unmutes a specific <tt>JitsiLocalTrack</tt>. If the muted state of
|
||||
* the specified <tt>track</tt> is already in accord with the specified
|
||||
* <tt>muted</tt> value, then does nothing.
|
||||
*
|
||||
* @param {JitsiLocalTrack} track - Track instance.
|
||||
* @param {boolean} muted - If audio stream should be muted or unmuted.
|
||||
* @param {JitsiLocalTrack} track - The <tt>JitsiLocalTrack</tt> to mute or
|
||||
* unmute.
|
||||
* @param {boolean} muted - If the specified <tt>track</tt> is to be muted, then
|
||||
* <tt>true</tt>; otherwise, <tt>false</tt>.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setTrackMuted(track, muted) {
|
||||
if (!track) {
|
||||
if (track.isMuted() === muted) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,11 @@ import {
|
|||
} from '../lib-jitsi-meet';
|
||||
import {
|
||||
AUDIO_MUTED_CHANGED,
|
||||
audioMutedChanged,
|
||||
CAMERA_FACING_MODE_CHANGED,
|
||||
MEDIA_TYPE,
|
||||
VIDEO_MUTED_CHANGED
|
||||
VIDEO_MUTED_CHANGED,
|
||||
videoMutedChanged
|
||||
} from '../media';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
|
@ -14,6 +16,7 @@ import {
|
|||
createLocalTracks,
|
||||
destroyLocalTracks
|
||||
} from './actions';
|
||||
import { TRACK_UPDATED } from './actionTypes';
|
||||
import {
|
||||
getLocalTrack,
|
||||
setTrackMuted
|
||||
|
@ -50,6 +53,9 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
store.dispatch(destroyLocalTracks());
|
||||
break;
|
||||
|
||||
case TRACK_UPDATED:
|
||||
return _trackUpdated(store, next, action);
|
||||
|
||||
case VIDEO_MUTED_CHANGED:
|
||||
_mutedChanged(store, action, MEDIA_TYPE.VIDEO);
|
||||
break;
|
||||
|
@ -58,6 +64,22 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
return next(action);
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the local track associated with a specific <tt>MEDIA_TYPE</tt> in a
|
||||
* specific Redux store.
|
||||
*
|
||||
* @param {Store} store - The Redux store from which the local track associated
|
||||
* with the specified <tt>mediaType</tt> is to be retrieved.
|
||||
* @param {MEDIA_TYPE} mediaType - The <tt>MEDIA_TYPE</tt> of the local track to
|
||||
* be retrieved from the specified <tt>store</tt>.
|
||||
* @private
|
||||
* @returns {Track} The local <tt>Track</tt> associated with the specified
|
||||
* <tt>mediaType</tt> in the specified <tt>store</tt>.
|
||||
*/
|
||||
function _getLocalTrack(store, mediaType) {
|
||||
return getLocalTrack(store.getState()['features/base/tracks'], mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutes or unmutes a local track with a specific media type.
|
||||
*
|
||||
|
@ -70,8 +92,67 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
* @returns {void}
|
||||
*/
|
||||
function _mutedChanged(store, action, mediaType) {
|
||||
const tracks = store.getState()['features/base/tracks'];
|
||||
const localTrack = getLocalTrack(tracks, mediaType);
|
||||
const localTrack = _getLocalTrack(store, mediaType);
|
||||
|
||||
localTrack && setTrackMuted(localTrack.jitsiTrack, action.muted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts the action <tt>TRACK_UPDATED</tt> in order to synchronize the
|
||||
* muted states of the local tracks of features/base/tracks with the muted
|
||||
* states of features/base/media.
|
||||
*
|
||||
* @param {Store} store - The Redux store in which the specified <tt>action</tt>
|
||||
* is being dispatched.
|
||||
* @param {Dispatch} next - The Redux dispatch function to dispatch the
|
||||
* specified <tt>action</tt> to the specified <tt>store</tt>.
|
||||
* @param {Action} action - The Redux action <tt>TRACK_UPDATED</tt> which is
|
||||
* being dispatched in the specified <tt>store</tt>.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _trackUpdated(store, next, action) {
|
||||
// Determine the muted state of the local track before the update.
|
||||
const track = action.track;
|
||||
let mediaType;
|
||||
let oldMuted;
|
||||
|
||||
if ('muted' in track) {
|
||||
// XXX The return value of JitsiTrack.getType() is of type MEDIA_TYPE
|
||||
// that happens to be compatible with the type MEDIA_TYPE defined by
|
||||
// jitsi-meet-react.
|
||||
mediaType = track.jitsiTrack.getType();
|
||||
|
||||
const localTrack = _getLocalTrack(store, mediaType);
|
||||
|
||||
if (localTrack) {
|
||||
oldMuted = localTrack.muted;
|
||||
}
|
||||
}
|
||||
|
||||
const result = next(action);
|
||||
|
||||
if (typeof oldMuted !== 'undefined') {
|
||||
// Determine the muted state of the local track after the update. If the
|
||||
// muted states before and after the update differ, then the respective
|
||||
// media state should by synchronized.
|
||||
const localTrack = _getLocalTrack(store, mediaType);
|
||||
|
||||
if (localTrack) {
|
||||
const newMuted = localTrack.muted;
|
||||
|
||||
if (oldMuted !== newMuted) {
|
||||
switch (mediaType) {
|
||||
case MEDIA_TYPE.AUDIO:
|
||||
store.dispatch(audioMutedChanged(newMuted));
|
||||
break;
|
||||
case MEDIA_TYPE.VIDEO:
|
||||
store.dispatch(videoMutedChanged(newMuted));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
action.track.jitsiTrack);
|
||||
const participantId = state['features/largeVideo'].participantId;
|
||||
|
||||
if (track.participantId === participantId) {
|
||||
store.dispatch(selectParticipant());
|
||||
}
|
||||
(track.participantId === participantId)
|
||||
&& store.dispatch(selectParticipant());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue