Add wifi scan ability and prepared connecting
This commit is contained in:
parent
900b07f088
commit
2d7186c7c9
@ -47,8 +47,10 @@
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource/roboto": "^5.0.12",
|
||||
"@mui/icons-material": "^5.15.14",
|
||||
"@mui/material": "^5.15.14",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
|
@ -1,13 +1,26 @@
|
||||
|
||||
|
||||
export type IPCChannel = 'WIFI_STATUS' | 'WIFI_SCAN' | 'WIFI_CONNECT';
|
||||
export type IPCChannel = 'WIFI_STATUS' | 'WIFI_SCAN' | 'WIFI_LIST' | 'WIFI_CONNECT' | 'FUNCTION_TEST';
|
||||
|
||||
|
||||
export interface IPCAnswer {
|
||||
status: boolean,
|
||||
data: any
|
||||
data?: any
|
||||
}
|
||||
|
||||
export interface IPCRequest {
|
||||
data?: any,
|
||||
}
|
||||
|
||||
export interface WiFiNetwork {
|
||||
ssid: string,
|
||||
isSecured: boolean,
|
||||
isKnown?: boolean,
|
||||
rssi?: number,
|
||||
}
|
||||
|
||||
export interface FunctionTest {
|
||||
hasSudo: boolean,
|
||||
hasWPASupplicant: boolean,
|
||||
hasInternet: boolean
|
||||
}
|
@ -3,14 +3,13 @@ import IpcMainInvokeEvent = Electron.IpcMainInvokeEvent;
|
||||
import {IPCAnswer, IPCChannel, IPCRequest} from "./IPCConstants";
|
||||
|
||||
|
||||
|
||||
export const IPCHandler = (
|
||||
channel: IPCChannel,
|
||||
listener: (
|
||||
event: IpcMainInvokeEvent,
|
||||
request: IPCRequest,
|
||||
...args: any[]
|
||||
) => Promise<IPCAnswer> | IPCAnswer|any
|
||||
) => Promise<IPCAnswer> | IPCAnswer
|
||||
): void => {
|
||||
ipcMain.handle(channel, listener);
|
||||
};
|
||||
|
114
src/OSHandler.ts
Normal file
114
src/OSHandler.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import {WiFiNetwork} from "./IPCConstants";
|
||||
import {spawn, exec} from 'node:child_process';
|
||||
const wifiScan = require("node-wifi-scanner");
|
||||
|
||||
|
||||
export default class OSHandler {
|
||||
static getKnownWifis(): Promise<WiFiNetwork[]> {
|
||||
return new Promise<WiFiNetwork[]>((resolve, reject) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
static addWifi(wifi: WiFiNetwork) {
|
||||
return new Promise<WiFiNetwork>((resolve, reject) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
static scanWifis() {
|
||||
return new Promise<WiFiNetwork[]>((resolve, reject) => {
|
||||
wifiScan.scan(true).then((result: {
|
||||
ssid: string,
|
||||
mac: string,
|
||||
channel: number,
|
||||
rssi: number,
|
||||
encrypted: boolean
|
||||
}[]) => {
|
||||
if (!result)
|
||||
return {status: false};
|
||||
|
||||
let networks: WiFiNetwork[] = [];
|
||||
for (let wifi of result) {
|
||||
networks.push({
|
||||
ssid: wifi.ssid,
|
||||
isKnown: true,
|
||||
isSecured: wifi.encrypted,
|
||||
rssi: wifi.rssi
|
||||
})
|
||||
}
|
||||
|
||||
// Sort best rssi to top
|
||||
networks.sort((a, b) => {
|
||||
return b.rssi - a.rssi;
|
||||
});
|
||||
|
||||
// Sort best rssi to top
|
||||
networks.sort((a, b) => {
|
||||
if (b.isSecured && !a.isSecured)
|
||||
return 1;
|
||||
else if (b.isSecured == a.isSecured)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
});
|
||||
|
||||
console.log(networks);
|
||||
|
||||
networks = networks.filter((ele, index) => {
|
||||
// If empty ssid
|
||||
if (!ele.ssid || ele.ssid == "")
|
||||
return false;
|
||||
|
||||
// Remove duplicates
|
||||
let i = 0;
|
||||
for (let x of networks) {
|
||||
if (x.ssid == ele.ssid) {
|
||||
return i == index;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
resolve(networks);
|
||||
}).catch(reject);
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
static disableAllWifis() {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
static checkForSudo() {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
const test = spawn("sudo", ["-v"], {detached: true, stdio: ["ignore", "pipe", "pipe"]});
|
||||
|
||||
test.on("close", (code: number) => {
|
||||
if (code != 0)
|
||||
resolve(false);
|
||||
else
|
||||
resolve(true);
|
||||
});
|
||||
test.on("error", (err) => {
|
||||
resolve(false);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static checkForInternet() {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
exec("ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error", (error, stdout, stderr) => {
|
||||
if (error)
|
||||
resolve(false);
|
||||
else
|
||||
resolve(stdout == "1");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
import {IPCHandler} from "./IPCHandler";
|
||||
import {FunctionTest, WiFiNetwork} from "./IPCConstants";
|
||||
import OSHandler from "./OSHandler";
|
||||
|
||||
const wifiScan = require("node-wifi-scanner");
|
||||
|
||||
|
||||
/**
|
||||
@ -7,11 +11,36 @@ import {IPCHandler} from "./IPCHandler";
|
||||
export default class SmartMonopoly {
|
||||
static run() {
|
||||
this.setupIPCEvents();
|
||||
OSHandler.checkForSudo().then(r => console.log("Wifistatus " + r))
|
||||
}
|
||||
|
||||
static setupIPCEvents() {
|
||||
IPCHandler("FUNCTION_TEST", async (e, request, args) => {
|
||||
let data: FunctionTest = {
|
||||
hasSudo: await OSHandler.checkForSudo(),
|
||||
hasWPASupplicant: false,
|
||||
hasInternet: await OSHandler.checkForInternet(),
|
||||
};
|
||||
|
||||
return {
|
||||
status: true,
|
||||
data: data
|
||||
}
|
||||
});
|
||||
|
||||
IPCHandler("WIFI_CONNECT", (e, request, args) => {
|
||||
console.log("Got wifi connect!")
|
||||
|
||||
return {status: false}
|
||||
});
|
||||
|
||||
IPCHandler("WIFI_SCAN", async (e, request, args) => {
|
||||
try {
|
||||
let networks = await OSHandler.scanWifis();
|
||||
return {status: true, data: networks};
|
||||
} catch(e)
|
||||
{
|
||||
return {status: false};
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ import {IPCAnswer, IPCChannel, IPCRequest} from "./IPCConstants";
|
||||
import IpcRendererEvent = Electron.IpcRendererEvent;
|
||||
|
||||
contextBridge.exposeInMainWorld('api', {
|
||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any) => {
|
||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any): Promise<IPCAnswer> => {
|
||||
return ipcRenderer.invoke(channel, request, ...args);
|
||||
},
|
||||
receive: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
|
||||
|
@ -88,10 +88,10 @@ export class App extends Component<{}, AppState> {
|
||||
}
|
||||
}
|
||||
|
||||
showWiFiSettings = () => {
|
||||
toggleWiFiSettings = (state: boolean) => {
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
showWiFi: true
|
||||
showWiFi: state
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,26 @@
|
||||
import React, {Component} from "react";
|
||||
import GameSetup from "./GameSetup";
|
||||
import {Backdrop, Box, CircularProgress, Fade, Modal, Stack, Typography, Button} from "@mui/material";
|
||||
import {
|
||||
Backdrop,
|
||||
Box,
|
||||
CircularProgress,
|
||||
Fade,
|
||||
Modal,
|
||||
Stack,
|
||||
Typography,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogTitle, DialogContent, DialogContentText, DialogActions
|
||||
} from "@mui/material";
|
||||
import {FunctionTest} from "../IPCConstants";
|
||||
|
||||
|
||||
interface StartupState {
|
||||
statusTxt: string,
|
||||
open: boolean,
|
||||
nextStep: boolean,
|
||||
cloudConnect: boolean,
|
||||
connectionIssue: boolean,
|
||||
openWifiQuestion: boolean,
|
||||
}
|
||||
|
||||
export default class Startup extends Component<{}, StartupState> {
|
||||
@ -14,7 +29,10 @@ export default class Startup extends Component<{}, StartupState> {
|
||||
this.state = {
|
||||
statusTxt: "Smart-Monopoly wird gestartet...",
|
||||
open: false,
|
||||
|
||||
nextStep: false,
|
||||
cloudConnect: false,
|
||||
connectionIssue: false,
|
||||
openWifiQuestion: false
|
||||
};
|
||||
}
|
||||
|
||||
@ -24,18 +42,29 @@ export default class Startup extends Component<{}, StartupState> {
|
||||
...prevState,
|
||||
open: true,
|
||||
statusTxt: "Möchten Sie CloudConnect+ nutzen?"
|
||||
}))
|
||||
}, 2000)
|
||||
}));
|
||||
this.cloudDecision(true).then();
|
||||
}, 1)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
||||
}
|
||||
|
||||
handleOpen = () => this.setState((prevState) => ({
|
||||
...prevState,
|
||||
open: true
|
||||
}));
|
||||
connectToCloud = () => {
|
||||
|
||||
}
|
||||
|
||||
checkForNext = () => {
|
||||
if(this.state.cloudConnect)
|
||||
{
|
||||
// Connect to cloud
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just start
|
||||
}
|
||||
}
|
||||
|
||||
handleClose = () => this.setState((prevState) => ({
|
||||
...prevState,
|
||||
@ -43,19 +72,24 @@ export default class Startup extends Component<{}, StartupState> {
|
||||
}));
|
||||
|
||||
style = {
|
||||
position: 'absolute' as 'absolute',
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 400,
|
||||
width: 600,
|
||||
bgcolor: 'background.paper',
|
||||
border: '2px solid #000',
|
||||
border: '2px solid #0000',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
};
|
||||
|
||||
wifiDecision(decision: boolean) {
|
||||
async cloudDecision(decision: boolean) {
|
||||
this.handleClose();
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
cloudConnect: decision,
|
||||
openWifiQuestion: false
|
||||
}));
|
||||
|
||||
|
||||
if(decision) {
|
||||
@ -63,18 +97,55 @@ export default class Startup extends Component<{}, StartupState> {
|
||||
...prevState,
|
||||
statusTxt: "WiFi-Verbindung wird hergestellt..."
|
||||
}));
|
||||
window.app.showWiFiSettings();
|
||||
|
||||
let status = (await window.api.request("FUNCTION_TEST", {})).data as FunctionTest;
|
||||
if(!status.hasInternet)
|
||||
{
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
openWifiQuestion: true
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.checkForNext();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
statusTxt: "Ready to go!"
|
||||
}));
|
||||
this.checkForNext();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="startup">
|
||||
<Dialog
|
||||
open={this.state.openWifiQuestion}
|
||||
onClose={null}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
Keine Internetverbindung!
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description">
|
||||
Es wurde keine Internetverbindung erkannt.<br/><br/>
|
||||
<strong>Möchten Sie eine WLAN-Verbindung einrichten?</strong>
|
||||
<br/><i>Andernfalls können Sie SmartMonopoly offline nutzen.</i>
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => this.cloudDecision(false)}>
|
||||
Offline nutzen
|
||||
</Button>
|
||||
<Button onClick={() => {window.app.toggleWiFiSettings(true)}} autoFocus>Einrichten</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Modal
|
||||
aria-labelledby="transition-modal-title"
|
||||
aria-describedby="transition-modal-description"
|
||||
@ -100,8 +171,8 @@ export default class Startup extends Component<{}, StartupState> {
|
||||
<i>Dafür wird eine WiFi-Verbindung hergestellt</i>
|
||||
<br/>
|
||||
<br/>
|
||||
<Button variant="contained" onClick={() => this.wifiDecision(true)}>Ja</Button>
|
||||
<Button variant="contained" onClick={() => this.wifiDecision(false)}
|
||||
<Button variant="contained" onClick={() => this.cloudDecision(true)}>Ja</Button>
|
||||
<Button variant="contained" onClick={() => this.cloudDecision(false)}
|
||||
color="error">Nein</Button>
|
||||
</Typography>
|
||||
</Box>
|
||||
|
167
src/web/WiFi.tsx
167
src/web/WiFi.tsx
@ -1,42 +1,115 @@
|
||||
import {Component} from "react";
|
||||
import {Backdrop, Box, Button, CircularProgress, Fade, Modal, Stack, Typography} from "@mui/material";
|
||||
import React, {Component} from "react";
|
||||
import {
|
||||
Alert,
|
||||
Backdrop,
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Fade,
|
||||
FormControl, InputLabel, LinearProgress,
|
||||
MenuItem,
|
||||
Modal,
|
||||
Select, SelectChangeEvent,
|
||||
Stack,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
|
||||
import WifiPasswordIcon from "@mui/icons-material/WifiPassword";
|
||||
import WifiIcon from "@mui/icons-material/Wifi";
|
||||
import {IPCAnswer, WiFiNetwork} from "../IPCConstants";
|
||||
|
||||
|
||||
interface WiFiState {
|
||||
open: boolean,
|
||||
currentSelection: string,
|
||||
foundWiFis: WiFiNetwork[],
|
||||
scanning: boolean,
|
||||
status: status
|
||||
}
|
||||
|
||||
type status = "NONE" | "SELECTION_FAILURE" | "CONNECTING" | "PASSWORD_NEEDED" | "FAILURE" | "CONNECTED" | 'SCAN_FAILURE';
|
||||
|
||||
export default class WiFi extends Component<{}, WiFiState> {
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
this.state = {
|
||||
open: false,
|
||||
open: true,
|
||||
currentSelection: "pleaseSelect",
|
||||
foundWiFis: [],
|
||||
scanning: false,
|
||||
status: "NONE",
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
setTimeout( () => this.setState({open: true}), 500);
|
||||
this.scanWifi();
|
||||
}
|
||||
|
||||
style = {
|
||||
position: 'absolute' as 'absolute',
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 400,
|
||||
width: '50%',
|
||||
bgcolor: 'background.paper',
|
||||
border: '2px solid #000',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
scanWifi = () => {
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
open: false
|
||||
//currentSelection: "pleaseSelect",
|
||||
//foundWiFis: [],
|
||||
scanning: true,
|
||||
}));
|
||||
window.api.request('WIFI_SCAN', {}).then((answer: IPCAnswer) => {
|
||||
if(answer.status)
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
foundWiFis: answer.data as WiFiNetwork[],
|
||||
scanning: false
|
||||
}));
|
||||
else
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
status: "SCAN_FAILURE",
|
||||
scanning: false
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
window.api.request("WIFI_CONNECT", {});
|
||||
handleClose = () => {
|
||||
window.app.toggleWiFiSettings(false);
|
||||
}
|
||||
|
||||
handleConnect = () => {
|
||||
if(this.state.currentSelection == "pleaseSelect")
|
||||
{
|
||||
return this.setState((prevState) => ({
|
||||
...prevState,
|
||||
status: "SELECTION_FAILURE"
|
||||
}));
|
||||
}
|
||||
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
status: "CONNECTING"
|
||||
}));
|
||||
window.api.request('WIFI_CONNECT', {data: this.state.currentSelection}).then((answer: IPCAnswer) => {
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
status: answer.status ? "CONNECTED" : "FAILURE"
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
onChange = (event: SelectChangeEvent) => {
|
||||
this.setState((prevState) => ({
|
||||
...prevState,
|
||||
currentSelection: event.target.value
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -55,18 +128,84 @@ export default class WiFi extends Component<{}, WiFiState> {
|
||||
>
|
||||
<Fade in={this.state.open}>
|
||||
<Box sx={this.style}>
|
||||
<Box sx={{width: '100%', mb: 2}}>
|
||||
{(this.state.scanning||this.state.status == "CONNECTING") && <LinearProgress/>}
|
||||
</Box>
|
||||
<Typography id="transition-modal-title" variant="h6" component="h2">
|
||||
WiFi Verbindungsmanager
|
||||
</Typography>
|
||||
<Typography id="transition-modal-description" sx={{mt: 2}}>
|
||||
Folgende Netzwerke wurden gefunden...
|
||||
<Alert variant={this.state.status == "FAILURE" ? "filled" : "standard"}
|
||||
severity={this.state.status.includes("FAILURE") ? "error" : "info"}>
|
||||
{this.state.status == "NONE" && "Bitte wählen Sie eins der folgenden Netzwerke aus"}
|
||||
{this.state.status == "CONNECTING" && "Verbinden..." }
|
||||
{this.state.status == "SCAN_FAILURE" && "Das Scannen ist fehlgeschlagen. - Möglicherweise fehlen Berechtigungen, um Netzwerke zu scannen, oder es befindet sich kein WLAN-Interface auf diesem Gerät." }
|
||||
{this.state.status == "FAILURE" && "Verbindungsfehler!" }
|
||||
{this.state.status == "SELECTION_FAILURE" && "Bitte zunächst ein Netzwerk auswählen!" }
|
||||
</Alert>
|
||||
<br/>
|
||||
<i>Dafür wird eine WiFi-Verbindung hergestellt</i>
|
||||
<FormControl sx={{m: 1, minWidth: '70%'}} error={this.state.status == "SELECTION_FAILURE"}>
|
||||
<InputLabel id="wifi-select-label">WiFi</InputLabel>
|
||||
<Select
|
||||
labelId="wifi-select-label"
|
||||
id="wifi-select"
|
||||
value={this.state.currentSelection}
|
||||
label="Age"
|
||||
|
||||
disabled={this.state.scanning}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<MenuItem disabled={true} value="pleaseSelect">Bitte wählen...</MenuItem>
|
||||
{this.state.foundWiFis.map((wifi: WiFiNetwork) => (
|
||||
<MenuItem value={wifi.ssid}>{wifi.ssid} {wifi.isSecured ? <WifiPasswordIcon sx={{ml: 1}}/> :
|
||||
<WifiIcon sx={{ml: 1}}/>}</MenuItem>
|
||||
))};
|
||||
{null}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<FormControl sx={{mt: 2, minWidth: '5%'}}>
|
||||
<Button variant="contained" disabled={this.state.scanning || this.state.status == "CONNECTING"} onClick={() => this.scanWifi()}>Aktualisieren
|
||||
{this.state.scanning && (
|
||||
<CircularProgress
|
||||
size={24}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
marginTop: '-12px',
|
||||
marginLeft: '-12px',
|
||||
}}
|
||||
/>
|
||||
)}</Button>
|
||||
</FormControl>
|
||||
<br/>
|
||||
<br/>
|
||||
<Button variant="contained" onClick={() => this.handleClose()}>Ja !</Button>
|
||||
<Button variant="contained" onClick={() => null}
|
||||
color="error">Nein</Button>
|
||||
|
||||
<FormControl sx={{mr: 2, minWidth: '20%'}}>
|
||||
<Button variant="contained" disabled={this.state.status == "CONNECTING" || this.state.scanning}
|
||||
onClick={() => this.handleConnect()}>Verbinden
|
||||
{this.state.status == "CONNECTING" && (
|
||||
<CircularProgress
|
||||
size={24}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
marginTop: '-12px',
|
||||
marginLeft: '-12px',
|
||||
}}
|
||||
/>
|
||||
)}</Button>
|
||||
</FormControl>
|
||||
<FormControl sx={{ml: 2, minWidth: '20%'}}>
|
||||
<Button variant="contained" disabled={this.state.status == "CONNECTING"}
|
||||
onClick={() => this.handleClose()}
|
||||
color="error">Abbrechen</Button>
|
||||
</FormControl>
|
||||
|
||||
|
||||
|
||||
|
||||
</Typography>
|
||||
</Box>
|
||||
</Fade>
|
||||
|
@ -6,7 +6,7 @@ export {}
|
||||
declare global {
|
||||
interface Window {
|
||||
"api": {
|
||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any) => Promise<IPCAnswer> | IPCAnswer | any;
|
||||
request: (channel: IPCChannel, request: IPCRequest, ...args: any) => Promise<IPCAnswer>;
|
||||
listen: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => void;
|
||||
}
|
||||
app: App;
|
||||
|
@ -7,6 +7,8 @@ body {
|
||||
padding-top: 0.3rem;
|
||||
/*background-color: #1F9598;*/
|
||||
color: black;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
|
||||
|
21
yarn.lock
21
yarn.lock
@ -730,6 +730,13 @@
|
||||
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz"
|
||||
integrity sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==
|
||||
|
||||
"@mui/icons-material@^5.15.14":
|
||||
version "5.15.14"
|
||||
resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.15.14.tgz#333468c94988d96203946d1cfeb8f4d7e8e7de34"
|
||||
integrity sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.23.9"
|
||||
|
||||
"@mui/material@^5.15.14":
|
||||
version "5.15.14"
|
||||
resolved "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz"
|
||||
@ -1630,6 +1637,11 @@ astral-regex@^2.0.0:
|
||||
resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz"
|
||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
||||
|
||||
async@3.2.4:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
|
||||
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
|
||||
|
||||
at-least-node@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz"
|
||||
@ -4227,7 +4239,7 @@ lodash.templatesettings@^4.0.0:
|
||||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
|
||||
lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
@ -4626,6 +4638,13 @@ node-releases@^2.0.14:
|
||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz"
|
||||
integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
|
||||
|
||||
"node-wifi-scanner@git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner":
|
||||
version "1.1.3"
|
||||
resolved "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner#c5cbde1a3cd51687dd7fa887be8ae075417a0ca4"
|
||||
dependencies:
|
||||
async "3.2.4"
|
||||
lodash "4.17.21"
|
||||
|
||||
nopt@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz"
|
||||
|
Loading…
x
Reference in New Issue
Block a user