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

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>
);
};