Added openvidu react tutorial
This commit is contained in:
parent
60dac7c25c
commit
4ac72dc2d2
21
openvidu-insecure-react/.gitignore
vendored
Normal file
21
openvidu-insecure-react/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
2444
openvidu-insecure-react/README.md
Normal file
2444
openvidu-insecure-react/README.md
Normal file
File diff suppressed because it is too large
Load Diff
15146
openvidu-insecure-react/package-lock.json
generated
Normal file
15146
openvidu-insecure-react/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
openvidu-insecure-react/package.json
Normal file
18
openvidu-insecure-react/package.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "openvidu-insecure-react",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"openvidu-browser": "^2.4.0",
|
||||
"react": "^16.4.2",
|
||||
"react-dom": "^16.4.2",
|
||||
"react-scripts": "1.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
}
|
||||
}
|
||||
76
openvidu-insecure-react/public/index.html
Normal file
76
openvidu-insecure-react/public/index.html
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="./resources/images/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
|
||||
crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
|
||||
crossorigin="anonymous">
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
|
||||
crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<!-- Bootstrap -->
|
||||
<title>openvidu-insecure-react App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img class="demo-logo" src="resources/images/openvidu_vert_white_bg_trans_cropped.png" /> Insecure React</a>
|
||||
<a class="navbar-brand nav-icon" href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-insecure-react" title="GitHub Repository" target="_blank">
|
||||
<i class="fa fa-github" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-insecure-react/" title="Documentation" target="_blank">
|
||||
<i class="fa fa-book" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<div class="text-muted">OpenVidu © 2018</div>
|
||||
<a href="http://www.openvidu.io/" target="_blank">
|
||||
<img class="openvidu-logo" src="resources/images/openvidu_globe_bg_transp_cropped.png" />
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
15
openvidu-insecure-react/public/manifest.json
Normal file
15
openvidu-insecure-react/public/manifest.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
BIN
openvidu-insecure-react/public/resources/images/favicon.ico
Normal file
BIN
openvidu-insecure-react/public/resources/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
3
openvidu-insecure-react/src/App.css
Normal file
3
openvidu-insecure-react/src/App.css
Normal file
@ -0,0 +1,3 @@
|
||||
.stream-container {
|
||||
padding: 0;
|
||||
}
|
||||
338
openvidu-insecure-react/src/App.js
Normal file
338
openvidu-insecure-react/src/App.js
Normal file
@ -0,0 +1,338 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios';
|
||||
import './App.css';
|
||||
import {OpenVidu} from 'openvidu-browser';
|
||||
import UserVideoComponent from './UserVideoComponent';
|
||||
|
||||
const OPENVIDU_SERVER_URL = 'https://' + window.location.hostname + ':4443';
|
||||
const OPENVIDU_SERVER_SECRET = 'MY_SECRET';
|
||||
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
mySessionId: 'SessionA',
|
||||
myUserName: 'Participant' + Math.floor(Math.random() * 100),
|
||||
session: undefined,
|
||||
mainStreamManager: undefined,
|
||||
publisher: undefined,
|
||||
subscribers: [],
|
||||
};
|
||||
|
||||
this.joinSession = this.joinSession.bind(this);
|
||||
this.leaveSession = this.leaveSession.bind(this);
|
||||
this.handleChangeSessionId = this.handleChangeSessionId.bind(this);
|
||||
this.handleChangeUserName = this.handleChangeUserName.bind(this);
|
||||
this.handleMainVideoStream = this.handleMainVideoStream.bind(this);
|
||||
this.onbeforeunload = this.onbeforeunload.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('beforeunload', this.onbeforeunload);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('beforeunload', this.onbeforeunload);
|
||||
}
|
||||
|
||||
onbeforeunload(event) {
|
||||
this.leaveSession();
|
||||
}
|
||||
|
||||
handleChangeSessionId(e) {
|
||||
this.setState({
|
||||
mySessionId: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handleChangeUserName(e) {
|
||||
this.setState({
|
||||
myUserName: e.target.value,
|
||||
});
|
||||
}
|
||||
|
||||
handleMainVideoStream(stream) {
|
||||
this.setState({
|
||||
mainStreamManager: stream,
|
||||
});
|
||||
}
|
||||
|
||||
deleteSubscriber(streamManager) {
|
||||
let subscribers = this.state.subscribers;
|
||||
let index = subscribers.indexOf(streamManager, 0);
|
||||
if (index > -1) {
|
||||
subscribers.splice(index, 1);
|
||||
this.setState({
|
||||
subscriber: subscribers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
joinSession() {
|
||||
// --- 1) Get an OpenVidu object ---
|
||||
|
||||
this.OV = new OpenVidu();
|
||||
|
||||
// --- 2) Init a session ---
|
||||
|
||||
this.setState(
|
||||
{
|
||||
session: this.OV.initSession(),
|
||||
},
|
||||
() => {
|
||||
var mySession = this.state.session;
|
||||
|
||||
// --- 3) Specify the actions when events take place in the session ---
|
||||
|
||||
// On every new Stream received...
|
||||
mySession.on('streamCreated', (event) => {
|
||||
// Subscribe to the Stream to receive it. Second parameter is undefined
|
||||
// so OpenVidu doesn't create an HTML video by its own
|
||||
var subscriber = mySession.subscribe(event.stream, undefined);
|
||||
var subscribers = this.state.subscribers;
|
||||
subscribers.push(subscriber);
|
||||
|
||||
// Update the state with the new subscribers
|
||||
this.setState({
|
||||
subscribers: subscribers,
|
||||
});
|
||||
});
|
||||
|
||||
// On every Stream destroyed...
|
||||
mySession.on('streamDestroyed', (event) => {
|
||||
|
||||
// Remove the stream from 'subscribers' array
|
||||
this.deleteSubscriber(event.stream.streamManager);
|
||||
});
|
||||
|
||||
// --- 4) Connect to the session with a valid user token ---
|
||||
|
||||
// 'getToken' method is simulating what your server-side should do.
|
||||
// 'token' parameter should be retrieved and returned by your own backend
|
||||
this.getToken().then((token) => {
|
||||
// First param is the token got from OpenVidu Server. Second param can be retrieved by every user on event
|
||||
// 'streamCreated' (property Stream.connection.data), and will be appended to DOM as the user's nickname
|
||||
mySession
|
||||
.connect(
|
||||
token,
|
||||
{ clientData: this.state.myUserName },
|
||||
)
|
||||
.then(() => {
|
||||
|
||||
// --- 5) Get your own camera stream ---
|
||||
|
||||
// Init a publisher passing undefined as targetElement (we don't want OpenVidu to insert a video
|
||||
// element: we will manage it on our own) and with the desired properties
|
||||
let publisher = this.OV.initPublisher(undefined, {
|
||||
audioSource: undefined, // The source of audio. If undefined default microphone
|
||||
videoSource: undefined, // The source of video. If undefined default webcam
|
||||
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
|
||||
publishVideo: true, // Whether you want to start publishing with your video enabled or not
|
||||
resolution: '640x480', // The resolution of your video
|
||||
frameRate: 30, // The frame rate of your video
|
||||
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
|
||||
mirror: false, // Whether to mirror your local video or not
|
||||
});
|
||||
|
||||
// --- 6) Publish your stream ---
|
||||
|
||||
mySession.publish(publisher);
|
||||
|
||||
// Set the main video in the page to display our webcam and store our Publisher
|
||||
this.setState({
|
||||
mainStreamManager: publisher,
|
||||
publisher: publisher,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('There was an error connecting to the session:', error.code, error.message);
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
leaveSession() {
|
||||
|
||||
// --- 7) Leave the session by calling 'disconnect' method over the Session object ---
|
||||
|
||||
const mySession = this.state.session;
|
||||
|
||||
if (mySession) {
|
||||
mySession.disconnect();
|
||||
}
|
||||
|
||||
// Empty all properties...
|
||||
this.OV = null;
|
||||
this.setState({
|
||||
session: undefined,
|
||||
subscribers: [],
|
||||
mySessionId: 'SessionA',
|
||||
myUserName: 'Participant' + Math.floor(Math.random() * 100),
|
||||
mainStreamManager: undefined,
|
||||
publisher: undefined
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const mySessionId = this.state.mySessionId;
|
||||
const myUserName = this.state.myUserName;
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
{this.state.session === undefined ? (
|
||||
<div id="join">
|
||||
<div id="img-div">
|
||||
<img src="resources/images/openvidu_grey_bg_transp_cropped.png" alt="OpenVidu logo" />
|
||||
</div>
|
||||
<div id="join-dialog" className="jumbotron vertical-center">
|
||||
<h1> Join a video session </h1>
|
||||
<form className="form-group" onSubmit={this.joinSession}>
|
||||
<p>
|
||||
<label>Participant: </label>
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
id="userName"
|
||||
value={myUserName}
|
||||
onChange={this.handleChangeUserName}
|
||||
required
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
<label> Session: </label>
|
||||
<input
|
||||
className="form-control"
|
||||
type="text"
|
||||
id="sessionId"
|
||||
value={mySessionId}
|
||||
onChange={this.handleChangeSessionId}
|
||||
required
|
||||
/>
|
||||
</p>
|
||||
<p className="text-center">
|
||||
<input className="btn btn-lg btn-success" name="commit" type="submit" value="JOIN" />
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{this.state.session !== undefined ? (
|
||||
<div id="session">
|
||||
<div id="session-header">
|
||||
<h1 id="session-title">{mySessionId}</h1>
|
||||
<input
|
||||
className="btn btn-large btn-danger"
|
||||
type="button"
|
||||
id="buttonLeaveSession"
|
||||
onClick={this.leaveSession}
|
||||
value="Leave session"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{this.state.mainStreamManager !== undefined ? (
|
||||
<div id="main-video" className="col-md-6">
|
||||
<UserVideoComponent streamManager={this.state.mainStreamManager} />
|
||||
</div>
|
||||
) : null}
|
||||
<div id="video-container" className="col-md-6">
|
||||
{this.state.publisher !== undefined ? (
|
||||
<div className="stream-container col-md-6 col-xs-6">
|
||||
<UserVideoComponent
|
||||
streamManager={this.state.publisher}
|
||||
mainVideoStream={this.handleMainVideoStream}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{this.state.subscribers.map((sub, i) => (
|
||||
<div key={i} className="stream-container col-md-6 col-xs-6">
|
||||
<UserVideoComponent streamManager={sub} mainVideoStream={this.handleMainVideoStream} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* --------------------------
|
||||
* SERVER-SIDE RESPONSIBILITY
|
||||
* --------------------------
|
||||
* These methods retrieve the mandatory user token from OpenVidu Server.
|
||||
* This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using
|
||||
* the API REST, openvidu-java-client or openvidu-node-client):
|
||||
* 1) Initialize a session in OpenVidu Server (POST /api/sessions)
|
||||
* 2) Generate a token in OpenVidu Server (POST /api/tokens)
|
||||
* 3) The token must be consumed in Session.connect() method
|
||||
*/
|
||||
|
||||
getToken() {
|
||||
return this.createSession(this.state.mySessionId).then((sessionId) => this.createToken(sessionId));
|
||||
}
|
||||
|
||||
createSession(sessionId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var data = JSON.stringify({ customSessionId: sessionId });
|
||||
axios
|
||||
.post(OPENVIDU_SERVER_URL + '/api/sessions', data, {
|
||||
headers: {
|
||||
Authorization: 'Basic ' + btoa('OPENVIDUAPP:' + OPENVIDU_SERVER_SECRET),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
console.log('CREATE SESION', response);
|
||||
resolve(response.data.id);
|
||||
})
|
||||
.catch((response) => {
|
||||
var error = Object.assign({}, response);
|
||||
if (error.response.status === 409) {
|
||||
resolve(sessionId);
|
||||
} else {
|
||||
console.log(error);
|
||||
console.warn(
|
||||
'No connection to OpenVidu Server. This may be a certificate error at ' +
|
||||
OPENVIDU_SERVER_URL,
|
||||
);
|
||||
if (
|
||||
window.confirm(
|
||||
'No connection to OpenVidu Server. This may be a certificate error at "' +
|
||||
OPENVIDU_SERVER_URL +
|
||||
'"\n\nClick OK to navigate and accept it. ' +
|
||||
'If no certificate warning is shown, then check that your OpenVidu Server is up and running at "' +
|
||||
OPENVIDU_SERVER_URL +
|
||||
'"',
|
||||
)
|
||||
) {
|
||||
window.location.assign(OPENVIDU_SERVER_URL + '/accept-certificate');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createToken(sessionId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var data = JSON.stringify({ session: sessionId });
|
||||
axios
|
||||
.post(OPENVIDU_SERVER_URL + '/api/tokens', data, {
|
||||
headers: {
|
||||
Authorization: 'Basic ' + btoa('OPENVIDUAPP:' + OPENVIDU_SERVER_SECRET),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then((response) => {
|
||||
console.log('TOKEN', response);
|
||||
resolve(response.data.token);
|
||||
})
|
||||
.catch((error) => reject(error));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
9
openvidu-insecure-react/src/App.test.js
Normal file
9
openvidu-insecure-react/src/App.test.js
Normal file
@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const div = document.createElement('div');
|
||||
ReactDOM.render(<App />, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
});
|
||||
27
openvidu-insecure-react/src/OvVideo.js
Normal file
27
openvidu-insecure-react/src/OvVideo.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class OpenViduVideoComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
console.log(props);
|
||||
|
||||
this.videoRef = React.createRef();
|
||||
}
|
||||
|
||||
/*componentWillReceiveProps(props) {
|
||||
if (props && !!this.videoRef) {
|
||||
this.props.streamManager.addVideoElement(this.videoRef.current);
|
||||
}
|
||||
}*/
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props && !!this.videoRef) {
|
||||
this.props.streamManager.addVideoElement(this.videoRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <video autoPlay={true} ref={this.videoRef} />;
|
||||
}
|
||||
}
|
||||
19
openvidu-insecure-react/src/UserVideo.css
Normal file
19
openvidu-insecure-react/src/UserVideo.css
Normal file
@ -0,0 +1,19 @@
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
.streamcomponent div {
|
||||
position: absolute;
|
||||
background: #f8f8f8;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
color: #777777;
|
||||
font-weight: bold;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
p{
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
38
openvidu-insecure-react/src/UserVideoComponent.js
Normal file
38
openvidu-insecure-react/src/UserVideoComponent.js
Normal file
@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react';
|
||||
import './UserVideo.css';
|
||||
import OpenViduVideoComponent from './OvVideo';
|
||||
|
||||
export default class UserVideoComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleVideoClicked = this.handleVideoClicked.bind(this);
|
||||
}
|
||||
|
||||
getNicknameTag() {
|
||||
// Gets the nickName of the user
|
||||
return JSON.parse(this.props.streamManager.stream.connection.data).clientData;
|
||||
}
|
||||
|
||||
handleVideoClicked(event) {
|
||||
// Triggers event for the parent component to update its main video display (other UserVideoComponent)
|
||||
if (this.props.mainVideoStream) {
|
||||
this.props.mainVideoStream(this.props.streamManager);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.streamManager !== undefined ? (
|
||||
<div className="streamcomponent" onClick={this.handleVideoClicked}>
|
||||
<OpenViduVideoComponent streamManager={this.props.streamManager} />
|
||||
<div>
|
||||
<p>{this.getNicknameTag()}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
231
openvidu-insecure-react/src/index.css
Normal file
231
openvidu-insecure-react/src/index.css
Normal file
@ -0,0 +1,231 @@
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
nav {
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
background-color: #4d4d4d !important;
|
||||
border-color: #4d4d4d !important;
|
||||
border-top-right-radius: 0 !important;
|
||||
border-top-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-header {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
padding: 5px 15px 5px 15px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
nav i.fa {
|
||||
font-size: 40px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
nav a:hover {
|
||||
color: #a9a9a9 !important;
|
||||
}
|
||||
|
||||
nav i.fa:hover {
|
||||
color: #a9a9a9;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
padding-bottom: 80px;
|
||||
}
|
||||
|
||||
.vertical-center {
|
||||
position: absolute;
|
||||
top: 56%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.horizontal-center {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
color: #0088aa;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #0088aa;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(0, 136, 170, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(0, 136, 170, 0.6);
|
||||
}
|
||||
|
||||
input.btn {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #06d362 !important;
|
||||
border-color: #06d362;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background-color: #1abd61 !important;
|
||||
border-color: #1abd61;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background-color: #4d4d4d;
|
||||
}
|
||||
|
||||
.footer .text-muted {
|
||||
margin: 20px 0;
|
||||
float: left;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.openvidu-logo {
|
||||
height: 35px;
|
||||
float: right;
|
||||
margin: 12px 0;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
-moz-transition: all 0.1s ease-in-out;
|
||||
-o-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
.openvidu-logo:hover {
|
||||
-webkit-filter: grayscale(0.5);
|
||||
filter: grayscale(0.5);
|
||||
}
|
||||
|
||||
.demo-logo {
|
||||
margin: 0;
|
||||
height: 22px;
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
a:hover .demo-logo {
|
||||
-webkit-filter: brightness(0.7);
|
||||
filter: brightness(0.7);
|
||||
}
|
||||
|
||||
#join-dialog h1 {
|
||||
color: #4d4d4d;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#img-div {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
top: 19%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
#img-div img {
|
||||
height: 15%;
|
||||
width: 42.5%;
|
||||
}
|
||||
|
||||
#join-dialog label {
|
||||
color: #0088aa;
|
||||
}
|
||||
|
||||
#join-dialog input.btn {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
#session-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#session-title {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#buttonLeaveSession {
|
||||
float: right;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#video-container video {
|
||||
position: relative;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#video-container p {
|
||||
display: inline-block;
|
||||
background: #f8f8f8;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
color: #777777;
|
||||
font-weight: bold;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/*video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}*/
|
||||
|
||||
#main-video p {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
background: #f8f8f8;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
left: 0;
|
||||
font-size: 22px;
|
||||
color: #777777;
|
||||
font-weight: bold;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
#main-video video {
|
||||
cursor: initial;
|
||||
}
|
||||
|
||||
#session img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: inline-block;
|
||||
object-fit: contain;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
#session #video-container img {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 50%;
|
||||
cursor: pointer;
|
||||
object-fit: cover;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
|
||||
/* xs ans md screen resolutions*/
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
.vertical-center {
|
||||
width: 85%;
|
||||
padding-top: 10px;
|
||||
top: 57%;
|
||||
}
|
||||
}
|
||||
8
openvidu-insecure-react/src/index.js
Normal file
8
openvidu-insecure-react/src/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
registerServiceWorker();
|
||||
117
openvidu-insecure-react/src/registerServiceWorker.js
Normal file
117
openvidu-insecure-react/src/registerServiceWorker.js
Normal file
@ -0,0 +1,117 @@
|
||||
// In production, we register a service worker to serve assets from local cache.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on the "N+1" visit to a page, since previously
|
||||
// cached resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
|
||||
// This link also includes instructions on opting out of this behavior.
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export default function register() {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://goo.gl/SC7cgQ'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not local host. Just register service worker
|
||||
registerValidSW(swUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the old content will have been purged and
|
||||
// the fresh content will have been added to the cache.
|
||||
// It's the perfect time to display a "New content is
|
||||
// available; please refresh." message in your web app.
|
||||
console.log('New content is available; please refresh.');
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
if (
|
||||
response.status === 404 ||
|
||||
response.headers.get('content-type').indexOf('javascript') === -1
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister();
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user