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/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@fontsource/roboto": "^5.0.12",
|
"@fontsource/roboto": "^5.0.12",
|
||||||
|
"@mui/icons-material": "^5.15.14",
|
||||||
"@mui/material": "^5.15.14",
|
"@mui/material": "^5.15.14",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
|
"node-wifi-scanner": "git+https://git.gaminggeneration.de/tobiash/node-wifi-scanner",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^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 {
|
export interface IPCAnswer {
|
||||||
status: boolean,
|
status: boolean,
|
||||||
data: any
|
data?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPCRequest {
|
export interface IPCRequest {
|
||||||
data?: any,
|
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";
|
import {IPCAnswer, IPCChannel, IPCRequest} from "./IPCConstants";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const IPCHandler = (
|
export const IPCHandler = (
|
||||||
channel: IPCChannel,
|
channel: IPCChannel,
|
||||||
listener: (
|
listener: (
|
||||||
event: IpcMainInvokeEvent,
|
event: IpcMainInvokeEvent,
|
||||||
request: IPCRequest,
|
request: IPCRequest,
|
||||||
...args: any[]
|
...args: any[]
|
||||||
) => Promise<IPCAnswer> | IPCAnswer|any
|
) => Promise<IPCAnswer> | IPCAnswer
|
||||||
): void => {
|
): void => {
|
||||||
ipcMain.handle(channel, listener);
|
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,17 +1,46 @@
|
|||||||
import {IPCHandler} from "./IPCHandler";
|
import {IPCHandler} from "./IPCHandler";
|
||||||
|
import {FunctionTest, WiFiNetwork} from "./IPCConstants";
|
||||||
|
import OSHandler from "./OSHandler";
|
||||||
|
|
||||||
|
const wifiScan = require("node-wifi-scanner");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background Class for doing stuff on the host
|
* Background Class for doing stuff on the host
|
||||||
*/
|
*/
|
||||||
export default class SmartMonopoly{
|
export default class SmartMonopoly {
|
||||||
static run() {
|
static run() {
|
||||||
this.setupIPCEvents();
|
this.setupIPCEvents();
|
||||||
|
OSHandler.checkForSudo().then(r => console.log("Wifistatus " + r))
|
||||||
}
|
}
|
||||||
|
|
||||||
static setupIPCEvents() {
|
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) => {
|
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;
|
import IpcRendererEvent = Electron.IpcRendererEvent;
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('api', {
|
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);
|
return ipcRenderer.invoke(channel, request, ...args);
|
||||||
},
|
},
|
||||||
receive: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => {
|
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) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
showWiFi: true
|
showWiFi: state
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,26 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import GameSetup from "./GameSetup";
|
import {
|
||||||
import {Backdrop, Box, CircularProgress, Fade, Modal, Stack, Typography, Button} from "@mui/material";
|
Backdrop,
|
||||||
|
Box,
|
||||||
|
CircularProgress,
|
||||||
|
Fade,
|
||||||
|
Modal,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle, DialogContent, DialogContentText, DialogActions
|
||||||
|
} from "@mui/material";
|
||||||
|
import {FunctionTest} from "../IPCConstants";
|
||||||
|
|
||||||
|
|
||||||
interface StartupState {
|
interface StartupState {
|
||||||
statusTxt: string,
|
statusTxt: string,
|
||||||
open: boolean,
|
open: boolean,
|
||||||
|
nextStep: boolean,
|
||||||
|
cloudConnect: boolean,
|
||||||
|
connectionIssue: boolean,
|
||||||
|
openWifiQuestion: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Startup extends Component<{}, StartupState> {
|
export default class Startup extends Component<{}, StartupState> {
|
||||||
@ -14,7 +29,10 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
this.state = {
|
this.state = {
|
||||||
statusTxt: "Smart-Monopoly wird gestartet...",
|
statusTxt: "Smart-Monopoly wird gestartet...",
|
||||||
open: false,
|
open: false,
|
||||||
|
nextStep: false,
|
||||||
|
cloudConnect: false,
|
||||||
|
connectionIssue: false,
|
||||||
|
openWifiQuestion: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,18 +42,29 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
...prevState,
|
...prevState,
|
||||||
open: true,
|
open: true,
|
||||||
statusTxt: "Möchten Sie CloudConnect+ nutzen?"
|
statusTxt: "Möchten Sie CloudConnect+ nutzen?"
|
||||||
}))
|
}));
|
||||||
}, 2000)
|
this.cloudDecision(true).then();
|
||||||
|
}, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOpen = () => this.setState((prevState) => ({
|
connectToCloud = () => {
|
||||||
...prevState,
|
|
||||||
open: true
|
}
|
||||||
}));
|
|
||||||
|
checkForNext = () => {
|
||||||
|
if(this.state.cloudConnect)
|
||||||
|
{
|
||||||
|
// Connect to cloud
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleClose = () => this.setState((prevState) => ({
|
handleClose = () => this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
@ -43,19 +72,24 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
style = {
|
style = {
|
||||||
position: 'absolute' as 'absolute',
|
position: 'absolute',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
left: '50%',
|
left: '50%',
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
width: 400,
|
width: 600,
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'background.paper',
|
||||||
border: '2px solid #000',
|
border: '2px solid #0000',
|
||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
p: 4,
|
p: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
wifiDecision(decision: boolean) {
|
async cloudDecision(decision: boolean) {
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
|
this.setState((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
cloudConnect: decision,
|
||||||
|
openWifiQuestion: false
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
if(decision) {
|
if(decision) {
|
||||||
@ -63,18 +97,55 @@ export default class Startup extends Component<{}, StartupState> {
|
|||||||
...prevState,
|
...prevState,
|
||||||
statusTxt: "WiFi-Verbindung wird hergestellt..."
|
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 {
|
else {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
statusTxt: "Ready to go!"
|
statusTxt: "Ready to go!"
|
||||||
}));
|
}));
|
||||||
|
this.checkForNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div className="startup">
|
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
|
<Modal
|
||||||
aria-labelledby="transition-modal-title"
|
aria-labelledby="transition-modal-title"
|
||||||
aria-describedby="transition-modal-description"
|
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>
|
<i>Dafür wird eine WiFi-Verbindung hergestellt</i>
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
<Button variant="contained" onClick={() => this.wifiDecision(true)}>Ja</Button>
|
<Button variant="contained" onClick={() => this.cloudDecision(true)}>Ja</Button>
|
||||||
<Button variant="contained" onClick={() => this.wifiDecision(false)}
|
<Button variant="contained" onClick={() => this.cloudDecision(false)}
|
||||||
color="error">Nein</Button>
|
color="error">Nein</Button>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
167
src/web/WiFi.tsx
167
src/web/WiFi.tsx
@ -1,42 +1,115 @@
|
|||||||
import {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Backdrop, Box, Button, CircularProgress, Fade, Modal, Stack, Typography} from "@mui/material";
|
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 {
|
interface WiFiState {
|
||||||
open: boolean,
|
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> {
|
export default class WiFi extends Component<{}, WiFiState> {
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
open: false,
|
open: true,
|
||||||
|
currentSelection: "pleaseSelect",
|
||||||
|
foundWiFis: [],
|
||||||
|
scanning: false,
|
||||||
|
status: "NONE",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
setTimeout( () => this.setState({open: true}), 500);
|
this.scanWifi();
|
||||||
}
|
}
|
||||||
|
|
||||||
style = {
|
style = {
|
||||||
position: 'absolute' as 'absolute',
|
position: 'absolute',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
left: '50%',
|
left: '50%',
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: 'translate(-50%, -50%)',
|
||||||
width: 400,
|
width: '50%',
|
||||||
bgcolor: 'background.paper',
|
bgcolor: 'background.paper',
|
||||||
border: '2px solid #000',
|
border: '2px solid #000',
|
||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
p: 4,
|
p: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleClose = () => {
|
scanWifi = () => {
|
||||||
this.setState((prevState) => ({
|
this.setState((prevState) => ({
|
||||||
...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() {
|
render() {
|
||||||
@ -55,18 +128,84 @@ export default class WiFi extends Component<{}, WiFiState> {
|
|||||||
>
|
>
|
||||||
<Fade in={this.state.open}>
|
<Fade in={this.state.open}>
|
||||||
<Box sx={this.style}>
|
<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">
|
<Typography id="transition-modal-title" variant="h6" component="h2">
|
||||||
WiFi Verbindungsmanager
|
WiFi Verbindungsmanager
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography id="transition-modal-description" sx={{mt: 2}}>
|
<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/>
|
<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/>
|
||||||
<br/>
|
<br/>
|
||||||
<Button variant="contained" onClick={() => this.handleClose()}>Ja !</Button>
|
|
||||||
<Button variant="contained" onClick={() => null}
|
<FormControl sx={{mr: 2, minWidth: '20%'}}>
|
||||||
color="error">Nein</Button>
|
<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>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Fade>
|
</Fade>
|
||||||
|
@ -6,7 +6,7 @@ export {}
|
|||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
"api": {
|
"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;
|
listen: (channel: IPCChannel, func: (event: IpcRendererEvent, message: IPCAnswer, ...args: any) => void) => void;
|
||||||
}
|
}
|
||||||
app: App;
|
app: App;
|
||||||
|
@ -7,6 +7,8 @@ body {
|
|||||||
padding-top: 0.3rem;
|
padding-top: 0.3rem;
|
||||||
/*background-color: #1F9598;*/
|
/*background-color: #1F9598;*/
|
||||||
color: black;
|
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"
|
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.15.14.tgz"
|
||||||
integrity sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==
|
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":
|
"@mui/material@^5.15.14":
|
||||||
version "5.15.14"
|
version "5.15.14"
|
||||||
resolved "https://registry.npmjs.org/@mui/material/-/material-5.15.14.tgz"
|
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"
|
resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz"
|
||||||
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
|
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:
|
at-least-node@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz"
|
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:
|
dependencies:
|
||||||
lodash._reinterpolate "^3.0.0"
|
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"
|
version "4.17.21"
|
||||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
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"
|
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz"
|
||||||
integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
|
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:
|
nopt@^6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz"
|
resolved "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user