ref: enable/disable video button

Dynamically enables/disables the toolbar video button. Prior to that
commit if we would start with no video there would be no way to enable
it later on.
This commit is contained in:
paweldomas 2017-06-28 09:15:46 -05:00 committed by virtuacoplenny
parent 6655ae5a84
commit 2281b1acd2
8 changed files with 116 additions and 43 deletions

View File

@ -35,6 +35,9 @@ import {
import {
isFatalJitsiConnectionError
} from './react/features/base/lib-jitsi-meet';
import {
setVideoAvailable
} from './react/features/base/media';
import {
localParticipantRoleChanged,
MAX_DISPLAY_NAME_LENGTH,
@ -1036,15 +1039,13 @@ export default {
this.isSharingScreen = newStream.videoType === 'desktop';
APP.UI.addLocalStream(newStream);
newStream.videoType === 'camera'
&& APP.UI.setCameraButtonEnabled(true);
} else {
// No video is treated the same way as being video muted
this.videoMuted = true;
this.isSharingScreen = false;
}
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
this.updateVideoIconEnabled();
APP.UI.updateDesktopSharingButtons();
});
},
@ -1953,6 +1954,7 @@ export default {
mediaDeviceHelper.setCurrentMediaDevices(devices);
APP.UI.onAvailableDevicesChanged(devices);
APP.store.dispatch(updateDeviceList(devices));
this.updateVideoIconEnabled();
});
this.deviceChangeListener = (devices) =>
@ -2030,8 +2032,32 @@ export default {
.then(() => {
mediaDeviceHelper.setCurrentMediaDevices(devices);
APP.UI.onAvailableDevicesChanged(devices);
this.updateVideoIconEnabled();
});
},
/**
* Determines whether or not the video button should be enabled.
*/
updateVideoIconEnabled() {
const videoMediaDevices
= mediaDeviceHelper.getCurrentMediaDevices().videoinput;
const videoDeviceCount
= videoMediaDevices ? videoMediaDevices.length : 0;
// The video functionality is considered available if there are any
// video devices detected or if there is local video stream already
// active which could be either screensharing stream or a video track
// created before the permissions were rejected (through browser
// config).
const available = videoDeviceCount > 0 || Boolean(localVideo);
logger.debug(
'Camera button enabled: ' + available,
'local video: ' + localVideo,
'video devices: ' + videoMediaDevices,
'device count: ' + videoDeviceCount);
APP.store.dispatch(setVideoAvailable(available));
},
/**
* Toggles the local "raised hand" status.

View File

@ -34,7 +34,6 @@ import {
dockToolbox,
setAudioIconEnabled,
setToolbarButton,
setVideoIconEnabled,
showDialPadButton,
showEtherpadButton,
showSharedVideoButton,
@ -724,9 +723,6 @@ UI.setVideoMuted = function (id, muted) {
VideoLayout.onVideoMute(id, muted);
if (APP.conference.isLocalId(id)) {
APP.store.dispatch(setVideoMuted(muted));
APP.store.dispatch(setToolbarButton('camera', {
toggled: muted
}));
}
};
@ -1341,15 +1337,6 @@ UI.onSharedVideoStop = function (id, attributes) {
sharedVideoManager.onSharedVideoStop(id, attributes);
};
/**
* Enables / disables camera toolbar button.
*
* @param {boolean} enabled indicates if the camera button should be enabled
* or disabled
*/
UI.setCameraButtonEnabled
= enabled => APP.store.dispatch(setVideoIconEnabled(enabled));
/**
* Enables / disables microphone toolbar button.
*

View File

@ -97,11 +97,6 @@ function getNewVideoInputDevice(newDevices, localVideo) {
availableVideoInputDevices[0].label !== '') {
return availableVideoInputDevices[0].deviceId;
}
// Otherwise we assume that we don't have any video input devices
// to use and that's why disable microphone button on UI.
else {
APP.UI.setCameraButtonEnabled(false);
}
} else {
// And here we handle case when we already have some device working,
// but we plug-in a "preferred" (previously selected in settings, stored

View File

@ -19,6 +19,16 @@ export const SET_AUDIO_MUTED = Symbol('SET_AUDIO_MUTED');
*/
export const SET_CAMERA_FACING_MODE = Symbol('SET_CAMERA_FACING_MODE');
/**
* The type of (redux) action to adjust the availability of the local video.
*
* {
* type: SET_VIDEO_AVAILABLE,
* muted: boolean
* }
*/
export const SET_VIDEO_AVAILABLE = Symbol('SET_VIDEO_AVAILABLE');
/**
* The type of (redux) action to set the muted state of the local video.
*

View File

@ -5,6 +5,7 @@ import type { Dispatch } from 'redux';
import {
SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE,
SET_VIDEO_AVAILABLE,
SET_VIDEO_MUTED,
TOGGLE_CAMERA_FACING_MODE
} from './actionTypes';
@ -43,6 +44,23 @@ export function setCameraFacingMode(cameraFacingMode: CAMERA_FACING_MODE) {
};
}
/**
* Action to adjust the availability of the local video.
*
* @param {boolean} available - True if the local video is to be marked as
* available or false if the local video is not available.
* @returns {{
* type: SET_VIDEO_AVAILABLE,
* available: boolean
* }}
*/
export function setVideoAvailable(available: boolean) {
return {
type: SET_VIDEO_AVAILABLE,
available
};
}
/**
* Action to set the muted state of the local video.
*

View File

@ -6,6 +6,7 @@ import {
SET_AUDIO_MUTED,
SET_CAMERA_FACING_MODE,
SET_VIDEO_MUTED,
SET_VIDEO_AVAILABLE,
TOGGLE_CAMERA_FACING_MODE
} from './actionTypes';
import { CAMERA_FACING_MODE } from './constants';
@ -63,7 +64,8 @@ function _audio(state = AUDIO_INITIAL_MEDIA_STATE, action) {
*/
const VIDEO_INITIAL_MEDIA_STATE = {
facingMode: CAMERA_FACING_MODE.USER,
muted: false
muted: true,
available: true
};
/**
@ -77,6 +79,12 @@ const VIDEO_INITIAL_MEDIA_STATE = {
*/
function _video(state = VIDEO_INITIAL_MEDIA_STATE, action) {
switch (action.type) {
case SET_VIDEO_AVAILABLE:
return {
...state,
available: action.available
};
case SET_CAMERA_FACING_MODE:
return {
...state,

View File

@ -225,27 +225,6 @@ export function setToolboxVisible(visible: boolean): Object {
};
}
/**
* Enables/disables audio toolbar button.
*
* @param {boolean} enabled - True if the button should be enabled; otherwise,
* false.
* @returns {Function}
*/
export function setVideoIconEnabled(enabled: boolean = false): Function {
return (dispatch: Dispatch<*>) => {
const i18nKey = enabled ? 'videomute' : 'cameraDisabled';
const i18n = `[content]toolbar.${i18nKey}`;
const button = {
enabled,
i18n,
toggled: !enabled
};
dispatch(setToolbarButton('camera', button));
};
}
/**
* Shows etherpad button if it's not shown.
*

View File

@ -7,6 +7,48 @@ import {
SET_TOOLBOX_TIMEOUT
} from './actionTypes';
import {
SET_VIDEO_AVAILABLE,
SET_VIDEO_MUTED
} from '../../features/base/media/actionTypes';
import {
setToolbarButton
} from './actions';
/**
* Adjusts the state of toolbar's camera button.
*
* @param {Store} store - The Redux store instance.
* @param {Object} action - Either SET_VIDEO_AVAILABLE or SET_VIDEO_MUTED.
*
* @returns {*}
*/
function setCameraButton(store, action) {
const video = store.getState()['features/base/media'].video;
let available = video.available;
if (typeof action.available === 'boolean') {
available = action.available;
}
let muted = video.muted;
if (typeof action.muted === 'boolean') {
muted = action.muted;
}
const i18nKey = available ? 'videomute' : 'cameraDisabled';
const i18n = `[content]toolbar.${i18nKey}`;
const button = {
enabled: available,
i18n,
toggled: available ? muted : true
};
store.dispatch(setToolbarButton('camera', button));
}
/**
* Middleware which intercepts Toolbox actions to handle changes to the
* visibility timeout of the Toolbox.
@ -33,6 +75,14 @@ MiddlewareRegistry.register(store => next => action => {
action.timeoutID = newTimeoutId;
break;
}
case SET_VIDEO_AVAILABLE:
case SET_VIDEO_MUTED: {
setCameraButton(store, action);
break;
}
}
return next(action);