From 2940791b9ea399b745d4770d4296332ddaaca292 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Wed, 11 Aug 2021 23:09:45 +1000 Subject: [PATCH] WIP --- package.json | 9 +- public/index.html | 4 + src/App.tsx | 70 +- src/components/Sidebar/Device/Settings.tsx | 85 -- src/components/TestForm.tsx | 204 +++++ src/components/chat/MessageBar.tsx | 16 +- src/components/form/Select.tsx | 54 +- src/components/form/Switch.tsx | 40 + src/components/form/Toggle.tsx | 33 - src/components/generic/Button.tsx | 43 +- src/components/generic/Drawer.tsx | 37 - src/components/generic/IconButton.tsx | 15 + src/components/menu/MobileNav.tsx | 46 +- src/components/menu/Navigation.tsx | 20 +- .../menu/buttons/DeviceStatusDropdown.tsx | 6 +- .../menu/buttons/LanguageDropdown.tsx | 8 +- .../menu/buttons/MobileNavToggle.tsx | 21 +- src/components/menu/buttons/ThemeToggle.tsx | 10 +- src/components/nodes/Node.tsx | 12 +- src/components/nodes/NodeDetails.tsx | 44 + src/components/templates/PrimaryTemplate.tsx | 6 +- src/{ => core}/connection.ts | 0 src/{ => core}/router.ts | 0 src/{ => core}/slices/appSlice.ts | 0 src/{ => core}/slices/meshtasticSlice.ts | 0 src/{ => core}/store.ts | 0 src/core/theme.ts | 28 + src/{ => core}/translation.ts | 6 +- src/hooks/redux.ts | 2 +- src/index.tsx | 6 +- src/pages/About.tsx | 2 + src/pages/Messages.tsx | 14 +- src/pages/Nodes.tsx | 34 +- src/pages/Settings.tsx | 68 +- tailwind.config.js | 3 +- yarn.lock | 775 ++++++++++++------ 36 files changed, 1097 insertions(+), 624 deletions(-) delete mode 100644 src/components/Sidebar/Device/Settings.tsx create mode 100644 src/components/TestForm.tsx create mode 100644 src/components/form/Switch.tsx delete mode 100644 src/components/form/Toggle.tsx delete mode 100644 src/components/generic/Drawer.tsx create mode 100644 src/components/generic/IconButton.tsx create mode 100644 src/components/nodes/NodeDetails.tsx rename src/{ => core}/connection.ts (100%) rename src/{ => core}/router.ts (100%) rename src/{ => core}/slices/appSlice.ts (100%) rename src/{ => core}/slices/meshtasticSlice.ts (100%) rename src/{ => core}/store.ts (100%) create mode 100644 src/core/theme.ts rename src/{ => core}/translation.ts (74%) diff --git a/package.json b/package.json index 4276f191..62231119 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,15 @@ "lint": "eslint 'src/**/*.{ts,tsx}'" }, "dependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", "@headlessui/react": "^1.3.0", "@heroicons/react": "^1.0.1", + "@material-ui/core": "^5.0.0-beta.3", "@meshtastic/meshtasticjs": "^0.6.16", "@reduxjs/toolkit": "^1.6.0", + "add": "^2.0.6", "boring-avatars": "^1.5.8", - "framer-motion": "^4.1.17", "i18next": "^20.3.5", "i18next-browser-languagedetector": "^6.1.2", "react": "^17.0.2", @@ -25,7 +28,9 @@ "react-hook-form": "^7.9.0", "react-i18next": "^11.11.4", "react-redux": "^7.2.4", - "type-route": "^0.6.0" + "react-select": "^5.0.0-beta.0", + "type-route": "^0.6.0", + "yarn": "^1.22.11" }, "devDependencies": { "@snowpack/plugin-dotenv": "^2.0.5", diff --git a/public/index.html b/public/index.html index 916482b3..e3678126 100644 --- a/public/index.html +++ b/public/index.html @@ -15,6 +15,10 @@ href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet" /> + { const dispatch = useAppDispatch(); @@ -126,39 +128,41 @@ const App = (): JSX.Element => { }, [dispatch, myNodeInfo.myNodeNum]); return ( -
-
-
-
-
-
- -
- - -
- - - + +
+
+
+
+
+
+ +
+ + +
+ + + +
+
-
-
- + -
-
- {route.name === 'messages' && } - {route.name === 'nodes' && } - {route.name === 'settings' && } - {route.name === 'about' && } - {route.name === false && 'Not Found'} +
+
+ {route.name === 'messages' && } + {route.name === 'nodes' && } + {route.name === 'settings' && } + {route.name === 'about' && } + {route.name === false && 'Not Found'} +
-
+
); }; diff --git a/src/components/Sidebar/Device/Settings.tsx b/src/components/Sidebar/Device/Settings.tsx deleted file mode 100644 index 422ba6c0..00000000 --- a/src/components/Sidebar/Device/Settings.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React from 'react'; - -import { useForm } from 'react-hook-form'; -import { useTranslation } from 'react-i18next'; - -import { SaveIcon } from '@heroicons/react/outline'; -import { Protobuf } from '@meshtastic/meshtasticjs'; - -import { connection } from '../../../connection'; -import { useAppSelector } from '../../../hooks/redux'; - -export const Settings = (): JSX.Element => { - const { t } = useTranslation(); - const preferences = useAppSelector((state) => state.meshtastic.preferences); - - const { register, handleSubmit } = - useForm({ - defaultValues: preferences, - }); - - const onSubmit = handleSubmit((data) => connection.setPreferences(data)); - return ( -
-
-
{t('strings.device_region')}
-
- -
-
-
-
{t('strings.wifi_ssid')}
-
- -
-
-
-
{t('strings.wifi_psk')}
-
- -
-
-
- -
-
- ); -}; diff --git a/src/components/TestForm.tsx b/src/components/TestForm.tsx new file mode 100644 index 00000000..aca81872 --- /dev/null +++ b/src/components/TestForm.tsx @@ -0,0 +1,204 @@ +import React from 'react'; + +import { Controller, useForm } from 'react-hook-form'; + +import Button from '@material-ui/core/Button'; +import Checkbox from '@material-ui/core/Checkbox'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; +import Radio from '@material-ui/core/Radio'; +import RadioGroup from '@material-ui/core/RadioGroup'; +import Switch from '@material-ui/core/Switch'; +import TextField from '@material-ui/core/TextField'; +import Typography from '@material-ui/core/Typography'; + +let renderCount = 0; + +const options = [ + { + value: 'chocolate', + label: 'Chocolate', + }, + { + value: 'strawberry', + label: 'Strawberry', + }, + { + value: 'vanilla', + label: 'Vanilla', + }, +]; + +const defaultValues = { + Native: '', + TextField: '', + Select: '', + ReactSelect: '', + Checkbox: false, + switch: false, + RadioGroup: '', +}; + +export const TestForm = () => { + const { handleSubmit, register, reset, control, watch } = useForm({ + defaultValues, + mode: 'onChange', + }); + renderCount++; + + const data = watch(); + + return ( +
+
console.info(data))} + > +
+ + Native Input: + + +
+ +
+ + MUI Checkbox + + ( + onChange(ev.target.checked)} + /> + )} + /> +
+ +
+ + Radio Group + + ( + + } + label="Female" + /> + } + label="Male" + /> + + )} + name="RadioGroup" + control={control} + /> +
+ +
+ + MUI TextField + + } + name="TextField" + control={control} + /> +
+ + {/*
+ + MUI Select + + ( + + )} + name="Select" + control={control} + /> +
*/} + +
+ + MUI Switch + + ( + onChange(ev.target.checked)} + /> + )} + /> +
+ +
+ + React Select + + {/* } + options={options} + name="ReactSelect" + isClearable + control={control} + onChange={([selected]) => { + return { value: selected }; + }} + /> */} +
+ +
+ + + +
+
+ +
+
+          {JSON.stringify(data, null, 2)}
+        
+ + + Render Count: {renderCount} + +
+
+ ); +}; diff --git a/src/components/chat/MessageBar.tsx b/src/components/chat/MessageBar.tsx index aace3545..1eb8dff2 100644 --- a/src/components/chat/MessageBar.tsx +++ b/src/components/chat/MessageBar.tsx @@ -8,9 +8,9 @@ import { PaperClipIcon, } from '@heroicons/react/outline'; -import { connection } from '../../connection'; +import { connection } from '../../core/connection'; import { useAppSelector } from '../../hooks/redux'; -import { Button } from '../generic/Button'; +import { IconButton } from '../generic/IconButton'; export const MessageBar = (): JSX.Element => { const ready = useAppSelector((state) => state.meshtastic.ready); @@ -25,13 +25,13 @@ export const MessageBar = (): JSX.Element => { return (
- + - +
{ }} className="focus:outline-none h-10 w-full resize-none rounded-full border border-gray-300 dark:bg-gray-900 px-4" /> - +
); diff --git a/src/components/form/Select.tsx b/src/components/form/Select.tsx index b95a3cdb..ba89734e 100644 --- a/src/components/form/Select.tsx +++ b/src/components/form/Select.tsx @@ -1,38 +1,38 @@ import React from 'react'; -type DefaultSelectProps = JSX.IntrinsicElements['select']; +import type { FieldValues, UseControllerProps } from 'react-hook-form'; +import { Controller } from 'react-hook-form'; +import ReactSelect from 'react-select'; -export interface SelectProps { +interface SelectProps extends UseControllerProps { + label: string; options: { value: string; label: string; }[]; - label: string; } -export const Select = React.forwardRef< - HTMLSelectElement, - SelectProps & DefaultSelectProps ->(function Select( - { options, label, id, ...props }: SelectProps & DefaultSelectProps, - ref, -) { +export const Select = ({ + name, + control, + label, + options, +}: SelectProps): JSX.Element => { return ( -
- - -
+ ( +
+ + {label} + + +
+ )} + /> ); -}); +}; diff --git a/src/components/form/Switch.tsx b/src/components/form/Switch.tsx new file mode 100644 index 00000000..86ee6e98 --- /dev/null +++ b/src/components/form/Switch.tsx @@ -0,0 +1,40 @@ +import React from 'react'; + +import type { FieldValues, UseControllerProps } from 'react-hook-form'; +import { Controller } from 'react-hook-form'; + +import MaterialSwitch from '@material-ui/core/Switch'; + +interface SwitchProps extends UseControllerProps { + label: string; +} + +export const Switch = ({ + name, + control, + label, +}: SwitchProps): JSX.Element => { + return ( + ( +
+ + {label} + +
+ onChange(ev.target.checked)} + /> +
+
+ )} + /> + ); +}; diff --git a/src/components/form/Toggle.tsx b/src/components/form/Toggle.tsx deleted file mode 100644 index 94b50775..00000000 --- a/src/components/form/Toggle.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; - -type DefaultInputProps = JSX.IntrinsicElements['input']; - -export interface ToggleProps { - label: string; -} - -export const Toggle = React.forwardRef< - HTMLInputElement, - ToggleProps & DefaultInputProps ->(function Input( - { label, id, checked, ...props }: ToggleProps & DefaultInputProps, - ref, -) { - return ( -
- {label} -
- - -
-
- ); -}); diff --git a/src/components/generic/Button.tsx b/src/components/generic/Button.tsx index db847c6e..74aab5f5 100644 --- a/src/components/generic/Button.tsx +++ b/src/components/generic/Button.tsx @@ -1,31 +1,28 @@ import React from 'react'; -export interface ButtonProps { - children: React.ReactNode; - className?: string; - clickAction?: () => void; - type?: 'button' | 'submit' | 'reset' | undefined; +import MaterialButton from '@material-ui/core/Button'; +import type { ButtonProps as MaterialButtonProps } from '@material-ui/core/Button/Button'; + +interface LocalButtonProps { + text: string; + icon?: JSX.Element; } -export const Button = ({ - children, - className, - clickAction, - type, -}: ButtonProps): JSX.Element => { +export type ButtonProps = MaterialButtonProps & LocalButtonProps; + +export const Button = ({ text, icon, ...props }: ButtonProps): JSX.Element => { return ( - +
+ {icon && + React.cloneElement(icon, { + className: 'h-6 w-6 mr-3 text-gray-500 dark:text-gray-400', + })} + {text} +
+ ); }; diff --git a/src/components/generic/Drawer.tsx b/src/components/generic/Drawer.tsx deleted file mode 100644 index 43061fe6..00000000 --- a/src/components/generic/Drawer.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react'; - -export interface DrawerProps { - open: boolean; - onClose: () => void; - children: React.ReactNode; -} - -export const Drawer = ({ - open, - onClose, - children, -}: DrawerProps): JSX.Element => { - return ( - <> - {open && ( -
-
-
- )} - - - - ); -}; diff --git a/src/components/generic/IconButton.tsx b/src/components/generic/IconButton.tsx new file mode 100644 index 00000000..2fbb61ce --- /dev/null +++ b/src/components/generic/IconButton.tsx @@ -0,0 +1,15 @@ +import React from 'react'; + +import MaterialIconButton from '@material-ui/core/IconButton'; +import type { IconButtonProps } from '@material-ui/core/IconButton/IconButton'; + +export const IconButton = ({ + children, + ...props +}: IconButtonProps): JSX.Element => { + return ( + + {children} + + ); +}; diff --git a/src/components/menu/MobileNav.tsx b/src/components/menu/MobileNav.tsx index 99d97dc5..cb84c596 100644 --- a/src/components/menu/MobileNav.tsx +++ b/src/components/menu/MobileNav.tsx @@ -6,13 +6,13 @@ import { InformationCircleIcon, ViewGridIcon, } from '@heroicons/react/outline'; +import SwipeableDrawer from '@material-ui/core/SwipeableDrawer/SwipeableDrawer'; +import { routes } from '../../core/router'; +import { closeMobileNav, openMobileNav } from '../../core/slices/appSlice'; import { useAppDispatch, useAppSelector } from '../../hooks/redux'; -import { routes } from '../../router'; -import { closeMobileNav } from '../../slices/appSlice'; -import { Drawer } from '../generic/Drawer'; +import { Button } from '../generic/Button'; import { Logo } from './Logo'; -import { MenuButton } from './MenuButton'; export const MobileNav = (): JSX.Element => { const dispatch = useAppDispatch(); @@ -20,49 +20,41 @@ export const MobileNav = (): JSX.Element => { const mobileNavOpen = useAppSelector((state) => state.app.mobileNavOpen); return ( - { dispatch(closeMobileNav()); }} + onOpen={() => { + dispatch(openMobileNav()); + }} > -
+
- } text={'Messages'} - link={routes.messages().link} - clickAction={() => { - dispatch(closeMobileNav()); - }} + {...routes.messages().link} /> - } text={'Nodes'} - link={routes.nodes().link} - clickAction={() => { - dispatch(closeMobileNav()); - }} + {...routes.nodes().link} /> - } text={'Settings'} - link={routes.settings().link} - clickAction={() => { - dispatch(closeMobileNav()); - }} + {...routes.settings().link} /> - } text={'About'} - link={routes.about().link} - clickAction={() => { - dispatch(closeMobileNav()); - }} + {...routes.about().link} />
- + ); }; diff --git a/src/components/menu/Navigation.tsx b/src/components/menu/Navigation.tsx index 325f869b..a3700328 100644 --- a/src/components/menu/Navigation.tsx +++ b/src/components/menu/Navigation.tsx @@ -7,32 +7,32 @@ import { ViewGridIcon, } from '@heroicons/react/outline'; -import { routes } from '../../router'; -import { MenuButton } from './MenuButton'; +import { routes } from '../../core/router'; +import { Button } from '../generic/Button'; export const Navigation = (): JSX.Element => { return (
- } text={'Messages'} - link={routes.messages().link} + {...routes.messages().link} /> - } text={'Nodes'} - link={routes.nodes().link} + {...routes.nodes().link} /> - } text={'Settings'} - link={routes.settings().link} + {...routes.settings().link} /> - } text={'About'} - link={routes.about().link} + {...routes.about().link} />
diff --git a/src/components/menu/buttons/DeviceStatusDropdown.tsx b/src/components/menu/buttons/DeviceStatusDropdown.tsx index b8e6eed6..eed595fa 100644 --- a/src/components/menu/buttons/DeviceStatusDropdown.tsx +++ b/src/components/menu/buttons/DeviceStatusDropdown.tsx @@ -3,14 +3,14 @@ import React from 'react'; import { SwitchVerticalIcon } from '@heroicons/react/outline'; import { useAppSelector } from '../../../hooks/redux'; -import { Button } from '../../generic/Button'; +import { IconButton } from '../../generic/IconButton'; export const DeviceStatusDropdown = (): JSX.Element => { const ready = useAppSelector((state) => state.meshtastic.ready); const deviceStatus = useAppSelector((state) => state.meshtastic.deviceStatus); return ( - + ); }; diff --git a/src/components/menu/buttons/LanguageDropdown.tsx b/src/components/menu/buttons/LanguageDropdown.tsx index 11b27d20..48ce2ad8 100644 --- a/src/components/menu/buttons/LanguageDropdown.tsx +++ b/src/components/menu/buttons/LanguageDropdown.tsx @@ -4,9 +4,9 @@ import { Jp, Pt, Us } from 'react-flags-select'; import { Menu } from '@headlessui/react'; +import i18n from '../../../core/translation'; import { useAppDispatch } from '../../../hooks/redux'; -import i18n from '../../../translation'; -import { Button } from '../../generic/Button'; +import { IconButton } from '../../generic/IconButton'; export const LanguageDropdown = (): JSX.Element => { const dispatch = useAppDispatch(); @@ -32,11 +32,11 @@ export const LanguageDropdown = (): JSX.Element => { return (
- + {languages.map((language, index) => ( diff --git a/src/components/menu/buttons/MobileNavToggle.tsx b/src/components/menu/buttons/MobileNavToggle.tsx index e6faef5a..1231b235 100644 --- a/src/components/menu/buttons/MobileNavToggle.tsx +++ b/src/components/menu/buttons/MobileNavToggle.tsx @@ -2,21 +2,22 @@ import React from 'react'; import { MenuIcon } from '@heroicons/react/outline'; +import { openMobileNav } from '../../../core/slices/appSlice'; import { useAppDispatch } from '../../../hooks/redux'; -import { openMobileNav } from '../../../slices/appSlice'; -import { Button } from '../../generic/Button'; +import { IconButton } from '../../generic/IconButton'; export const MobileNavToggle = (): JSX.Element => { const dispatch = useAppDispatch(); return ( - +
+ { + dispatch(openMobileNav()); + }} + > + + +
); }; diff --git a/src/components/menu/buttons/ThemeToggle.tsx b/src/components/menu/buttons/ThemeToggle.tsx index f8796b9a..5eb21c80 100644 --- a/src/components/menu/buttons/ThemeToggle.tsx +++ b/src/components/menu/buttons/ThemeToggle.tsx @@ -2,17 +2,17 @@ import React from 'react'; import { MoonIcon, SunIcon } from '@heroicons/react/outline'; +import { setDarkModeEnabled } from '../../../core/slices/appSlice'; import { useAppDispatch, useAppSelector } from '../../../hooks/redux'; -import { setDarkModeEnabled } from '../../../slices/appSlice'; -import { Button } from '../../generic/Button'; +import { IconButton } from '../../generic/IconButton'; export const ThemeToggle = (): JSX.Element => { const dispatch = useAppDispatch(); const darkMode = useAppSelector((state) => state.app.darkMode); return ( - + ); }; diff --git a/src/components/nodes/Node.tsx b/src/components/nodes/Node.tsx index f5ff0d7e..4180e53f 100644 --- a/src/components/nodes/Node.tsx +++ b/src/components/nodes/Node.tsx @@ -4,13 +4,21 @@ import Avatar from 'boring-avatars'; import type { Protobuf } from '@meshtastic/meshtasticjs'; +type DefaultDivProps = JSX.IntrinsicElements['div']; + export interface NodeProps { node: Protobuf.NodeInfo; } -export const Node = ({ node }: NodeProps): JSX.Element => { +export const Node = ({ + node, + ...props +}: NodeProps & DefaultDivProps): JSX.Element => { return ( -
+
void; +} + +export const NodeDetails = ({ node }: NodeProps): JSX.Element => { + const { register, handleSubmit } = useForm({ + defaultValues: node.user, + }); + + const onSubmit = handleSubmit((data) => { + console.log(data); + connection.setOwner(data); + }); + + return ( +
+
+
{node.user?.longName ?? node.num}
+ +
+
+
+ {/* */} + +
+
+
+ ); +}; diff --git a/src/components/templates/PrimaryTemplate.tsx b/src/components/templates/PrimaryTemplate.tsx index 28bc1d19..86ecdfd5 100644 --- a/src/components/templates/PrimaryTemplate.tsx +++ b/src/components/templates/PrimaryTemplate.tsx @@ -27,11 +27,7 @@ export const PrimaryTemplate = ({
-
-
-
{children}
-
-
+
{children}
); }; diff --git a/src/connection.ts b/src/core/connection.ts similarity index 100% rename from src/connection.ts rename to src/core/connection.ts diff --git a/src/router.ts b/src/core/router.ts similarity index 100% rename from src/router.ts rename to src/core/router.ts diff --git a/src/slices/appSlice.ts b/src/core/slices/appSlice.ts similarity index 100% rename from src/slices/appSlice.ts rename to src/core/slices/appSlice.ts diff --git a/src/slices/meshtasticSlice.ts b/src/core/slices/meshtasticSlice.ts similarity index 100% rename from src/slices/meshtasticSlice.ts rename to src/core/slices/meshtasticSlice.ts diff --git a/src/store.ts b/src/core/store.ts similarity index 100% rename from src/store.ts rename to src/core/store.ts diff --git a/src/core/theme.ts b/src/core/theme.ts new file mode 100644 index 00000000..faa3797f --- /dev/null +++ b/src/core/theme.ts @@ -0,0 +1,28 @@ +import type { Theme } from '@material-ui/core'; +import { createTheme } from '@material-ui/core/styles'; + +export const theme = (darkMode: boolean): Theme => { + return createTheme( + darkMode + ? { + palette: { + mode: 'dark', + primary: { + main: '#67ea94', + }, + background: { + default: '#0F172A', + paper: '#0F172A', + }, + }, + } + : { + palette: { + mode: 'light', + primary: { + main: '#67ea94', + }, + }, + }, + ); +}; diff --git a/src/translation.ts b/src/core/translation.ts similarity index 74% rename from src/translation.ts rename to src/core/translation.ts index e32cf7e8..cd99a95c 100644 --- a/src/translation.ts +++ b/src/core/translation.ts @@ -2,9 +2,9 @@ import i18n from 'i18next'; import detector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -import { en } from './translations/en'; -import { jp } from './translations/jp'; -import { pt } from './translations/pt'; +import { en } from '../translations/en'; +import { jp } from '../translations/jp'; +import { pt } from '../translations/pt'; i18n .use(detector) diff --git a/src/hooks/redux.ts b/src/hooks/redux.ts index 6f02a25a..1579525b 100644 --- a/src/hooks/redux.ts +++ b/src/hooks/redux.ts @@ -1,7 +1,7 @@ import type { TypedUseSelectorHook } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux'; -import type { AppDispatch, RootState } from '../store'; +import type { AppDispatch, RootState } from '../core/store'; export const useAppDispatch = () => useDispatch(); export const useAppSelector: TypedUseSelectorHook = useSelector; diff --git a/src/index.tsx b/src/index.tsx index 99b2a251..50fd75c0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,5 +1,5 @@ import './index.css'; -import './translation'; +import './core/translation'; import React from 'react'; import ReactDOM from 'react-dom'; @@ -7,8 +7,8 @@ import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import App from './App'; -import { RouteProvider } from './router'; -import { store } from './store'; +import { RouteProvider } from './core/router'; +import { store } from './core/store'; ReactDOM.render( diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 0af0d231..8b48c746 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -1,11 +1,13 @@ import React from 'react'; import { PrimaryTemplate } from '../components/templates/PrimaryTemplate'; +import { TestForm } from '../components/TestForm'; export const About = (): JSX.Element => { return (

Content

+
); }; diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx index 6239a32f..faffa10a 100644 --- a/src/pages/Messages.tsx +++ b/src/pages/Messages.tsx @@ -5,7 +5,7 @@ import { Protobuf } from '@meshtastic/meshtasticjs'; import { Message } from '../components/chat/Message'; import { MessageBar } from '../components/chat/MessageBar'; -import { Button } from '../components/generic/Button'; +import { IconButton } from '../components/generic/IconButton'; import { useAppSelector } from '../hooks/redux'; export const Messages = (): JSX.Element => { @@ -29,12 +29,12 @@ export const Messages = (): JSX.Element => { {channelName()}
- - +
@@ -56,6 +56,6 @@ export const Messages = (): JSX.Element => {
); }; -; +; diff --git a/src/pages/Nodes.tsx b/src/pages/Nodes.tsx index 0c88f381..f9f12a0d 100644 --- a/src/pages/Nodes.tsx +++ b/src/pages/Nodes.tsx @@ -1,17 +1,45 @@ import React from 'react'; +import type { Protobuf } from '@meshtastic/meshtasticjs'; + import { Node } from '../components/nodes/Node'; +import { NodeDetails } from '../components/nodes/NodeDetails'; import { PrimaryTemplate } from '../components/templates/PrimaryTemplate'; import { useAppSelector } from '../hooks/redux'; export const Nodes = (): JSX.Element => { const nodes = useAppSelector((state) => state.meshtastic.nodes); + const [currentNode, setCurrentNode] = React.useState< + Protobuf.NodeInfo | undefined + >(); return ( - {nodes.map((node) => ( - - ))} +
+
+ {nodes.map((node) => ( + { + setCurrentNode(node); + }} + /> + ))} +
+
+ {currentNode ? ( + { + setCurrentNode(undefined); + }} + node={currentNode} + /> + ) : ( +
Node not selected
+ )} +
+
); }; diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 3eacc992..f70a0e21 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -7,14 +7,14 @@ import { Protobuf } from '@meshtastic/meshtasticjs'; import { Input } from '../components/form/Input'; import { Select } from '../components/form/Select'; -import { Toggle } from '../components/form/Toggle'; +import { Switch } from '../components/form/Switch'; import { PrimaryTemplate } from '../components/templates/PrimaryTemplate'; -import { connection } from '../connection'; -import { useAppDispatch, useAppSelector } from '../hooks/redux'; +import { connection } from '../core/connection'; import { setHostOverride, setHostOverrideEnabled, -} from '../slices/meshtasticSlice'; +} from '../core/slices/meshtasticSlice'; +import { useAppDispatch, useAppSelector } from '../hooks/redux'; export const Settings = (): JSX.Element => { const { t } = useTranslation(); @@ -26,7 +26,7 @@ export const Settings = (): JSX.Element => { (state) => state.meshtastic.hostOverrideEnabled, ); - const { register, handleSubmit } = + const { register, handleSubmit, control } = useForm({ defaultValues: radioConfig, }); @@ -65,36 +65,46 @@ export const Settings = (): JSX.Element => {
Node
- - - - - - - +