From 25e3caab0d280e268db73f752dbb2610d240a92a Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Sat, 7 Aug 2021 22:06:26 +1000 Subject: [PATCH] WIP --- src/App.tsx | 20 +++++++----- src/components/chat/Message.tsx | 23 ++++++++------ src/components/form/Input.tsx | 6 ++++ src/components/form/Toggle.tsx | 26 ++++++++++++++++ src/pages/Messages.tsx | 5 +++ src/pages/Settings.tsx | 54 ++++++++++++++++++++++++++++++--- src/slices/appSlice.ts | 3 +- src/slices/meshtasticSlice.ts | 23 ++++++++++++++ 8 files changed, 139 insertions(+), 21 deletions(-) create mode 100644 src/components/form/Toggle.tsx diff --git a/src/App.tsx b/src/App.tsx index a4976520..c43dabb6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -34,20 +34,25 @@ const App = (): JSX.Element => { 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; connection.connect({ - address: - import.meta.env.NODE_ENV === 'production' - ? window.location.hostname - : import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP, + address: hostOverrideEnabled + ? hostOverride + : import.meta.env.NODE_ENV === 'production' + ? window.location.hostname + : import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP, receiveBatchRequests: false, tls: false, fetchInterval: 2000, }); - }, []); + }, [hostOverrideEnabled, hostOverride]); React.useEffect(() => { connection.onDeviceStatus.subscribe((status) => { @@ -56,6 +61,9 @@ const App = (): JSX.Element => { if (status === Types.DeviceStatusEnum.DEVICE_CONFIGURED) { dispatch(setReady(true)); } + if (status === Types.DeviceStatusEnum.DEVICE_DISCONNECTED) { + dispatch(setReady(false)); + } }); connection.onMyNodeInfo.subscribe((nodeInfo) => { @@ -88,8 +96,6 @@ const App = (): JSX.Element => { ); connection.onTextPacket.subscribe((message) => { - console.log(message.packet.from, '===', myNodeInfo.myNodeNum); - dispatch( addMessage({ message: message, diff --git a/src/components/chat/Message.tsx b/src/components/chat/Message.tsx index caa23315..7b8c0fa9 100644 --- a/src/components/chat/Message.tsx +++ b/src/components/chat/Message.tsx @@ -7,6 +7,7 @@ export interface MessageProps { ack: boolean; isSender: boolean; rxTime: Date; + senderName: string; } export const Message = ({ @@ -14,6 +15,7 @@ export const Message = ({ ack, isSender, rxTime, + senderName, }: MessageProps): JSX.Element => { return (
-
-
{message}
+
+
+
{message}
+
+
{senderName}
-
+
{rxTime.getHours()}:{rxTime.getMinutes()}
diff --git a/src/components/form/Input.tsx b/src/components/form/Input.tsx index fa8cff40..8b09dc66 100644 --- a/src/components/form/Input.tsx +++ b/src/components/form/Input.tsx @@ -8,6 +8,8 @@ export interface InputProps { type: string; name: string; value?: string; + disabled?: boolean; + onChange: (event: React.ChangeEvent) => void; } export const Input = ({ @@ -18,6 +20,8 @@ export const Input = ({ type, name, value, + disabled, + onChange, }: InputProps): JSX.Element => { return (
@@ -40,10 +44,12 @@ export const Input = ({ name={name} id={name} value={value} + onChange={onChange} className={`block w-full h-11 rounded-md border shadow-sm focus:outline-none focus:border-primary dark:focus:border-primary dark:bg-secondaryDark dark:border-gray-600 dark:text-white ${ icon ? 'pl-9' : 'pl-2' }`} placeholder={placeholder} + disabled={disabled} />
{!valid && ( diff --git a/src/components/form/Toggle.tsx b/src/components/form/Toggle.tsx new file mode 100644 index 00000000..02d8b11e --- /dev/null +++ b/src/components/form/Toggle.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import { Switch } from '@headlessui/react'; + +export interface ToggleProps { + enabled: boolean; + setEnabled: (state: boolean) => void; +} + +export const Toggle = ({ enabled, setEnabled }: ToggleProps): JSX.Element => { + return ( + + Use setting + + ); +}; diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index d88d823a..b4bae254 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -6,6 +6,7 @@ import { useAppSelector } from '../hooks/redux'; export const Messages = (): JSX.Element => { const messages = useAppSelector((state) => state.meshtastic.messages); + const nodes = useAppSelector((state) => state.meshtastic.nodes); return (
@@ -17,6 +18,10 @@ export const Messages = (): JSX.Element => { message={message.message.data} ack={message.ack} rxTime={new Date()} + senderName={ + nodes.find((node) => node.num === message.message.packet.from) + ?.user?.longName ?? 'UNK' + } /> ))}
diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 039e5269..bcce4fa6 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -3,18 +3,32 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { Input } from '../components/form/Input'; +import { Toggle } from '../components/form/Toggle'; import { PrimaryTemplate } from '../components/templates/PrimaryTemplate'; -import { useAppSelector } from '../hooks/redux'; +import { useAppDispatch, useAppSelector } from '../hooks/redux'; +import { + setHostOverride, + setHostOverrideEnabled, +} from '../slices/meshtasticSlice'; export const Settings = (): JSX.Element => { const { t } = useTranslation(); - const radioConfig = useAppSelector((state) => state.meshtastic.preferences); + const dispatch = useAppDispatch(); - console.log(radioConfig); + const radioConfig = useAppSelector((state) => state.meshtastic.preferences); + const hostOverride = useAppSelector((state) => state.meshtastic.hostOverride); + const hostOverrideEnabled = useAppSelector( + (state) => state.meshtastic.hostOverrideEnabled, + ); + + const [localHostOverride, setLocalHostOverride] = + React.useState(hostOverride); + const [localHostOverrideEnabled, setLocalHostOverrideEnabled] = + React.useState(hostOverrideEnabled); return ( -
+
WiFi
{ />
+
+
Client
+
+ { + setLocalHostOverrideEnabled(state); + }} + /> + { + setLocalHostOverride(event.target.value); + }} + type="text" + valid={true} + disabled={!localHostOverrideEnabled} + /> +
+
+ + ); }; diff --git a/src/slices/appSlice.ts b/src/slices/appSlice.ts index 4fec2bb1..6016aa5f 100644 --- a/src/slices/appSlice.ts +++ b/src/slices/appSlice.ts @@ -11,7 +11,7 @@ interface AppState { const initialState: AppState = { mobileNavOpen: false, - darkMode: false, + darkMode: localStorage.getItem('darkMode') === 'true' ?? false, currentPage: 'messages', }; @@ -26,6 +26,7 @@ export const appSlice = createSlice({ state.mobileNavOpen = false; }, setDarkModeEnabled(state, action: PayloadAction) { + localStorage.setItem('darkMode', String(action.payload)); state.darkMode = action.payload; }, setCurrentPage(state, action: PayloadAction) { diff --git a/src/slices/meshtasticSlice.ts b/src/slices/meshtasticSlice.ts index d0ba31e5..fcb103f6 100644 --- a/src/slices/meshtasticSlice.ts +++ b/src/slices/meshtasticSlice.ts @@ -2,6 +2,8 @@ import { Protobuf, Types } from '@meshtastic/meshtasticjs'; import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; +import { connection } from '../connection'; + export interface MessageWithAck { message: Types.TextPacket; ack: boolean; @@ -19,6 +21,8 @@ interface AppState { channels: Protobuf.Channel[]; preferences: Protobuf.RadioConfig_UserPreferences; messages: MessageWithAck[]; + hostOverrideEnabled: boolean; + hostOverride: string; } const initialState: AppState = { @@ -31,6 +35,9 @@ const initialState: AppState = { channels: [], preferences: Protobuf.RadioConfig_UserPreferences.create(), messages: [], + hostOverrideEnabled: + localStorage.getItem('hostOverrideEnabled') === 'true' ?? false, + hostOverride: localStorage.getItem('hostOverride') ?? '', }; export const meshtasticSlice = createSlice({ @@ -95,6 +102,20 @@ export const meshtasticSlice = createSlice({ } }); }, + setHostOverrideEnabled: (state, action: PayloadAction) => { + state.hostOverrideEnabled = action.payload; + localStorage.setItem('hostOverrideEnabled', String(action.payload)); + if (state.hostOverrideEnabled !== action.payload) { + connection.disconnect(); + } + }, + setHostOverride: (state, action: PayloadAction) => { + state.hostOverride = action.payload; + localStorage.setItem('hostOverride', action.payload); + if (state.hostOverride !== action.payload) { + connection.disconnect(); + } + }, }, }); @@ -109,6 +130,8 @@ export const { setPreferences, addMessage, ackMessage, + setHostOverrideEnabled, + setHostOverride, } = meshtasticSlice.actions; export default meshtasticSlice.reducer;