diff --git a/bigbluebutton-html5/imports/api/users-settings/server/methods/addUserSettings.js b/bigbluebutton-html5/imports/api/users-settings/server/methods/addUserSettings.js index 93719cad394604c4aedde1d35dbff120faba0abe..06b42ef77c7df7e8f59d800c686eb5a522932400 100644 --- a/bigbluebutton-html5/imports/api/users-settings/server/methods/addUserSettings.js +++ b/bigbluebutton-html5/imports/api/users-settings/server/methods/addUserSettings.js @@ -48,6 +48,7 @@ const currentParameters = [ 'bbb_enable_video', 'bbb_record_video', 'bbb_skip_video_preview', + 'bbb_skip_video_preview_on_first_join', 'bbb_mirror_own_webcam', // PRESENTATION 'bbb_force_restore_presentation_on_new_events', diff --git a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx index 67ea6939228b9339b9facfc99d5adf72c9ee9290..a4cf37443cc427d8dbc86a1290b9ddb23cf286de 100755 --- a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx @@ -7,10 +7,10 @@ import Button from '/imports/ui/components/button/component'; // import { notify } from '/imports/ui/services/notification'; import logger from '/imports/startup/client/logger'; import Modal from '/imports/ui/components/modal/simple/component'; -import Service from './service'; import browser from 'browser-detect'; -import VideoService from '../video-provider/service'; import cx from 'classnames'; +import Service from './service'; +import VideoService from '../video-provider/service'; import { styles } from './styles'; const CAMERA_PROFILES = Meteor.settings.public.kurento.cameraProfiles; @@ -30,7 +30,6 @@ const propTypes = { changeWebcam: PropTypes.func.isRequired, changeProfile: PropTypes.func.isRequired, resolve: PropTypes.func, - skipVideoPreview: PropTypes.bool.isRequired, hasMediaDevices: PropTypes.bool.isRequired, hasVideoStream: PropTypes.bool.isRequired, webcamDeviceId: PropTypes.string, @@ -206,13 +205,13 @@ class VideoPreview extends Component { this.userParameterProfile = VideoService.getUserParameterProfile(); this.mirrorOwnWebcam = VideoService.mirrorOwnWebcam(); + this.skipVideoPreview = Service.getSkipVideoPreview(); } componentDidMount() { const { webcamDeviceId, hasMediaDevices, - skipVideoPreview, } = this.props; this._isMounted = true; @@ -282,15 +281,15 @@ class VideoPreview extends Component { }); this.displayInitialPreview(initialDeviceId); } - if (!skipVideoPreview) { + if (!this.skipVideoPreview) { this.setState({ viewState: VIEW_STATES.found, }); } }).catch((error) => { this.handleDeviceError('enumerate', error, 'enumerating devices'); + }); }); - }); } catch (error) { this.handleDeviceError('grabbing', error, 'grabbing initial video stream'); } @@ -451,7 +450,6 @@ class VideoPreview extends Component { displayPreview(deviceId, profile) { const { changeProfile, - skipVideoPreview, } = this.props; this.setState({ @@ -460,7 +458,7 @@ class VideoPreview extends Component { previewError: undefined, }); changeProfile(profile.id); - if (skipVideoPreview) return this.handleStartSharing(); + if (this.skipVideoPreview) return this.handleStartSharing(); this.doGUM(deviceId, profile).then((stream) => { if (!this._isMounted) return; @@ -493,7 +491,6 @@ class VideoPreview extends Component { renderDeviceSelectors() { const { intl, - skipVideoPreview, sharedDevices, } = this.props; @@ -518,7 +515,7 @@ class VideoPreview extends Component { value={webcamDeviceId || ''} className={styles.select} onChange={this.handleSelectWebcam} - disabled={skipVideoPreview} + disabled={this.skipVideoPreview} > {availableWebcams.map(webcam => ( <option key={webcam.deviceId} value={webcam.deviceId}> @@ -536,14 +533,14 @@ class VideoPreview extends Component { { shared ? ( <span className={styles.label}> - {intl.formatMessage(intlMessages.sharedCameraLabel)} - </span> + {intl.formatMessage(intlMessages.sharedCameraLabel)} + </span> ) : ( <span> - <label className={styles.label} htmlFor="setQuality"> - {intl.formatMessage(intlMessages.qualityLabel)} - </label> + <label className={styles.label} htmlFor="setQuality"> + {intl.formatMessage(intlMessages.qualityLabel)} + </label> {availableProfiles && availableProfiles.length > 0 ? ( <select @@ -551,9 +548,9 @@ class VideoPreview extends Component { value={selectedProfile || ''} className={styles.select} onChange={this.handleSelectProfile} - disabled={skipVideoPreview} + disabled={this.skipVideoPreview} > - {availableProfiles.map(profile => { + {availableProfiles.map((profile) => { const label = intlMessages[`${profile.id}`] ? intl.formatMessage(intlMessages[`${profile.id}`]) : profile.name; @@ -562,14 +559,14 @@ class VideoPreview extends Component { <option key={profile.id} value={profile.id}> {`${label}`} </option> - ) + ); })} </select> ) : ( <span> - {intl.formatMessage(intlMessages.profileNotFoundLabel)} - </span> + {intl.formatMessage(intlMessages.profileNotFoundLabel)} + </span> ) } </span> @@ -643,7 +640,6 @@ class VideoPreview extends Component { renderModalContent() { const { intl, - skipVideoPreview, sharedDevices, hasVideoStream, } = this.props; @@ -654,7 +650,7 @@ class VideoPreview extends Component { deviceError, previewError, } = this.state; - const shouldDisableButtons = skipVideoPreview && !(deviceError || previewError); + const shouldDisableButtons = this.skipVideoPreview && !(deviceError || previewError); const shared = sharedDevices.includes(webcamDeviceId); @@ -679,15 +675,17 @@ class VideoPreview extends Component { {this.renderContent()} <div className={styles.footer}> - {hasVideoStream ? - (<div className={styles.extraActions}> - <Button - color="danger" - label={intl.formatMessage(intlMessages.stopSharingAllLabel)} - onClick={this.handleStopSharingAll} - disabled={shouldDisableButtons} - /> - </div>) + {hasVideoStream + ? ( + <div className={styles.extraActions}> + <Button + color="danger" + label={intl.formatMessage(intlMessages.stopSharingAllLabel)} + onClick={this.handleStopSharingAll} + disabled={shouldDisableButtons} + /> + </div> + ) : null } <div className={styles.actions}> @@ -713,7 +711,6 @@ class VideoPreview extends Component { const { intl, hasMediaDevices, - skipVideoPreview, isCamLocked, } = this.props; @@ -727,7 +724,7 @@ class VideoPreview extends Component { previewError, } = this.state; - const allowCloseModal = !!(deviceError || previewError) || !skipVideoPreview; + const allowCloseModal = !!(deviceError || previewError) || !this.skipVideoPreview; return ( <Modal diff --git a/bigbluebutton-html5/imports/ui/components/video-preview/container.jsx b/bigbluebutton-html5/imports/ui/components/video-preview/container.jsx index 746f01de492924623cae010b977d2dd2c666cb01..c13e0d5e8f8cf9c4f18b693c4cd060d9a6bf4353 100755 --- a/bigbluebutton-html5/imports/ui/components/video-preview/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-preview/container.jsx @@ -27,7 +27,7 @@ const isCamLocked = () => { return false; }; -export default withModalMounter(withTracker(({ mountModal, fromInterface }) => ({ +export default withModalMounter(withTracker(({ mountModal }) => ({ startSharing: (deviceId) => { mountModal(null); VideoService.joinVideo(deviceId); @@ -48,6 +48,5 @@ export default withModalMounter(withTracker(({ mountModal, fromInterface }) => ( webcamDeviceId: Service.webcamDeviceId(), changeProfile: profileId => Service.changeProfile(profileId), hasMediaDevices: deviceInfo.hasMediaDevices, - skipVideoPreview: VideoService.getSkipVideoPreview(fromInterface), hasVideoStream: VideoService.hasVideoStream(), }))(VideoPreviewContainer)); diff --git a/bigbluebutton-html5/imports/ui/components/video-preview/service.js b/bigbluebutton-html5/imports/ui/components/video-preview/service.js index a5d92d6cb05918e8a56ef77bdb0d1fc6701d754e..910e9e07203a70b5553f41bbe5b12a990ee075d7 100755 --- a/bigbluebutton-html5/imports/ui/components/video-preview/service.js +++ b/bigbluebutton-html5/imports/ui/components/video-preview/service.js @@ -1,3 +1,6 @@ +import Storage from '/imports/ui/services/storage/session'; +import getFromUserSettings from '/imports/ui/services/users-settings'; + const promiseTimeout = (ms, promise) => { const timeout = new Promise((resolve, reject) => { const id = setTimeout(() => { @@ -18,6 +21,24 @@ const promiseTimeout = (ms, promise) => { ]); }; +const getSkipVideoPreview = () => { + const KURENTO_CONFIG = Meteor.settings.public.kurento; + + const skipVideoPreviewOnFirstJoin = getFromUserSettings( + 'bbb_skip_video_preview_on_first_join', + KURENTO_CONFIG.skipVideoPreviewOnFirstJoin, + ); + const skipVideoPreview = getFromUserSettings( + 'bbb_skip_video_preview', + KURENTO_CONFIG.skipVideoPreview, + ); + + return ( + (Storage.getItem('isFirstJoin') !== false && skipVideoPreviewOnFirstJoin) + || skipVideoPreview + ); +}; + export default { promiseTimeout, changeWebcam: (deviceId) => { @@ -27,4 +48,5 @@ export default { changeProfile: (profileId) => { Session.set('WebcamProfileId', profileId); }, + getSkipVideoPreview, }; diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/service.js b/bigbluebutton-html5/imports/ui/components/video-provider/service.js index e1d61fa0ff3da42ff2bab0dea124c85d98fbe3a8..f0934ea57f9a537906367a16236515ef61c06e5d 100755 --- a/bigbluebutton-html5/imports/ui/components/video-provider/service.js +++ b/bigbluebutton-html5/imports/ui/components/video-provider/service.js @@ -11,12 +11,13 @@ import { notify } from '/imports/ui/services/notification'; import { monitorVideoConnection } from '/imports/utils/stats'; import browser from 'browser-detect'; import getFromUserSettings from '/imports/ui/services/users-settings'; +import VideoPreviewService from '../video-preview/service'; +import Storage from '/imports/ui/services/storage/session'; import logger from '/imports/startup/client/logger'; import _ from 'lodash'; const CAMERA_PROFILES = Meteor.settings.public.kurento.cameraProfiles; const MULTIPLE_CAMERAS = Meteor.settings.public.app.enableMultipleCameras; -const SKIP_VIDEO_PREVIEW = Meteor.settings.public.kurento.skipVideoPreview; const SFU_URL = Meteor.settings.public.kurento.wsUrl; const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator; @@ -63,7 +64,6 @@ class VideoService { currentVideoPageIndex: 0, numberOfPages: 0, }); - this.skipVideoPreview = null; this.userParameterProfile = null; const BROWSER_RESULTS = browser(); this.isMobile = BROWSER_RESULTS.mobile || BROWSER_RESULTS.os.includes('Android'); @@ -130,6 +130,7 @@ class VideoService { joinVideo(deviceId) { this.deviceId = deviceId; this.isConnecting = true; + Storage.setItem('isFirstJoin', false); } joinedVideo() { @@ -577,14 +578,6 @@ class VideoService { return isLocal ? 'share' : 'viewer'; } - getSkipVideoPreview(fromInterface = false) { - if (this.skipVideoPreview === null) { - this.skipVideoPreview = getFromUserSettings('bbb_skip_video_preview', false) || SKIP_VIDEO_PREVIEW; - } - - return this.skipVideoPreview && !fromInterface; - } - getUserParameterProfile() { if (this.userParameterProfile === null) { this.userParameterProfile = getFromUserSettings( @@ -601,7 +594,7 @@ class VideoService { // Mobile shouldn't be able to share more than one camera at the same time // Safari needs to implement devicechange event for safe device control return MULTIPLE_CAMERAS - && !this.getSkipVideoPreview() + && !VideoPreviewService.getSkipVideoPreview() && !this.isMobile && !this.isSafari && this.numberOfDevices > 1; @@ -768,7 +761,6 @@ export default { getRole: isLocal => videoService.getRole(isLocal), getRecord: () => videoService.getRecord(), getSharedDevices: () => videoService.getSharedDevices(), - getSkipVideoPreview: fromInterface => videoService.getSkipVideoPreview(fromInterface), getUserParameterProfile: () => videoService.getUserParameterProfile(), isMultipleCamerasEnabled: () => videoService.isMultipleCamerasEnabled(), monitor: conn => videoService.monitor(conn), diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-button/container.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-button/container.jsx index b730020c953f177402147a26df8b9cb46ff8ff33..b0beacce256de7951e257aecf754ea3b8dfbb96f 100755 --- a/bigbluebutton-html5/imports/ui/components/video-provider/video-button/container.jsx +++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-button/container.jsx @@ -15,7 +15,7 @@ const JoinVideoOptionsContainer = (props) => { ...restProps } = props; - const mountVideoPreview = () => { mountModal(<VideoPreviewContainer fromInterface />); }; + const mountVideoPreview = () => { mountModal(<VideoPreviewContainer />); }; return ( <JoinVideoButton {...{ diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml index c9a21301f3ba09a215ed4d9b08d1b26e103e0d5d..cca03719a36c8518db5fa3a997c0fe325c746668 100755 --- a/bigbluebutton-html5/private/config/settings.yml +++ b/bigbluebutton-html5/private/config/settings.yml @@ -240,6 +240,7 @@ public: enableListenOnly: true autoShareWebcam: false skipVideoPreview: false + skipVideoPreviewOnFirstJoin: false # Entry `thresholds` is an array of: # - threshold: minimum number of cameras being shared for profile to applied # profile: a camera profile id from the cameraProfiles configuration array