You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.7 KiB
140 lines
4.7 KiB
import type React from 'react';
|
|
import { useEffect } from 'react';
|
|
|
|
import { AnimatePresence, m } from 'framer-motion';
|
|
|
|
import { BLE } from '@components/connection/BLE';
|
|
import { HTTP } from '@components/connection/HTTP';
|
|
import { Serial } from '@components/connection/Serial';
|
|
import { Select } from '@components/generic/form/Select';
|
|
import { Modal } from '@components/generic/Modal';
|
|
import { connectionUrl, setConnection } from '@core/connection';
|
|
import {
|
|
closeConnectionModal,
|
|
connType,
|
|
setConnectionParams,
|
|
setConnType,
|
|
} from '@core/slices/appSlice';
|
|
import { useAppDispatch } from '@hooks/useAppDispatch';
|
|
import { useAppSelector } from '@hooks/useAppSelector';
|
|
import { Types } from '@meshtastic/meshtasticjs';
|
|
|
|
export const Connection = (): JSX.Element => {
|
|
const dispatch = useAppDispatch();
|
|
|
|
const meshtasticState = useAppSelector((state) => state.meshtastic);
|
|
const appState = useAppSelector((state) => state.app);
|
|
|
|
useEffect(() => {
|
|
if (!import.meta.env.VITE_PUBLIC_HOSTED) {
|
|
dispatch(
|
|
setConnectionParams({
|
|
type: connType.HTTP,
|
|
params: {
|
|
address: connectionUrl,
|
|
tls: false,
|
|
receiveBatchRequests: false,
|
|
fetchInterval: 2000,
|
|
},
|
|
}),
|
|
);
|
|
void setConnection(connType.HTTP);
|
|
}
|
|
}, [dispatch]);
|
|
|
|
useEffect(() => {
|
|
if (meshtasticState.ready) {
|
|
dispatch(closeConnectionModal());
|
|
}
|
|
}, [meshtasticState.ready, dispatch]);
|
|
|
|
return (
|
|
<AnimatePresence>
|
|
{appState.connectionModalOpen && (
|
|
<Modal
|
|
title="Connect to a device"
|
|
onClose={(): void => {
|
|
dispatch(closeConnectionModal());
|
|
}}
|
|
>
|
|
<div className="flex max-w-3xl flex-col gap-4 md:flex-row">
|
|
<div className="md:w-1/2">
|
|
<div className="space-y-2">
|
|
<Select
|
|
label="Connection Method"
|
|
optionsEnum={connType}
|
|
value={appState.connType}
|
|
onChange={(e): void => {
|
|
dispatch(setConnType(parseInt(e.target.value)));
|
|
}}
|
|
disabled={
|
|
meshtasticState.deviceStatus ===
|
|
Types.DeviceStatusEnum.DEVICE_CONNECTED
|
|
}
|
|
/>
|
|
{appState.connType === connType.HTTP && (
|
|
<HTTP
|
|
connecting={
|
|
meshtasticState.deviceStatus ===
|
|
Types.DeviceStatusEnum.DEVICE_CONNECTED
|
|
}
|
|
/>
|
|
)}
|
|
{appState.connType === connType.BLE && (
|
|
<BLE
|
|
connecting={
|
|
meshtasticState.deviceStatus ===
|
|
Types.DeviceStatusEnum.DEVICE_CONNECTED
|
|
}
|
|
/>
|
|
)}
|
|
{appState.connType === connType.SERIAL && (
|
|
<Serial
|
|
connecting={
|
|
meshtasticState.deviceStatus ===
|
|
Types.DeviceStatusEnum.DEVICE_CONNECTED
|
|
}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="md:w-1/2">
|
|
<div className="h-96 overflow-y-auto rounded-md border border-gray-300 bg-gray-200 p-2 dark:border-gray-600 dark:bg-secondaryDark dark:text-gray-400">
|
|
{meshtasticState.logs.length === 0 && (
|
|
<div className="flex h-full w-full">
|
|
<m.img
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
className="m-auto h-40 w-40 text-green-500"
|
|
src={`/placeholders/${
|
|
appState.darkMode
|
|
? 'View Code Dark.svg'
|
|
: 'View Code.svg'
|
|
}`}
|
|
/>
|
|
</div>
|
|
)}
|
|
{meshtasticState.logs
|
|
.filter((log) => {
|
|
return ![
|
|
Types.Emitter.handleFromRadio,
|
|
Types.Emitter.handleMeshPacket,
|
|
Types.Emitter.sendPacket,
|
|
].includes(log.emitter);
|
|
})
|
|
.map((log, index) => (
|
|
<div key={index} className="flex">
|
|
<div className="truncate font-mono text-sm">
|
|
{log.message}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Modal>
|
|
)}
|
|
</AnimatePresence>
|
|
);
|
|
};
|
|
|