From e695909911b3587cb1b01d8c935a67dfbbae8c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5var=20Aamb=C3=B8=20Fosstveit?= Date: Wed, 14 Nov 2018 13:23:22 +0100 Subject: [PATCH 1/2] Added support for moving video to new window. Fixed various bugs. --- app/lib/RoomClient.js | 24 ++++- app/lib/components/Chat/Chat.jsx | 2 +- app/lib/components/FullScreenView.jsx | 1 - app/lib/components/FullView.jsx | 7 +- app/lib/components/Peer.jsx | 27 ++++- app/lib/components/Room.jsx | 3 + app/lib/components/ScreenView.jsx | 4 +- .../components/VideoWindow/VideoWindow.jsx | 98 +++++++++++++++++++ app/lib/redux/reducers/room.js | 12 +++ app/lib/redux/stateActions.js | 8 ++ app/package.json | 1 + .../images/icon_new_window_black.svg | 8 ++ app/stylus/components/Peer.styl | 5 + 13 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 app/lib/components/VideoWindow/VideoWindow.jsx create mode 100644 app/resources/images/icon_new_window_black.svg diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index 4700f52..b709fbc 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -16,7 +16,7 @@ import { const logger = new Logger('RoomClient'); -const ROOM_OPTIONS = +let ROOM_OPTIONS = { requestTimeout : requestTimeout, transportOptions : transportOptions, @@ -71,6 +71,9 @@ export default class RoomClient // Socket.io peer connection this._signalingSocket = io(signalingUrl); + if (this._device.flag === 'firefox') + ROOM_OPTIONS = Object.assign({ iceTransportPolicy: 'relay' }, ROOM_OPTIONS); + // mediasoup-client Room instance. this._room = new mediasoupClient.Room(ROOM_OPTIONS); this._room.roomId = roomId; @@ -160,6 +163,21 @@ export default class RoomClient { this._dispatch(stateActions.toggleAdvancedMode()); this.notify('Toggled advanced mode.'); + break; + } + + case '1': // Set democratic view + { + this._dispatch(stateActions.setDisplayMode('democratic')); + this.notify('Changed layout to democratic view.'); + break; + } + + case '2': // Set filmstrip view + { + this._dispatch(stateActions.setDisplayMode('filmstrip')); + this.notify('Changed layout to filmstrip view.'); + break; } } } @@ -213,9 +231,9 @@ export default class RoomClient if (called) return; called = true; - callback(new Error('Callback timeout')); + callback(new Error('Request timeout.')); }, - 5000 + ROOM_OPTIONS.requestTimeout ); return (...args) => diff --git a/app/lib/components/Chat/Chat.jsx b/app/lib/components/Chat/Chat.jsx index 33d3d53..20f330c 100644 --- a/app/lib/components/Chat/Chat.jsx +++ b/app/lib/components/Chat/Chat.jsx @@ -58,7 +58,7 @@ Chat.propTypes = Chat.defaultProps = { senderPlaceHolder : 'Type a message...', - autofocus : true, + autofocus : false, displayName : null }; diff --git a/app/lib/components/FullScreenView.jsx b/app/lib/components/FullScreenView.jsx index d47ffda..0b3d2cb 100644 --- a/app/lib/components/FullScreenView.jsx +++ b/app/lib/components/FullScreenView.jsx @@ -56,7 +56,6 @@ const FullScreenView = (props) => videoTrack={consumer ? consumer.track : null} videoVisible={consumerVisible} videoProfile={consumerProfile} - toggleFullscreen={() => toggleConsumerFullscreen(consumer)} /> ); diff --git a/app/lib/components/FullView.jsx b/app/lib/components/FullView.jsx index 96b1f0f..ee64aa6 100644 --- a/app/lib/components/FullView.jsx +++ b/app/lib/components/FullView.jsx @@ -84,8 +84,7 @@ export default class FullView extends React.Component FullView.propTypes = { - videoTrack : PropTypes.any, - videoVisible : PropTypes.bool, - videoProfile : PropTypes.string, - toggleFullscreen : PropTypes.func.isRequired + videoTrack : PropTypes.any, + videoVisible : PropTypes.bool, + videoProfile : PropTypes.string }; diff --git a/app/lib/components/Peer.jsx b/app/lib/components/Peer.jsx index fc11ce3..ee0861f 100644 --- a/app/lib/components/Peer.jsx +++ b/app/lib/components/Peer.jsx @@ -39,6 +39,7 @@ class Peer extends Component onMuteMic, onUnmuteMic, toggleConsumerFullscreen, + toggleConsumerWindow, style } = this.props; @@ -126,6 +127,15 @@ class Peer extends Component }} /> +
+ { + e.stopPropagation(); + toggleConsumerWindow(webcamConsumer); + }} + /> +
@@ -155,6 +165,15 @@ class Peer extends Component visible : this.state.controlsVisible })} > +
+ { + e.stopPropagation(); + toggleConsumerWindow(screenConsumer); + }} + /> +
@@ -190,7 +209,8 @@ Peer.propTypes = onUnmuteMic : PropTypes.func.isRequired, streamDimensions : PropTypes.object, style : PropTypes.object, - toggleConsumerFullscreen : PropTypes.func.isRequired + toggleConsumerFullscreen : PropTypes.func.isRequired, + toggleConsumerWindow : PropTypes.func.isRequired }; const mapStateToProps = (state, { name }) => @@ -228,6 +248,11 @@ const mapDispatchToProps = (dispatch) => { if (consumer) dispatch(stateActions.toggleConsumerFullscreen(consumer.id)); + }, + toggleConsumerWindow : (consumer) => + { + if (consumer) + dispatch(stateActions.toggleConsumerWindow(consumer.id)); } }; }; diff --git a/app/lib/components/Room.jsx b/app/lib/components/Room.jsx index 64c10af..653b377 100644 --- a/app/lib/components/Room.jsx +++ b/app/lib/components/Room.jsx @@ -16,6 +16,7 @@ import Notifications from './Notifications'; import ToolAreaButton from './ToolArea/ToolAreaButton'; import ToolArea from './ToolArea/ToolArea'; import FullScreenView from './FullScreenView'; +import VideoWindow from './VideoWindow/VideoWindow'; import Draggable from 'react-draggable'; import { idle } from '../utils'; import Sidebar from './Sidebar'; @@ -88,6 +89,8 @@ class Room extends React.Component + +
diff --git a/app/lib/components/ScreenView.jsx b/app/lib/components/ScreenView.jsx index b95be2b..719c406 100644 --- a/app/lib/components/ScreenView.jsx +++ b/app/lib/components/ScreenView.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import Spinner from 'react-spinner'; -export default class PeerView extends React.Component +export default class ScreenView extends React.Component { constructor(props) { @@ -157,7 +157,7 @@ export default class PeerView extends React.Component } } -PeerView.propTypes = +ScreenView.propTypes = { isMe : PropTypes.bool, advancedMode : PropTypes.bool, diff --git a/app/lib/components/VideoWindow/VideoWindow.jsx b/app/lib/components/VideoWindow/VideoWindow.jsx new file mode 100644 index 0000000..c03fbdf --- /dev/null +++ b/app/lib/components/VideoWindow/VideoWindow.jsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import NewWindow from 'react-new-window'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import * as appPropTypes from '../appPropTypes'; +import * as stateActions from '../../redux/stateActions'; +import FullView from '../FullView'; + +const VideoWindow = (props) => +{ + const { + advancedMode, + consumer, + toggleConsumerWindow, + toolbarsVisible + } = props; + + if (!consumer) + return null; + + const consumerVisible = ( + Boolean(consumer) && + !consumer.locallyPaused && + !consumer.remotelyPaused + ); + + let consumerProfile; + + if (consumer) + consumerProfile = consumer.profile; + + return ( + +
+ {consumerVisible && !consumer.supported ? +
+

incompatible video

+
+ :null + } + +
+
+ { + e.stopPropagation(); + toggleConsumerWindow(); + }} + /> +
+ + +
+ + ); +}; + +VideoWindow.propTypes = +{ + advancedMode : PropTypes.bool, + consumer : appPropTypes.Consumer, + toggleConsumerWindow : PropTypes.func.isRequired, + toolbarsVisible : PropTypes.bool +}; + +const mapStateToProps = (state) => +{ + return { + consumer : state.consumers[state.room.windowConsumer], + toolbarsVisible : state.room.toolbarsVisible + }; +}; + +const mapDispatchToProps = (dispatch) => +{ + return { + toggleConsumerWindow : () => + { + dispatch(stateActions.toggleConsumerWindow(null)); + } + }; +}; + +const VideoWindowContainer = connect( + mapStateToProps, + mapDispatchToProps +)(VideoWindow); + +export default VideoWindowContainer; diff --git a/app/lib/redux/reducers/room.js b/app/lib/redux/reducers/room.js index 6a956fd..89d2b21 100644 --- a/app/lib/redux/reducers/room.js +++ b/app/lib/redux/reducers/room.js @@ -6,6 +6,7 @@ const initialState = showSettings : false, advancedMode : false, fullScreenConsumer : null, // ConsumerID + windowConsumer : null, // ConsumerID toolbarsVisible : true, mode : 'democratic', selectedPeerName : null, @@ -62,6 +63,17 @@ const room = (state = initialState, action) => return { ...state, fullScreenConsumer: currentConsumer ? null : consumerId }; } + case 'TOGGLE_WINDOW_CONSUMER': + { + const { consumerId } = action.payload; + const currentConsumer = state.windowConsumer; + + if (currentConsumer === consumerId) + return { ...state, windowConsumer: null }; + else + return { ...state, windowConsumer: consumerId }; + } + case 'SET_TOOLBARS_VISIBLE': { const { toolbarsVisible } = action.payload; diff --git a/app/lib/redux/stateActions.js b/app/lib/redux/stateActions.js index 2a7d30c..3ced6b6 100644 --- a/app/lib/redux/stateActions.js +++ b/app/lib/redux/stateActions.js @@ -389,6 +389,14 @@ export const toggleConsumerFullscreen = (consumerId) => }; }; +export const toggleConsumerWindow = (consumerId) => +{ + return { + type : 'TOGGLE_WINDOW_CONSUMER', + payload : { consumerId } + }; +}; + export const setToolbarsVisible = (toolbarsVisible) => ({ type : 'SET_TOOLBARS_VISIBLE', payload : { toolbarsVisible } diff --git a/app/package.json b/app/package.json index ff04fbd..ebb8fe1 100644 --- a/app/package.json +++ b/app/package.json @@ -28,6 +28,7 @@ "react-dom": "^16.5.2", "react-draggable": "^3.0.5", "react-dropdown": "^1.5.0", + "react-new-window": "0.0.9", "react-redux": "^5.0.7", "react-spinner": "^0.2.7", "react-tooltip": "^3.9.0", diff --git a/app/resources/images/icon_new_window_black.svg b/app/resources/images/icon_new_window_black.svg new file mode 100644 index 0000000..a0915e8 --- /dev/null +++ b/app/resources/images/icon_new_window_black.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/stylus/components/Peer.styl b/app/stylus/components/Peer.styl index 1f1d493..9e38042 100644 --- a/app/stylus/components/Peer.styl +++ b/app/stylus/components/Peer.styl @@ -189,6 +189,11 @@ background-image: url('/resources/images/icon_fullscreen_black.svg'); background-color: rgba(#fff, 0.7); } + + &.newwindow { + background-image: url('/resources/images/icon_new_window_black.svg'); + background-color: rgba(#fff, 0.7); + } } } } From e6b46a983aaa401a725577571cfb8eaa521ffe7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5var=20Aamb=C3=B8=20Fosstveit?= Date: Wed, 14 Nov 2018 13:54:39 +0100 Subject: [PATCH 2/2] Fix keylistener --- app/lib/RoomClient.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/RoomClient.js b/app/lib/RoomClient.js index b17dfc3..fa283d7 100644 --- a/app/lib/RoomClient.js +++ b/app/lib/RoomClient.js @@ -147,7 +147,7 @@ export default class RoomClient // Add keypress event listner on document document.addEventListener('keypress', (event) => { - const key = String.fromCharCode(event.keyCode); + const key = String.fromCharCode(event.which); const source = event.target;