diff --git a/app/lib/components/Sidebar.jsx b/app/lib/components/Sidebar.jsx
index 7f03abb..fc9f9ae 100644
--- a/app/lib/components/Sidebar.jsx
+++ b/app/lib/components/Sidebar.jsx
@@ -4,46 +4,52 @@ import { connect } from 'react-redux';
import classnames from 'classnames';
import * as appPropTypes from './appPropTypes';
import * as requestActions from '../redux/requestActions';
-import fscreen from 'fscreen';
+import FullScreen from './FullScreen';
class Sidebar extends Component
{
- state = {
- fullscreen : false
- };
+ constructor(props)
+ {
+ super(props);
+
+ this.fullscreen = new FullScreen(document);
+ this.state = {
+ fullscreen : false
+ };
+ }
handleToggleFullscreen = () =>
{
- if (fscreen.fullscreenElement)
+ if (this.fullscreen.fullscreenElement)
{
- fscreen.exitFullscreen();
+ this.fullscreen.exitFullscreen();
}
else
{
- fscreen.requestFullscreen(document.documentElement);
+ this.fullscreen.requestFullscreen(document.documentElement);
}
};
handleFullscreenChange = () =>
{
this.setState({
- fullscreen : fscreen.fullscreenElement !== null
+ fullscreen : this.fullscreen.fullscreenElement !== null
});
};
componentDidMount()
{
- if (fscreen.fullscreenEnabled)
+ if (this.fullscreen.fullscreenEnabled)
{
- fscreen.addEventListener('fullscreenchange', this.handleFullscreenChange);
+ this.fullscreen.addEventListener('fullscreenchange', this.handleFullscreenChange);
}
}
componentWillUnmount()
{
- if (fscreen.fullscreenEnabled)
+ if (this.fullscreen.fullscreenEnabled)
{
- fscreen.removeEventListener('fullscreenchange', this.handleFullscreenChange);
+ this.fullscreen.removeEventListener('fullscreenchange', this.handleFullscreenChange);
}
}
@@ -85,7 +91,7 @@ class Sidebar extends Component
})}
data-component='Sidebar'
>
- {fscreen.fullscreenEnabled && (
+ {this.fullscreen.fullscreenEnabled && (
+ {
+ if (this.fullscreen.fullscreenElement)
+ {
+ this.fullscreen.exitFullscreen();
+ }
+ else
+ {
+ this.fullscreen.requestFullscreen(this.window.document.documentElement);
+ }
+ };
+
+ handleFullscreenChange = () =>
+ {
+ this.setState({
+ fullscreen : this.fullscreen.fullscreenElement !== null
+ });
+ };
+
+ constructor(props)
+ {
+ super(props);
+
+ this.container = document.createElement('div');
+ this.window = null;
+ this.windowCheckerInterval = null;
+ this.released = false;
+ this.fullscreen = null;
+
+ this.state = {
+ mounted : false,
+ fullscreen : false
+ };
+ }
+
+ render()
+ {
+ if (!this.state.mounted)
+ return null;
+
+ return ReactDOM.createPortal([
+
+
+ {this.fullscreen.fullscreenEnabled && (
+
+ )}
+
+ {this.props.children}
+
+ ], this.container);
+ }
+
+ componentDidMount()
+ {
+ this.openChild();
+ // eslint-disable-next-line react/no-did-mount-set-state
+ this.setState({ mounted: true });
+
+ this.fullscreen = new FullScreen(this.window.document);
+
+ if (this.fullscreen.fullscreenEnabled)
+ {
+ this.fullscreen.addEventListener('fullscreenchange', this.handleFullscreenChange);
+ }
+ }
+
+ openChild()
+ {
+ const {
+ url,
+ title,
+ name,
+ features,
+ onBlock,
+ center
+ } = this.props;
+
+ if (center === 'parent')
+ {
+ features.left =
+ (window.top.outerWidth / 2) + window.top.screenX - (features.width / 2);
+ features.top =
+ (window.top.outerHeight / 2) + window.top.screenY - (features.height / 2);
+ }
+ else if (center === 'screen')
+ {
+ const screenLeft =
+ window.screenLeft !== undefined ? window.screenLeft : screen.left;
+ const screenTop =
+ window.screenTop !== undefined ? window.screenTop : screen.top;
+
+ const width = window.innerWidth
+ ? window.innerWidth
+ : document.documentElement.clientWidth
+ ? document.documentElement.clientWidth
+ : screen.width;
+ const height = window.innerHeight
+ ? window.innerHeight
+ : document.documentElement.clientHeight
+ ? document.documentElement.clientHeight
+ : screen.height;
+
+ features.left = (width / 2) - (features.width / 2) + screenLeft;
+ features.top = (height / 2) - (features.height / 2) + screenTop;
+ }
+
+ this.window = window.open(url, name, toWindowFeatures(features));
+
+ this.windowCheckerInterval = setInterval(() =>
+ {
+ if (!this.window || this.window.closed)
+ {
+ this.release();
+ }
+ }, 50);
+
+ if (this.window)
+ {
+ this.window.document.title = title;
+ this.window.document.body.appendChild(this.container);
+
+ if (this.props.copyStyles)
+ {
+ setTimeout(() => copyStyles(document, this.window.document), 0);
+ }
+
+ this.window.addEventListener('beforeunload', () => this.release());
+ }
+ else if (typeof onBlock === 'function')
+ {
+ onBlock(null);
+ }
+ }
+
+ componentWillUnmount()
+ {
+ if (this.window)
+ {
+ if (this.fullscreen.fullscreenEnabled)
+ {
+ this.fullscreen.removeEventListener('fullscreenchange', this.handleFullscreenChange);
+ }
+
+ this.window.close();
+ }
+ }
+
+ release()
+ {
+ if (this.released)
+ {
+ return;
+ }
+
+ this.released = true;
+
+ clearInterval(this.windowCheckerInterval);
+
+ const { onUnload } = this.props;
+
+ if (typeof onUnload === 'function')
+ {
+ onUnload(null);
+ }
+ }
+}
+
+NewWindow.propTypes = {
+ children : PropTypes.node,
+ url : PropTypes.string,
+ name : PropTypes.string,
+ title : PropTypes.string,
+ features : PropTypes.object,
+ onUnload : PropTypes.func,
+ onBlock : PropTypes.func,
+ center : PropTypes.oneOf([ 'parent', 'screen' ]),
+ copyStyles : PropTypes.bool
+};
+
+function copyStyles(source, target)
+{
+ Array.from(source.styleSheets).forEach((styleSheet) =>
+ {
+ let rules;
+
+ try
+ {
+ rules = styleSheet.cssRules;
+ }
+ catch (err) {}
+
+ if (rules)
+ {
+ const newStyleEl = source.createElement('style');
+
+ Array.from(styleSheet.cssRules).forEach((cssRule) =>
+ {
+ const { cssText, type } = cssRule;
+
+ let returnText = cssText;
+
+ if ([ 3, 5 ].includes(type))
+ {
+ returnText = cssText
+ .split('url(')
+ .map((line) =>
+ {
+ if (line[1] === '/')
+ {
+ return `${line.slice(0, 1)}${
+ window.location.origin
+ }${line.slice(1)}`;
+ }
+
+ return line;
+ })
+ .join('url(');
+ }
+
+ newStyleEl.appendChild(source.createTextNode(returnText));
+ });
+
+ target.head.appendChild(newStyleEl);
+ }
+ else if (styleSheet.href)
+ {
+ const newLinkEl = source.createElement('link');
+
+ newLinkEl.rel = 'stylesheet';
+ newLinkEl.href = styleSheet.href;
+ target.head.appendChild(newLinkEl);
+ }
+ });
+}
+
+function toWindowFeatures(obj)
+{
+ return Object.keys(obj)
+ .reduce((features, name) =>
+ {
+ const value = obj[name];
+
+ if (typeof value === 'boolean')
+ {
+ features.push(`${name}=${value ? 'yes' : 'no'}`);
+ }
+ else
+ {
+ features.push(`${name}=${value}`);
+ }
+
+ return features;
+ }, [])
+ .join(',');
+}
+
+export default NewWindow;
diff --git a/app/lib/components/VideoWindow/VideoWindow.jsx b/app/lib/components/VideoWindow/VideoWindow.jsx
index c03fbdf..c5a4a56 100644
--- a/app/lib/components/VideoWindow/VideoWindow.jsx
+++ b/app/lib/components/VideoWindow/VideoWindow.jsx
@@ -1,8 +1,7 @@
import React from 'react';
import { connect } from 'react-redux';
-import NewWindow from 'react-new-window';
+import NewWindow from './NewWindow';
import PropTypes from 'prop-types';
-import classnames from 'classnames';
import * as appPropTypes from '../appPropTypes';
import * as stateActions from '../../redux/stateActions';
import FullView from '../FullView';
@@ -12,8 +11,7 @@ const VideoWindow = (props) =>
const {
advancedMode,
consumer,
- toggleConsumerWindow,
- toolbarsVisible
+ toggleConsumerWindow
} = props;
if (!consumer)
@@ -32,34 +30,12 @@ const VideoWindow = (props) =>
return (
-
- {consumerVisible && !consumer.supported ?
-
- :null
- }
-
-
-
- {
- e.stopPropagation();
- toggleConsumerWindow();
- }}
- />
-
-
-
-
+
);
};
@@ -68,15 +44,13 @@ VideoWindow.propTypes =
{
advancedMode : PropTypes.bool,
consumer : appPropTypes.Consumer,
- toggleConsumerWindow : PropTypes.func.isRequired,
- toolbarsVisible : PropTypes.bool
+ toggleConsumerWindow : PropTypes.func.isRequired
};
const mapStateToProps = (state) =>
{
return {
- consumer : state.consumers[state.room.windowConsumer],
- toolbarsVisible : state.room.toolbarsVisible
+ consumer : state.consumers[state.room.windowConsumer]
};
};
@@ -85,7 +59,7 @@ const mapDispatchToProps = (dispatch) =>
return {
toggleConsumerWindow : () =>
{
- dispatch(stateActions.toggleConsumerWindow(null));
+ dispatch(stateActions.toggleConsumerWindow());
}
};
};
diff --git a/app/package.json b/app/package.json
index ebb8fe1..21db4b7 100644
--- a/app/package.json
+++ b/app/package.json
@@ -14,7 +14,6 @@
"domready": "^1.0.8",
"drag-drop": "^4.2.0",
"file-saver": "^1.3.8",
- "fscreen": "^1.0.2",
"hark": "^1.2.2",
"js-cookie": "^2.2.0",
"magnet-uri": "^5.2.3",
diff --git a/app/stylus/components/FullScreenView.styl b/app/stylus/components/FullScreenView.styl
index fe6458d..f1f4c29 100644
--- a/app/stylus/components/FullScreenView.styl
+++ b/app/stylus/components/FullScreenView.styl
@@ -44,10 +44,15 @@
height: 5vmin;
}
- &.fullscreen {
+ &.exitfullscreen {
background-image: url('/resources/images/icon_fullscreen_exit_black.svg');
background-color: rgba(#fff, 0.7);
}
+
+ &.fullscreen {
+ background-image: url('/resources/images/icon_fullscreen_black.svg');
+ background-color: rgba(#fff, 0.7);
+ }
}
}