Redo openvidu-electron with Electron 19

This commit is contained in:
pabloFuente 2022-07-28 19:57:51 +02:00
parent 6045088d72
commit ebdf7087b0
12 changed files with 3942 additions and 21509 deletions

View File

@ -1,2 +1,3 @@
node_modules
out
.git

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,5 @@
{
"name": "openvidu-electron",
"productName": "openvidu-electron",
"version": "2.22.0",
"description": "OpenVidu Electron Tutorial",
"main": "src/main.js",
@ -8,19 +7,26 @@
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "echo \"No linting configured\""
},
"repository": "https://github.com/OpenVidu/openvidu-tutorials",
"keywords": [
"Electron",
"quick",
"start",
"tutorial",
"demo"
],
"author": "pablofuenteperez@gmail.com",
"license": "Apache-2.0",
"devDependencies": {
"@electron-forge/cli": "6.0.0-beta.65",
"@electron-forge/maker-deb": "6.0.0-beta.65",
"@electron-forge/maker-rpm": "6.0.0-beta.65",
"@electron-forge/maker-squirrel": "6.0.0-beta.65",
"@electron-forge/maker-zip": "6.0.0-beta.65",
"electron": "19.0.10"
},
"dependencies": {
"@electron/remote": "2.0.8",
"axios": "0.27.2",
"electron-squirrel-startup": "1.0.0",
"openvidu-browser": "2.22.0"
},
"config": {
"forge": {
"packagerConfig": {},
@ -28,7 +34,7 @@
{
"name": "@electron-forge/maker-squirrel",
"config": {
"name": "openvidu_electron_forge"
"name": "my_electron_app"
}
},
{
@ -47,16 +53,5 @@
}
]
}
},
"dependencies": {
"electron-squirrel-startup": "1.0.0"
},
"devDependencies": {
"@electron-forge/cli": "6.0.0-beta.57",
"@electron-forge/maker-deb": "6.0.0-beta.57",
"@electron-forge/maker-rpm": "6.0.0-beta.57",
"@electron-forge/maker-squirrel": "6.0.0-beta.57",
"@electron-forge/maker-zip": "6.0.0-beta.57",
"electron": "13.1.4"
}
}

View File

@ -1,172 +0,0 @@
const ipcRenderer = require('electron').ipcRenderer;
const BrowserWindow = require('electron').remote.BrowserWindow;
var openvidu;
var session;
var publisher;
var mySessionId;
ipcRenderer.on('screen-share-ready', (event, message) => {
if (!!message) {
// User has chosen a screen to share. screenId is message parameter
showSession();
publisher = openvidu.initPublisher("publisher", {
videoSource: "screen:" + message
});
joinSession();
}
});
function initPublisher() {
openvidu = new OpenVidu();
const shareScreen = document.getElementById("screen-sharing").checked;
if (shareScreen) {
openScreenShareModal();
} else {
publisher = openvidu.initPublisher("publisher");
joinSession();
}
}
function joinSession() {
session = openvidu.initSession();
session.on("streamCreated", function (event) {
session.subscribe(event.stream, "subscriber");
});
mySessionId = document.getElementById("sessionId").value;
getToken(mySessionId).then(token => {
session.connect(token, {
clientData: 'OpenVidu Electron'
})
.then(() => {
showSession();
session.publish(publisher);
})
.catch(error => {
console.log("There was an error connecting to the session:", error.code, error.message);
});
});
}
function leaveSession() {
session.disconnect();
hideSession();
}
function showSession() {
document.getElementById("session-header").innerText = mySessionId;
document.getElementById("join").style.display = "none";
document.getElementById("session").style.display = "block";
}
function hideSession() {
document.getElementById("join").style.display = "block";
document.getElementById("session").style.display = "none";
}
function openScreenShareModal() {
let win = new BrowserWindow({
parent: require('electron').remote.getCurrentWindow(),
modal: true,
minimizable: false,
maximizable: false,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
},
resizable: false
});
win.setMenu(null);
// win.webContents.openDevTools();
var theUrl = 'file://' + __dirname + '/modal.html'
win.loadURL(theUrl);
}
/**
* --------------------------
* SERVER-SIDE RESPONSIBILITY
* --------------------------
* These methods retrieve the mandatory user token from OpenVidu Server.
* This behavior 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 /openvidu/api/sessions)
* 2) Create a Connection in OpenVidu Server (POST /openvidu/api/sessions/<SESSION_ID>/connection)
* 3) The Connection.token must be consumed in Session.connect() method
*/
var OPENVIDU_SERVER_URL = "https://localhost:4443";
var OPENVIDU_SERVER_SECRET = "MY_SECRET";
function getToken(mySessionId) {
return createSession(mySessionId).then(sessionId => createToken(sessionId));
}
function createSession(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessions
return new Promise((resolve, reject) => {
axios.post(
OPENVIDU_SERVER_URL + "/openvidu/api/sessions",
JSON.stringify({
customSessionId: sessionId
}), {
headers: {
'Authorization': "Basic " + btoa("OPENVIDUAPP:" + OPENVIDU_SERVER_SECRET),
'Content-Type': 'application/json',
},
crossdomain: true
}
)
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server. Resolve token
resolve(res.data.id);
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
}
}).catch(error => {
if (error.response.status === 409) {
resolve(sessionId);
return false;
} else {
console.warn('No connection to OpenVidu Server. This may be a certificate error at ' + OPENVIDU_SERVER_URL);
return false;
}
});
return false;
});
}
function createToken(sessionId) { // See https://docs.openvidu.io/en/stable/reference-docs/REST-API/#post-openviduapisessionsltsession_idgtconnection
return new Promise((resolve, reject) => {
axios.post(
OPENVIDU_SERVER_URL + "/openvidu/api/sessions/" + sessionId + "/connection", {
headers: {
'Authorization': "Basic " + btoa("OPENVIDUAPP:" + OPENVIDU_SERVER_SECRET),
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
data: JSON.stringify({})
}
)
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server. Resolve token
resolve(res.data.token);
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
}
}).catch(error => {
reject(error);
});
return false;
});
}

File diff suppressed because one or more lines are too long

View File

@ -3,56 +3,49 @@
<html>
<head>
<meta charset="UTF-8">
<title>OpenVidu Electron</title>
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-2.22.0.js"></script>
<script src="axios.min.js"></script>
<script src="app.js"></script>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<title>OpenVidu Electron</title>
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
</head>
<body>
<h1>OpenVidu Electron</h1>
<!-- All of the Node.js APIs are available in this renderer process. -->
We are using Node.js <script>
document.write(process.versions.node)
</script>,
Chromium <script>
document.write(process.versions.chrome)
</script>,
and Electron <script>
document.write(process.versions.electron)
</script>
<h1>OpenVidu Electron</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<div id="join">
<h1>Join a video session</h1>
<form onsubmit="initPublisher(); return false">
<p>
<label>Session:</label>
<input type="text" id="sessionId" value="SessionA" required>
</p>
<p>
<input id="screen-sharing" type="checkbox" name="screenshare"> Share screen?<br>
</p>
<p>
<input type="submit" value="JOIN">
</p>
</form>
</div>
<div id="session" style="display: none;">
<h1 id="session-header"></h1>
<input type="button" onclick="leaveSession()" value="LEAVE">
<div>
<div id="publisher">
<h3>YOU</h3>
</div>
<div id="subscriber">
<h3>OTHERS</h3>
</div>
<div id="join">
<h1>Join a video session</h1>
<form onsubmit="initPublisher(); return false">
<p>
<label>Session:</label>
<input type="text" id="sessionId" value="SessionA" required>
</p>
<p>
<input id="screen-sharing" type="checkbox" name="screenshare"> Share screen?<br>
</p>
<p>
<input type="submit" value="JOIN">
</p>
</form>
</div>
</div>
<div id="session" style="display: none;">
<h1 id="session-header"></h1>
<input type="button" onclick="leaveSession()" value="LEAVE">
<div>
<div id="publisher">
<h3>YOU</h3>
</div>
<div id="subscriber">
<h3>OTHERS</h3>
</div>
</div>
</div>
<script src="index.js"></script>
</body>

View File

@ -0,0 +1,125 @@
const ipcRenderer = require('electron').ipcRenderer;
const { BrowserWindow } = require('@electron/remote');
const { OpenVidu } = require('openvidu-browser');
const axios = require('axios');
var openvidu;
var session;
var publisher;
var mySessionId;
ipcRenderer.on('screen-share-ready', (event, message) => {
if (!!message) {
// User has chosen a screen to share. screenId is message parameter
showSession();
publisher = openvidu.initPublisher("publisher", {
videoSource: "screen:" + message
});
joinSession();
}
});
function initPublisher() {
openvidu = new OpenVidu();
const shareScreen = document.getElementById("screen-sharing").checked;
if (shareScreen) {
openScreenShareModal();
} else {
publisher = openvidu.initPublisher("publisher");
joinSession();
}
}
async function joinSession() {
session = openvidu.initSession();
session.on("streamCreated", function (event) {
session.subscribe(event.stream, "subscriber");
});
mySessionId = document.getElementById("sessionId").value;
const token = await getToken(mySessionId);
await session.connect(token, { clientData: 'OpenVidu Electron' });
showSession();
session.publish(publisher);
}
function leaveSession() {
session.disconnect();
hideSession();
}
function showSession() {
document.getElementById("session-header").innerText = mySessionId;
document.getElementById("join").style.display = "none";
document.getElementById("session").style.display = "block";
}
function hideSession() {
document.getElementById("join").style.display = "block";
document.getElementById("session").style.display = "none";
}
function openScreenShareModal() {
let win = new BrowserWindow({
parent: require('@electron/remote').getCurrentWindow(),
modal: true,
minimizable: false,
maximizable: false,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
},
resizable: false
});
require("@electron/remote").require("@electron/remote/main").enable(win.webContents);
win.setMenu(null);
win.webContents.openDevTools();
var theUrl = 'file://' + __dirname + '/modal.html'
win.loadURL(theUrl);
}
/**
* --------------------------------------------
* 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.
*/
var APPLICATION_SERVER_URL = 'http://localhost:5000/';
async function getToken(mySessionId) {
const sessionId = await createSession(mySessionId);
return await createToken(sessionId);
}
async function 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 function createToken(sessionId) {
const response = await axios.post(APPLICATION_SERVER_URL + 'api/sessions/' + sessionId + '/connections', {}, {
headers: { 'Content-Type': 'application/json', },
});
return response.data; // The token
}

View File

@ -1,77 +1,61 @@
const {
app,
BrowserWindow,
ipcMain
} = require('electron');
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
require('@electron/remote/main').initialize()
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
})
// Enable remote module in the main window WebContents.
require("@electron/remote/main").enable(mainWindow.webContents);
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
ipcMain.on('screen-share-selected', (event, message) => {
mainWindow.webContents.send('screen-share-ready', message);
});
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
});
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`);
// Open the DevTools.
// mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
ipcMain.on('screen-share-selected', (event, message) => {
mainWindow.webContents.send('screen-share-ready', message);
});
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
app.whenReady().then(() => {
createWindow()
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
// On certificate error we disable default behaviour (stop loading the page)
// and we then say "it is all fine - true" to the callback
event.preventDefault();
callback(true);
// On certificate error we disable default behaviour (stop loading the page)
// and we then say "it is all fine - true" to the callback
event.preventDefault();
callback(true);
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
// code. You can also put them in separate files and require them here.

View File

@ -4,6 +4,7 @@
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<title>OpenVidu Electron</title>
<style>
@ -41,10 +42,7 @@
var htmlElements = [];
var selectedElement;
const {
desktopCapturer
} = require('electron')
const desktopCapturer = require('@electron/remote').desktopCapturer;
const ipcRenderer = require('electron').ipcRenderer;
// Call Electron API to list all available screens
@ -91,6 +89,6 @@
}
function closeWindow() {
require('electron').remote.getCurrentWindow().close();
require('@electron/remote').getCurrentWindow().close();
}
</script>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})

File diff suppressed because it is too large Load Diff