From 209fccbfc339a571dca52e569efbd1f2b465006e Mon Sep 17 00:00:00 2001 From: Torjus Date: Thu, 19 Jul 2018 09:14:07 +0200 Subject: [PATCH 1/6] Tear out old fullscreen functionality --- app/lib/components/FullView.jsx | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/app/lib/components/FullView.jsx b/app/lib/components/FullView.jsx index 28c1094..96b1f0f 100644 --- a/app/lib/components/FullView.jsx +++ b/app/lib/components/FullView.jsx @@ -2,7 +2,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Spinner from 'react-spinner'; -import fscreen from 'fscreen'; export default class FullView extends React.Component { @@ -51,27 +50,8 @@ export default class FullView extends React.Component const { videoTrack } = this.props; this._setTracks(videoTrack); - - if (fscreen.fullscreenEnabled) - { - fscreen.addEventListener('fullscreenchange', this.handleExitFullscreen, false); - fscreen.requestFullscreen(this.video.current); - } } - componentWillUnmount() - { - fscreen.removeEventListener('fullscreenchange', this.handleExitFullscreen); - } - - handleExitFullscreen = () => - { - if (!fscreen.fullscreenElement) - { - this.props.toggleFullscreen(); - } - }; - componentDidUpdate() { const { videoTrack } = this.props; From 88f59214e6b010eb9c26ff09029f81799a6b5905 Mon Sep 17 00:00:00 2001 From: Torjus Date: Thu, 19 Jul 2018 09:31:47 +0200 Subject: [PATCH 2/6] Move Sidebar into a separate component --- app/lib/components/Room.jsx | 116 ++---------------------------- app/lib/components/Sidebar.jsx | 125 +++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 111 deletions(-) create mode 100644 app/lib/components/Sidebar.jsx diff --git a/app/lib/components/Room.jsx b/app/lib/components/Room.jsx index 1b2ce31..7202c90 100644 --- a/app/lib/components/Room.jsx +++ b/app/lib/components/Room.jsx @@ -16,6 +16,7 @@ import ToolArea from './ToolArea/ToolArea'; import FullScreenView from './FullScreenView'; import Draggable from 'react-draggable'; import { idle } from '../utils'; +import Sidebar from './Sidebar'; // Hide toolbars after 10 seconds of inactivity. const TIMEOUT = 10 * 1000; @@ -58,42 +59,11 @@ class Room extends React.Component { const { room, - me, toolAreaOpen, amActiveSpeaker, - screenProducer, - onRoomLinkCopy, - onLogin, - onShareScreen, - onUnShareScreen, - onNeedExtension, - onLeaveMeeting + onRoomLinkCopy } = this.props; - let screenState; - let screenTip; - - if (me.needExtension) - { - screenState = 'need-extension'; - screenTip = 'Install screen sharing extension'; - } - else if (!me.canShareScreen) - { - screenState = 'unsupported'; - screenTip = 'Screen sharing not supported'; - } - else if (screenProducer) - { - screenState = 'on'; - screenTip = 'Stop screen sharing'; - } - else - { - screenState = 'off'; - screenTip = 'Start screen sharing'; - } - return (
@@ -105,6 +75,7 @@ class Room extends React.Component }} > + {room.advancedMode ? @@ -166,60 +137,7 @@ class Room extends React.Component
-
-
- { - switch (screenState) - { - case 'on': - { - onUnShareScreen(); - break; - } - case 'off': - { - onShareScreen(); - break; - } - case 'need-extension': - { - onNeedExtension(); - break; - } - default: - { - break; - } - } - }} - /> - - {me.loginEnabled ? -
onLogin()} - /> - :null - } - -
onLeaveMeeting()} - /> -
+ text : 'Room link copied to the clipboard' })); }, - onLeaveMeeting : () => - { - dispatch(requestActions.leaveRoom()); - }, - onShareScreen : () => - { - dispatch(requestActions.enableScreenSharing()); - }, - onUnShareScreen : () => - { - dispatch(requestActions.disableScreenSharing()); - }, - onNeedExtension : () => - { - dispatch(requestActions.installExtension()); - }, - onLogin : () => - { - dispatch(requestActions.userLogin()); - }, + setToolbarsVisible : (visible) => { dispatch(stateActions.setToolbarsVisible(visible)); diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Sidebar.jsx new file mode 100644 index 0000000..e065576 --- /dev/null +++ b/app/lib/components/Sidebar.jsx @@ -0,0 +1,125 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import classnames from 'classnames'; +import * as appPropTypes from './appPropTypes'; +import * as requestActions from '../redux/requestActions'; + +const Sidebar = ({ + toolbarsVisible, me, screenProducer, onLogin, onShareScreen, + onUnShareScreen, onNeedExtension, onLeaveMeeting +}) => +{ + let screenState; + let screenTip; + + if (me.needExtension) + { + screenState = 'need-extension'; + screenTip = 'Install screen sharing extension'; + } + else if (!me.canShareScreen) + { + screenState = 'unsupported'; + screenTip = 'Screen sharing not supported'; + } + else if (screenProducer) + { + screenState = 'on'; + screenTip = 'Stop screen sharing'; + } + else + { + screenState = 'off'; + screenTip = 'Start screen sharing'; + } + + return ( +
+
+ { + switch (screenState) + { + case 'on': + { + onUnShareScreen(); + break; + } + case 'off': + { + onShareScreen(); + break; + } + case 'need-extension': + { + onNeedExtension(); + break; + } + default: + { + break; + } + } + }} + /> + + {me.loginEnabled ? +
onLogin()} + /> + :null + } + +
onLeaveMeeting()} + /> +
+ ); +}; + +Sidebar.propTypes = { + toolbarsVisible : PropTypes.bool.isRequired, + me : appPropTypes.Me.isRequired, + onShareScreen : PropTypes.func.isRequired, + onUnShareScreen : PropTypes.func.isRequired, + onNeedExtension : PropTypes.func.isRequired, + onLeaveMeeting : PropTypes.func.isRequired, + onLogin : PropTypes.func.isRequired, + screenProducer : appPropTypes.Producer +}; + +const mapStateToProps = (state) => + ({ + toolbarsVisible : state.room.toolbarsVisible, + screenProducer : Object.values(state.producers) + .find((producer) => producer.source === 'screen'), + me : state.me + }); + +const mapDispatchToProps = { + onLeaveMeeting : requestActions.leaveRoom, + onShareScreen : requestActions.enableScreenSharing, + onUnShareScreen : requestActions.disableScreenSharing, + onNeedExtension : requestActions.installExtension, + onLogin : requestActions.userLogin +}; + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Sidebar); \ No newline at end of file From a26cf2fa14188070e6f71f44a482c5402bb9e732 Mon Sep 17 00:00:00 2001 From: Torjus Date: Thu, 19 Jul 2018 10:01:34 +0200 Subject: [PATCH 3/6] Add global fullscreen toggle button --- app/lib/components/Sidebar.jsx | 205 +++++++++++------- .../images/icon_fullscreen_exit_white.svg | 4 + .../images/icon_fullscreen_white.svg | 4 + app/stylus/components/Room.styl | 9 + 4 files changed, 145 insertions(+), 77 deletions(-) create mode 100644 app/resources/images/icon_fullscreen_exit_white.svg create mode 100644 app/resources/images/icon_fullscreen_white.svg diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Sidebar.jsx index e065576..28dab5f 100644 --- a/app/lib/components/Sidebar.jsx +++ b/app/lib/components/Sidebar.jsx @@ -1,96 +1,147 @@ -import React from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import classnames from 'classnames'; import * as appPropTypes from './appPropTypes'; import * as requestActions from '../redux/requestActions'; +import fscreen from 'fscreen'; -const Sidebar = ({ - toolbarsVisible, me, screenProducer, onLogin, onShareScreen, - onUnShareScreen, onNeedExtension, onLeaveMeeting -}) => +class Sidebar extends Component { - let screenState; - let screenTip; + state = { + fullscreen: false + }; - if (me.needExtension) + handleToggleFullscreen = () => { - screenState = 'need-extension'; - screenTip = 'Install screen sharing extension'; - } - else if (!me.canShareScreen) + if (fscreen.fullscreenElement) { + fscreen.exitFullscreen(); + } else { + fscreen.requestFullscreen(document.documentElement); + } + }; + + handleFullscreenChange = () => { + this.setState({ + fullscreen: fscreen.fullscreenElement !== null + }) + }; + + componentDidMount() { - screenState = 'unsupported'; - screenTip = 'Screen sharing not supported'; - } - else if (screenProducer) - { - screenState = 'on'; - screenTip = 'Stop screen sharing'; - } - else - { - screenState = 'off'; - screenTip = 'Start screen sharing'; + if (fscreen.fullscreenEnabled) + { + fscreen.addEventListener('fullscreenchange', this.handleFullscreenChange); + } } - return ( -
-
- { - switch (screenState) - { - case 'on': - { - onUnShareScreen(); - break; - } - case 'off': - { - onShareScreen(); - break; - } - case 'need-extension': - { - onNeedExtension(); - break; - } - default: - { - break; - } - } - }} - /> + componentWillUnmount() + { + if (fscreen.fullscreenEnabled) + { + fscreen.removeEventListener('fullscreenchange', this.handleFullscreenChange); + } + } + + render() { + const { + toolbarsVisible, me, screenProducer, onLogin, onShareScreen, + onUnShareScreen, onNeedExtension, onLeaveMeeting + } = this.props; + + let screenState; + let screenTip; + + if (me.needExtension) + { + screenState = 'need-extension'; + screenTip = 'Install screen sharing extension'; + } + else if (!me.canShareScreen) + { + screenState = 'unsupported'; + screenTip = 'Screen sharing not supported'; + } + else if (screenProducer) + { + screenState = 'on'; + screenTip = 'Stop screen sharing'; + } + else + { + screenState = 'off'; + screenTip = 'Start screen sharing'; + } + + return ( +
+ {fscreen.fullscreenEnabled && ( +
+ )} - {me.loginEnabled ?
onLogin()} + onClick={() => + { + switch (screenState) + { + case 'on': + { + onUnShareScreen(); + break; + } + case 'off': + { + onShareScreen(); + break; + } + case 'need-extension': + { + onNeedExtension(); + break; + } + default: + { + break; + } + } + }} /> - :null - } - -
onLeaveMeeting()} - /> -
- ); -}; + + {me.loginEnabled ? +
onLogin()} + /> + :null + } + +
onLeaveMeeting()} + /> +
+ ); + } +} Sidebar.propTypes = { toolbarsVisible : PropTypes.bool.isRequired, diff --git a/app/resources/images/icon_fullscreen_exit_white.svg b/app/resources/images/icon_fullscreen_exit_white.svg new file mode 100644 index 0000000..0d60d8e --- /dev/null +++ b/app/resources/images/icon_fullscreen_exit_white.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/resources/images/icon_fullscreen_white.svg b/app/resources/images/icon_fullscreen_white.svg new file mode 100644 index 0000000..c0f5762 --- /dev/null +++ b/app/resources/images/icon_fullscreen_white.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/stylus/components/Room.styl b/app/stylus/components/Room.styl index 932406c..ea3b42c 100644 --- a/app/stylus/components/Room.styl +++ b/app/stylus/components/Room.styl @@ -232,6 +232,14 @@ } } + &.fullscreen { + background-image: url('/resources/images/icon_fullscreen_white.svg'); + + &.on { + background-image: url('/resources/images/icon_fullscreen_exit_white.svg'); + } + } + &.screen { &.on { background-image: url('/resources/images/no-share-screen-black.svg'); @@ -250,6 +258,7 @@ background-image: url('/resources/images/share-screen-extension.svg'); } } + &.raise-hand { background-image: url('/resources/images/icon-hand-white.svg'); From f518833deb2aa737e4d14231783efb4cc55f014d Mon Sep 17 00:00:00 2001 From: Torjus Date: Thu, 19 Jul 2018 10:04:19 +0200 Subject: [PATCH 4/6] Move Sidebar CSS into separate file --- app/lib/components/Sidebar.jsx | 8 ++- app/stylus/components/Room.styl | 108 ----------------------------- app/stylus/components/Sidebar.styl | 107 ++++++++++++++++++++++++++++ app/stylus/index.styl | 1 + 4 files changed, 113 insertions(+), 111 deletions(-) create mode 100644 app/stylus/components/Sidebar.styl diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Sidebar.jsx index 28dab5f..2408229 100644 --- a/app/lib/components/Sidebar.jsx +++ b/app/lib/components/Sidebar.jsx @@ -74,9 +74,11 @@ class Sidebar extends Component } return ( -
{fscreen.fullscreenEnabled && (
.sidebar { - position: fixed; - z-index: 101; - top: calc(50% - 60px); - height: 120px; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - - +desktop() { - left: 20px; - width: 36px; - } - - +mobile() { - left: 10px; - width: 32px; - } - - > .button { - flex: 0 0 auto; - margin: 4px 0; - background-position: center; - background-size: 75%; - background-repeat: no-repeat; - background-color: rgba(#fff, 0.3); - cursor: pointer; - transition-property: opacity, background-color; - transition-duration: 0.15s; - border-radius: 100%; - - +desktop() { - height: 36px; - width: 36px; - } - - +mobile() { - height: 32px; - width: 32px; - } - - &.on { - background-color: rgba(#fff, 0.7); - } - - &.disabled { - pointer-events: none; - opacity: 0.5; - } - - &.login { - &.off { - background-image: url('/resources/images/icon_login_white.svg'); - } - } - - &.settings { - &.off { - background-image: url('/resources/images/icon_settings_white.svg'); - } - - &.on { - background-image: url('/resources/images/icon_settings_black.svg'); - } - } - - &.fullscreen { - background-image: url('/resources/images/icon_fullscreen_white.svg'); - - &.on { - background-image: url('/resources/images/icon_fullscreen_exit_white.svg'); - } - } - - &.screen { - &.on { - background-image: url('/resources/images/no-share-screen-black.svg'); - } - - &.off { - background-image: url('/resources/images/share-screen-white.svg'); - } - - &.unsupported { - 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-extension.svg'); - } - } - - &.raise-hand { - background-image: url('/resources/images/icon-hand-white.svg'); - - &.on { - background-image: url('/resources/images/icon-hand-black.svg'); - } - } - - &.leave-meeting { - background-image: url('/resources/images/leave-meeting.svg'); - } - } - } } > .toolarea-wrapper { diff --git a/app/stylus/components/Sidebar.styl b/app/stylus/components/Sidebar.styl new file mode 100644 index 0000000..12a2eb3 --- /dev/null +++ b/app/stylus/components/Sidebar.styl @@ -0,0 +1,107 @@ +[data-component='Sidebar'] { + position: fixed; + z-index: 101; + top: calc(50% - 60px); + height: 120px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + +desktop() { + left: 20px; + width: 36px; + } + + +mobile() { + left: 10px; + width: 32px; + } + + > .button { + flex: 0 0 auto; + margin: 4px 0; + background-position: center; + background-size: 75%; + background-repeat: no-repeat; + background-color: rgba(#fff, 0.3); + cursor: pointer; + transition-property: opacity, background-color; + transition-duration: 0.15s; + border-radius: 100%; + + +desktop() { + height: 36px; + width: 36px; + } + + +mobile() { + height: 32px; + width: 32px; + } + + &.on { + background-color: rgba(#fff, 0.7); + } + + &.disabled { + pointer-events: none; + opacity: 0.5; + } + + &.login { + &.off { + background-image: url('/resources/images/icon_login_white.svg'); + } + } + + &.settings { + &.off { + background-image: url('/resources/images/icon_settings_white.svg'); + } + + &.on { + background-image: url('/resources/images/icon_settings_black.svg'); + } + } + + &.fullscreen { + background-image: url('/resources/images/icon_fullscreen_white.svg'); + + &.on { + background-image: url('/resources/images/icon_fullscreen_exit_white.svg'); + } + } + + &.screen { + &.on { + background-image: url('/resources/images/no-share-screen-black.svg'); + } + + &.off { + background-image: url('/resources/images/share-screen-white.svg'); + } + + &.unsupported { + 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-extension.svg'); + } + } + + &.raise-hand { + background-image: url('/resources/images/icon-hand-white.svg'); + + &.on { + background-image: url('/resources/images/icon-hand-black.svg'); + } + } + + &.leave-meeting { + background-image: url('/resources/images/leave-meeting.svg'); + } + } +} \ No newline at end of file diff --git a/app/stylus/index.styl b/app/stylus/index.styl index dbc11ba..94e08b8 100644 --- a/app/stylus/index.styl +++ b/app/stylus/index.styl @@ -37,6 +37,7 @@ body { // Components @import './components/Room'; + @import './components/Sidebar'; @import './components/Me'; @import './components/Peers'; @import './components/Peer'; From 9c2d7bbce292b9ffc8a8643025d8fe686664529f Mon Sep 17 00:00:00 2001 From: Torjus Date: Thu, 19 Jul 2018 10:04:46 +0200 Subject: [PATCH 5/6] Fix linting in Sidebar --- app/lib/components/Sidebar.jsx | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Sidebar.jsx index 2408229..1631c7c 100644 --- a/app/lib/components/Sidebar.jsx +++ b/app/lib/components/Sidebar.jsx @@ -9,22 +9,26 @@ import fscreen from 'fscreen'; class Sidebar extends Component { state = { - fullscreen: false + fullscreen : false }; handleToggleFullscreen = () => { - if (fscreen.fullscreenElement) { + if (fscreen.fullscreenElement) + { fscreen.exitFullscreen(); - } else { + } + else + { fscreen.requestFullscreen(document.documentElement); } }; - handleFullscreenChange = () => { + handleFullscreenChange = () => + { this.setState({ - fullscreen: fscreen.fullscreenElement !== null - }) + fullscreen : fscreen.fullscreenElement !== null + }); }; componentDidMount() @@ -43,7 +47,8 @@ class Sidebar extends Component } } - render() { + render() + { const { toolbarsVisible, me, screenProducer, onLogin, onShareScreen, onUnShareScreen, onNeedExtension, onLeaveMeeting @@ -83,7 +88,7 @@ class Sidebar extends Component {fscreen.fullscreenEnabled && (
Date: Thu, 19 Jul 2018 10:23:29 +0200 Subject: [PATCH 6/6] Use the generic black background for FullView --- app/stylus/components/FullView.styl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/stylus/components/FullView.styl b/app/stylus/components/FullView.styl index a31f3d9..103a491 100644 --- a/app/stylus/components/FullView.styl +++ b/app/stylus/components/FullView.styl @@ -6,9 +6,10 @@ display: flex; flex-direction: column; overflow: hidden; - background-color: rgba(#2a4b58, 0.9); - background-position: bottom; - background-size: auto 85%; + background-image: url('/resources/images/background.svg'); + background-attachment: fixed; + background-position: center; + background-size: cover; background-repeat: no-repeat; > .info {