import React from 'react'; import { useAppDispatch, useAppSelector } from '@app/hooks/redux'; import { DeviceStatusDropdown } from '@components/menu/buttons/DeviceStatusDropdown'; import { MobileNavToggle } from '@components/menu/buttons/MobileNavToggle'; import { ThemeToggle } from '@components/menu/buttons/ThemeToggle'; import { Logo } from '@components/menu/Logo'; import { MobileNav } from '@components/menu/MobileNav'; import { Navigation } from '@components/menu/Navigation'; import { connection } from '@core/connection'; import { useRoute } from '@core/router'; import { ackMessage, addChannel, addMessage, addNode, setDeviceStatus, setLastMeshInterraction, setMyNodeInfo, setPreferences, setReady, setUser, } from '@core/slices/meshtasticSlice'; import { Protobuf, SettingsManager, Types } from '@meshtastic/meshtasticjs'; import { About } from '@pages/About'; import { Messages } from '@pages/Messages'; import { Nodes } from '@pages/Nodes/Index'; import { Settings } from '@pages/settings/Index'; const App = (): JSX.Element => { const dispatch = useAppDispatch(); const route = useRoute(); const myNodeInfo = useAppSelector((state) => state.meshtastic.myNodeInfo); const darkMode = useAppSelector((state) => state.app.darkMode); const hostOverrideEnabled = useAppSelector( (state) => state.meshtastic.hostOverrideEnabled, ); const hostOverride = useAppSelector((state) => state.meshtastic.hostOverride); React.useEffect(() => { SettingsManager.debugMode = Protobuf.LogRecord_Level.TRACE; void connection.connect({ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment address: hostOverrideEnabled ? hostOverride : import.meta.env.NODE_ENV === 'production' ? window.location.hostname : import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP ?? 'http://meshtastic.local', receiveBatchRequests: false, tls: false, fetchInterval: 2000, }); }, [hostOverrideEnabled, hostOverride]); React.useEffect(() => { connection.onDeviceStatus.subscribe((status) => { dispatch(setDeviceStatus(status)); if (status === Types.DeviceStatusEnum.DEVICE_CONFIGURED) { dispatch(setReady(true)); } if (status === Types.DeviceStatusEnum.DEVICE_DISCONNECTED) { dispatch(setReady(false)); } }); connection.onMyNodeInfo.subscribe((nodeInfo) => { dispatch(setMyNodeInfo(nodeInfo)); }); connection.onUserDataPacket.subscribe((user) => { dispatch(setUser(user)); }); connection.onNodeInfoPacket.subscribe((nodeInfoPacket) => dispatch(addNode(nodeInfoPacket.data)), ); connection.onAdminPacket.subscribe((adminPacket) => { switch (adminPacket.data.variant.oneofKind) { case 'getChannelResponse': dispatch(addChannel(adminPacket.data.variant.getChannelResponse)); break; case 'getRadioResponse': if (adminPacket.data.variant.getRadioResponse.preferences) { dispatch( setPreferences( adminPacket.data.variant.getRadioResponse.preferences, ), ); } break; } }); connection.onMeshHeartbeat.subscribe((date) => dispatch(setLastMeshInterraction(date.getTime())), ); connection.onTextPacket.subscribe((message) => { dispatch( addMessage({ message: message, ack: message.packet.from !== myNodeInfo.myNodeNum, isSender: message.packet.from === myNodeInfo.myNodeNum, received: new Date(message.packet.rxTime), }), ); }); connection.onRoutingPacket.subscribe((routingPacket) => { if (routingPacket.packet.payloadVariant.oneofKind === 'decoded') { dispatch( ackMessage(routingPacket.packet.payloadVariant.decoded.requestId), ); } }); return (): void => { connection.onDeviceStatus.cancelAll(); connection.onMyNodeInfo.cancelAll(); connection.onUserDataPacket.cancelAll(); connection.onNodeInfoPacket.cancelAll(); connection.onAdminPacket.cancelAll(); connection.onMeshHeartbeat.cancelAll(); connection.onTextPacket.cancelAll(); connection.onRoutingPacket.cancelAll(); }; }, [dispatch, myNodeInfo.myNodeNum]); return (
{/* */}
{route.name === 'messages' && } {route.name === 'nodes' && } {route.name === 'settings' && } {route.name === 'about' && } {route.name === false && 'Not Found'}
); }; export default App;