Merged electron into main code. One unified codebase for both web and native version of client.
parent
aea08b4cbe
commit
99dd6433a6
|
|
@ -0,0 +1,2 @@
|
|||
react: npm start
|
||||
electron: node src/electron-wait-react
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
"description": "multiparty meeting service",
|
||||
"author": "Håvar Aambø Fosstveit <h@fosstveit.net>",
|
||||
"license": "MIT",
|
||||
"homepage": "./",
|
||||
"main": "src/electron-starter.js",
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.5.1",
|
||||
"@material-ui/icons": "^4.5.1",
|
||||
|
|
@ -13,6 +15,7 @@
|
|||
"domready": "^1.0.8",
|
||||
"file-saver": "^2.0.2",
|
||||
"hark": "^1.2.3",
|
||||
"is-electron": "^2.2.0",
|
||||
"marked": "^0.7.0",
|
||||
"mediasoup-client": "^3.2.7",
|
||||
"notistack": "^0.9.5",
|
||||
|
|
@ -41,7 +44,9 @@
|
|||
"start": "HTTPS=true PORT=4443 react-scripts start",
|
||||
"build": "react-scripts build && mkdir -p ../server/public && rm -rf ../server/public/* && cp -r build/* ../server/public/",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
"eject": "react-scripts eject",
|
||||
"electron": "electron .",
|
||||
"dev": "nf start -p 3000"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
|
|
@ -50,8 +55,10 @@
|
|||
"not op_mini all"
|
||||
],
|
||||
"devDependencies": {
|
||||
"electron": "^7.1.1",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-plugin-import": "^2.18.2",
|
||||
"eslint-plugin-react": "^7.16.0"
|
||||
"eslint-plugin-react": "^7.16.0",
|
||||
"foreman": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ var config =
|
|||
{
|
||||
loginEnabled : false,
|
||||
developmentPort : 3443,
|
||||
productionPort : 443,
|
||||
multipartyServer : 'letsmeet.no',
|
||||
turnServers : [
|
||||
{
|
||||
urls : [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,70 @@
|
|||
import isElectron from 'is-electron';
|
||||
|
||||
let electron = null;
|
||||
|
||||
if (isElectron())
|
||||
electron = window.require('electron');
|
||||
|
||||
class ElectronScreenShare
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this._stream = null;
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
return Promise.resolve()
|
||||
.then(() =>
|
||||
{
|
||||
return electron.desktopCapturer.getSources({ types: [ 'window', 'screen' ] });
|
||||
})
|
||||
.then((sources) =>
|
||||
{
|
||||
for (const source of sources)
|
||||
{
|
||||
// Currently only getting whole screen
|
||||
if (source.name === 'Entire Screen')
|
||||
{
|
||||
return navigator.mediaDevices.getUserMedia({
|
||||
audio : false,
|
||||
video :
|
||||
{
|
||||
mandatory :
|
||||
{
|
||||
chromeMediaSource : 'desktop',
|
||||
chromeMediaSourceId : source.id
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((stream) =>
|
||||
{
|
||||
this._stream = stream;
|
||||
|
||||
return stream;
|
||||
});
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
if (this._stream instanceof MediaStream === false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this._stream.getTracks().forEach((track) => track.stop());
|
||||
this._stream = null;
|
||||
}
|
||||
|
||||
isScreenShareAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DisplayMediaScreenShare
|
||||
{
|
||||
constructor()
|
||||
|
|
@ -130,6 +197,10 @@ class DefaultScreenShare
|
|||
export default class ScreenShare
|
||||
{
|
||||
static create(device)
|
||||
{
|
||||
if (isElectron())
|
||||
return new ElectronScreenShare();
|
||||
else
|
||||
{
|
||||
switch (device.flag)
|
||||
{
|
||||
|
|
@ -155,3 +226,4 @@ export default class ScreenShare
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ const App = (props) =>
|
|||
room
|
||||
} = props;
|
||||
|
||||
let { id } = useParams();
|
||||
const { id } = useParams();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
|
|||
import { connect } from 'react-redux';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import { withRoomContext } from '../RoomContext';
|
||||
import isElectron from 'is-electron';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl, FormattedMessage } from 'react-intl';
|
||||
import randomString from 'random-string';
|
||||
|
|
@ -239,12 +240,14 @@ const ChooseRoom = ({
|
|||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
{ !isElectron() &&
|
||||
<CookieConsent>
|
||||
<FormattedMessage
|
||||
id='room.cookieConsent'
|
||||
defaultMessage='This website uses cookies to enhance the user experience'
|
||||
/>
|
||||
</CookieConsent>
|
||||
}
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import { withRoomContext } from '../RoomContext';
|
||||
import isElectron from 'is-electron';
|
||||
import * as settingsActions from '../actions/settingsActions';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useIntl, FormattedMessage } from 'react-intl';
|
||||
|
|
@ -334,12 +335,14 @@ const JoinDialog = ({
|
|||
</DialogContent>
|
||||
}
|
||||
|
||||
{ !isElectron() &&
|
||||
<CookieConsent>
|
||||
<FormattedMessage
|
||||
id='room.cookieConsent'
|
||||
defaultMessage='This website uses cookies to enhance the user experience'
|
||||
/>
|
||||
</CookieConsent>
|
||||
}
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { connect } from 'react-redux';
|
|||
import PropTypes from 'prop-types';
|
||||
import * as appPropTypes from './appPropTypes';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import isElectron from 'is-electron';
|
||||
import * as roomActions from '../actions/roomActions';
|
||||
import * as toolareaActions from '../actions/toolareaActions';
|
||||
import { idle } from '../utils';
|
||||
|
|
@ -152,12 +153,14 @@ class Room extends React.PureComponent
|
|||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
{ !isElectron() &&
|
||||
<CookieConsent>
|
||||
<FormattedMessage
|
||||
id='room.cookieConsent'
|
||||
defaultMessage='This website uses cookies to enhance the user experience'
|
||||
/>
|
||||
</CookieConsent>
|
||||
}
|
||||
|
||||
<FullScreenView advancedMode={advancedMode} />
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
const electron = require('electron');
|
||||
|
||||
const app = electron.app;
|
||||
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
|
||||
let mainWindow;
|
||||
|
||||
function createWindow()
|
||||
{
|
||||
mainWindow = new BrowserWindow({
|
||||
width : 1280,
|
||||
height : 720,
|
||||
webPreferences : { nodeIntegration: true }
|
||||
});
|
||||
|
||||
const startUrl = process.env.ELECTRON_START_URL || url.format({
|
||||
pathname : path.join(__dirname, '/../build/index.html'),
|
||||
protocol : 'file:',
|
||||
slashes : true
|
||||
});
|
||||
|
||||
mainWindow.loadURL(startUrl);
|
||||
|
||||
mainWindow.on('closed', () =>
|
||||
{
|
||||
mainWindow = null;
|
||||
});
|
||||
}
|
||||
|
||||
app.on('ready', createWindow);
|
||||
|
||||
app.on('window-all-closed', () =>
|
||||
{
|
||||
if (process.platform !== 'darwin')
|
||||
{
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on('activate', () =>
|
||||
{
|
||||
if (mainWindow === null)
|
||||
{
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
const net = require('net');
|
||||
const port = process.env.PORT ? (process.env.PORT - 100) : 3000;
|
||||
|
||||
process.env.ELECTRON_START_URL = `http://localhost:${port}`;
|
||||
|
||||
const client = new net.Socket();
|
||||
|
||||
let startedElectron = false;
|
||||
|
||||
const tryConnection = () =>
|
||||
client.connect({ port: port }, () =>
|
||||
{
|
||||
client.end();
|
||||
|
||||
if (!startedElectron)
|
||||
{
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('starting electron');
|
||||
|
||||
startedElectron = true;
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
const electron = exec('npm run electron');
|
||||
|
||||
electron.stdout.on('data', (data) =>
|
||||
{
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`stdout: ${data.toString()}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
tryConnection();
|
||||
|
||||
client.on('error', () =>
|
||||
{
|
||||
setTimeout(tryConnection, 1000);
|
||||
});
|
||||
|
|
@ -3,7 +3,7 @@ import React, { Suspense } from 'react';
|
|||
import { render } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { createIntl, createIntlCache, RawIntlProvider } from 'react-intl';
|
||||
import { Route, BrowserRouter as Router } from 'react-router-dom'
|
||||
import { Route, HashRouter as Router } from 'react-router-dom';
|
||||
import randomString from 'random-string';
|
||||
import Logger from './Logger';
|
||||
import debug from 'debug';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
export function getSignalingUrl(peerId, roomId)
|
||||
{
|
||||
const hostname = window.location.hostname;
|
||||
const hostname = window.config.multipartyServer;
|
||||
|
||||
const port = process.env.NODE_ENV !== 'production' ? window.config.developmentPort : window.location.port;
|
||||
const port =
|
||||
process.env.NODE_ENV !== 'production' ?
|
||||
window.config.developmentPort
|
||||
:
|
||||
window.config.productionPort;
|
||||
|
||||
const url = `wss://${hostname}:${port}/?peerId=${peerId}&roomId=${roomId}`;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue