openvidu-react: Removed unnecessary files
This commit is contained in:
parent
8a47b0039c
commit
15b49adbc3
@ -1,27 +1 @@
|
||||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
```js
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
```
|
||||
|
||||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
||||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
||||
# openvidu-react
|
||||
|
||||
@ -1,350 +0,0 @@
|
||||
import { OpenVidu } from 'openvidu-browser';
|
||||
|
||||
import axios from 'axios';
|
||||
import React, { Component } from 'react';
|
||||
import './App.css';
|
||||
import UserVideoComponent from './UserVideoComponent';
|
||||
|
||||
const APPLICATION_SERVER_URL = process.env.NODE_ENV === 'production' ? '' : 'https://demos.openvidu.io/';
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// These properties are in the state's component in order to re-render the HTML whenever their values change
|
||||
this.state = {
|
||||
mySessionId: 'SessionA',
|
||||
myUserName: 'Participant' + Math.floor(Math.random() * 100),
|
||||
session: undefined,
|
||||
mainStreamManager: undefined, // Main video of the page. Will be the 'publisher' or one of the 'subscribers'
|
||||
publisher: undefined,
|
||||
subscribers: [],
|
||||
};
|
||||
|
||||
this.joinSession = this.joinSession.bind(this);
|
||||
this.leaveSession = this.leaveSession.bind(this);
|
||||
this.switchCamera = this.switchCamera.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) {
|
||||
if (this.state.mainStreamManager !== 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({
|
||||
subscribers: 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);
|
||||
});
|
||||
|
||||
// On every asynchronous exception...
|
||||
mySession.on('exception', (exception) => {
|
||||
console.warn(exception);
|
||||
});
|
||||
|
||||
// --- 4) Connect to the session with a valid user token ---
|
||||
|
||||
// Get a token from the OpenVidu deployment
|
||||
this.getToken().then((token) => {
|
||||
// First param is the token got from the OpenVidu deployment. 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(async () => {
|
||||
|
||||
// --- 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 = await this.OV.initPublisherAsync(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);
|
||||
|
||||
// Obtain the current video device in use
|
||||
var devices = await this.OV.getDevices();
|
||||
var videoDevices = devices.filter(device => device.kind === 'videoinput');
|
||||
var currentVideoDeviceId = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings().deviceId;
|
||||
var currentVideoDevice = videoDevices.find(device => device.deviceId === currentVideoDeviceId);
|
||||
|
||||
// Set the main video in the page to display our webcam and store our Publisher
|
||||
this.setState({
|
||||
currentVideoDevice: currentVideoDevice,
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
async switchCamera() {
|
||||
try {
|
||||
const devices = await this.OV.getDevices()
|
||||
var videoDevices = devices.filter(device => device.kind === 'videoinput');
|
||||
|
||||
if (videoDevices && videoDevices.length > 1) {
|
||||
|
||||
var newVideoDevice = videoDevices.filter(device => device.deviceId !== this.state.currentVideoDevice.deviceId)
|
||||
|
||||
if (newVideoDevice.length > 0) {
|
||||
// Creating a new publisher with specific videoSource
|
||||
// In mobile devices the default and first camera is the front one
|
||||
var newPublisher = this.OV.initPublisher(undefined, {
|
||||
videoSource: newVideoDevice[0].deviceId,
|
||||
publishAudio: true,
|
||||
publishVideo: true,
|
||||
mirror: true
|
||||
});
|
||||
|
||||
//newPublisher.once("accessAllowed", () => {
|
||||
await this.state.session.unpublish(this.state.mainStreamManager)
|
||||
|
||||
await this.state.session.publish(newPublisher)
|
||||
this.setState({
|
||||
currentVideoDevice: newVideoDevice[0],
|
||||
mainStreamManager: newPublisher,
|
||||
publisher: newPublisher,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
/>
|
||||
<input
|
||||
className="btn btn-large btn-success"
|
||||
type="button"
|
||||
id="buttonSwitchCamera"
|
||||
onClick={this.switchCamera}
|
||||
value="Switch Camera"
|
||||
/>
|
||||
</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" onClick={() => this.handleMainVideoStream(this.state.publisher)}>
|
||||
<UserVideoComponent
|
||||
streamManager={this.state.publisher} />
|
||||
</div>
|
||||
) : null}
|
||||
{this.state.subscribers.map((sub, i) => (
|
||||
<div key={sub.id} className="stream-container col-md-6 col-xs-6" onClick={() => this.handleMainVideoStream(sub)}>
|
||||
<span>{sub.id}</span>
|
||||
<UserVideoComponent streamManager={sub} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* --------------------------------------------
|
||||
* GETTING A TOKEN FROM YOUR APPLICATION SERVER
|
||||
* --------------------------------------------
|
||||
* The methods below request the creation of a Session and a Token to
|
||||
* your application server. This keeps your OpenVidu deployment secure.
|
||||
*
|
||||
* In this sample code, there is no user control at all. Anybody could
|
||||
* access your application server endpoints! In a real production
|
||||
* environment, your application server must identify the user to allow
|
||||
* access to the endpoints.
|
||||
*
|
||||
* Visit https://docs.openvidu.io/en/stable/application-server to learn
|
||||
* more about the integration of OpenVidu in your application server.
|
||||
*/
|
||||
async getToken() {
|
||||
const sessionId = await this.createSession(this.state.mySessionId);
|
||||
return await this.createToken(sessionId);
|
||||
}
|
||||
|
||||
async createSession(sessionId) {
|
||||
const response = await axios.post(APPLICATION_SERVER_URL + 'api/sessions', { customSessionId: sessionId }, {
|
||||
headers: { 'Content-Type': 'application/json', },
|
||||
});
|
||||
return response.data; // The sessionId
|
||||
}
|
||||
|
||||
async createToken(sessionId) {
|
||||
const response = await axios.post(APPLICATION_SERVER_URL + 'api/sessions/' + sessionId + '/connections', {}, {
|
||||
headers: { 'Content-Type': 'application/json', },
|
||||
});
|
||||
return response.data; // The token
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
@ -1,9 +0,0 @@
|
||||
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);
|
||||
});
|
||||
@ -1,26 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class OpenViduVideoComponent extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.videoRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidUpdate(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} />;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
import OpenViduVideoComponent from './OvVideo';
|
||||
import './UserVideo.css';
|
||||
|
||||
export default class UserVideoComponent extends Component {
|
||||
|
||||
getNicknameTag() {
|
||||
// Gets the nickName of the user
|
||||
return JSON.parse(this.props.streamManager.stream.connection.data).clientData;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{this.props.streamManager !== undefined ? (
|
||||
<div className="streamcomponent">
|
||||
<OpenViduVideoComponent streamManager={this.props.streamManager} />
|
||||
<div><p>{this.getNicknameTag()}</p></div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
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();
|
||||
@ -1,117 +0,0 @@
|
||||
// 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