COnnection modal fix & notification basics

This commit is contained in:
Sacha Weatherstone
2021-12-17 00:13:58 +11:00
parent c3a4f81b1c
commit 8b221e28c5
10 changed files with 160 additions and 93 deletions
+10 -4
View File
@@ -1,4 +1,4 @@
import type React from 'react';
import React from 'react';
import { DeviceStatus } from '@app/components/menu/buttons/DeviceStatus';
import { useAppSelector } from '@app/hooks/redux';
@@ -9,17 +9,23 @@ import { Logo } from '@components/menu/Logo';
import { MobileNav } from '@components/menu/MobileNav';
import { Navigation } from '@components/menu/Navigation';
import { useRoute } from '@core/router';
import { requestNotificationPermission } from '@core/utils/notifications';
import { Messages } from '@pages/Messages';
import { Nodes } from '@pages/Nodes/Index';
import { NotFound } from '@pages/NotFound';
import { Plugins } from '@pages/Plugins/Index';
import { Settings } from '@pages/settings/Index';
import { NotFound } from './pages/NotFound';
import { Plugins } from './pages/Plugins/Index';
export const App = (): JSX.Element => {
const route = useRoute();
const darkMode = useAppSelector((state) => state.app.darkMode);
React.useEffect(() => {
requestNotificationPermission().catch((e) => {
console.log(e);
});
}, []);
return (
<div className={`h-screen w-screen ${darkMode ? 'dark' : ''}`}>
<Connection />
+19 -35
View File
@@ -1,12 +1,13 @@
import React from 'react';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { BLE } from '@components/connection/BLE';
import { HTTP } from '@components/connection/HTTP';
import { Serial } from '@components/connection/Serial';
import { Button } from '@components/generic/Button';
import { Card } from '@components/generic/Card';
import { Select } from '@components/generic/form/Select';
import { Modal } from '@components/generic/Modal';
import { DeviceStatus } from '@components/menu/buttons/DeviceStatus';
import { connection, connectionUrl, setConnection } from '@core/connection';
import {
closeConnectionModal,
@@ -16,9 +17,6 @@ import {
} from '@core/slices/appSlice';
import { Types } from '@meshtastic/meshtasticjs';
import { BLE } from './connection/BLE';
import { HTTP } from './connection/HTTP';
export const Connection = (): JSX.Element => {
const dispatch = useAppDispatch();
@@ -58,23 +56,25 @@ export const Connection = (): JSX.Element => {
>
<Card>
<div className="w-full max-w-3xl p-10">
<div className="flex justify-between w-full border rounded-md">
<div className="p-2">
<DeviceStatus />
{state.deviceStatus === Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
<div className="space-y-2">
<Select
label="Connection Method"
optionsEnum={connType}
value={appState.connType}
onChange={(e): void => {
dispatch(setConnType(parseInt(e.target.value)));
}}
/>
{appState.connType === connType.HTTP && <HTTP />}
{appState.connType === connType.BLE && <BLE />}
{appState.connType === connType.SERIAL && <Serial />}
</div>
<div className="p-2 my-auto">
) : (
<div>
<span>Connecting...</span>
{state.deviceStatus ===
Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
<Button
padding={2}
border
onClick={async (): Promise<void> => {
await setConnection(appState.connType);
}}
>
Connect
</Button>
) : (
Types.DeviceStatusEnum.DEVICE_CONNECTED && (
<Button
padding={2}
border
@@ -86,22 +86,6 @@ export const Connection = (): JSX.Element => {
</Button>
)}
</div>
</div>
{state.deviceStatus ===
Types.DeviceStatusEnum.DEVICE_DISCONNECTED && (
<form className="space-y-2">
<Select
label="Method"
optionsEnum={connType}
value={appState.connType}
onChange={(e): void => {
dispatch(setConnType(parseInt(e.target.value)));
}}
/>
{appState.connType === connType.HTTP && <HTTP />}
{appState.connType === connType.BLE && <BLE />}
{appState.connType === connType.SERIAL && <Serial />}
</form>
)}
</div>
</Card>
+15 -2
View File
@@ -1,14 +1,20 @@
import React from 'react';
import { useForm } from 'react-hook-form';
import { FiCheck } from 'react-icons/fi';
import { connType } from '@app/core/slices/appSlice';
import { Button } from '@components/generic/Button';
import { IconButton } from '@components/generic/IconButton';
import { ble, setConnection } from '@core/connection';
export const BLE = (): JSX.Element => {
const [bleDevices, setBleDevices] = React.useState<BluetoothDevice[]>([]);
const { register, handleSubmit, control } = useForm<{
device?: BluetoothDevice;
}>();
const updateBleDeviceList = React.useCallback(async (): Promise<void> => {
const devices = await ble.getDevices();
setBleDevices(devices);
@@ -18,8 +24,12 @@ export const BLE = (): JSX.Element => {
void updateBleDeviceList();
}, [updateBleDeviceList]);
const onSubmit = handleSubmit(async (data) => {
await setConnection(connType.BLE);
});
return (
<div className="space-y-2">
<form onSubmit={onSubmit} className="space-y-2">
{bleDevices.map((device, index) => (
<div
onClick={async (): Promise<void> => {
@@ -37,6 +47,9 @@ export const BLE = (): JSX.Element => {
/>
</div>
))}
</div>
<Button type="submit" className="mt-2 ml-auto" border>
Connect
</Button>
</form>
);
};
+49 -14
View File
@@ -1,17 +1,52 @@
import React from 'react';
import type React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { useAppDispatch } from '@app/hooks/redux.js';
import { Button } from '@components/generic/Button';
import { Checkbox } from '@components/generic/form/Checkbox';
import { Input } from '@components/generic/form/Input';
import { Select } from '@components/generic/form/Select';
import { connectionUrl } from '@core/connection';
import { connectionUrl, setConnection } from '@core/connection';
import { connType, setConnectionParams } from '@core/slices/appSlice';
export const HTTP = (): JSX.Element => {
const [httpIpSource, setHttpIpSource] = React.useState<'local' | 'remote'>(
'local',
);
const dispatch = useAppDispatch();
const { register, handleSubmit, control } = useForm<{
ipSource: 'local' | 'remote';
ip?: string;
tls: boolean;
}>({
defaultValues: {
ipSource: 'local',
ip: connectionUrl,
tls: false,
},
});
const watchIpSource = useWatch({
control,
name: 'ipSource',
defaultValue: 'local',
});
const onSubmit = handleSubmit(async (data) => {
dispatch(
setConnectionParams({
type: connType.HTTP,
params: {
address: data.ip ?? connectionUrl,
tls: data.tls,
fetchInterval: 2000,
},
}),
);
await setConnection(connType.HTTP);
});
return (
<div>
<form onSubmit={onSubmit}>
<Select
label="Host Source"
options={[
@@ -24,17 +59,17 @@ export const HTTP = (): JSX.Element => {
value: 'remote',
},
]}
value={httpIpSource}
onChange={(e): void => {
setHttpIpSource(e.target.value as 'local' | 'remote');
}}
{...register('ipSource')}
/>
{httpIpSource === 'local' ? (
{watchIpSource === 'local' ? (
<Input label="Host" value={connectionUrl} disabled />
) : (
<Input label="Host" />
<Input label="Host" {...register('ip')} />
)}
<Checkbox label="Use TLS?" />
</div>
<Checkbox label="Use TLS?" {...register('tls')} />
<Button type="submit" className="mt-2 ml-auto" border>
Connect
</Button>
</form>
);
};
+15 -2
View File
@@ -1,7 +1,9 @@
import React from 'react';
import { useForm } from 'react-hook-form';
import { FiCheck } from 'react-icons/fi';
import { Button } from '@components/generic/Button';
import { IconButton } from '@components/generic/IconButton';
import { serial, setConnection } from '@core/connection';
import { connType } from '@core/slices/appSlice';
@@ -9,6 +11,10 @@ import { connType } from '@core/slices/appSlice';
export const Serial = (): JSX.Element => {
const [serialDevices, setSerialDevices] = React.useState<SerialPort[]>([]);
const { register, handleSubmit, control } = useForm<{
device?: SerialPort;
}>();
const updateSerialDeviceList = React.useCallback(async (): Promise<void> => {
const devices = await serial.getPorts();
setSerialDevices(devices);
@@ -18,8 +24,12 @@ export const Serial = (): JSX.Element => {
void updateSerialDeviceList();
}, [updateSerialDeviceList]);
const onSubmit = handleSubmit(async (data) => {
await setConnection(connType.SERIAL);
});
return (
<div className="space-y-2">
<form onSubmit={onSubmit} className="space-y-2">
{serialDevices.map((device, index) => (
<div
className="flex justify-between p-2 bg-gray-700 rounded-md"
@@ -41,6 +51,9 @@ export const Serial = (): JSX.Element => {
/>
</div>
))}
</div>
<Button type="submit" className="mt-2 ml-auto" border>
Connect
</Button>
</form>
);
};
+3
View File
@@ -23,6 +23,8 @@ import {
Types,
} from '@meshtastic/meshtasticjs';
import { showNotification } from './utils/notifications.js';
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
export let connection: connectionType = new IHTTPConnection();
@@ -151,6 +153,7 @@ const registerListeners = (): void => {
connection.onTextPacket.subscribe((message) => {
const myNodeNum = store.getState().meshtastic.radio.hardware.myNodeNum;
showNotification('New message', message.data);
store.dispatch(
addMessage({
+12
View File
@@ -0,0 +1,12 @@
export const requestNotificationPermission = async (): Promise<void> => {
if (window.Notification && Notification.permission !== 'denied') {
await Notification.requestPermission();
}
};
export const showNotification = (title: string, body: string): void => {
new Notification(title, {
body,
icon: 'android-512.png',
});
};