From 161d4323307fb97422d3e63317d7cc193f7d1c89 Mon Sep 17 00:00:00 2001 From: Sacha Weatherstone Date: Tue, 18 Jan 2022 00:39:55 +1100 Subject: [PATCH] Move plugins to settings page --- package.json | 4 +- pnpm-lock.yaml | 344 ++---------------- src/App.tsx | 4 +- src/components/generic/Loading.tsx | 9 - src/components/generic/Sidebar.tsx | 2 +- src/components/generic/form/Form.tsx | 22 ++ src/components/menu/BottomNav.tsx | 7 + src/components/menu/Navigation.tsx | 19 +- src/components/modals/VersionInfo.tsx | 56 +++ .../pages/settings/plugins/PluginsSidebar.tsx | 76 ++++ .../ExternalNotifications/DebugPanel.tsx | 32 ++ .../ExternalNotifications/SettingsPlanel.tsx | 97 +++++ .../plugins/panels/RangeTest/DebugPanel.tsx | 28 ++ .../panels/RangeTest/SettingsPanel.tsx | 79 ++++ .../plugins/panels/Serial/DebugPanel.tsx | 31 ++ .../plugins/panels/Serial/SettingsPanel.tsx | 100 +++++ .../panels/StoreForward/DebugPanel.tsx | 32 ++ .../panels/StoreForward/SettingsPanel.tsx | 95 +++++ .../{ => radio}/channels/ChannelsSidebar.tsx | 0 .../channels/panels/DebugPanel.tsx | 0 .../channels/panels/QRCodePanel.tsx | 0 .../channels/panels/SettingsPanel.tsx | 7 +- src/core/router.ts | 1 - src/pages/Plugins/ExternalNotification.tsx | 135 ------- src/pages/Plugins/Files.tsx | 128 ------- src/pages/Plugins/Index.tsx | 59 --- src/pages/Plugins/RangeTest.tsx | 106 ------ src/pages/Plugins/Serial.tsx | 133 ------- src/pages/Plugins/StoreAndForward.tsx | 98 ----- src/pages/settings/Channels.tsx | 4 +- src/pages/settings/Index.tsx | 12 +- src/pages/settings/Plugins.tsx | 130 +++++++ 32 files changed, 834 insertions(+), 1016 deletions(-) delete mode 100644 src/components/generic/Loading.tsx create mode 100644 src/components/generic/form/Form.tsx create mode 100644 src/components/modals/VersionInfo.tsx create mode 100644 src/components/pages/settings/plugins/PluginsSidebar.tsx create mode 100644 src/components/pages/settings/plugins/panels/ExternalNotifications/DebugPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/ExternalNotifications/SettingsPlanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/RangeTest/DebugPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/RangeTest/SettingsPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/Serial/DebugPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/Serial/SettingsPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/StoreForward/DebugPanel.tsx create mode 100644 src/components/pages/settings/plugins/panels/StoreForward/SettingsPanel.tsx rename src/components/pages/settings/{ => radio}/channels/ChannelsSidebar.tsx (100%) rename src/components/pages/settings/{ => radio}/channels/panels/DebugPanel.tsx (100%) rename src/components/pages/settings/{ => radio}/channels/panels/QRCodePanel.tsx (100%) rename src/components/pages/settings/{ => radio}/channels/panels/SettingsPanel.tsx (96%) delete mode 100644 src/pages/Plugins/ExternalNotification.tsx delete mode 100644 src/pages/Plugins/Files.tsx delete mode 100644 src/pages/Plugins/Index.tsx delete mode 100644 src/pages/Plugins/RangeTest.tsx delete mode 100644 src/pages/Plugins/Serial.tsx delete mode 100644 src/pages/Plugins/StoreAndForward.tsx create mode 100644 src/pages/settings/Plugins.tsx diff --git a/package.json b/package.json index dbb56e6d..cbd85f99 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "dependencies": { "@floating-ui/react-dom": "^0.4.3", "@headlessui/react": "^1.4.3", - "@meshtastic/components": "^1.0.17", + "@meshtastic/components": "^1.0.19", "@meshtastic/meshtasticjs": "^0.6.38", "@reduxjs/toolkit": "^1.7.1", "@tippyjs/react": "^4.2.6", @@ -65,7 +65,7 @@ "eslint-plugin-import": "^2.25.4", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", - "gzipper": "^6.2.1", + "gzipper": "^7.0.0", "postcss": "^8.4.5", "prettier": "^2.5.1", "tailwindcss": "^3.0.15", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b976e8be..14176e7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,7 +3,7 @@ lockfileVersion: 5.3 specifiers: '@floating-ui/react-dom': ^0.4.3 '@headlessui/react': ^1.4.3 - '@meshtastic/components': ^1.0.17 + '@meshtastic/components': ^1.0.19 '@meshtastic/meshtasticjs': ^0.6.38 '@reduxjs/toolkit': ^1.7.1 '@tippyjs/react': ^4.2.6 @@ -30,7 +30,7 @@ specifiers: eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 graphql-request: ^3.7.0 - gzipper: ^6.2.1 + gzipper: ^7.0.0 i18next: ^21.6.6 i18next-browser-languagedetector: ^6.1.2 mapbox-gl: ^2.6.1 @@ -66,7 +66,7 @@ specifiers: dependencies: '@floating-ui/react-dom': 0.4.3_b3482aaf5744fc7c2aeb7941b0e0a78f '@headlessui/react': 1.4.3_react-dom@17.0.2+react@17.0.2 - '@meshtastic/components': 1.0.17_@types+react@17.0.38 + '@meshtastic/components': 1.0.19_@types+react@17.0.38 '@meshtastic/meshtasticjs': 0.6.38 '@reduxjs/toolkit': 1.7.1_react-redux@7.2.6+react@17.0.2 '@tippyjs/react': 4.2.6_react-dom@17.0.2+react@17.0.2 @@ -117,7 +117,7 @@ devDependencies: eslint-plugin-import: 2.25.4_eslint@8.7.0 eslint-plugin-react: 7.28.0_eslint@8.7.0 eslint-plugin-react-hooks: 4.3.0_eslint@8.7.0 - gzipper: 6.2.1 + gzipper: 7.0.0 postcss: 8.4.5 prettier: 2.5.1 tailwindcss: 3.0.15_ef48b3b8837f8a23677bffe8f9cd866d @@ -1451,6 +1451,13 @@ packages: - '@types/react' dev: false + /@gfx/zopfli/1.0.15: + resolution: {integrity: sha512-7mBgpi7UD82fsff5ThQKet0uBTl4BYerQuc+/qA1ELTwWEiIedRTcD3JgiUu9wwZ2kytW8JOb165rSdAt8PfcQ==} + engines: {node: '>= 8'} + dependencies: + base64-js: 1.5.1 + dev: true + /@headlessui/react/1.4.3_react-dom@17.0.2+react@17.0.2: resolution: {integrity: sha512-n2IQkaaw0aAAlQS5MEXsM4uRK+w18CrM72EqnGRl/UBOQeQajad8oiKXR9Nk15jOzTFQjpxzrZMf1NxHidFBiw==} engines: {node: '>=10'} @@ -1532,8 +1539,8 @@ packages: engines: {node: '>=6.0.0'} dev: false - /@meshtastic/components/1.0.17_@types+react@17.0.38: - resolution: {integrity: sha512-e9ETFrzQUtpxVHc6NiiYMCkr7Ml4v7xlbILWK3LV48ALMDojBAFKLHdxuClpt0Rszo91ORACSSVpUkJNfWnp1A==} + /@meshtastic/components/1.0.19_@types+react@17.0.38: + resolution: {integrity: sha512-Uls4JpJFrxi86MlxRNTPRHFBW5m/3VVFaz1anvam1vHXpJZz/ikcEmW5Xgu+f7lkBO6JGtEgvdXSbJFCkr5gqQ==} dependencies: inter-ui: 3.19.3 react: 17.0.2 @@ -1715,8 +1722,8 @@ packages: '@types/geojson': 7946.0.8 dev: true - /@types/node/17.0.8: - resolution: {integrity: sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==} + /@types/node/17.0.9: + resolution: {integrity: sha512-5dNBXu/FOER+EXnyah7rn8xlNrfMOQb/qXnw4NQgLkCygKBKhdmF/CA5oXVOKZLBEahw8s2WP9LxIcN/oDDRgQ==} dev: true /@types/parse-json/4.0.0: @@ -1763,7 +1770,7 @@ packages: /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 17.0.8 + '@types/node': 17.0.9 dev: true /@types/scheduler/0.16.2: @@ -2113,11 +2120,6 @@ packages: engines: {node: '>=6'} dev: true - /ansi-regex/2.1.1: - resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} - engines: {node: '>=0.10.0'} - dev: true - /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2145,17 +2147,6 @@ packages: picomatch: 2.3.1 dev: true - /aproba/1.2.0: - resolution: {integrity: sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==} - dev: true - - /are-we-there-yet/1.1.7: - resolution: {integrity: sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==} - dependencies: - delegates: 1.0.0 - readable-stream: 2.3.7 - dev: true - /arg/5.0.1: resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} dev: true @@ -2230,7 +2221,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.19.1 - caniuse-lite: 1.0.30001299 + caniuse-lite: 1.0.30001300 fraction.js: 4.1.2 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -2308,14 +2299,6 @@ packages: engines: {node: '>=8'} dev: true - /bl/4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.0 - dev: true - /boring-avatars/1.6.1: resolution: {integrity: sha512-P7BZRz1DEdx61iW7q8EoB10rDLGGH4ec8uwQsMKOCag8TznC5A/efd5OBuL9Su3HjMEDHN3X8/JRRQNsVZMl4Q==} dev: false @@ -2339,7 +2322,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001299 + caniuse-lite: 1.0.30001300 electron-to-chromium: 1.4.46 escalade: 3.1.1 node-releases: 2.0.1 @@ -2350,13 +2333,6 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: true - /buffer/5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - /builtin-modules/3.2.0: resolution: {integrity: sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==} engines: {node: '>=6'} @@ -2379,8 +2355,8 @@ packages: engines: {node: '>= 6'} dev: true - /caniuse-lite/1.0.30001299: - resolution: {integrity: sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==} + /caniuse-lite/1.0.30001300: + resolution: {integrity: sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==} dev: true /chalk/2.4.2: @@ -2415,25 +2391,11 @@ packages: fsevents: 2.3.2 dev: true - /chownr/1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - dev: true - /chownr/2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} dev: true - /clone/1.0.4: - resolution: {integrity: sha1-2jCcwmPfFZlMaIypAheco8fNfH4=} - engines: {node: '>=0.8'} - dev: true - - /code-point-at/1.1.0: - resolution: {integrity: sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=} - engines: {node: '>=0.10.0'} - dev: true - /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2466,10 +2428,6 @@ packages: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true - /commander/3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - dev: true - /commander/7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} @@ -2484,10 +2442,6 @@ packages: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} dev: true - /console-control-strings/1.1.0: - resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} - dev: true - /convert-source-map/1.8.0: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} dependencies: @@ -2579,13 +2533,6 @@ packages: ms: 2.1.2 dev: true - /decompress-response/4.2.1: - resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} - engines: {node: '>=8'} - dependencies: - mimic-response: 2.1.0 - dev: true - /deep-equal/2.0.5: resolution: {integrity: sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==} dependencies: @@ -2606,11 +2553,6 @@ packages: which-typed-array: 1.1.7 dev: true - /deep-extend/0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: true - /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -2620,12 +2562,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /defaults/1.0.3: - resolution: {integrity: sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=} - dependencies: - clone: 1.0.4 - dev: true - /define-properties/1.1.3: resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} engines: {node: '>= 0.4'} @@ -2642,16 +2578,6 @@ packages: engines: {node: '>=0.4.0'} dev: false - /delegates/1.0.0: - resolution: {integrity: sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=} - dev: true - - /detect-libc/1.0.3: - resolution: {integrity: sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=} - engines: {node: '>=0.10'} - hasBin: true - dev: true - /detective/5.2.0: resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} engines: {node: '>=0.8.0'} @@ -3383,11 +3309,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /expand-template/2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - dev: true - /extract-files/9.0.0: resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==} engines: {node: ^10.17.0 || ^12.0.0 || >= 13.7.0} @@ -3493,10 +3414,6 @@ packages: resolution: {integrity: sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==} dev: true - /fs-constants/1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: true - /fs-extra/9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} @@ -3534,19 +3451,6 @@ packages: resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} dev: true - /gauge/2.7.4: - resolution: {integrity: sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=} - dependencies: - aproba: 1.2.0 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.6 - string-width: 1.0.2 - strip-ansi: 3.0.1 - wide-align: 1.1.5 - dev: true - /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -3581,10 +3485,6 @@ packages: get-intrinsic: 1.1.1 dev: true - /github-from-package/0.0.0: - resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=} - dev: true - /gl-matrix/3.4.3: resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} dev: false @@ -3656,14 +3556,14 @@ packages: resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} dev: false - /gzipper/6.2.1: - resolution: {integrity: sha512-HGCFv3hZy87B+AHRuDpbyRbvOdaJllyGB+OTqDqKy54e8M1RDgF64QN/buyqpqhvSXWePNIE0jqbHpcjCWG6YQ==} + /gzipper/7.0.0: + resolution: {integrity: sha512-Pfr8FXg4JOQ9hwWWS+d5KDOokRlfjkuNuK7HVJsiXwQhYTugKMHXAnAeEuKr5ILtxX0cAzJBtR6g3Wclze8+LA==} engines: {node: '>=14'} hasBin: true dependencies: + '@gfx/zopfli': 1.0.15 commander: 7.2.0 deep-equal: 2.0.5 - node-zopfli: 2.1.4 simple-zstd: 1.4.0 uuid: 8.3.2 dev: true @@ -3694,10 +3594,6 @@ packages: has-symbols: 1.0.2 dev: true - /has-unicode/2.0.1: - resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} - dev: true - /has/1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -3745,6 +3641,7 @@ packages: /ieee754/1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false /ignore/4.0.6: resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} @@ -3784,10 +3681,6 @@ packages: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true - /ini/1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - /inter-ui/3.19.3: resolution: {integrity: sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg==} dev: false @@ -3857,13 +3750,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /is-fullwidth-code-point/1.0.0: - resolution: {integrity: sha1-754xOG8DGn8NZDr4L95QxFfvAMs=} - engines: {node: '>=0.10.0'} - dependencies: - number-is-nan: 1.0.1 - dev: true - /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} @@ -4010,7 +3896,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 17.0.8 + '@types/node': 17.0.9 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -4251,11 +4137,6 @@ packages: mime-db: 1.51.0 dev: false - /mimic-response/2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} - dev: true - /minimatch/3.0.4: resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} dependencies: @@ -4280,10 +4161,6 @@ packages: yallist: 4.0.0 dev: true - /mkdirp-classic/0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - dev: true - /mkdirp/1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -4306,30 +4183,16 @@ packages: resolution: {integrity: sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=} dev: false - /nanoid/3.1.32: - resolution: {integrity: sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==} + /nanoid/3.2.0: + resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true dev: true - /napi-build-utils/1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} - dev: true - /natural-compare/1.4.0: resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} dev: true - /node-abi/2.30.1: - resolution: {integrity: sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==} - dependencies: - semver: 5.7.1 - dev: true - - /node-addon-api/1.7.2: - resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} - dev: true - /node-fetch/2.6.1: resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} engines: {node: 4.x || >=6.0.0} @@ -4339,22 +4202,6 @@ packages: resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} dev: true - /node-zopfli/2.1.4: - resolution: {integrity: sha512-5kxbPxNQHbORFBNNf083V7h0dTFy6+C1W4ZA4qTXjpCQqEMzxAQFAOfi6BlCmXAkC/+Vr8d6h0XOmdjvp+9FNw==} - engines: {node: '>=8'} - hasBin: true - requiresBuild: true - dependencies: - commander: 3.0.2 - defaults: 1.0.3 - node-addon-api: 1.7.2 - prebuild-install: 5.3.6 - dev: true - - /noop-logger/0.1.1: - resolution: {integrity: sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=} - dev: true - /normalize-path/3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -4365,20 +4212,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /npmlog/4.1.2: - resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} - dependencies: - are-we-there-yet: 1.1.7 - console-control-strings: 1.1.0 - gauge: 2.7.4 - set-blocking: 2.0.0 - dev: true - - /number-is-nan/1.0.1: - resolution: {integrity: sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=} - engines: {node: '>=0.10.0'} - dev: true - /object-assign/4.1.1: resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} engines: {node: '>=0.10.0'} @@ -4632,7 +4465,7 @@ packages: resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.1.32 + nanoid: 3.2.0 picocolors: 1.0.0 source-map-js: 1.0.1 dev: true @@ -4641,28 +4474,6 @@ packages: resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} dev: false - /prebuild-install/5.3.6: - resolution: {integrity: sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==} - engines: {node: '>=6'} - hasBin: true - dependencies: - detect-libc: 1.0.3 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.5 - mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 2.30.1 - noop-logger: 0.1.1 - npmlog: 4.1.2 - pump: 3.0.0 - rc: 1.2.8 - simple-get: 3.1.0 - tar-fs: 2.1.1 - tunnel-agent: 0.6.0 - which-pm-runs: 1.0.0 - dev: true - /prelude-ls/1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4707,13 +4518,6 @@ packages: resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} dev: false - /pump/3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - dev: true - /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -4746,16 +4550,6 @@ packages: safe-buffer: 5.2.1 dev: true - /rc/1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.5 - strip-json-comments: 2.0.1 - dev: true - /react-dom/17.0.2_react@17.0.2: resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} peerDependencies: @@ -5144,11 +4938,6 @@ packages: object-assign: 4.1.1 dev: false - /semver/5.7.1: - resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} - hasBin: true - dev: true - /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true @@ -5173,10 +4962,6 @@ packages: randombytes: 2.1.0 dev: true - /set-blocking/2.0.0: - resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} - dev: true - /shebang-command/2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -5197,22 +4982,6 @@ packages: object-inspect: 1.12.0 dev: true - /signal-exit/3.0.6: - resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==} - dev: true - - /simple-concat/1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - dev: true - - /simple-get/3.1.0: - resolution: {integrity: sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==} - dependencies: - decompress-response: 4.2.1 - once: 1.4.0 - simple-concat: 1.0.1 - dev: true - /simple-zstd/1.4.0: resolution: {integrity: sha512-9zBNnu7MkwRiZm7voFUX7ehCcLO2d1FmJ2RWEVsN8Exw2tVYK9k/0/8WjPUmSmtoHOyoFTkHHaOLuPSwkgFmrA==} dependencies: @@ -5287,15 +5056,6 @@ packages: resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} dev: true - /string-width/1.0.2: - resolution: {integrity: sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=} - engines: {node: '>=0.10.0'} - dependencies: - code-point-at: 1.1.0 - is-fullwidth-code-point: 1.0.0 - strip-ansi: 3.0.1 - dev: true - /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -5353,13 +5113,6 @@ packages: is-regexp: 1.0.0 dev: true - /strip-ansi/3.0.1: - resolution: {integrity: sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=} - engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - dev: true - /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -5377,11 +5130,6 @@ packages: engines: {node: '>=10'} dev: true - /strip-json-comments/2.0.1: - resolution: {integrity: sha1-PFMZQukIwml8DsNEhYwobHygpgo=} - engines: {node: '>=0.10.0'} - dev: true - /strip-json-comments/3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -5474,26 +5222,6 @@ packages: - ts-node dev: true - /tar-fs/2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.0 - tar-stream: 2.2.0 - dev: true - - /tar-stream/2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.0 - dev: true - /tar/6.1.11: resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} engines: {node: '>= 10'} @@ -5633,12 +5361,6 @@ packages: typescript: 4.5.4 dev: true - /tunnel-agent/0.6.0: - resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} - dependencies: - safe-buffer: 5.2.1 - dev: true - /type-check/0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -5867,10 +5589,6 @@ packages: is-weakset: 2.0.2 dev: true - /which-pm-runs/1.0.0: - resolution: {integrity: sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=} - dev: true - /which-typed-array/1.1.7: resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==} engines: {node: '>= 0.4'} @@ -5891,12 +5609,6 @@ packages: isexe: 2.0.0 dev: true - /wide-align/1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - dependencies: - string-width: 1.0.2 - dev: true - /word-wrap/1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} diff --git a/src/App.tsx b/src/App.tsx index 5424a962..f11f98ea 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,7 +13,6 @@ import { useAppSelector } from '@hooks/useAppSelector'; import { Messages } from '@pages/Messages'; import { Nodes } from '@pages/Nodes'; import { NotFound } from '@pages/NotFound'; -import { Plugins } from '@pages/Plugins/Index'; import { Settings } from '@pages/settings/Index'; import { ErrorFallback } from './components/ErrorFallback'; @@ -67,7 +66,7 @@ export const App = (): JSX.Element => {
- + @@ -81,7 +80,6 @@ export const App = (): JSX.Element => { )} - {route.name === 'plugins' && } {route.name === 'settings' && } {route.name === false && } diff --git a/src/components/generic/Loading.tsx b/src/components/generic/Loading.tsx deleted file mode 100644 index 5778d4bc..00000000 --- a/src/components/generic/Loading.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import type React from 'react'; - -export const Loading = (): JSX.Element => { - return ( -
-
Loading
-
- ); -}; diff --git a/src/components/generic/Sidebar.tsx b/src/components/generic/Sidebar.tsx index 2b415504..8564a43c 100644 --- a/src/components/generic/Sidebar.tsx +++ b/src/components/generic/Sidebar.tsx @@ -37,7 +37,7 @@ export const Sidebar = ({ {children ?? ( -
+
Please select item
)} diff --git a/src/components/generic/form/Form.tsx b/src/components/generic/form/Form.tsx new file mode 100644 index 00000000..1003fb72 --- /dev/null +++ b/src/components/generic/form/Form.tsx @@ -0,0 +1,22 @@ +import type React from 'react'; + +import { Loading } from '@meshtastic/components'; + +export interface FormProps { + loading?: boolean; + children: React.ReactNode; +} + +export const Form = ({ loading, children }: FormProps): JSX.Element => { + return ( +
{ + e.preventDefault(); + }} + className="relative flex-grow gap-3 p-2" + > + {loading && } + {children} + + ); +}; diff --git a/src/components/menu/BottomNav.tsx b/src/components/menu/BottomNav.tsx index 7cbba3cf..f63b217d 100644 --- a/src/components/menu/BottomNav.tsx +++ b/src/components/menu/BottomNav.tsx @@ -26,6 +26,7 @@ import { useAppSelector } from '@hooks/useAppSelector'; import { Protobuf, Types } from '@meshtastic/meshtasticjs'; import { Tooltip } from '../generic/Tooltip'; +import { VersionInfo } from '../modals/VersionInfo'; // export interface BottomNavProps { @@ -99,6 +100,12 @@ export const BottomNav = (): JSX.Element => {
+ { + setShowVersionInfo(false); + }} + />
{ diff --git a/src/components/menu/Navigation.tsx b/src/components/menu/Navigation.tsx index c014b15c..00ef2258 100644 --- a/src/components/menu/Navigation.tsx +++ b/src/components/menu/Navigation.tsx @@ -1,19 +1,11 @@ import type React from 'react'; -import { FiGrid, FiMessageSquare, FiPackage, FiSettings } from 'react-icons/fi'; +import { FiGrid, FiMessageSquare, FiSettings } from 'react-icons/fi'; import type { Link } from 'type-route'; import { routes, useRoute } from '@core/router'; -type DefaultDivProps = JSX.IntrinsicElements['div']; - -export type NavigationProps = DefaultDivProps; - -export const Navigation = ({ - onClick, - className, - ...props -}: NavigationProps): JSX.Element => { +export const Navigation = (): JSX.Element => { const route = useRoute(); return ( @@ -34,13 +26,6 @@ export const Navigation = ({ link={routes.nodes().link} /> - } - active={route.name === 'plugins'} - link={routes.plugins().link} - /> - } diff --git a/src/components/modals/VersionInfo.tsx b/src/components/modals/VersionInfo.tsx new file mode 100644 index 00000000..c1615877 --- /dev/null +++ b/src/components/modals/VersionInfo.tsx @@ -0,0 +1,56 @@ +import React from 'react'; + +import { Modal } from '@components/generic/Modal'; +import { Card } from '@meshtastic/components'; + +export interface VersionInfoProps { + visible: boolean; + onclose: () => void; +} + +export const VersionInfo = ({ + visible, + onclose, +}: VersionInfoProps): JSX.Element => { + // const { data } = useSWR( + // `query { + // repository(owner: "meshtastic", name: "meshtastic-web") { + // ref(qualifiedName: "master") { + // name + // target { + // ... on Commit { + // history(first: 4) { + // edges { + // node { + // abbreviatedOid + // message + // author { + // avatarUrl + // name + // } + // } + // } + // } + // } + // } + // } + // } + // }`, + // fetcher, + // ); + // console.log(data); + + return ( + { + onclose(); + }} + > + +
Version Info
+ {/* {data?.sha} */} +
+
+ ); +}; diff --git a/src/components/pages/settings/plugins/PluginsSidebar.tsx b/src/components/pages/settings/plugins/PluginsSidebar.tsx new file mode 100644 index 00000000..73ea39c7 --- /dev/null +++ b/src/components/pages/settings/plugins/PluginsSidebar.tsx @@ -0,0 +1,76 @@ +import type React from 'react'; + +import { FiCode, FiSliders } from 'react-icons/fi'; + +import { TabButton } from '@app/components/TabButton'; +import type { Plugin } from '@app/pages/settings/Plugins'; +import { Sidebar } from '@components/generic/Sidebar'; +import { Tab } from '@headlessui/react'; + +import { ExternalNotificationsDebugPanel } from './panels/ExternalNotifications/DebugPanel'; +import { ExternalNotificationsSettingsPlanel } from './panels/ExternalNotifications/SettingsPlanel'; +import { RangeTestDebugPanel } from './panels/RangeTest/DebugPanel'; +import { RangeTestSettingsPanel } from './panels/RangeTest/SettingsPanel'; +import { SerialDebugPanel } from './panels/Serial/DebugPanel'; +import { SerialSettingsPanel } from './panels/Serial/SettingsPanel'; +import { StoreForwardDebugPanel } from './panels/StoreForward/DebugPanel'; +import { StoreForwardSettingsPanel } from './panels/StoreForward/SettingsPanel'; + +export interface PluginsSidebarProps { + plugin?: Plugin; + closeSidebar: () => void; +} + +export const PluginsSidebar = ({ + plugin, + closeSidebar, +}: PluginsSidebarProps): JSX.Element => { + return ( + + {plugin && ( + +
+ + + + + + + + +
+ + {plugin === 'Range Test' && ( + <> + + + + )} + {plugin === 'External Notifications' && ( + <> + + + + )} + {plugin === 'Serial' && ( + <> + + + + )} + {plugin === 'Store & Forward' && ( + <> + + + + )} + +
+ )} +
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/ExternalNotifications/DebugPanel.tsx b/src/components/pages/settings/plugins/panels/ExternalNotifications/DebugPanel.tsx new file mode 100644 index 00000000..95dba259 --- /dev/null +++ b/src/components/pages/settings/plugins/panels/ExternalNotifications/DebugPanel.tsx @@ -0,0 +1,32 @@ +import type React from 'react'; + +import JSONPretty from 'react-json-pretty'; + +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { CopyButton } from '@components/menu/buttons/CopyButton'; +import { Tab } from '@headlessui/react'; + +export const ExternalNotificationsDebugPanel = (): JSX.Element => { + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const debugData = { + extNotificationPluginActive: preferences.extNotificationPluginActive, + extNotificationPluginAlertBell: preferences.extNotificationPluginAlertBell, + extNotificationPluginAlertMessage: + preferences.extNotificationPluginAlertMessage, + extNotificationPluginEnabled: preferences.extNotificationPluginEnabled, + extNotificationPluginOutput: preferences.extNotificationPluginOutput, + extNotificationPluginOutputMs: preferences.extNotificationPluginOutputMs, + }; + + return ( + +
+ +
+ +
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/ExternalNotifications/SettingsPlanel.tsx b/src/components/pages/settings/plugins/panels/ExternalNotifications/SettingsPlanel.tsx new file mode 100644 index 00000000..781bab8e --- /dev/null +++ b/src/components/pages/settings/plugins/panels/ExternalNotifications/SettingsPlanel.tsx @@ -0,0 +1,97 @@ +import React from 'react'; + +import { useForm, useWatch } from 'react-hook-form'; +import { FiSave } from 'react-icons/fi'; + +import { Form } from '@app/components/generic/form/Form'; +import { connection } from '@app/core/connection'; +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { Tab } from '@headlessui/react'; +import { Checkbox, IconButton, Input } from '@meshtastic/components'; +import type { Protobuf } from '@meshtastic/meshtasticjs'; + +export const ExternalNotificationsSettingsPlanel = (): JSX.Element => { + const [loading, setLoading] = React.useState(false); + + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const { register, handleSubmit, formState, reset, control } = + useForm({ + defaultValues: preferences, + }); + + React.useEffect(() => { + reset(preferences); + }, [reset, preferences]); + + const onSubmit = handleSubmit(async (data) => { + setLoading(true); + await connection.setPreferences(data, async (): Promise => { + reset({ ...data }); + setLoading(false); + await Promise.resolve(); + }); + }); + + const pluginEnabled = useWatch({ + control, + name: 'extNotificationPluginEnabled', + defaultValue: false, + }); + + return ( + +
+ + + + + + + +
+
+ => { + await onSubmit(); + }} + icon={} + /> +
+
+
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/RangeTest/DebugPanel.tsx b/src/components/pages/settings/plugins/panels/RangeTest/DebugPanel.tsx new file mode 100644 index 00000000..a877979a --- /dev/null +++ b/src/components/pages/settings/plugins/panels/RangeTest/DebugPanel.tsx @@ -0,0 +1,28 @@ +import type React from 'react'; + +import JSONPretty from 'react-json-pretty'; + +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { CopyButton } from '@components/menu/buttons/CopyButton'; +import { Tab } from '@headlessui/react'; + +export const RangeTestDebugPanel = (): JSX.Element => { + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const debugData = { + rangeTestPluginEnabled: preferences.rangeTestPluginEnabled, + rangeTestPluginSave: preferences.rangeTestPluginSave, + rangeTestPluginSender: preferences.rangeTestPluginSender, + }; + + return ( + +
+ +
+ +
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/RangeTest/SettingsPanel.tsx b/src/components/pages/settings/plugins/panels/RangeTest/SettingsPanel.tsx new file mode 100644 index 00000000..ec5c4c2a --- /dev/null +++ b/src/components/pages/settings/plugins/panels/RangeTest/SettingsPanel.tsx @@ -0,0 +1,79 @@ +import React from 'react'; + +import { useForm, useWatch } from 'react-hook-form'; +import { FiSave } from 'react-icons/fi'; + +import { Form } from '@app/components/generic/form/Form'; +import { connection } from '@app/core/connection'; +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { Tab } from '@headlessui/react'; +import { Checkbox, IconButton, Input } from '@meshtastic/components'; +import type { Protobuf } from '@meshtastic/meshtasticjs'; + +export const RangeTestSettingsPanel = (): JSX.Element => { + const [loading, setLoading] = React.useState(false); + + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const { register, handleSubmit, formState, reset, control } = + useForm({ + defaultValues: preferences, + }); + + React.useEffect(() => { + reset(preferences); + }, [reset, preferences]); + + const onSubmit = handleSubmit(async (data) => { + setLoading(true); + await connection.setPreferences(data, async (): Promise => { + reset({ ...data }); + setLoading(false); + await Promise.resolve(); + }); + }); + + const pluginEnabled = useWatch({ + control, + name: 'rangeTestPluginEnabled', + defaultValue: false, + }); + + return ( + +
+ + + + +
+
+ => { + await onSubmit(); + }} + icon={} + /> +
+
+
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/Serial/DebugPanel.tsx b/src/components/pages/settings/plugins/panels/Serial/DebugPanel.tsx new file mode 100644 index 00000000..87127823 --- /dev/null +++ b/src/components/pages/settings/plugins/panels/Serial/DebugPanel.tsx @@ -0,0 +1,31 @@ +import type React from 'react'; + +import JSONPretty from 'react-json-pretty'; + +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { CopyButton } from '@components/menu/buttons/CopyButton'; +import { Tab } from '@headlessui/react'; + +export const SerialDebugPanel = (): JSX.Element => { + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const debugData = { + serialpluginEnabled: preferences.serialpluginEnabled, + serialpluginEcho: preferences.serialpluginEcho, + serialpluginMode: preferences.serialpluginMode, + serialpluginRxd: preferences.serialpluginRxd, + serialpluginTxd: preferences.serialpluginTxd, + serialpluginTimeout: preferences.serialpluginTimeout, + }; + + return ( + +
+ +
+ +
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/Serial/SettingsPanel.tsx b/src/components/pages/settings/plugins/panels/Serial/SettingsPanel.tsx new file mode 100644 index 00000000..e5afb96b --- /dev/null +++ b/src/components/pages/settings/plugins/panels/Serial/SettingsPanel.tsx @@ -0,0 +1,100 @@ +import React from 'react'; + +import { useForm, useWatch } from 'react-hook-form'; +import { FiSave } from 'react-icons/fi'; + +import { Form } from '@app/components/generic/form/Form'; +import { connection } from '@app/core/connection'; +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { Tab } from '@headlessui/react'; +import { Checkbox, IconButton, Input } from '@meshtastic/components'; +import type { Protobuf } from '@meshtastic/meshtasticjs'; + +export const SerialSettingsPanel = (): JSX.Element => { + const [loading, setLoading] = React.useState(false); + + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const { register, handleSubmit, formState, reset, control } = + useForm({ + defaultValues: preferences, + }); + + React.useEffect(() => { + reset(preferences); + }, [reset, preferences]); + + const onSubmit = handleSubmit(async (data) => { + setLoading(true); + await connection.setPreferences(data, async (): Promise => { + reset({ ...data }); + setLoading(false); + await Promise.resolve(); + }); + }); + + const pluginEnabled = useWatch({ + control, + name: 'serialpluginEnabled', + defaultValue: false, + }); + + return ( + +
+ + + + + + + + +
+
+ => { + await onSubmit(); + }} + icon={} + /> +
+
+
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/StoreForward/DebugPanel.tsx b/src/components/pages/settings/plugins/panels/StoreForward/DebugPanel.tsx new file mode 100644 index 00000000..b9dbc5c3 --- /dev/null +++ b/src/components/pages/settings/plugins/panels/StoreForward/DebugPanel.tsx @@ -0,0 +1,32 @@ +import type React from 'react'; + +import JSONPretty from 'react-json-pretty'; + +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { CopyButton } from '@components/menu/buttons/CopyButton'; +import { Tab } from '@headlessui/react'; + +export const StoreForwardDebugPanel = (): JSX.Element => { + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const debugData = { + storeForwardPluginEnabled: preferences.storeForwardPluginEnabled, + storeForwardPluginHeartbeat: preferences.storeForwardPluginHeartbeat, + storeForwardPluginRecords: preferences.storeForwardPluginRecords, + storeForwardPluginHistoryReturnMax: + preferences.storeForwardPluginHistoryReturnMax, + storeForwardPluginHistoryReturnWindow: + preferences.storeForwardPluginHistoryReturnWindow, + }; + + return ( + +
+ +
+ +
+ ); +}; diff --git a/src/components/pages/settings/plugins/panels/StoreForward/SettingsPanel.tsx b/src/components/pages/settings/plugins/panels/StoreForward/SettingsPanel.tsx new file mode 100644 index 00000000..b5150693 --- /dev/null +++ b/src/components/pages/settings/plugins/panels/StoreForward/SettingsPanel.tsx @@ -0,0 +1,95 @@ +import React from 'react'; + +import { useForm, useWatch } from 'react-hook-form'; +import { FiSave } from 'react-icons/fi'; + +import { Form } from '@app/components/generic/form/Form'; +import { connection } from '@app/core/connection'; +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { Tab } from '@headlessui/react'; +import { Checkbox, IconButton, Input } from '@meshtastic/components'; +import type { Protobuf } from '@meshtastic/meshtasticjs'; + +export const StoreForwardSettingsPanel = (): JSX.Element => { + const [loading, setLoading] = React.useState(false); + + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const { register, handleSubmit, formState, reset, control } = + useForm({ + defaultValues: preferences, + }); + + React.useEffect(() => { + reset(preferences); + }, [reset, preferences]); + + const onSubmit = handleSubmit(async (data) => { + setLoading(true); + await connection.setPreferences(data, async (): Promise => { + reset({ ...data }); + setLoading(false); + await Promise.resolve(); + }); + }); + + const pluginEnabled = useWatch({ + control, + name: 'storeForwardPluginEnabled', + defaultValue: false, + }); + + return ( + +
+ + + + + + +
+
+ => { + await onSubmit(); + }} + icon={} + /> +
+
+
+ ); +}; diff --git a/src/components/pages/settings/channels/ChannelsSidebar.tsx b/src/components/pages/settings/radio/channels/ChannelsSidebar.tsx similarity index 100% rename from src/components/pages/settings/channels/ChannelsSidebar.tsx rename to src/components/pages/settings/radio/channels/ChannelsSidebar.tsx diff --git a/src/components/pages/settings/channels/panels/DebugPanel.tsx b/src/components/pages/settings/radio/channels/panels/DebugPanel.tsx similarity index 100% rename from src/components/pages/settings/channels/panels/DebugPanel.tsx rename to src/components/pages/settings/radio/channels/panels/DebugPanel.tsx diff --git a/src/components/pages/settings/channels/panels/QRCodePanel.tsx b/src/components/pages/settings/radio/channels/panels/QRCodePanel.tsx similarity index 100% rename from src/components/pages/settings/channels/panels/QRCodePanel.tsx rename to src/components/pages/settings/radio/channels/panels/QRCodePanel.tsx diff --git a/src/components/pages/settings/channels/panels/SettingsPanel.tsx b/src/components/pages/settings/radio/channels/panels/SettingsPanel.tsx similarity index 96% rename from src/components/pages/settings/channels/panels/SettingsPanel.tsx rename to src/components/pages/settings/radio/channels/panels/SettingsPanel.tsx index 677f3999..e0676bcf 100644 --- a/src/components/pages/settings/channels/panels/SettingsPanel.tsx +++ b/src/components/pages/settings/radio/channels/panels/SettingsPanel.tsx @@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form'; import { FiSave } from 'react-icons/fi'; import { MdRefresh, MdVisibility, MdVisibilityOff } from 'react-icons/md'; -import { Loading } from '@app/components/generic/Loading'; +import { Form } from '@app/components/generic/form/Form'; import { connection } from '@app/core/connection'; import { Tab } from '@headlessui/react'; import { Checkbox, IconButton, Input, Select } from '@meshtastic/components'; @@ -73,8 +73,7 @@ export const SettingsPanel = ({ channel }: SettingsPanelProps): JSX.Element => { return ( - {loading && } -
+ {channel?.index !== 0 && ( <> { /> - +
>; -} - -export const ExternalNotification = ({ - navOpen, - setNavOpen, -}: ExternalNotificationProps): JSX.Element => { - const preferences = useAppSelector( - (state) => state.meshtastic.radio.preferences, - ); - - const { register, handleSubmit, formState, reset, control } = - useForm({ - defaultValues: { - extNotificationPluginActive: preferences.extNotificationPluginActive, - extNotificationPluginAlertBell: - preferences.extNotificationPluginAlertBell, - extNotificationPluginAlertMessage: - preferences.extNotificationPluginAlertMessage, - extNotificationPluginEnabled: preferences.extNotificationPluginEnabled, - extNotificationPluginOutput: preferences.extNotificationPluginOutput, - extNotificationPluginOutputMs: - preferences.extNotificationPluginOutputMs, - }, - }); - - React.useEffect(() => { - reset({ - extNotificationPluginActive: preferences.extNotificationPluginActive, - extNotificationPluginAlertBell: - preferences.extNotificationPluginAlertBell, - extNotificationPluginAlertMessage: - preferences.extNotificationPluginAlertMessage, - extNotificationPluginEnabled: preferences.extNotificationPluginEnabled, - extNotificationPluginOutput: preferences.extNotificationPluginOutput, - extNotificationPluginOutputMs: preferences.extNotificationPluginOutputMs, - }); - }, [reset, preferences]); - - const onSubmit = handleSubmit((data) => { - void connection.setPreferences(data, async (): Promise => { - //add loading indicator - reset({ ...data }); - await Promise.resolve(); - }); - }); - - //todo, add loading indicator - - const watchExternalNotificationPluginEnabled = useWatch({ - control, - name: 'extNotificationPluginEnabled', - defaultValue: false, - }); - - return ( - } - onClick={(): void => { - setNavOpen && setNavOpen(!navOpen); - }} - /> - } - footer={ - - } - > -
- -
-
- - - - - - - -
-
-
-
- ); -}; diff --git a/src/pages/Plugins/Files.tsx b/src/pages/Plugins/Files.tsx deleted file mode 100644 index ccf0b5c4..00000000 --- a/src/pages/Plugins/Files.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import type React from 'react'; - -// import { DefaultExtensionType, defaultStyles, FileIcon } from 'react-file-icon'; -import { FiMenu, FiTrash, FiUploadCloud } from 'react-icons/fi'; -import useSWR from 'swr'; - -import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; -import { connectionUrl } from '@core/connection'; -import fetcher from '@core/utils/fetcher'; -import { Card, IconButton } from '@meshtastic/components'; - -export interface RangeTestProps { - navOpen?: boolean; - setNavOpen?: React.Dispatch>; -} -interface IFile { - name: string; - nameModified: string; - size: number; -} -interface IFiles { - data: { - files: IFile[]; - filesystem: { - free: number; - total: number; - used: number; - }; - }; - - status: boolean; -} - -export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => { - const { data } = useSWR( - `http://${connectionUrl}/json/spiffs/browse/static`, - fetcher, - ); - - return ( - } - onClick={(): void => { - setNavOpen && setNavOpen(!navOpen); - }} - /> - } - > -
- - {data ? ( -
-
-
- {JSON.stringify(data.data.filesystem.used)} bytes total -
-
- ) : ( -
Loading...
- )} -
- } />} - className="md:w-1/3" - > - {data ? ( -
- {data.data.files.map((file: IFile) => ( -
- - => { - // await fetch( - // `http://${connectionUrl}/json/spiffs/delete/static?remove=${file.name}`, - // { - // method: 'DELETE', - // }, - // ); - // }} - icon={} - /> -
- ))} -
- ) : ( -
Loading...
- )} -
-
-
- ); -}; diff --git a/src/pages/Plugins/Index.tsx b/src/pages/Plugins/Index.tsx deleted file mode 100644 index 2f93530b..00000000 --- a/src/pages/Plugins/Index.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import type React from 'react'; - -import { - FiAlignLeft, - FiBell, - FiFastForward, - FiFileText, - FiRss, -} from 'react-icons/fi'; - -import { PageLayout } from '@components/templates/PageLayout'; - -import { ExternalNotification } from './ExternalNotification'; -import { Files } from './Files'; -import { RangeTest } from './RangeTest'; -import { Serial } from './Serial'; -import { StoreAndForward } from './StoreAndForward'; - -export const Plugins = (): JSX.Element => { - return ( - , - }, - { - title: 'File Browser', - description: 'HTTP only file browser', - icon: , - }, - { - title: 'External Notification', - description: 'External hardware alerts', - icon: , - }, - { - title: 'Serial', - description: 'Send serial data over the mesh', - icon: , - }, - { - title: 'Store & Forward', - description: 'Retrive message history', - icon: , - }, - ]} - panels={[ - , - , - , - , - , - ]} - /> - ); -}; diff --git a/src/pages/Plugins/RangeTest.tsx b/src/pages/Plugins/RangeTest.tsx deleted file mode 100644 index 8a13849c..00000000 --- a/src/pages/Plugins/RangeTest.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import React from 'react'; - -import { useForm, useWatch } from 'react-hook-form'; -import { FiMenu } from 'react-icons/fi'; - -import { FormFooter } from '@components/FormFooter'; -import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; -import { connection } from '@core/connection'; -import { useAppSelector } from '@hooks/useAppSelector'; -import { Card, Checkbox, IconButton, Input } from '@meshtastic/components'; -import type { RadioConfig_UserPreferences } from '@meshtastic/meshtasticjs/dist/generated'; - -export interface RangeTestProps { - navOpen?: boolean; - setNavOpen?: React.Dispatch>; -} - -export const RangeTest = ({ - navOpen, - setNavOpen, -}: RangeTestProps): JSX.Element => { - const preferences = useAppSelector( - (state) => state.meshtastic.radio.preferences, - ); - - const { register, handleSubmit, formState, reset, control } = - useForm({ - defaultValues: { - rangeTestPluginEnabled: preferences.rangeTestPluginEnabled, - rangeTestPluginSave: preferences.rangeTestPluginSave, - rangeTestPluginSender: preferences.rangeTestPluginSender, - }, - }); - - React.useEffect(() => { - reset({ - rangeTestPluginEnabled: preferences.rangeTestPluginEnabled, - rangeTestPluginSave: preferences.rangeTestPluginSave, - rangeTestPluginSender: preferences.rangeTestPluginSender, - }); - }, [reset, preferences]); - - const onSubmit = handleSubmit((data) => { - void connection.setPreferences(data, async (): Promise => { - //add loading indicator - reset({ ...data }); - await Promise.resolve(); - }); - }); - - //todo, add loading indicator - - const watchRangeTestPluginEnabled = useWatch({ - control, - name: 'rangeTestPluginEnabled', - defaultValue: false, - }); - - return ( - } - onClick={(): void => { - setNavOpen && setNavOpen(!navOpen); - }} - /> - } - footer={ - - } - > -
- -
-
- - - - -
-
-
-
- ); -}; diff --git a/src/pages/Plugins/Serial.tsx b/src/pages/Plugins/Serial.tsx deleted file mode 100644 index b176a8b1..00000000 --- a/src/pages/Plugins/Serial.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import React from 'react'; - -import { useForm, useWatch } from 'react-hook-form'; -import { FiMenu } from 'react-icons/fi'; - -import { FormFooter } from '@components/FormFooter'; -import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; -import { connection } from '@core/connection'; -import { useAppSelector } from '@hooks/useAppSelector'; -import { Card, Checkbox, IconButton, Input } from '@meshtastic/components'; -import type { RadioConfig_UserPreferences } from '@meshtastic/meshtasticjs/dist/generated'; - -export interface SerialProps { - navOpen?: boolean; - setNavOpen?: React.Dispatch>; -} - -export const Serial = ({ navOpen, setNavOpen }: SerialProps): JSX.Element => { - const preferences = useAppSelector( - (state) => state.meshtastic.radio.preferences, - ); - - const { register, handleSubmit, formState, reset, control } = - useForm({ - defaultValues: { - serialpluginEnabled: preferences.serialpluginEnabled, - serialpluginEcho: preferences.serialpluginEcho, - serialpluginMode: preferences.serialpluginMode, - serialpluginRxd: preferences.serialpluginRxd, - serialpluginTimeout: preferences.serialpluginTimeout, - serialpluginTxd: preferences.serialpluginTxd, - }, - }); - - React.useEffect(() => { - reset({ - serialpluginEnabled: preferences.serialpluginEnabled, - serialpluginEcho: preferences.serialpluginEcho, - serialpluginMode: preferences.serialpluginMode, - serialpluginRxd: preferences.serialpluginRxd, - serialpluginTimeout: preferences.serialpluginTimeout, - serialpluginTxd: preferences.serialpluginTxd, - }); - }, [reset, preferences]); - - const onSubmit = handleSubmit((data) => { - void connection.setPreferences(data, async (): Promise => { - //add loading indicator - reset({ ...data }); - await Promise.resolve(); - }); - }); - //todo, add loading indicator - - const watchSerialPluginEnabled = useWatch({ - control, - name: 'serialpluginEnabled', - defaultValue: false, - }); - - return ( - } - onClick={(): void => { - setNavOpen && setNavOpen(!navOpen); - }} - /> - } - footer={ - - } - > -
- -
-
- - - - - - - - -
-
-
-
- ); -}; diff --git a/src/pages/Plugins/StoreAndForward.tsx b/src/pages/Plugins/StoreAndForward.tsx deleted file mode 100644 index 8379abde..00000000 --- a/src/pages/Plugins/StoreAndForward.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React from 'react'; - -import { useForm, useWatch } from 'react-hook-form'; -import { FiMenu } from 'react-icons/fi'; - -import { FormFooter } from '@components/FormFooter'; -import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; -import { connection } from '@core/connection'; -import { useAppSelector } from '@hooks/useAppSelector'; -import { Card, Checkbox, IconButton, Input } from '@meshtastic/components'; -import type { RadioConfig_UserPreferences } from '@meshtastic/meshtasticjs/dist/generated'; - -export interface StoreAndForwardProps { - navOpen?: boolean; - setNavOpen?: React.Dispatch>; -} - -export const StoreAndForward = ({ - navOpen, - setNavOpen, -}: StoreAndForwardProps): JSX.Element => { - const preferences = useAppSelector( - (state) => state.meshtastic.radio.preferences, - ); - - const { register, handleSubmit, formState, reset, control } = - useForm({ - defaultValues: { - storeForwardPluginEnabled: preferences.storeForwardPluginEnabled, - storeForwardPluginRecords: preferences.storeForwardPluginRecords, - }, - }); - - React.useEffect(() => { - reset({ - storeForwardPluginEnabled: preferences.storeForwardPluginEnabled, - storeForwardPluginRecords: preferences.storeForwardPluginRecords, - }); - }, [reset, preferences]); - - const onSubmit = handleSubmit((data) => { - void connection.setPreferences(data, async (): Promise => { - //add loading indicator - reset({ ...data }); - await Promise.resolve(); - }); - }); - //todo, add loading indicator - - const watchStoreForwardPluginEnabled = useWatch({ - control, - name: 'storeForwardPluginEnabled', - defaultValue: false, - }); - - return ( - } - onClick={(): void => { - setNavOpen && setNavOpen(!navOpen); - }} - /> - } - footer={ - - } - > -
- -
-
- - - -
-
-
-
- ); -}; diff --git a/src/pages/settings/Channels.tsx b/src/pages/settings/Channels.tsx index d0222ecc..14df0bd5 100644 --- a/src/pages/settings/Channels.tsx +++ b/src/pages/settings/Channels.tsx @@ -11,7 +11,6 @@ import { import { Tooltip } from '@app/components/generic/Tooltip'; import type { ChannelData } from '@app/core/slices/meshtasticSlice'; import { FormFooter } from '@components/FormFooter'; -import { Loading } from '@components/generic/Loading'; import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; import { connection } from '@core/connection'; import { useAppSelector } from '@hooks/useAppSelector'; @@ -21,11 +20,12 @@ import { Checkbox, IconButton, Input, + Loading, Select, } from '@meshtastic/components'; import { Protobuf } from '@meshtastic/meshtasticjs'; -import { ChannelsSidebar } from '../../components/pages/settings/channels/ChannelsSidebar'; +import { ChannelsSidebar } from '../../components/pages/settings/radio/channels/ChannelsSidebar'; export interface ChannelsProps { navOpen?: boolean; diff --git a/src/pages/settings/Index.tsx b/src/pages/settings/Index.tsx index 40c3f407..c9c68518 100644 --- a/src/pages/settings/Index.tsx +++ b/src/pages/settings/Index.tsx @@ -4,6 +4,7 @@ import { FiLayers, FiLayout, FiMapPin, + FiPackage, FiRadio, FiUser, FiWifi, @@ -15,6 +16,7 @@ import { PageLayout } from '@components/templates/PageLayout'; import { Channels } from './Channels'; import { Interface } from './Interface'; +import { Plugins } from './Plugins'; import { Position } from './Position'; import { Power } from './Power'; import { Radio } from './Radio'; @@ -31,8 +33,9 @@ export const Settings = (): JSX.Element => { , , , - , - , + , + , + , ]; const sidebarItems: SidebarItemProps[] = [ @@ -56,6 +59,11 @@ export const Settings = (): JSX.Element => { description: 'Manage channels', icon: , }, + { + title: 'Plugins', + description: 'Plugins', + icon: , + }, { title: 'Interface', description: 'Language and UI settings', diff --git a/src/pages/settings/Plugins.tsx b/src/pages/settings/Plugins.tsx new file mode 100644 index 00000000..67afdc11 --- /dev/null +++ b/src/pages/settings/Plugins.tsx @@ -0,0 +1,130 @@ +import React from 'react'; + +import { + FiAlignLeft, + FiBell, + FiExternalLink, + FiFastForward, + FiMenu, + FiRss, +} from 'react-icons/fi'; + +import { PluginsSidebar } from '@app/components/pages/settings/plugins/PluginsSidebar'; +import { useAppSelector } from '@app/hooks/useAppSelector'; +import { PrimaryTemplate } from '@components/templates/PrimaryTemplate'; +import { Button, Card, IconButton } from '@meshtastic/components'; + +export type Plugin = + | 'Range Test' + | 'External Notifications' + | 'Serial' + | 'Store & Forward'; + +export interface PluginsProps { + navOpen?: boolean; + setNavOpen?: React.Dispatch>; +} + +export const Plugins = ({ navOpen, setNavOpen }: PluginsProps): JSX.Element => { + const [sidebarOpen, setSidebarOpen] = React.useState(false); + const [selectedPlugin, setSelectedPlugin] = React.useState< + Plugin | undefined + >(); + const preferences = useAppSelector( + (state) => state.meshtastic.radio.preferences, + ); + + const plugins: { + name: Plugin; + description: string; + enabled: boolean; + icon: JSX.Element; + }[] = [ + { + name: 'Range Test', + description: 'Test the range of your Meshtastic node', + enabled: preferences.rangeTestPluginEnabled, + icon: , + }, + { + name: 'External Notifications', + description: 'External hardware alerts', + enabled: preferences.extNotificationPluginEnabled, + icon: , + }, + { + name: 'Serial', + description: 'Send serial data over the mesh', + enabled: preferences.serialpluginEnabled, + icon: , + }, + { + name: 'Store & Forward', + description: 'Retrive message history', + enabled: preferences.storeForwardPluginEnabled, + icon: , + }, + ]; + + return ( + <> + } + onClick={(): void => { + setNavOpen && setNavOpen(!navOpen); + }} + /> + } + > + +
+ {plugins.map((plugin, index) => ( +
{ + setSelectedPlugin(plugin.name); + setSidebarOpen(true); + }} + className={`flex justify-between p-2 border border-gray-300 dark:border-gray-600 bg-gray-100 rounded-md dark:bg-secondaryDark shadow-md ${ + selectedPlugin === plugin.name + ? 'border-primary dark:border-primary' + : '' + }`} + > +
+
+
+
{plugin.icon}
+ {plugin.name} +
+
+
+ } /> +
+
+ ))} +
+ + + {sidebarOpen && ( + { + setSidebarOpen(false); + }} + plugin={selectedPlugin} + /> + )} + + ); +};