32 changed files with 834 additions and 1016 deletions
@ -3,7 +3,7 @@ lockfileVersion: 5.3 |
|||||
specifiers: |
specifiers: |
||||
'@floating-ui/react-dom': ^0.4.3 |
'@floating-ui/react-dom': ^0.4.3 |
||||
'@headlessui/react': ^1.4.3 |
'@headlessui/react': ^1.4.3 |
||||
'@meshtastic/components': ^1.0.17 |
'@meshtastic/components': ^1.0.19 |
||||
'@meshtastic/meshtasticjs': ^0.6.38 |
'@meshtastic/meshtasticjs': ^0.6.38 |
||||
'@reduxjs/toolkit': ^1.7.1 |
'@reduxjs/toolkit': ^1.7.1 |
||||
'@tippyjs/react': ^4.2.6 |
'@tippyjs/react': ^4.2.6 |
||||
@ -30,7 +30,7 @@ specifiers: |
|||||
eslint-plugin-react: ^7.28.0 |
eslint-plugin-react: ^7.28.0 |
||||
eslint-plugin-react-hooks: ^4.3.0 |
eslint-plugin-react-hooks: ^4.3.0 |
||||
graphql-request: ^3.7.0 |
graphql-request: ^3.7.0 |
||||
gzipper: ^6.2.1 |
gzipper: ^7.0.0 |
||||
i18next: ^21.6.6 |
i18next: ^21.6.6 |
||||
i18next-browser-languagedetector: ^6.1.2 |
i18next-browser-languagedetector: ^6.1.2 |
||||
mapbox-gl: ^2.6.1 |
mapbox-gl: ^2.6.1 |
||||
@ -66,7 +66,7 @@ specifiers: |
|||||
dependencies: |
dependencies: |
||||
'@floating-ui/react-dom': 0.4.3_b3482aaf5744fc7c2aeb7941b0e0a78f |
'@floating-ui/react-dom': 0.4.3_b3482aaf5744fc7c2aeb7941b0e0a78f |
||||
'@headlessui/react': 1.4[email protected][email protected] |
'@headlessui/react': 1.4[email protected][email protected] |
||||
'@meshtastic/components': 1.0.17_@[email protected] |
'@meshtastic/components': 1.0.19_@[email protected] |
||||
'@meshtastic/meshtasticjs': 0.6.38 |
'@meshtastic/meshtasticjs': 0.6.38 |
||||
'@reduxjs/toolkit': 1.7[email protected][email protected] |
'@reduxjs/toolkit': 1.7[email protected][email protected] |
||||
'@tippyjs/react': 4.2[email protected][email protected] |
'@tippyjs/react': 4.2[email protected][email protected] |
||||
@ -117,7 +117,7 @@ devDependencies: |
|||||
eslint-plugin-import: 2.25[email protected] |
eslint-plugin-import: 2.25[email protected] |
||||
eslint-plugin-react: 7.28[email protected] |
eslint-plugin-react: 7.28[email protected] |
||||
eslint-plugin-react-hooks: 4.3[email protected] |
eslint-plugin-react-hooks: 4.3[email protected] |
||||
gzipper: 6.2.1 |
gzipper: 7.0.0 |
||||
postcss: 8.4.5 |
postcss: 8.4.5 |
||||
prettier: 2.5.1 |
prettier: 2.5.1 |
||||
tailwindcss: 3.0.15_ef48b3b8837f8a23677bffe8f9cd866d |
tailwindcss: 3.0.15_ef48b3b8837f8a23677bffe8f9cd866d |
||||
@ -1451,6 +1451,13 @@ packages: |
|||||
- '@types/react' |
- '@types/react' |
||||
dev: false |
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/[email protected][email protected]: |
/@headlessui/react/[email protected][email protected]: |
||||
resolution: {integrity: sha512-n2IQkaaw0aAAlQS5MEXsM4uRK+w18CrM72EqnGRl/UBOQeQajad8oiKXR9Nk15jOzTFQjpxzrZMf1NxHidFBiw==} |
resolution: {integrity: sha512-n2IQkaaw0aAAlQS5MEXsM4uRK+w18CrM72EqnGRl/UBOQeQajad8oiKXR9Nk15jOzTFQjpxzrZMf1NxHidFBiw==} |
||||
engines: {node: '>=10'} |
engines: {node: '>=10'} |
||||
@ -1532,8 +1539,8 @@ packages: |
|||||
engines: {node: '>=6.0.0'} |
engines: {node: '>=6.0.0'} |
||||
dev: false |
dev: false |
||||
|
|
||||
/@meshtastic/components/1.0.17_@[email protected]: |
/@meshtastic/components/1.0.19_@[email protected]: |
||||
resolution: {integrity: sha512-e9ETFrzQUtpxVHc6NiiYMCkr7Ml4v7xlbILWK3LV48ALMDojBAFKLHdxuClpt0Rszo91ORACSSVpUkJNfWnp1A==} |
resolution: {integrity: sha512-Uls4JpJFrxi86MlxRNTPRHFBW5m/3VVFaz1anvam1vHXpJZz/ikcEmW5Xgu+f7lkBO6JGtEgvdXSbJFCkr5gqQ==} |
||||
dependencies: |
dependencies: |
||||
inter-ui: 3.19.3 |
inter-ui: 3.19.3 |
||||
react: 17.0.2 |
react: 17.0.2 |
||||
@ -1715,8 +1722,8 @@ packages: |
|||||
'@types/geojson': 7946.0.8 |
'@types/geojson': 7946.0.8 |
||||
dev: true |
dev: true |
||||
|
|
||||
/@types/node/17.0.8: |
/@types/node/17.0.9: |
||||
resolution: {integrity: sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg==} |
resolution: {integrity: sha512-5dNBXu/FOER+EXnyah7rn8xlNrfMOQb/qXnw4NQgLkCygKBKhdmF/CA5oXVOKZLBEahw8s2WP9LxIcN/oDDRgQ==} |
||||
dev: true |
dev: true |
||||
|
|
||||
/@types/parse-json/4.0.0: |
/@types/parse-json/4.0.0: |
||||
@ -1763,7 +1770,7 @@ packages: |
|||||
/@types/resolve/1.17.1: |
/@types/resolve/1.17.1: |
||||
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} |
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} |
||||
dependencies: |
dependencies: |
||||
'@types/node': 17.0.8 |
'@types/node': 17.0.9 |
||||
dev: true |
dev: true |
||||
|
|
||||
/@types/scheduler/0.16.2: |
/@types/scheduler/0.16.2: |
||||
@ -2113,11 +2120,6 @@ packages: |
|||||
engines: {node: '>=6'} |
engines: {node: '>=6'} |
||||
dev: true |
dev: true |
||||
|
|
||||
/ansi-regex/2.1.1: |
|
||||
resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} |
|
||||
engines: {node: '>=0.10.0'} |
|
||||
dev: true |
|
||||
|
|
||||
/ansi-regex/5.0.1: |
/ansi-regex/5.0.1: |
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} |
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -2145,17 +2147,6 @@ packages: |
|||||
picomatch: 2.3.1 |
picomatch: 2.3.1 |
||||
dev: true |
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: |
/arg/5.0.1: |
||||
resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} |
resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} |
||||
dev: true |
dev: true |
||||
@ -2230,7 +2221,7 @@ packages: |
|||||
postcss: ^8.1.0 |
postcss: ^8.1.0 |
||||
dependencies: |
dependencies: |
||||
browserslist: 4.19.1 |
browserslist: 4.19.1 |
||||
caniuse-lite: 1.0.30001299 |
caniuse-lite: 1.0.30001300 |
||||
fraction.js: 4.1.2 |
fraction.js: 4.1.2 |
||||
normalize-range: 0.1.2 |
normalize-range: 0.1.2 |
||||
picocolors: 1.0.0 |
picocolors: 1.0.0 |
||||
@ -2308,14 +2299,6 @@ packages: |
|||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
dev: true |
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: |
/boring-avatars/1.6.1: |
||||
resolution: {integrity: sha512-P7BZRz1DEdx61iW7q8EoB10rDLGGH4ec8uwQsMKOCag8TznC5A/efd5OBuL9Su3HjMEDHN3X8/JRRQNsVZMl4Q==} |
resolution: {integrity: sha512-P7BZRz1DEdx61iW7q8EoB10rDLGGH4ec8uwQsMKOCag8TznC5A/efd5OBuL9Su3HjMEDHN3X8/JRRQNsVZMl4Q==} |
||||
dev: false |
dev: false |
||||
@ -2339,7 +2322,7 @@ packages: |
|||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} |
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} |
||||
hasBin: true |
hasBin: true |
||||
dependencies: |
dependencies: |
||||
caniuse-lite: 1.0.30001299 |
caniuse-lite: 1.0.30001300 |
||||
electron-to-chromium: 1.4.46 |
electron-to-chromium: 1.4.46 |
||||
escalade: 3.1.1 |
escalade: 3.1.1 |
||||
node-releases: 2.0.1 |
node-releases: 2.0.1 |
||||
@ -2350,13 +2333,6 @@ packages: |
|||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} |
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} |
||||
dev: true |
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: |
/builtin-modules/3.2.0: |
||||
resolution: {integrity: sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==} |
resolution: {integrity: sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==} |
||||
engines: {node: '>=6'} |
engines: {node: '>=6'} |
||||
@ -2379,8 +2355,8 @@ packages: |
|||||
engines: {node: '>= 6'} |
engines: {node: '>= 6'} |
||||
dev: true |
dev: true |
||||
|
|
||||
/caniuse-lite/1.0.30001299: |
/caniuse-lite/1.0.30001300: |
||||
resolution: {integrity: sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==} |
resolution: {integrity: sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==} |
||||
dev: true |
dev: true |
||||
|
|
||||
/chalk/2.4.2: |
/chalk/2.4.2: |
||||
@ -2415,25 +2391,11 @@ packages: |
|||||
fsevents: 2.3.2 |
fsevents: 2.3.2 |
||||
dev: true |
dev: true |
||||
|
|
||||
/chownr/1.1.4: |
|
||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} |
|
||||
dev: true |
|
||||
|
|
||||
/chownr/2.0.0: |
/chownr/2.0.0: |
||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} |
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} |
||||
engines: {node: '>=10'} |
engines: {node: '>=10'} |
||||
dev: true |
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: |
/color-convert/1.9.3: |
||||
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} |
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} |
||||
dependencies: |
dependencies: |
||||
@ -2466,10 +2428,6 @@ packages: |
|||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} |
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} |
||||
dev: true |
dev: true |
||||
|
|
||||
/commander/3.0.2: |
|
||||
resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} |
|
||||
dev: true |
|
||||
|
|
||||
/commander/7.2.0: |
/commander/7.2.0: |
||||
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} |
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} |
||||
engines: {node: '>= 10'} |
engines: {node: '>= 10'} |
||||
@ -2484,10 +2442,6 @@ packages: |
|||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} |
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} |
||||
dev: true |
dev: true |
||||
|
|
||||
/console-control-strings/1.1.0: |
|
||||
resolution: {integrity: sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=} |
|
||||
dev: true |
|
||||
|
|
||||
/convert-source-map/1.8.0: |
/convert-source-map/1.8.0: |
||||
resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} |
resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} |
||||
dependencies: |
dependencies: |
||||
@ -2579,13 +2533,6 @@ packages: |
|||||
ms: 2.1.2 |
ms: 2.1.2 |
||||
dev: true |
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: |
/deep-equal/2.0.5: |
||||
resolution: {integrity: sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==} |
resolution: {integrity: sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==} |
||||
dependencies: |
dependencies: |
||||
@ -2606,11 +2553,6 @@ packages: |
|||||
which-typed-array: 1.1.7 |
which-typed-array: 1.1.7 |
||||
dev: true |
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: |
/deep-is/0.1.4: |
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} |
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} |
||||
dev: true |
dev: true |
||||
@ -2620,12 +2562,6 @@ packages: |
|||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
dev: true |
dev: true |
||||
|
|
||||
/defaults/1.0.3: |
|
||||
resolution: {integrity: sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=} |
|
||||
dependencies: |
|
||||
clone: 1.0.4 |
|
||||
dev: true |
|
||||
|
|
||||
/define-properties/1.1.3: |
/define-properties/1.1.3: |
||||
resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} |
resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} |
||||
engines: {node: '>= 0.4'} |
engines: {node: '>= 0.4'} |
||||
@ -2642,16 +2578,6 @@ packages: |
|||||
engines: {node: '>=0.4.0'} |
engines: {node: '>=0.4.0'} |
||||
dev: false |
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: |
/detective/5.2.0: |
||||
resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} |
resolution: {integrity: sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==} |
||||
engines: {node: '>=0.8.0'} |
engines: {node: '>=0.8.0'} |
||||
@ -3383,11 +3309,6 @@ packages: |
|||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
dev: true |
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: |
/extract-files/9.0.0: |
||||
resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==} |
resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==} |
||||
engines: {node: ^10.17.0 || ^12.0.0 || >= 13.7.0} |
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==} |
resolution: {integrity: sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==} |
||||
dev: true |
dev: true |
||||
|
|
||||
/fs-constants/1.0.0: |
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} |
|
||||
dev: true |
|
||||
|
|
||||
/fs-extra/9.1.0: |
/fs-extra/9.1.0: |
||||
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} |
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} |
||||
engines: {node: '>=10'} |
engines: {node: '>=10'} |
||||
@ -3534,19 +3451,6 @@ packages: |
|||||
resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} |
resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} |
||||
dev: true |
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: |
/gensync/1.0.0-beta.2: |
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} |
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} |
||||
engines: {node: '>=6.9.0'} |
engines: {node: '>=6.9.0'} |
||||
@ -3581,10 +3485,6 @@ packages: |
|||||
get-intrinsic: 1.1.1 |
get-intrinsic: 1.1.1 |
||||
dev: true |
dev: true |
||||
|
|
||||
/github-from-package/0.0.0: |
|
||||
resolution: {integrity: sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=} |
|
||||
dev: true |
|
||||
|
|
||||
/gl-matrix/3.4.3: |
/gl-matrix/3.4.3: |
||||
resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} |
resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==} |
||||
dev: false |
dev: false |
||||
@ -3656,14 +3556,14 @@ packages: |
|||||
resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} |
resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} |
||||
dev: false |
dev: false |
||||
|
|
||||
/gzipper/6.2.1: |
/gzipper/7.0.0: |
||||
resolution: {integrity: sha512-HGCFv3hZy87B+AHRuDpbyRbvOdaJllyGB+OTqDqKy54e8M1RDgF64QN/buyqpqhvSXWePNIE0jqbHpcjCWG6YQ==} |
resolution: {integrity: sha512-Pfr8FXg4JOQ9hwWWS+d5KDOokRlfjkuNuK7HVJsiXwQhYTugKMHXAnAeEuKr5ILtxX0cAzJBtR6g3Wclze8+LA==} |
||||
engines: {node: '>=14'} |
engines: {node: '>=14'} |
||||
hasBin: true |
hasBin: true |
||||
dependencies: |
dependencies: |
||||
|
'@gfx/zopfli': 1.0.15 |
||||
commander: 7.2.0 |
commander: 7.2.0 |
||||
deep-equal: 2.0.5 |
deep-equal: 2.0.5 |
||||
node-zopfli: 2.1.4 |
|
||||
simple-zstd: 1.4.0 |
simple-zstd: 1.4.0 |
||||
uuid: 8.3.2 |
uuid: 8.3.2 |
||||
dev: true |
dev: true |
||||
@ -3694,10 +3594,6 @@ packages: |
|||||
has-symbols: 1.0.2 |
has-symbols: 1.0.2 |
||||
dev: true |
dev: true |
||||
|
|
||||
/has-unicode/2.0.1: |
|
||||
resolution: {integrity: sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=} |
|
||||
dev: true |
|
||||
|
|
||||
/has/1.0.3: |
/has/1.0.3: |
||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} |
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} |
||||
engines: {node: '>= 0.4.0'} |
engines: {node: '>= 0.4.0'} |
||||
@ -3745,6 +3641,7 @@ packages: |
|||||
|
|
||||
/ieee754/1.2.1: |
/ieee754/1.2.1: |
||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} |
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} |
||||
|
dev: false |
||||
|
|
||||
/ignore/4.0.6: |
/ignore/4.0.6: |
||||
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} |
resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} |
||||
@ -3784,10 +3681,6 @@ packages: |
|||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} |
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} |
||||
dev: true |
dev: true |
||||
|
|
||||
/ini/1.3.8: |
|
||||
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} |
|
||||
dev: true |
|
||||
|
|
||||
/inter-ui/3.19.3: |
/inter-ui/3.19.3: |
||||
resolution: {integrity: sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg==} |
resolution: {integrity: sha512-5FG9fjuYOXocIfjzcCBhICL5cpvwEetseL3FU6tP3d6Bn7g8wODhB+I9RNGRTizCT7CUG4GOK54OPxqq3msQgg==} |
||||
dev: false |
dev: false |
||||
@ -3857,13 +3750,6 @@ packages: |
|||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
dev: true |
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: |
/is-fullwidth-code-point/3.0.0: |
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} |
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -4010,7 +3896,7 @@ packages: |
|||||
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} |
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} |
||||
engines: {node: '>= 10.13.0'} |
engines: {node: '>= 10.13.0'} |
||||
dependencies: |
dependencies: |
||||
'@types/node': 17.0.8 |
'@types/node': 17.0.9 |
||||
merge-stream: 2.0.0 |
merge-stream: 2.0.0 |
||||
supports-color: 7.2.0 |
supports-color: 7.2.0 |
||||
dev: true |
dev: true |
||||
@ -4251,11 +4137,6 @@ packages: |
|||||
mime-db: 1.51.0 |
mime-db: 1.51.0 |
||||
dev: false |
dev: false |
||||
|
|
||||
/mimic-response/2.1.0: |
|
||||
resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} |
|
||||
engines: {node: '>=8'} |
|
||||
dev: true |
|
||||
|
|
||||
/minimatch/3.0.4: |
/minimatch/3.0.4: |
||||
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} |
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} |
||||
dependencies: |
dependencies: |
||||
@ -4280,10 +4161,6 @@ packages: |
|||||
yallist: 4.0.0 |
yallist: 4.0.0 |
||||
dev: true |
dev: true |
||||
|
|
||||
/mkdirp-classic/0.5.3: |
|
||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} |
|
||||
dev: true |
|
||||
|
|
||||
/mkdirp/1.0.4: |
/mkdirp/1.0.4: |
||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} |
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} |
||||
engines: {node: '>=10'} |
engines: {node: '>=10'} |
||||
@ -4306,30 +4183,16 @@ packages: |
|||||
resolution: {integrity: sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=} |
resolution: {integrity: sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=} |
||||
dev: false |
dev: false |
||||
|
|
||||
/nanoid/3.1.32: |
/nanoid/3.2.0: |
||||
resolution: {integrity: sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw==} |
resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} |
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} |
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} |
||||
hasBin: true |
hasBin: true |
||||
dev: true |
dev: true |
||||
|
|
||||
/napi-build-utils/1.0.2: |
|
||||
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} |
|
||||
dev: true |
|
||||
|
|
||||
/natural-compare/1.4.0: |
/natural-compare/1.4.0: |
||||
resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} |
resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} |
||||
dev: true |
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: |
/node-fetch/2.6.1: |
||||
resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} |
resolution: {integrity: sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==} |
||||
engines: {node: 4.x || >=6.0.0} |
engines: {node: 4.x || >=6.0.0} |
||||
@ -4339,22 +4202,6 @@ packages: |
|||||
resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} |
resolution: {integrity: sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==} |
||||
dev: true |
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: |
/normalize-path/3.0.0: |
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} |
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} |
||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
@ -4365,20 +4212,6 @@ packages: |
|||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
dev: true |
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: |
/object-assign/4.1.1: |
||||
resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} |
resolution: {integrity: sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=} |
||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
@ -4632,7 +4465,7 @@ packages: |
|||||
resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} |
resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} |
||||
engines: {node: ^10 || ^12 || >=14} |
engines: {node: ^10 || ^12 || >=14} |
||||
dependencies: |
dependencies: |
||||
nanoid: 3.1.32 |
nanoid: 3.2.0 |
||||
picocolors: 1.0.0 |
picocolors: 1.0.0 |
||||
source-map-js: 1.0.1 |
source-map-js: 1.0.1 |
||||
dev: true |
dev: true |
||||
@ -4641,28 +4474,6 @@ packages: |
|||||
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} |
resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} |
||||
dev: false |
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: |
/prelude-ls/1.2.1: |
||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} |
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} |
||||
engines: {node: '>= 0.8.0'} |
engines: {node: '>= 0.8.0'} |
||||
@ -4707,13 +4518,6 @@ packages: |
|||||
resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} |
resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} |
||||
dev: false |
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: |
/punycode/2.1.1: |
||||
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} |
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} |
||||
engines: {node: '>=6'} |
engines: {node: '>=6'} |
||||
@ -4746,16 +4550,6 @@ packages: |
|||||
safe-buffer: 5.2.1 |
safe-buffer: 5.2.1 |
||||
dev: true |
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/[email protected]: |
/react-dom/[email protected]: |
||||
resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} |
resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} |
||||
peerDependencies: |
peerDependencies: |
||||
@ -5144,11 +4938,6 @@ packages: |
|||||
object-assign: 4.1.1 |
object-assign: 4.1.1 |
||||
dev: false |
dev: false |
||||
|
|
||||
/semver/5.7.1: |
|
||||
resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} |
|
||||
hasBin: true |
|
||||
dev: true |
|
||||
|
|
||||
/semver/6.3.0: |
/semver/6.3.0: |
||||
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} |
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} |
||||
hasBin: true |
hasBin: true |
||||
@ -5173,10 +4962,6 @@ packages: |
|||||
randombytes: 2.1.0 |
randombytes: 2.1.0 |
||||
dev: true |
dev: true |
||||
|
|
||||
/set-blocking/2.0.0: |
|
||||
resolution: {integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=} |
|
||||
dev: true |
|
||||
|
|
||||
/shebang-command/2.0.0: |
/shebang-command/2.0.0: |
||||
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} |
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -5197,22 +4982,6 @@ packages: |
|||||
object-inspect: 1.12.0 |
object-inspect: 1.12.0 |
||||
dev: true |
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: |
/simple-zstd/1.4.0: |
||||
resolution: {integrity: sha512-9zBNnu7MkwRiZm7voFUX7ehCcLO2d1FmJ2RWEVsN8Exw2tVYK9k/0/8WjPUmSmtoHOyoFTkHHaOLuPSwkgFmrA==} |
resolution: {integrity: sha512-9zBNnu7MkwRiZm7voFUX7ehCcLO2d1FmJ2RWEVsN8Exw2tVYK9k/0/8WjPUmSmtoHOyoFTkHHaOLuPSwkgFmrA==} |
||||
dependencies: |
dependencies: |
||||
@ -5287,15 +5056,6 @@ packages: |
|||||
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} |
resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} |
||||
dev: true |
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: |
/string-width/4.2.3: |
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} |
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -5353,13 +5113,6 @@ packages: |
|||||
is-regexp: 1.0.0 |
is-regexp: 1.0.0 |
||||
dev: true |
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: |
/strip-ansi/6.0.1: |
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} |
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -5377,11 +5130,6 @@ packages: |
|||||
engines: {node: '>=10'} |
engines: {node: '>=10'} |
||||
dev: true |
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: |
/strip-json-comments/3.1.1: |
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} |
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -5474,26 +5222,6 @@ packages: |
|||||
- ts-node |
- ts-node |
||||
dev: true |
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: |
/tar/6.1.11: |
||||
resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} |
resolution: {integrity: sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==} |
||||
engines: {node: '>= 10'} |
engines: {node: '>= 10'} |
||||
@ -5633,12 +5361,6 @@ packages: |
|||||
typescript: 4.5.4 |
typescript: 4.5.4 |
||||
dev: true |
dev: true |
||||
|
|
||||
/tunnel-agent/0.6.0: |
|
||||
resolution: {integrity: sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=} |
|
||||
dependencies: |
|
||||
safe-buffer: 5.2.1 |
|
||||
dev: true |
|
||||
|
|
||||
/type-check/0.4.0: |
/type-check/0.4.0: |
||||
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} |
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} |
||||
engines: {node: '>= 0.8.0'} |
engines: {node: '>= 0.8.0'} |
||||
@ -5867,10 +5589,6 @@ packages: |
|||||
is-weakset: 2.0.2 |
is-weakset: 2.0.2 |
||||
dev: true |
dev: true |
||||
|
|
||||
/which-pm-runs/1.0.0: |
|
||||
resolution: {integrity: sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=} |
|
||||
dev: true |
|
||||
|
|
||||
/which-typed-array/1.1.7: |
/which-typed-array/1.1.7: |
||||
resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==} |
resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==} |
||||
engines: {node: '>= 0.4'} |
engines: {node: '>= 0.4'} |
||||
@ -5891,12 +5609,6 @@ packages: |
|||||
isexe: 2.0.0 |
isexe: 2.0.0 |
||||
dev: true |
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: |
/word-wrap/1.2.3: |
||||
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} |
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} |
||||
engines: {node: '>=0.10.0'} |
engines: {node: '>=0.10.0'} |
||||
|
|||||
@ -1,9 +0,0 @@ |
|||||
import type React from 'react'; |
|
||||
|
|
||||
export const Loading = (): JSX.Element => { |
|
||||
return ( |
|
||||
<div className="absolute top-0 bottom-0 left-0 right-0 z-10 flex rounded-md backdrop-filter backdrop-blur-sm"> |
|
||||
<div className="m-auto text-lg font-medium text-gray-400">Loading</div> |
|
||||
</div> |
|
||||
); |
|
||||
}; |
|
||||
@ -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 ( |
||||
|
<form |
||||
|
onSubmit={(e): void => { |
||||
|
e.preventDefault(); |
||||
|
}} |
||||
|
className="relative flex-grow gap-3 p-2" |
||||
|
> |
||||
|
{loading && <Loading />} |
||||
|
{children} |
||||
|
</form> |
||||
|
); |
||||
|
}; |
||||
@ -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<CommitHistory>(
|
||||
|
// `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 ( |
||||
|
<Modal |
||||
|
open={visible} |
||||
|
onClose={(): void => { |
||||
|
onclose(); |
||||
|
}} |
||||
|
> |
||||
|
<Card> |
||||
|
<div className="w-full max-w-3xl p-10">Version Info</div> |
||||
|
{/* {data?.sha} */} |
||||
|
</Card> |
||||
|
</Modal> |
||||
|
); |
||||
|
}; |
||||
@ -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 ( |
||||
|
<Sidebar |
||||
|
title={plugin ?? 'Please select plugin'} |
||||
|
tagline={plugin ? 'settings' : '...'} |
||||
|
closeSidebar={closeSidebar} |
||||
|
> |
||||
|
{plugin && ( |
||||
|
<Tab.Group> |
||||
|
<div className="shadow-md"> |
||||
|
<Tab.List className="flex justify-between border-b border-gray-300 dark:border-gray-600"> |
||||
|
<TabButton> |
||||
|
<FiSliders /> |
||||
|
</TabButton> |
||||
|
<TabButton> |
||||
|
<FiCode /> |
||||
|
</TabButton> |
||||
|
</Tab.List> |
||||
|
</div> |
||||
|
<Tab.Panels className="flex flex-grow overflow-y-auto bg-gray-100 dark:bg-primaryDark"> |
||||
|
{plugin === 'Range Test' && ( |
||||
|
<> |
||||
|
<RangeTestSettingsPanel /> |
||||
|
<RangeTestDebugPanel /> |
||||
|
</> |
||||
|
)} |
||||
|
{plugin === 'External Notifications' && ( |
||||
|
<> |
||||
|
<ExternalNotificationsSettingsPlanel /> |
||||
|
<ExternalNotificationsDebugPanel /> |
||||
|
</> |
||||
|
)} |
||||
|
{plugin === 'Serial' && ( |
||||
|
<> |
||||
|
<SerialSettingsPanel /> |
||||
|
<SerialDebugPanel /> |
||||
|
</> |
||||
|
)} |
||||
|
{plugin === 'Store & Forward' && ( |
||||
|
<> |
||||
|
<StoreForwardSettingsPanel /> |
||||
|
<StoreForwardDebugPanel /> |
||||
|
</> |
||||
|
)} |
||||
|
</Tab.Panels> |
||||
|
</Tab.Group> |
||||
|
)} |
||||
|
</Sidebar> |
||||
|
); |
||||
|
}; |
||||
@ -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 ( |
||||
|
<Tab.Panel className="relative"> |
||||
|
<div className="fixed right-0 m-2"> |
||||
|
<CopyButton data={JSON.stringify(debugData)} /> |
||||
|
</div> |
||||
|
<JSONPretty className="max-w-sm" data={debugData} /> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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<Protobuf.RadioConfig_UserPreferences>({ |
||||
|
defaultValues: preferences, |
||||
|
}); |
||||
|
|
||||
|
React.useEffect(() => { |
||||
|
reset(preferences); |
||||
|
}, [reset, preferences]); |
||||
|
|
||||
|
const onSubmit = handleSubmit(async (data) => { |
||||
|
setLoading(true); |
||||
|
await connection.setPreferences(data, async (): Promise<void> => { |
||||
|
reset({ ...data }); |
||||
|
setLoading(false); |
||||
|
await Promise.resolve(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
const pluginEnabled = useWatch({ |
||||
|
control, |
||||
|
name: 'extNotificationPluginEnabled', |
||||
|
defaultValue: false, |
||||
|
}); |
||||
|
|
||||
|
return ( |
||||
|
<Tab.Panel className="flex flex-col w-full"> |
||||
|
<Form loading={loading}> |
||||
|
<Checkbox |
||||
|
label="Plugin Enabled" |
||||
|
{...register('extNotificationPluginEnabled')} |
||||
|
/> |
||||
|
<Checkbox |
||||
|
label="Active" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('extNotificationPluginActive')} |
||||
|
/> |
||||
|
<Checkbox |
||||
|
label="Bell" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('extNotificationPluginAlertBell')} |
||||
|
/> |
||||
|
<Checkbox |
||||
|
label="Message" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('extNotificationPluginAlertMessage')} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Output" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('extNotificationPluginOutput', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Output MS" |
||||
|
suffix="ms" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('extNotificationPluginOutputMs', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
</Form> |
||||
|
<div className="flex w-full bg-white dark:bg-secondaryDark"> |
||||
|
<div className="p-2 ml-auto"> |
||||
|
<IconButton |
||||
|
disabled={!formState.isDirty} |
||||
|
onClick={async (): Promise<void> => { |
||||
|
await onSubmit(); |
||||
|
}} |
||||
|
icon={<FiSave />} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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 ( |
||||
|
<Tab.Panel className="relative"> |
||||
|
<div className="fixed right-0 m-2"> |
||||
|
<CopyButton data={JSON.stringify(debugData)} /> |
||||
|
</div> |
||||
|
<JSONPretty className="max-w-sm" data={debugData} /> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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<Protobuf.RadioConfig_UserPreferences>({ |
||||
|
defaultValues: preferences, |
||||
|
}); |
||||
|
|
||||
|
React.useEffect(() => { |
||||
|
reset(preferences); |
||||
|
}, [reset, preferences]); |
||||
|
|
||||
|
const onSubmit = handleSubmit(async (data) => { |
||||
|
setLoading(true); |
||||
|
await connection.setPreferences(data, async (): Promise<void> => { |
||||
|
reset({ ...data }); |
||||
|
setLoading(false); |
||||
|
await Promise.resolve(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
const pluginEnabled = useWatch({ |
||||
|
control, |
||||
|
name: 'rangeTestPluginEnabled', |
||||
|
defaultValue: false, |
||||
|
}); |
||||
|
|
||||
|
return ( |
||||
|
<Tab.Panel className="flex flex-col w-full"> |
||||
|
<Form loading={loading}> |
||||
|
<Checkbox |
||||
|
label="Range Test Plugin Enabled?" |
||||
|
{...register('rangeTestPluginEnabled')} |
||||
|
/> |
||||
|
<Checkbox |
||||
|
label="Range Test Plugin Save?" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('rangeTestPluginSave')} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Message Interval" |
||||
|
disabled={!pluginEnabled} |
||||
|
suffix="Seconds" |
||||
|
{...register('rangeTestPluginSender', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
</Form> |
||||
|
<div className="flex w-full bg-white dark:bg-secondaryDark"> |
||||
|
<div className="p-2 ml-auto"> |
||||
|
<IconButton |
||||
|
disabled={!formState.isDirty} |
||||
|
onClick={async (): Promise<void> => { |
||||
|
await onSubmit(); |
||||
|
}} |
||||
|
icon={<FiSave />} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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 ( |
||||
|
<Tab.Panel className="relative"> |
||||
|
<div className="fixed right-0 m-2"> |
||||
|
<CopyButton data={JSON.stringify(debugData)} /> |
||||
|
</div> |
||||
|
<JSONPretty className="max-w-sm" data={debugData} /> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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<Protobuf.RadioConfig_UserPreferences>({ |
||||
|
defaultValues: preferences, |
||||
|
}); |
||||
|
|
||||
|
React.useEffect(() => { |
||||
|
reset(preferences); |
||||
|
}, [reset, preferences]); |
||||
|
|
||||
|
const onSubmit = handleSubmit(async (data) => { |
||||
|
setLoading(true); |
||||
|
await connection.setPreferences(data, async (): Promise<void> => { |
||||
|
reset({ ...data }); |
||||
|
setLoading(false); |
||||
|
await Promise.resolve(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
const pluginEnabled = useWatch({ |
||||
|
control, |
||||
|
name: 'serialpluginEnabled', |
||||
|
defaultValue: false, |
||||
|
}); |
||||
|
|
||||
|
return ( |
||||
|
<Tab.Panel className="flex flex-col w-full"> |
||||
|
<Form loading={loading}> |
||||
|
<Checkbox label="Plugin Enabled" {...register('serialpluginEnabled')} /> |
||||
|
<Checkbox |
||||
|
label="Echo" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('serialpluginEcho')} |
||||
|
/> |
||||
|
|
||||
|
<Input |
||||
|
type="number" |
||||
|
label="RX" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('serialpluginRxd', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="TX" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('serialpluginTxd', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Mode" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('serialpluginMode', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Timeout" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('serialpluginTimeout', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
</Form> |
||||
|
<div className="flex w-full bg-white dark:bg-secondaryDark"> |
||||
|
<div className="p-2 ml-auto"> |
||||
|
<IconButton |
||||
|
disabled={!formState.isDirty} |
||||
|
onClick={async (): Promise<void> => { |
||||
|
await onSubmit(); |
||||
|
}} |
||||
|
icon={<FiSave />} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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 ( |
||||
|
<Tab.Panel className="relative"> |
||||
|
<div className="fixed right-0 m-2"> |
||||
|
<CopyButton data={JSON.stringify(debugData)} /> |
||||
|
</div> |
||||
|
<JSONPretty className="max-w-sm" data={debugData} /> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -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<Protobuf.RadioConfig_UserPreferences>({ |
||||
|
defaultValues: preferences, |
||||
|
}); |
||||
|
|
||||
|
React.useEffect(() => { |
||||
|
reset(preferences); |
||||
|
}, [reset, preferences]); |
||||
|
|
||||
|
const onSubmit = handleSubmit(async (data) => { |
||||
|
setLoading(true); |
||||
|
await connection.setPreferences(data, async (): Promise<void> => { |
||||
|
reset({ ...data }); |
||||
|
setLoading(false); |
||||
|
await Promise.resolve(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
const pluginEnabled = useWatch({ |
||||
|
control, |
||||
|
name: 'storeForwardPluginEnabled', |
||||
|
defaultValue: false, |
||||
|
}); |
||||
|
|
||||
|
return ( |
||||
|
<Tab.Panel className="flex flex-col w-full"> |
||||
|
<Form loading={loading}> |
||||
|
<Checkbox |
||||
|
label="Plugin Enabled" |
||||
|
{...register('storeForwardPluginEnabled')} |
||||
|
/> |
||||
|
<Checkbox |
||||
|
label="Heartbeat Enabled" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('storeForwardPluginHeartbeat')} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="Number of records" |
||||
|
suffix="Records" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('storeForwardPluginRecords', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="History return max" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('storeForwardPluginHistoryReturnMax', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
<Input |
||||
|
type="number" |
||||
|
label="History return window" |
||||
|
disabled={!pluginEnabled} |
||||
|
{...register('storeForwardPluginHistoryReturnWindow', { |
||||
|
valueAsNumber: true, |
||||
|
})} |
||||
|
/> |
||||
|
</Form> |
||||
|
<div className="flex w-full bg-white dark:bg-secondaryDark"> |
||||
|
<div className="p-2 ml-auto"> |
||||
|
<IconButton |
||||
|
disabled={!formState.isDirty} |
||||
|
onClick={async (): Promise<void> => { |
||||
|
await onSubmit(); |
||||
|
}} |
||||
|
icon={<FiSave />} |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</Tab.Panel> |
||||
|
); |
||||
|
}; |
||||
@ -1,135 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
|
|
||||
import { useForm, useWatch } from 'react-hook-form'; |
|
||||
import { FiMenu } from 'react-icons/fi'; |
|
||||
|
|
||||
import { FormFooter } from '@app/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 ExternalNotificationProps { |
|
||||
navOpen?: boolean; |
|
||||
setNavOpen?: React.Dispatch<React.SetStateAction<boolean>>; |
|
||||
} |
|
||||
|
|
||||
export const ExternalNotification = ({ |
|
||||
navOpen, |
|
||||
setNavOpen, |
|
||||
}: ExternalNotificationProps): JSX.Element => { |
|
||||
const preferences = useAppSelector( |
|
||||
(state) => state.meshtastic.radio.preferences, |
|
||||
); |
|
||||
|
|
||||
const { register, handleSubmit, formState, reset, control } = |
|
||||
useForm<RadioConfig_UserPreferences>({ |
|
||||
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<void> => { |
|
||||
//add loading indicator
|
|
||||
reset({ ...data }); |
|
||||
await Promise.resolve(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
//todo, add loading indicator
|
|
||||
|
|
||||
const watchExternalNotificationPluginEnabled = useWatch({ |
|
||||
control, |
|
||||
name: 'extNotificationPluginEnabled', |
|
||||
defaultValue: false, |
|
||||
}); |
|
||||
|
|
||||
return ( |
|
||||
<PrimaryTemplate |
|
||||
title="External Notification" |
|
||||
tagline="Plugin" |
|
||||
leftButton={ |
|
||||
<IconButton |
|
||||
icon={<FiMenu className="w-5 h-5" />} |
|
||||
onClick={(): void => { |
|
||||
setNavOpen && setNavOpen(!navOpen); |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
footer={ |
|
||||
<FormFooter |
|
||||
dirty={formState.isDirty} |
|
||||
saveAction={onSubmit} |
|
||||
clearAction={reset} |
|
||||
/> |
|
||||
} |
|
||||
> |
|
||||
<div className="w-full space-y-4"> |
|
||||
<Card> |
|
||||
<div className="w-full max-w-3xl p-10 md:max-w-xl"> |
|
||||
<form onSubmit={onSubmit}> |
|
||||
<Checkbox |
|
||||
label="Plugin Enabled" |
|
||||
{...register('extNotificationPluginEnabled')} |
|
||||
/> |
|
||||
<Checkbox |
|
||||
label="Active" |
|
||||
disabled={!watchExternalNotificationPluginEnabled} |
|
||||
{...register('extNotificationPluginActive')} |
|
||||
/> |
|
||||
<Checkbox |
|
||||
label="Bell" |
|
||||
disabled={!watchExternalNotificationPluginEnabled} |
|
||||
{...register('extNotificationPluginAlertBell')} |
|
||||
/> |
|
||||
<Checkbox |
|
||||
label="Message" |
|
||||
disabled={!watchExternalNotificationPluginEnabled} |
|
||||
{...register('extNotificationPluginAlertMessage')} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Output" |
|
||||
disabled={!watchExternalNotificationPluginEnabled} |
|
||||
{...register('extNotificationPluginOutput', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Output MS" |
|
||||
disabled={!watchExternalNotificationPluginEnabled} |
|
||||
{...register('extNotificationPluginOutputMs', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
</Card> |
|
||||
</div> |
|
||||
</PrimaryTemplate> |
|
||||
); |
|
||||
}; |
|
||||
@ -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<React.SetStateAction<boolean>>; |
|
||||
} |
|
||||
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<IFiles>( |
|
||||
`http://${connectionUrl}/json/spiffs/browse/static`, |
|
||||
fetcher, |
|
||||
); |
|
||||
|
|
||||
return ( |
|
||||
<PrimaryTemplate |
|
||||
title="File Browser" |
|
||||
tagline="Plugin" |
|
||||
leftButton={ |
|
||||
<IconButton |
|
||||
icon={<FiMenu className="w-5 h-5" />} |
|
||||
onClick={(): void => { |
|
||||
setNavOpen && setNavOpen(!navOpen); |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
> |
|
||||
<div className="flex flex-col justify-between w-full gap-4 md:flex-row-reverse"> |
|
||||
<Card title="SPIFFS" description="Statistics"> |
|
||||
{data ? ( |
|
||||
<div className="flex"> |
|
||||
<div className="mx-auto my-4 bg-gray-500 rounded-3xl"> |
|
||||
<div></div> |
|
||||
{JSON.stringify(data.data.filesystem.used)} bytes total |
|
||||
</div> |
|
||||
</div> |
|
||||
) : ( |
|
||||
<div>Loading...</div> |
|
||||
)} |
|
||||
</Card> |
|
||||
<Card |
|
||||
title="Files" |
|
||||
description="SPIFFS Contents" |
|
||||
buttons={<IconButton icon={<FiUploadCloud className="w-8 h-8" />} />} |
|
||||
className="md:w-1/3" |
|
||||
> |
|
||||
{data ? ( |
|
||||
<div className="flex flex-col my-4 space-y-2"> |
|
||||
{data.data.files.map((file: IFile) => ( |
|
||||
<div |
|
||||
key={file.name} |
|
||||
className="flex justify-between mx-4 bg-gray-300 rounded-md dark:bg-secondaryDark " |
|
||||
> |
|
||||
<div className="flex p-2 max-h-12"> |
|
||||
<div className="flex w-12"> |
|
||||
{/* <FileIcon |
|
||||
extension={ |
|
||||
(file.nameModified ?? file.name).split('.')[ |
|
||||
(file.nameModified ?? file.name).split('.').length - |
|
||||
1 |
|
||||
] |
|
||||
} |
|
||||
{...defaultStyles[ |
|
||||
(file.nameModified ?? file.name).split('.')[ |
|
||||
(file.nameModified ?? file.name).split('.').length - |
|
||||
1 |
|
||||
] as DefaultExtensionType |
|
||||
]} |
|
||||
/> */} |
|
||||
</div> |
|
||||
<a |
|
||||
href={`http://${connectionUrl}/${file.name.replace( |
|
||||
'static/', |
|
||||
'', |
|
||||
)}`}
|
|
||||
className="my-auto font-semibold" |
|
||||
> |
|
||||
{file.nameModified ?? file.name} |
|
||||
</a> |
|
||||
</div> |
|
||||
<IconButton |
|
||||
className="mx-2 my-auto" |
|
||||
// confirmAction={async (): Promise<void> => {
|
|
||||
// await fetch(
|
|
||||
// `http://${connectionUrl}/json/spiffs/delete/static?remove=${file.name}`,
|
|
||||
// {
|
|
||||
// method: 'DELETE',
|
|
||||
// },
|
|
||||
// );
|
|
||||
// }}
|
|
||||
icon={<FiTrash className="w-5 h-5" />} |
|
||||
/> |
|
||||
</div> |
|
||||
))} |
|
||||
</div> |
|
||||
) : ( |
|
||||
<div>Loading...</div> |
|
||||
)} |
|
||||
</Card> |
|
||||
</div> |
|
||||
</PrimaryTemplate> |
|
||||
); |
|
||||
}; |
|
||||
@ -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 ( |
|
||||
<PageLayout |
|
||||
title="Plugins" |
|
||||
sidebarItems={[ |
|
||||
{ |
|
||||
title: 'Range Test', |
|
||||
description: 'Test the range of your Meshtastic node', |
|
||||
icon: <FiRss className="flex-shrink-0 w-6 h-6" />, |
|
||||
}, |
|
||||
{ |
|
||||
title: 'File Browser', |
|
||||
description: 'HTTP only file browser', |
|
||||
icon: <FiFileText className="flex-shrink-0 w-6 h-6" />, |
|
||||
}, |
|
||||
{ |
|
||||
title: 'External Notification', |
|
||||
description: 'External hardware alerts', |
|
||||
icon: <FiBell className="flex-shrink-0 w-6 h-6" />, |
|
||||
}, |
|
||||
{ |
|
||||
title: 'Serial', |
|
||||
description: 'Send serial data over the mesh', |
|
||||
icon: <FiAlignLeft className="flex-shrink-0 w-6 h-6" />, |
|
||||
}, |
|
||||
{ |
|
||||
title: 'Store & Forward', |
|
||||
description: 'Retrive message history', |
|
||||
icon: <FiFastForward className="flex-shrink-0 w-6 h-6" />, |
|
||||
}, |
|
||||
]} |
|
||||
panels={[ |
|
||||
<RangeTest key={1} />, |
|
||||
<Files key={2} />, |
|
||||
<ExternalNotification key={3} />, |
|
||||
<Serial key={4} />, |
|
||||
<StoreAndForward key={5} />, |
|
||||
]} |
|
||||
/> |
|
||||
); |
|
||||
}; |
|
||||
@ -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<React.SetStateAction<boolean>>; |
|
||||
} |
|
||||
|
|
||||
export const RangeTest = ({ |
|
||||
navOpen, |
|
||||
setNavOpen, |
|
||||
}: RangeTestProps): JSX.Element => { |
|
||||
const preferences = useAppSelector( |
|
||||
(state) => state.meshtastic.radio.preferences, |
|
||||
); |
|
||||
|
|
||||
const { register, handleSubmit, formState, reset, control } = |
|
||||
useForm<RadioConfig_UserPreferences>({ |
|
||||
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<void> => { |
|
||||
//add loading indicator
|
|
||||
reset({ ...data }); |
|
||||
await Promise.resolve(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
//todo, add loading indicator
|
|
||||
|
|
||||
const watchRangeTestPluginEnabled = useWatch({ |
|
||||
control, |
|
||||
name: 'rangeTestPluginEnabled', |
|
||||
defaultValue: false, |
|
||||
}); |
|
||||
|
|
||||
return ( |
|
||||
<PrimaryTemplate |
|
||||
title="Range Test" |
|
||||
tagline="Plugin" |
|
||||
leftButton={ |
|
||||
<IconButton |
|
||||
icon={<FiMenu className="w-5 h-5" />} |
|
||||
onClick={(): void => { |
|
||||
setNavOpen && setNavOpen(!navOpen); |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
footer={ |
|
||||
<FormFooter |
|
||||
dirty={formState.isDirty} |
|
||||
saveAction={onSubmit} |
|
||||
clearAction={reset} |
|
||||
/> |
|
||||
} |
|
||||
> |
|
||||
<div className="w-full space-y-4"> |
|
||||
<Card> |
|
||||
<div className="w-full max-w-3xl p-10 md:max-w-xl"> |
|
||||
<form onSubmit={onSubmit}> |
|
||||
<Checkbox |
|
||||
label="Range Test Plugin Enabled?" |
|
||||
{...register('rangeTestPluginEnabled')} |
|
||||
/> |
|
||||
<Checkbox |
|
||||
label="Range Test Plugin Save?" |
|
||||
disabled={!watchRangeTestPluginEnabled} |
|
||||
{...register('rangeTestPluginSave')} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Message Interval" |
|
||||
disabled={!watchRangeTestPluginEnabled} |
|
||||
{...register('rangeTestPluginSender', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
</Card> |
|
||||
</div> |
|
||||
</PrimaryTemplate> |
|
||||
); |
|
||||
}; |
|
||||
@ -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<React.SetStateAction<boolean>>; |
|
||||
} |
|
||||
|
|
||||
export const Serial = ({ navOpen, setNavOpen }: SerialProps): JSX.Element => { |
|
||||
const preferences = useAppSelector( |
|
||||
(state) => state.meshtastic.radio.preferences, |
|
||||
); |
|
||||
|
|
||||
const { register, handleSubmit, formState, reset, control } = |
|
||||
useForm<RadioConfig_UserPreferences>({ |
|
||||
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<void> => { |
|
||||
//add loading indicator
|
|
||||
reset({ ...data }); |
|
||||
await Promise.resolve(); |
|
||||
}); |
|
||||
}); |
|
||||
//todo, add loading indicator
|
|
||||
|
|
||||
const watchSerialPluginEnabled = useWatch({ |
|
||||
control, |
|
||||
name: 'serialpluginEnabled', |
|
||||
defaultValue: false, |
|
||||
}); |
|
||||
|
|
||||
return ( |
|
||||
<PrimaryTemplate |
|
||||
title="Serial" |
|
||||
tagline="Plugin" |
|
||||
leftButton={ |
|
||||
<IconButton |
|
||||
icon={<FiMenu className="w-5 h-5" />} |
|
||||
onClick={(): void => { |
|
||||
setNavOpen && setNavOpen(!navOpen); |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
footer={ |
|
||||
<FormFooter |
|
||||
dirty={formState.isDirty} |
|
||||
saveAction={onSubmit} |
|
||||
clearAction={reset} |
|
||||
/> |
|
||||
} |
|
||||
> |
|
||||
<div className="w-full space-y-4"> |
|
||||
<Card> |
|
||||
<div className="w-full max-w-3xl p-10 md:max-w-xl"> |
|
||||
<form onSubmit={onSubmit}> |
|
||||
<Checkbox |
|
||||
label="Plugin Enabled" |
|
||||
{...register('serialpluginEnabled')} |
|
||||
/> |
|
||||
<Checkbox |
|
||||
label="Echo" |
|
||||
disabled={!watchSerialPluginEnabled} |
|
||||
{...register('serialpluginEcho')} |
|
||||
/> |
|
||||
|
|
||||
<Input |
|
||||
type="number" |
|
||||
label="RX" |
|
||||
disabled={!watchSerialPluginEnabled} |
|
||||
{...register('serialpluginRxd', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="TX" |
|
||||
disabled={!watchSerialPluginEnabled} |
|
||||
{...register('serialpluginTxd', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Mode" |
|
||||
disabled={!watchSerialPluginEnabled} |
|
||||
{...register('serialpluginMode', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Timeout" |
|
||||
disabled={!watchSerialPluginEnabled} |
|
||||
{...register('serialpluginTimeout', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
</Card> |
|
||||
</div> |
|
||||
</PrimaryTemplate> |
|
||||
); |
|
||||
}; |
|
||||
@ -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<React.SetStateAction<boolean>>; |
|
||||
} |
|
||||
|
|
||||
export const StoreAndForward = ({ |
|
||||
navOpen, |
|
||||
setNavOpen, |
|
||||
}: StoreAndForwardProps): JSX.Element => { |
|
||||
const preferences = useAppSelector( |
|
||||
(state) => state.meshtastic.radio.preferences, |
|
||||
); |
|
||||
|
|
||||
const { register, handleSubmit, formState, reset, control } = |
|
||||
useForm<RadioConfig_UserPreferences>({ |
|
||||
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<void> => { |
|
||||
//add loading indicator
|
|
||||
reset({ ...data }); |
|
||||
await Promise.resolve(); |
|
||||
}); |
|
||||
}); |
|
||||
//todo, add loading indicator
|
|
||||
|
|
||||
const watchStoreForwardPluginEnabled = useWatch({ |
|
||||
control, |
|
||||
name: 'storeForwardPluginEnabled', |
|
||||
defaultValue: false, |
|
||||
}); |
|
||||
|
|
||||
return ( |
|
||||
<PrimaryTemplate |
|
||||
title="Serial" |
|
||||
tagline="Plugin" |
|
||||
leftButton={ |
|
||||
<IconButton |
|
||||
icon={<FiMenu className="w-5 h-5" />} |
|
||||
onClick={(): void => { |
|
||||
setNavOpen && setNavOpen(!navOpen); |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
footer={ |
|
||||
<FormFooter |
|
||||
dirty={formState.isDirty} |
|
||||
saveAction={onSubmit} |
|
||||
clearAction={reset} |
|
||||
/> |
|
||||
} |
|
||||
> |
|
||||
<div className="w-full space-y-4"> |
|
||||
<Card> |
|
||||
<div className="w-full max-w-3xl p-10 md:max-w-xl"> |
|
||||
<form onSubmit={onSubmit}> |
|
||||
<Checkbox |
|
||||
label="Plugin Enabled" |
|
||||
{...register('storeForwardPluginEnabled')} |
|
||||
/> |
|
||||
<Input |
|
||||
type="number" |
|
||||
label="Number of records" |
|
||||
disabled={!watchStoreForwardPluginEnabled} |
|
||||
{...register('storeForwardPluginRecords', { |
|
||||
valueAsNumber: true, |
|
||||
})} |
|
||||
/> |
|
||||
</form> |
|
||||
</div> |
|
||||
</Card> |
|
||||
</div> |
|
||||
</PrimaryTemplate> |
|
||||
); |
|
||||
}; |
|
||||
@ -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<React.SetStateAction<boolean>>; |
||||
|
} |
||||
|
|
||||
|
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: <FiRss />, |
||||
|
}, |
||||
|
{ |
||||
|
name: 'External Notifications', |
||||
|
description: 'External hardware alerts', |
||||
|
enabled: preferences.extNotificationPluginEnabled, |
||||
|
icon: <FiBell />, |
||||
|
}, |
||||
|
{ |
||||
|
name: 'Serial', |
||||
|
description: 'Send serial data over the mesh', |
||||
|
enabled: preferences.serialpluginEnabled, |
||||
|
icon: <FiAlignLeft />, |
||||
|
}, |
||||
|
{ |
||||
|
name: 'Store & Forward', |
||||
|
description: 'Retrive message history', |
||||
|
enabled: preferences.storeForwardPluginEnabled, |
||||
|
icon: <FiFastForward />, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<PrimaryTemplate |
||||
|
title="Plugins" |
||||
|
tagline="Settings" |
||||
|
leftButton={ |
||||
|
<Button |
||||
|
icon={<FiMenu className="w-5 h-5" />} |
||||
|
onClick={(): void => { |
||||
|
setNavOpen && setNavOpen(!navOpen); |
||||
|
}} |
||||
|
/> |
||||
|
} |
||||
|
> |
||||
|
<Card |
||||
|
title="Basic settings" |
||||
|
description="Device name and user parameters" |
||||
|
> |
||||
|
<div className="w-full max-w-3xl p-10 space-y-2 md:max-w-xl"> |
||||
|
{plugins.map((plugin, index) => ( |
||||
|
<div |
||||
|
key={index} |
||||
|
onClick={(): void => { |
||||
|
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' |
||||
|
: '' |
||||
|
}`}
|
||||
|
> |
||||
|
<div className="flex my-auto space-x-2"> |
||||
|
<div |
||||
|
className={`h-3 my-auto w-3 rounded-full ${ |
||||
|
plugin.enabled ? 'bg-green-500' : 'bg-gray-400' |
||||
|
}`}
|
||||
|
/> |
||||
|
<div className="flex gap-2"> |
||||
|
<div className="my-auto">{plugin.icon}</div> |
||||
|
{plugin.name} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className="flex gap-2"> |
||||
|
<IconButton active icon={<FiExternalLink />} /> |
||||
|
</div> |
||||
|
</div> |
||||
|
))} |
||||
|
</div> |
||||
|
</Card> |
||||
|
</PrimaryTemplate> |
||||
|
{sidebarOpen && ( |
||||
|
<PluginsSidebar |
||||
|
closeSidebar={(): void => { |
||||
|
setSidebarOpen(false); |
||||
|
}} |
||||
|
plugin={selectedPlugin} |
||||
|
/> |
||||
|
)} |
||||
|
</> |
||||
|
); |
||||
|
}; |
||||
Loading…
Reference in new issue