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}
+
-
+
{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 dispatch = useAppDispatch();
+
const radioConfig = useAppSelector((state) => state.meshtastic.preferences);
+ const hostOverride = useAppSelector((state) => state.meshtastic.hostOverride);
+ const hostOverrideEnabled = useAppSelector(
+ (state) => state.meshtastic.hostOverrideEnabled,
+ );
- console.log(radioConfig);
+ const [localHostOverride, setLocalHostOverride] =
+ React.useState(hostOverride);
+ const [localHostOverrideEnabled, setLocalHostOverrideEnabled] =
+ React.useState(hostOverrideEnabled);
return (
-
+
+
+
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;