mirror of
https://gitlab.com/futo-org/fcast.git
synced 2025-06-24 21:25:23 +00:00
Moved network interface querying off main process
This commit is contained in:
parent
28a617daa7
commit
7ce2dcbca3
8 changed files with 143 additions and 123 deletions
|
@ -1,11 +1,9 @@
|
|||
import { PlayMessage, PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage } from 'common/Packets';
|
||||
import * as os from 'os';
|
||||
import * as http from 'http';
|
||||
import * as url from 'url';
|
||||
import { AddressInfo } from 'modules/ws';
|
||||
import { v4 as uuidv4 } from 'modules/uuid';
|
||||
import { Main } from 'src/Main';
|
||||
import si from 'modules/systeminformation';
|
||||
|
||||
export class NetworkService {
|
||||
static key: string = null;
|
||||
|
@ -13,8 +11,6 @@ export class NetworkService {
|
|||
static proxyServer: http.Server;
|
||||
static proxyServerAddress: AddressInfo;
|
||||
static proxiedFiles: Map<string, { url: string, headers: { [key: string]: string } }> = new Map();
|
||||
static networkStateChangeListenerTimeout = 2500;
|
||||
private static networkStateChangeListenerInterfaces = [];
|
||||
|
||||
private static setupProxyServer(): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
@ -106,55 +102,4 @@ export class NetworkService {
|
|||
NetworkService.proxiedFiles.set(proxiedUrl, { url: url, headers: headers });
|
||||
return proxiedUrl;
|
||||
}
|
||||
|
||||
static async networkStateChangeListener(forceUpdate: boolean, networkChangedCb: (networkInfo: any) => void) {
|
||||
const queriedInterfaces: si.Systeminformation.NetworkInterfacesData[] = await new Promise<si.Systeminformation.NetworkInterfacesData[]>((resolve, reject) => {
|
||||
si.networkInterfaces((data) => {
|
||||
// console.log(data);
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
resolve(data);
|
||||
}
|
||||
else {
|
||||
resolve([data]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const wifiConnections: si.Systeminformation.WifiConnectionData[] = await new Promise<si.Systeminformation.WifiConnectionData[]>((resolve, reject) => {
|
||||
si.wifiConnections((data) => {
|
||||
// console.log(data);
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
resolve(data);
|
||||
}
|
||||
else {
|
||||
resolve([data]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const interfaces = [];
|
||||
for (const iface of queriedInterfaces) {
|
||||
if (iface.ip4 !== '' && !iface.internal && !iface.virtual) {
|
||||
const isWireless = wifiConnections.some(e => {
|
||||
if (e.iface === iface.iface) {
|
||||
interfaces.push({ type: 'wireless', name: e.ssid, address: iface.ip4, signalLevel: e.quality });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!isWireless) {
|
||||
interfaces.push({ type: 'wired', name: iface.ifaceName, address: iface.ip4 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forceUpdate || (JSON.stringify(interfaces) !== JSON.stringify(NetworkService.networkStateChangeListenerInterfaces))) {
|
||||
NetworkService.networkStateChangeListenerInterfaces = interfaces;
|
||||
networkChangedCb(interfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ const connectionStatusText = document.getElementById("connection-status-text");
|
|||
const connectionStatusSpinner = document.getElementById("connection-spinner");
|
||||
const connectionStatusCheck = document.getElementById("connection-check");
|
||||
let connections = [];
|
||||
let renderedConnectionInfo = false;
|
||||
let renderedAddresses = null;
|
||||
|
||||
// Window might be re-created while devices are still connected
|
||||
|
@ -66,8 +67,8 @@ function renderIPsAndQRCode() {
|
|||
toast("Network connections has changed, please reconnect sender devices to receiver if you experience issues", ToastIcon.WARNING);
|
||||
}
|
||||
else if (addresses.length === 0) {
|
||||
connInfo.setAttribute("style", "display: none");
|
||||
connError.setAttribute("style", "display: block");
|
||||
connInfo.style.display = 'none';
|
||||
connError.style.display = 'block';
|
||||
|
||||
if (renderedAddresses !== null) {
|
||||
toast("Lost network connection, please reconnect to a network", ToastIcon.ERROR);
|
||||
|
@ -78,8 +79,8 @@ function renderIPsAndQRCode() {
|
|||
}
|
||||
|
||||
if (renderedAddresses !== null && renderedAddresses.length === 0) {
|
||||
connInfo.setAttribute("style", "display: block");
|
||||
connError.setAttribute("style", "display: none");
|
||||
connInfo.style.display = 'block';
|
||||
connError.style.display = 'none';
|
||||
}
|
||||
|
||||
renderIPs(value.interfaces);
|
||||
|
@ -124,6 +125,12 @@ function renderIPsAndQRCode() {
|
|||
}
|
||||
});
|
||||
|
||||
if (!renderedConnectionInfo) {
|
||||
const connInfoLoading = document.getElementById('connection-information-loading');
|
||||
connInfoLoading.style.display = 'none';
|
||||
connInfo.style.display = 'block';
|
||||
}
|
||||
|
||||
onQRCodeRendered();
|
||||
}
|
||||
|
||||
|
|
|
@ -72,11 +72,15 @@ body, html {
|
|||
gap: 15vw;
|
||||
|
||||
font-family: InterVariable;
|
||||
font-size: 20px;
|
||||
font-size: 28px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#main-view {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
#title-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -85,7 +89,7 @@ body, html {
|
|||
|
||||
#title-text {
|
||||
font-family: Outfit;
|
||||
font-size: 100px;
|
||||
font-size: 140px;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
|
||||
|
@ -96,12 +100,12 @@ body, html {
|
|||
}
|
||||
|
||||
#title-icon {
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
width: 124px;
|
||||
height: 124px;
|
||||
|
||||
background-image: url(../assets/icons/app/icon.svg);
|
||||
background-size: cover;
|
||||
margin-right: 15px;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
#connection-status {
|
||||
|
@ -109,35 +113,13 @@ body, html {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#main-view {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
#manual-connection-info {
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#manual-connection-info-separator {
|
||||
height: 1px;
|
||||
background: #2E2E2E;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
#qr-code {
|
||||
display: flex;
|
||||
margin: 20px auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#scan-to-connect {
|
||||
#connection-status-text {
|
||||
margin-top: 20px;
|
||||
font-weight: bold;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#connection-spinner {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#connection-error {
|
||||
|
@ -159,9 +141,37 @@ body, html {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
#connection-status-text {
|
||||
#connection-information-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#connection-information-loading-text {
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 10px 20px;
|
||||
}
|
||||
|
||||
#connection-information {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#scan-to-connect {
|
||||
margin-top: 20px;
|
||||
white-space: pre;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#qr-code {
|
||||
display: flex;
|
||||
margin: 20px auto;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#ips {
|
||||
|
@ -219,10 +229,6 @@ body, html {
|
|||
background-image: url(../assets/icons/app/wifi-strength-outline.svg);
|
||||
}
|
||||
|
||||
#connection-spinner {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#window-can-be-closed {
|
||||
color: #666666;
|
||||
position: absolute;
|
||||
|
@ -230,7 +236,7 @@ body, html {
|
|||
margin-bottom: 20px;
|
||||
|
||||
font-family: InterVariable;
|
||||
font-size: 18px;
|
||||
font-size: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
@ -238,15 +244,15 @@ body, html {
|
|||
.lds-ring {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
.lds-ring div {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
margin: 8px;
|
||||
border: 8px solid #fff;
|
||||
border-radius: 50%;
|
||||
|
@ -275,8 +281,8 @@ body, html {
|
|||
/* display: inline-block; */
|
||||
display: none;
|
||||
position: relative;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
margin: 18px;
|
||||
padding: 10px;
|
||||
|
||||
|
@ -329,8 +335,8 @@ body, html {
|
|||
}
|
||||
|
||||
#toast-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
background-image: url(../assets/icons/app/info.svg);
|
||||
background-size: cover;
|
||||
flex-shrink: 0;
|
||||
|
@ -345,7 +351,7 @@ body, html {
|
|||
word-break: break-word;
|
||||
|
||||
font-family: InterVariable;
|
||||
font-size: 20px;
|
||||
font-size: 28px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
|
|
@ -302,27 +302,28 @@ export class Main {
|
|||
}
|
||||
});
|
||||
|
||||
let networkStateChangeListener = null;
|
||||
Main.mainWindow.loadFile(path.join(__dirname, 'main/index.html'));
|
||||
Main.mainWindow.on('closed', () => {
|
||||
Main.mainWindow = null;
|
||||
clearInterval(networkStateChangeListener);
|
||||
});
|
||||
|
||||
Main.mainWindow.maximize();
|
||||
Main.mainWindow.show();
|
||||
|
||||
Main.mainWindow.on('ready-to-show', () => {
|
||||
NetworkService.networkStateChangeListener(true, (interfaces: any) => {
|
||||
Main.mainWindow.webContents.send("device-info", { name: os.hostname(), interfaces: interfaces });
|
||||
|
||||
networkStateChangeListener = setInterval(() => {
|
||||
NetworkService.networkStateChangeListener(false, (interfaces: any) => {
|
||||
Main.mainWindow.webContents.send("device-info", { name: os.hostname(), interfaces: interfaces });
|
||||
});
|
||||
},
|
||||
NetworkService.networkStateChangeListenerTimeout);
|
||||
const networkWorker = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
preload: path.join(__dirname, 'main/networkWorker.js')
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('network-changed', (event: IpcMainEvent, value: any) => {
|
||||
Main.mainWindow.webContents.send("device-info", { name: os.hostname(), interfaces: value });
|
||||
});
|
||||
networkWorker.loadFile(path.join(__dirname, 'main/worker.html'));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
47
receivers/electron/src/main/NetworkWorker.ts
Normal file
47
receivers/electron/src/main/NetworkWorker.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { ipcRenderer } from 'electron';
|
||||
import si from 'modules/systeminformation';
|
||||
|
||||
const networkStateChangeListenerTimeout = 2500;
|
||||
let networkStateChangeListenerInterfaces = [];
|
||||
|
||||
networkStateChangeListener(true);
|
||||
setInterval(networkStateChangeListener, networkStateChangeListenerTimeout);
|
||||
|
||||
function networkStateChangeListener(forceUpdate: boolean) {
|
||||
new Promise<void>((resolve) => {
|
||||
si.networkInterfaces((data) => {
|
||||
// console.log(data);
|
||||
const queriedInterfaces = Array.isArray(data) ? data : [data];
|
||||
|
||||
si.wifiConnections((data) => {
|
||||
// console.log(data);
|
||||
const wifiConnections = Array.isArray(data) ? data : [data];
|
||||
|
||||
const interfaces = [];
|
||||
for (const iface of queriedInterfaces) {
|
||||
if (iface.ip4 !== '' && !iface.internal && !iface.virtual) {
|
||||
const isWireless = wifiConnections.some(e => {
|
||||
if (e.iface === iface.iface) {
|
||||
interfaces.push({ type: 'wireless', name: e.ssid, address: iface.ip4, signalLevel: e.quality });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!isWireless) {
|
||||
interfaces.push({ type: 'wired', name: iface.ifaceName, address: iface.ip4 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forceUpdate || (JSON.stringify(interfaces) !== JSON.stringify(networkStateChangeListenerInterfaces))) {
|
||||
networkStateChangeListenerInterfaces = interfaces;
|
||||
ipcRenderer.send('network-changed', interfaces);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -47,6 +47,14 @@
|
|||
<div class="non-selectable card-title">Connection Information</div>
|
||||
<div class="card-title-separator"></div>
|
||||
|
||||
<div id="connection-information-loading">
|
||||
<div id="connection-information-loading-text" class="lds-ring">Fetching Network Info...</div>
|
||||
<div id="connection-information-loading-spinner" class="lds-ring"><div></div><div></div><div></div><div></div></div>
|
||||
</div>
|
||||
<div id="connection-error">
|
||||
<div id="connection-error-icon"></div>
|
||||
<div id="connection-error-text">Device not connected to a network</div>
|
||||
</div>
|
||||
<div id="connection-information">
|
||||
<div id="scan-to-connect" class="non-selectable">Scan with a FCast sender app</div>
|
||||
<canvas id="qr-code"></canvas>
|
||||
|
@ -64,10 +72,6 @@
|
|||
<div id="ip-ports">Port<br>46899 (TCP), 46898 (WS)</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="connection-error">
|
||||
<div id="connection-error-icon"></div>
|
||||
<div id="connection-error-text">Device not connected to a network</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
9
receivers/electron/src/main/worker.html
Normal file
9
receivers/electron/src/main/worker.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>FCast Receiver Worker</title>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -63,6 +63,7 @@ module.exports = [
|
|||
entry: {
|
||||
preload: './src/main/Preload.ts',
|
||||
renderer: './src/main/Renderer.ts',
|
||||
networkWorker: './src/main/NetworkWorker.ts'
|
||||
},
|
||||
target: 'electron-renderer',
|
||||
module: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue