diff --git a/app/index.html b/app/index.html index ea79bc7..62d7bb6 100644 --- a/app/index.html +++ b/app/index.html @@ -16,7 +16,7 @@ if (window.antiglobal) { - window.antiglobal('___browserSync___oldSocketIo', 'io', '___browserSync___', '__core-js_shared__'); + window.antiglobal('__multipartyMeetingScreenShareExtensionAvailable__', '___browserSync___oldSocketIo', 'io', '___browserSync___', '__core-js_shared__'); setInterval(window.antiglobal, 180000); } diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index ab5b7a4..5109311 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -6,7 +6,6 @@ import { getProtooUrl } from './urlFactory'; import * as cookiesManager from './cookiesManager'; import * as requestActions from './redux/requestActions'; import * as stateActions from './redux/stateActions'; -import { getBrowserType } from './utils'; const logger = new Logger('RoomClient'); @@ -81,8 +80,7 @@ export default class RoomClient // Local Webcam. Object with: // - {MediaDeviceInfo} [device] // - {String} [resolution] - 'qvga' / 'vga' / 'hd'. - this._webcam = - { + this._webcam = { device : null, resolution : 'hd' }; @@ -195,6 +193,57 @@ export default class RoomClient this._micProducer.resume(); } + installExtension() + { + logger.debug('installExtension()'); + + return Promise.resolve() + .then(() => + { + window.addEventListener('message', _onExtensionMessage, false); + function _onExtensionMessage({ data }) + { + if (data.type === 'ScreenShareInjected') + { + logger.debug('installExtension() | installation succeeded'); + + return; + } + } + + function _failedInstall(reason) + { + window.removeEventListener('message', _onExtensionMessage); + + return Promise.reject( + new Error('Failed to install extension: %s', reason)); + } + + function _successfulInstall() + { + logger.debug('installExtension() | installation accepted'); + } + + // eslint-disable-next-line no-undef + chrome.webstore.install(null, _successfulInstall, _failedInstall); + }) + .then(() => + { + this._dispatch(stateActions.setScreenCapabilities( + { + canShareScreen : true, + needExtension : false + })); + }) + .catch((error) => + { + logger.error('enableScreenSharing() | failed: %o', error); + + this._dispatch( + stateActions.setScreenShareInProgress(false)); + }); + } + enableScreenSharing() { logger.debug('enableScreenSharing()'); @@ -203,37 +252,6 @@ export default class RoomClient stateActions.setScreenShareInProgress(true)); return Promise.resolve() - .then(() => - { - const browser = getBrowserType(); - - switch (browser) - { - case 'chrome': - { - // Check if we have extension, if not, try to install - // if (!('__multipartyMeetingScreenShareExtensionAvailable__' in window)) - // { - // window.addEventListener('message', function(ev) - // { - // if (ev.data.type === 'ScreenShareInjected') - // { - // } - // }, false); - // } - break; - } - case 'firefox': - { - break; - } - default: - { - return Promise.reject( - new Error('Unsupported browser for screen sharing')); - } - } - }) .then(() => { return this._setScreenShareProducer(); @@ -820,9 +838,14 @@ export default class RoomClient // Set our media capabilities. this._dispatch(stateActions.setMediaCapabilities( { - canSendMic : this._room.canSend('audio'), - canSendWebcam : this._room.canSend('video'), - canShareScreen : this._room.canSend('video') + canSendMic : this._room.canSend('audio'), + canSendWebcam : this._room.canSend('video') + })); + this._dispatch(stateActions.setScreenCapabilities( + { + canShareScreen : this._room.canSend('video') && + this._screenSharing.isScreenShareAvailable(), + needExtension : this._screenSharing.needExtension() })); }) .then(() => @@ -1007,7 +1030,8 @@ export default class RoomClient return Promise.resolve() .then(() => { - const available = this._screenSharing.isScreenShareAvailable(); + const available = this._screenSharing.isScreenShareAvailable() && + !this._screenSharing.needExtension(); if (!available) throw new Error('screen sharing not available'); diff --git a/app/lib/ScreenShare.js b/app/lib/ScreenShare.js index b598bc6..36d2760 100644 --- a/app/lib/ScreenShare.js +++ b/app/lib/ScreenShare.js @@ -63,6 +63,16 @@ class ChromeScreenShare return false; } + + needExtension() + { + if ('__multipartyMeetingScreenShareExtensionAvailable__' in window) + { + return false; + } + + return true; + } _toConstraints(options, streamId) { @@ -135,6 +145,11 @@ class FirefoxScreenShare return true; } + needExtension() + { + return false; + } + _toConstraints(options) { const constraints = { diff --git a/app/lib/components/Room.jsx b/app/lib/components/Room.jsx index 74284bc..2f16175 100644 --- a/app/lib/components/Room.jsx +++ b/app/lib/components/Room.jsx @@ -20,12 +20,27 @@ class Room extends React.Component room, me, amActiveSpeaker, + screenProducer, onRoomLinkCopy, onSetAudioMode, onRestartIce, - onLeaveMeeting + onLeaveMeeting, + onShareScreen, + onUnShareScreen, + onNeedExtension } = this.props; + let screenState; + + if (me.needExtension) + screenState = 'need-extension'; + else if (!me.canShareScreen) + screenState = 'unsupported'; + else if (screenProducer) + screenState = 'on'; + else + screenState = 'off'; + return (
@@ -79,6 +94,37 @@ class Room extends React.Component
+
+ { + switch (screenState) + { + case 'on': + { + onUnShareScreen(); + break; + } + case 'off': + { + onShareScreen(); + break; + } + case 'need-extension': + { + onNeedExtension(); + break; + } + default: + { + break; + } + } + }} + /> +
{ + const producersArray = Object.values(state.producers); + const screenProducer = + producersArray.find((producer) => producer.source === 'screen'); + return { room : state.room, me : state.me, - amActiveSpeaker : state.me.name === state.room.activeSpeakerName + amActiveSpeaker : state.me.name === state.room.activeSpeakerName, + screenProducer : screenProducer }; }; @@ -161,6 +216,18 @@ const mapDispatchToProps = (dispatch) => onLeaveMeeting : () => { dispatch(requestActions.leaveRoom()); + }, + onShareScreen : () => + { + dispatch(requestActions.enableScreenSharing()); + }, + onUnShareScreen : () => + { + dispatch(requestActions.disableScreenSharing()); + }, + onNeedExtension : () => + { + dispatch(requestActions.installExtension()); } }; }; diff --git a/app/lib/redux/reducers/me.js b/app/lib/redux/reducers/me.js index be24a81..dd6b41c 100644 --- a/app/lib/redux/reducers/me.js +++ b/app/lib/redux/reducers/me.js @@ -6,7 +6,8 @@ const initialState = device : null, canSendMic : false, canSendWebcam : false, - canShareScreen : true, + canShareScreen : false, + needExtension : false, canChangeWebcam : false, webcamInProgress : false, screenShareInProgress : false, @@ -28,9 +29,16 @@ const me = (state = initialState, action) => case 'SET_MEDIA_CAPABILITIES': { - const { canSendMic, canSendWebcam, canShareScreen } = action.payload; + const { canSendMic, canSendWebcam } = action.payload; - return { ...state, canSendMic, canSendWebcam, canShareScreen }; + return { ...state, canSendMic, canSendWebcam }; + } + + case 'SET_SCREEN_CAPABILITIES': + { + const { canShareScreen, needExtension } = action.payload; + + return { ...state, canShareScreen, needExtension }; } case 'SET_CAN_CHANGE_WEBCAM': diff --git a/app/lib/redux/requestActions.js b/app/lib/redux/requestActions.js index 5a53fb5..1c3b304 100644 --- a/app/lib/redux/requestActions.js +++ b/app/lib/redux/requestActions.js @@ -99,6 +99,13 @@ export const disableScreenSharing = () => }; }; +export const installExtension = () => +{ + return { + type : 'INSTALL_EXTENSION' + }; +}; + export const sendChatMessage = (text, name) => { const message = createNewMessage(text, 'response', name); diff --git a/app/lib/redux/roomClientMiddleware.js b/app/lib/redux/roomClientMiddleware.js index 9ba36a8..fed0951 100644 --- a/app/lib/redux/roomClientMiddleware.js +++ b/app/lib/redux/roomClientMiddleware.js @@ -123,6 +123,13 @@ export default ({ dispatch, getState }) => (next) => break; } + case 'INSTALL_EXTENSION': + { + client.installExtension(); + + break; + } + case 'SEND_CHAT_MESSAGE': { const { message } = action.payload; diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index c788b25..c55bfcd 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -30,11 +30,19 @@ export const setMe = ({ peerName, displayName, displayNameSet, device }) => }; }; -export const setMediaCapabilities = ({ canSendMic, canSendWebcam, canShareScreen }) => +export const setMediaCapabilities = ({ canSendMic, canSendWebcam }) => { return { type : 'SET_MEDIA_CAPABILITIES', - payload : { canSendMic, canSendWebcam, canShareScreen } + payload : { canSendMic, canSendWebcam } + }; +}; + +export const setScreenCapabilities = ({ canShareScreen, needExtension }) => +{ + return { + type : 'SET_SCREEN_CAPABILITIES', + payload : { canShareScreen, needExtension } }; }; diff --git a/app/resources/images/share-screen-extension.svg b/app/resources/images/share-screen-extension.svg new file mode 100644 index 0000000..8d30bb3 --- /dev/null +++ b/app/resources/images/share-screen-extension.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index d305da7..8f8ec1e 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -234,20 +234,20 @@ &.screen { &.on { - background-image: url('/resources/images/unshare-screen.svg'); + background-image: url('/resources/images/no-share-screen-black.svg'); } &.off { - background-image: url('/resources/images/share-screen.svg'); + background-image: url('/resources/images/share-screen-black.svg'); } &.unsupported { - background-image: url('/resources/images/unshare-screen.svg'); + background-image: url('/resources/images/no-share-screen-white.svg'); background-color: rgba(#d42241, 0.7); } &.need-extension { - background-image: url('/resources/images/share-screen.svg'); + background-image: url('/resources/images/share-screen-extension.svg'); } }