@@ -111,19 +140,35 @@ export default class PeerView extends React.Component
+ {screenVisible ?
+
+
+
+ :null
+ }
+
- {videoProfile === 'none' ?
+ {videoProfile === 'none' && screenProfile === 'none' ?
@@ -135,9 +180,9 @@ export default class PeerView extends React.Component
componentDidMount()
{
- const { audioTrack, videoTrack } = this.props;
+ const { audioTrack, videoTrack, screenTrack } = this.props;
- this._setTracks(audioTrack, videoTrack);
+ this._setTracks(audioTrack, videoTrack, screenTrack);
}
componentWillUnmount()
@@ -150,18 +195,21 @@ export default class PeerView extends React.Component
componentWillReceiveProps(nextProps)
{
- const { audioTrack, videoTrack } = nextProps;
+ const { audioTrack, videoTrack, screenTrack } = nextProps;
- this._setTracks(audioTrack, videoTrack);
+ this._setTracks(audioTrack, videoTrack, screenTrack);
}
- _setTracks(audioTrack, videoTrack)
+ _setTracks(audioTrack, videoTrack, screenTrack)
{
- if (this._audioTrack === audioTrack && this._videoTrack === videoTrack)
+ if (this._audioTrack === audioTrack &&
+ this._videoTrack === videoTrack &&
+ this._screenTrack === screenTrack)
return;
this._audioTrack = audioTrack;
this._videoTrack = videoTrack;
+ this._screenTrack = screenTrack;
if (this._hark)
this._hark.stop();
@@ -169,9 +217,9 @@ export default class PeerView extends React.Component
clearInterval(this._videoResolutionTimer);
this._hideVideoResolution();
- const { video } = this.refs;
+ const { video, minivideo } = this.refs;
- if (audioTrack || videoTrack)
+ if (audioTrack || videoTrack || screenTrack)
{
const stream = new MediaStream;
@@ -181,7 +229,19 @@ export default class PeerView extends React.Component
if (videoTrack)
stream.addTrack(videoTrack);
- video.srcObject = stream;
+ if (screenTrack)
+ {
+ const screenStream = new MediaStream;
+
+ screenStream.addTrack(screenTrack);
+
+ video.srcObject = screenStream;
+ minivideo.srcObject = stream;
+ }
+ else
+ {
+ video.srcObject = stream;
+ }
if (audioTrack)
this._runHark(stream);
@@ -252,9 +312,13 @@ PeerView.propTypes =
[ appPropTypes.Me, appPropTypes.Peer ]).isRequired,
audioTrack : PropTypes.any,
videoTrack : PropTypes.any,
+ screenTrack : PropTypes.any,
videoVisible : PropTypes.bool.isRequired,
videoProfile : PropTypes.string,
+ screenVisible : PropTypes.bool.isRequired,
+ screenProfile : PropTypes.string,
audioCodec : PropTypes.string,
videoCodec : PropTypes.string,
+ screenCodec : PropTypes.string,
onChangeDisplayName : PropTypes.func
};
diff --git a/app/lib/index.jsx b/app/lib/index.jsx
index dbd91c4..e4f9cd2 100644
--- a/app/lib/index.jsx
+++ b/app/lib/index.jsx
@@ -5,7 +5,8 @@ import { render } from 'react-dom';
import { Provider } from 'react-redux';
import {
applyMiddleware as applyReduxMiddleware,
- createStore as createReduxStore
+ createStore as createReduxStore,
+ compose as composeRedux
} from 'redux';
import thunk from 'redux-thunk';
import { createLogger as createReduxLogger } from 'redux-logger';
@@ -40,10 +41,22 @@ if (process.env.NODE_ENV === 'development')
reduxMiddlewares.push(reduxLogger);
}
+const composeEnhancers =
+typeof window === 'object' &&
+window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
+ window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+ // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
+ }) : composeRedux;
+
+const enhancer = composeEnhancers(
+ applyReduxMiddleware(...reduxMiddlewares)
+ // other store enhancers if any
+);
+
const store = createReduxStore(
reducers,
undefined,
- applyReduxMiddleware(...reduxMiddlewares)
+ enhancer
);
domready(() =>
diff --git a/app/stylus/components/PeerScreenView.styl b/app/stylus/components/PeerScreenView.styl
deleted file mode 100644
index d83e108..0000000
--- a/app/stylus/components/PeerScreenView.styl
+++ /dev/null
@@ -1,146 +0,0 @@
-[data-component='PeerScreenView'] {
- position: relative;
- flex: 100 100 auto;
- height: 100%;
- width: 100%;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- background-color: rgba(#2a4b58, 0.9);
- background-image: url('/resources/images/buddy.svg');
- background-position: bottom;
- background-size: auto 85%;
- background-repeat: no-repeat;
-
- > .info {
- $backgroundTint = #000;
-
- position: absolute;
- z-index: 5
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- background: linear-gradient(to bottom,
- rgba($backgroundTint, 0) 0%,
- rgba($backgroundTint, 0) 60%,
- rgba($backgroundTint, 0.1) 70%,
- rgba($backgroundTint, 0.8) 100%);
-
- > .media {
- flex: 0 0 auto;
- display: flex;
- flex-direction: row;
-
- > .box {
- margin: 4px;
- padding: 2px 4px;
- border-radius: 2px;
- background-color: rgba(#000, 0.25);
-
- > p {
- user-select: none;
- pointer-events: none;
- margin-bottom: 2px;
- color: rgba(#fff, 0.7);
- font-size: 10px;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
- }
-
- > .peer {
- flex: 0 0 auto;
- display: flex;
- flex-direction: column;
- justify-content: flex-end;
-
- +desktop() {
- &.is-me {
- padding: 10px;
- align-items: flex-start;
- }
-
- &:not(.is-me) {
- padding: 20px;
- align-items: flex-start;
- }
- }
-
- +mobile() {
- &.is-me {
- padding: 10px;
- align-items: flex-start;
- }
-
- &:not(.is-me) {
- padding: 10px;
- align-items: flex-end;
- }
- }
- }
- }
-
- > video {
- flex: 100 100 auto;
- height: 100%;
- width: 100%;
- object-fit: cover;
- user-select: none;
- transition-property: opacity;
- transition-duration: .15s;
- background-color: rgba(#000, 0.75);
-
- &.is-me {
- transform: scaleX(-1);
- }
-
- &.hidden {
- opacity: 0;
- transition-duration: 0s;
- }
-
- &.loading {
- filter: blur(5px);
- }
- }
-
- > .spinner-container {
- position: absolute;
- top: 0
- bottom: 0;
- left: 0;
- right: 0;
- background-color: rgba(#000, 0.75);
-
- .react-spinner {
- position: relative;
- width: 48px;
- height: 48px;
- top: 50%;
- left: 50%;
-
- .react-spinner_bar {
- position: absolute;
- width: 20%;
- height: 7.8%;
- top: -3.9%;
- left: -10%;
- animation: PeerView-spinner 1.2s linear infinite;
- border-radius: 5px;
- background-color: rgba(#fff, 0.5);
- }
- }
- }
-}
-
-@keyframes PeerScreenView-spinner {
- 0% { opacity: 1; }
- 100% { opacity: 0.15; }
-}
diff --git a/app/stylus/components/PeerView.styl b/app/stylus/components/PeerView.styl
index a44610c..1230284 100644
--- a/app/stylus/components/PeerView.styl
+++ b/app/stylus/components/PeerView.styl
@@ -24,11 +24,6 @@
display: flex;
flex-direction: column;
justify-content: space-between;
- background: linear-gradient(to bottom,
- rgba($backgroundTint, 0) 0%,
- rgba($backgroundTint, 0) 60%,
- rgba($backgroundTint, 0.1) 70%,
- rgba($backgroundTint, 0.8) 100%);
> .media {
flex: 0 0 auto;
@@ -195,6 +190,39 @@
}
}
+ > .minivideo {
+ height: 15%;
+ width: 15%;
+ bottom: 1%;
+ right: 1%;
+ position: absolute;
+ overflow: hidden;
+
+ > video {
+ flex: 100 100 auto;
+ height: 100%;
+ width: 100%;
+ object-fit: cover;
+ user-select: none;
+ transition-property: opacity;
+ transition-duration: .15s;
+ background-color: rgba(#000, 0.75);
+
+ &.is-me {
+ transform: scaleX(-1);
+ }
+
+ &.hidden {
+ opacity: 0;
+ transition-duration: 0s;
+ }
+
+ &.loading {
+ filter: blur(5px);
+ }
+ }
+ }
+
> .volume-container {
position: absolute;
top: 0
diff --git a/app/stylus/index.styl b/app/stylus/index.styl
index db3084e..f73898b 100644
--- a/app/stylus/index.styl
+++ b/app/stylus/index.styl
@@ -40,7 +40,6 @@ body {
@import './components/Peers';
@import './components/Peer';
@import './components/PeerView';
- @import './components/PeerScreenView';
@import './components/Notifications';
@import './components/Chat';
}
diff --git a/server/lib/Room.js b/server/lib/Room.js
index 4a72188..dbe067e 100644
--- a/server/lib/Room.js
+++ b/server/lib/Room.js
@@ -254,7 +254,7 @@ class Room extends EventEmitter
protooPeer.send(
'chat-history-receive',
- { chatHistory : this._chatHistory }
+ { chatHistory: this._chatHistory }
);
break;