Browse Source

Fixes

pull/2/head
Sacha Weatherstone 5 years ago
parent
commit
a5d67279de
  1. 10
      package.json
  2. 336
      pnpm-lock.yaml
  3. 23
      src/App.tsx
  4. 30
      src/components/generic/IconButton.tsx
  5. 10
      src/core/connection.ts
  6. 32
      src/core/slices/meshtasticSlice.ts
  7. 16
      src/pages/Plugins/Files.tsx
  8. 1
      src/pages/Plugins/Index.tsx
  9. 282
      src/pages/settings/Connection.tsx

10
package.json

@ -12,7 +12,7 @@
},
"dependencies": {
"@headlessui/react": "^1.4.1",
"@meshtastic/meshtasticjs": "^0.6.19",
"@meshtastic/meshtasticjs": "^0.6.22",
"@reduxjs/toolkit": "^1.6.2",
"apexcharts": "^3.29.0",
"boring-avatars": "^1.5.8",
@ -24,8 +24,8 @@
"react-dom": "^17.0.2",
"react-file-icon": "^1.1.0",
"react-flags-select": "^2.1.2",
"react-hook-form": "^7.17.5",
"react-i18next": "^11.12.0",
"react-hook-form": "^7.18.0",
"react-i18next": "^11.13.0",
"react-icons": "^4.3.1",
"react-redux": "^7.2.6",
"swr": "^1.0.1",
@ -42,10 +42,12 @@
"@types/react-file-icon": "^1.0.1",
"@types/react-redux": "^7.1.20",
"@types/snowpack-env": "^2.3.4",
"@types/w3c-web-serial": "^1.0.2",
"@types/web-bluetooth": "^0.0.11",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"@verypossible/eslint-config": "^1.6.1",
"autoprefixer": "^10.3.7",
"autoprefixer": "^10.4.0",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "8.1.0",
"eslint-config-prettier": "^8.3.0",

336
pnpm-lock.yaml

@ -2,7 +2,7 @@ lockfileVersion: 5.3
specifiers:
'@headlessui/react': ^1.4.1
'@meshtastic/meshtasticjs': ^0.6.19
'@meshtastic/meshtasticjs': ^0.6.22
'@reduxjs/toolkit': ^1.6.2
'@snowpack/plugin-dotenv': ^2.2.0
'@snowpack/plugin-postcss': ^1.4.3
@ -13,11 +13,13 @@ specifiers:
'@types/react-file-icon': ^1.0.1
'@types/react-redux': ^7.1.20
'@types/snowpack-env': ^2.3.4
'@types/w3c-web-serial': ^1.0.2
'@types/web-bluetooth': ^0.0.11
'@typescript-eslint/eslint-plugin': ^5.2.0
'@typescript-eslint/parser': ^5.2.0
'@verypossible/eslint-config': ^1.6.1
apexcharts: ^3.29.0
autoprefixer: ^10.3.7
autoprefixer: ^10.4.0
babel-plugin-module-resolver: ^4.1.0
boring-avatars: ^1.5.8
eslint: 8.1.0
@ -38,8 +40,8 @@ specifiers:
react-dom: ^17.0.2
react-file-icon: ^1.1.0
react-flags-select: ^2.1.2
react-hook-form: ^7.17.5
react-i18next: ^11.12.0
react-hook-form: ^7.18.0
react-i18next: ^11.13.0
react-icons: ^4.3.1
react-redux: ^7.2.6
snowpack: ^3.8.8
@ -52,7 +54,7 @@ specifiers:
dependencies:
'@headlessui/react': 1.4[email protected][email protected]
'@meshtastic/meshtasticjs': 0.6.19
'@meshtastic/meshtasticjs': 0.6.22
'@reduxjs/toolkit': 1.6[email protected][email protected]
apexcharts: 3.29.0
boring-avatars: 1.5.8
@ -64,8 +66,8 @@ dependencies:
react-dom: 17.0[email protected]
react-file-icon: 1.1[email protected][email protected]
react-flags-select: 2.1[email protected][email protected]
react-hook-form: 7.17.5[email protected]
react-i18next: 11.12[email protected][email protected]
react-hook-form: 7.18.0[email protected]
react-i18next: 11.13[email protected][email protected]
react-icons: 4.3[email protected]
react-redux: 7.2[email protected][email protected]
swr: 1.0[email protected]
@ -82,10 +84,12 @@ devDependencies:
'@types/react-file-icon': 1.0.1
'@types/react-redux': 7.1.20
'@types/snowpack-env': 2.3.4
'@types/w3c-web-serial': 1.0.2
'@types/web-bluetooth': 0.0.11
'@typescript-eslint/eslint-plugin': 5.2.0_9a56ca1c5fc1d82b3da3317a5c6f9ab1
'@typescript-eslint/parser': 5.2[email protected][email protected]
'@verypossible/eslint-config': 1.6[email protected]
autoprefixer: 10.3.7[email protected]
autoprefixer: 10.4.0[email protected]
babel-plugin-module-resolver: 4.1.0
eslint: 8.1.0
eslint-config-prettier: 8.3[email protected]
@ -98,7 +102,7 @@ devDependencies:
postcss: 8.3.11
prettier: 2.4.1
snowpack: 3.8.8
tailwindcss: 3.0.0-alpha.1_fa866e6aa6eb85ed70431566fb699b34
tailwindcss: 3.0.0-alpha.1_0c54bdadaf9d9c9c6c134cb2c6c061a3
tar: 6.1.11
typescript: 4.4.4
@ -107,34 +111,34 @@ packages:
/@babel/code-frame/7.12.11:
resolution: {integrity: sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==}
dependencies:
'@babel/highlight': 7.14.5
'@babel/highlight': 7.16.0
dev: true
/@babel/code-frame/7.15.8:
resolution: {integrity: sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==}
/@babel/code-frame/7.16.0:
resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.14.5
'@babel/highlight': 7.16.0
dev: true
/@babel/compat-data/7.15.0:
resolution: {integrity: sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==}
/@babel/compat-data/7.16.0:
resolution: {integrity: sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/core/7.15.8:
resolution: {integrity: sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==}
/@babel/core/7.16.0:
resolution: {integrity: sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.15.8
'@babel/generator': 7.15.8
'@babel/helper-compilation-targets': 7.15.4_@[email protected]
'@babel/helper-module-transforms': 7.15.8
'@babel/helpers': 7.15.4
'@babel/parser': 7.15.8
'@babel/template': 7.15.4
'@babel/traverse': 7.15.4
'@babel/types': 7.15.6
'@babel/code-frame': 7.16.0
'@babel/generator': 7.16.0
'@babel/helper-compilation-targets': 7.16.0_@[email protected]
'@babel/helper-module-transforms': 7.16.0
'@babel/helpers': 7.16.0
'@babel/parser': 7.16.0
'@babel/template': 7.16.0
'@babel/traverse': 7.16.0
'@babel/types': 7.16.0
convert-source-map: 1.8.0
debug: 4.3.2
gensync: 1.0.0-beta.2
@ -145,86 +149,86 @@ packages:
- supports-color
dev: true
/@babel/generator/7.15.8:
resolution: {integrity: sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==}
/@babel/generator/7.16.0:
resolution: {integrity: sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
jsesc: 2.5.2
source-map: 0.5.7
dev: true
/@babel/helper-compilation-targets/7.15.4_@[email protected]:
resolution: {integrity: sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==}
/@babel/helper-compilation-targets/7.16.0_@[email protected]:
resolution: {integrity: sha512-S7iaOT1SYlqK0sQaCi21RX4+13hmdmnxIEAnQUB/eh7GeAnRjOUgTYpLkUOiRXzD+yog1JxP0qyAQZ7ZxVxLVg==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/compat-data': 7.15.0
'@babel/core': 7.15.8
'@babel/compat-data': 7.16.0
'@babel/core': 7.16.0
'@babel/helper-validator-option': 7.14.5
browserslist: 4.17.5
semver: 6.3.0
dev: true
/@babel/helper-function-name/7.15.4:
resolution: {integrity: sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==}
/@babel/helper-function-name/7.16.0:
resolution: {integrity: sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-get-function-arity': 7.15.4
'@babel/template': 7.15.4
'@babel/types': 7.15.6
'@babel/helper-get-function-arity': 7.16.0
'@babel/template': 7.16.0
'@babel/types': 7.16.0
dev: true
/@babel/helper-get-function-arity/7.15.4:
resolution: {integrity: sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==}
/@babel/helper-get-function-arity/7.16.0:
resolution: {integrity: sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-hoist-variables/7.15.4:
resolution: {integrity: sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==}
/@babel/helper-hoist-variables/7.16.0:
resolution: {integrity: sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-member-expression-to-functions/7.15.4:
resolution: {integrity: sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==}
/@babel/helper-member-expression-to-functions/7.16.0:
resolution: {integrity: sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-module-imports/7.15.4:
resolution: {integrity: sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==}
/@babel/helper-module-imports/7.16.0:
resolution: {integrity: sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-module-transforms/7.15.8:
resolution: {integrity: sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==}
/@babel/helper-module-transforms/7.16.0:
resolution: {integrity: sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-module-imports': 7.15.4
'@babel/helper-replace-supers': 7.15.4
'@babel/helper-simple-access': 7.15.4
'@babel/helper-split-export-declaration': 7.15.4
'@babel/helper-module-imports': 7.16.0
'@babel/helper-replace-supers': 7.16.0
'@babel/helper-simple-access': 7.16.0
'@babel/helper-split-export-declaration': 7.16.0
'@babel/helper-validator-identifier': 7.15.7
'@babel/template': 7.15.4
'@babel/traverse': 7.15.4
'@babel/types': 7.15.6
'@babel/template': 7.16.0
'@babel/traverse': 7.16.0
'@babel/types': 7.16.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/helper-optimise-call-expression/7.15.4:
resolution: {integrity: sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==}
/@babel/helper-optimise-call-expression/7.16.0:
resolution: {integrity: sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-plugin-utils/7.14.5:
@ -232,30 +236,30 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-replace-supers/7.15.4:
resolution: {integrity: sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==}
/@babel/helper-replace-supers/7.16.0:
resolution: {integrity: sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-member-expression-to-functions': 7.15.4
'@babel/helper-optimise-call-expression': 7.15.4
'@babel/traverse': 7.15.4
'@babel/types': 7.15.6
'@babel/helper-member-expression-to-functions': 7.16.0
'@babel/helper-optimise-call-expression': 7.16.0
'@babel/traverse': 7.16.0
'@babel/types': 7.16.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/helper-simple-access/7.15.4:
resolution: {integrity: sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==}
/@babel/helper-simple-access/7.16.0:
resolution: {integrity: sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-split-export-declaration/7.15.4:
resolution: {integrity: sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==}
/@babel/helper-split-export-declaration/7.16.0:
resolution: {integrity: sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.15.6
'@babel/types': 7.16.0
dev: true
/@babel/helper-validator-identifier/7.15.7:
@ -268,19 +272,19 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
/@babel/helpers/7.15.4:
resolution: {integrity: sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==}
/@babel/helpers/7.16.0:
resolution: {integrity: sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.15.4
'@babel/traverse': 7.15.4
'@babel/types': 7.15.6
'@babel/template': 7.16.0
'@babel/traverse': 7.16.0
'@babel/types': 7.16.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/highlight/7.14.5:
resolution: {integrity: sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==}
/@babel/highlight/7.16.0:
resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.15.7
@ -288,55 +292,55 @@ packages:
js-tokens: 4.0.0
dev: true
/@babel/parser/7.15.8:
resolution: {integrity: sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==}
/@babel/parser/7.16.0:
resolution: {integrity: sha512-TEHWXf0xxpi9wKVyBCmRcSSDjbJ/cl6LUdlbYUHEaNQUJGhreJbZrXT6sR4+fZLxVUJqNRB4KyOvjuy/D9009A==}
engines: {node: '>=6.0.0'}
hasBin: true
dev: true
/@babel/plugin-syntax-class-properties/7.12.13_@[email protected]5.8:
/@babel/plugin-syntax-class-properties/7.12.13_@[email protected]6.0:
resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.15.8
'@babel/core': 7.16.0
'@babel/helper-plugin-utils': 7.14.5
dev: true
/@babel/runtime/7.15.4:
resolution: {integrity: sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==}
/@babel/runtime/7.16.0:
resolution: {integrity: sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==}
engines: {node: '>=6.9.0'}
dependencies:
regenerator-runtime: 0.13.9
/@babel/template/7.15.4:
resolution: {integrity: sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==}
/@babel/template/7.16.0:
resolution: {integrity: sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.15.8
'@babel/parser': 7.15.8
'@babel/types': 7.15.6
'@babel/code-frame': 7.16.0
'@babel/parser': 7.16.0
'@babel/types': 7.16.0
dev: true
/@babel/traverse/7.15.4:
resolution: {integrity: sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==}
/@babel/traverse/7.16.0:
resolution: {integrity: sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.15.8
'@babel/generator': 7.15.8
'@babel/helper-function-name': 7.15.4
'@babel/helper-hoist-variables': 7.15.4
'@babel/helper-split-export-declaration': 7.15.4
'@babel/parser': 7.15.8
'@babel/types': 7.15.6
'@babel/code-frame': 7.16.0
'@babel/generator': 7.16.0
'@babel/helper-function-name': 7.16.0
'@babel/helper-hoist-variables': 7.16.0
'@babel/helper-split-export-declaration': 7.16.0
'@babel/parser': 7.16.0
'@babel/types': 7.16.0
debug: 4.3.2
globals: 11.12.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/types/7.15.6:
resolution: {integrity: sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==}
/@babel/types/7.16.0:
resolution: {integrity: sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.15.7
@ -350,7 +354,7 @@ packages:
ajv: 6.12.6
debug: 4.3.2
espree: 7.3.1
globals: 13.11.0
globals: 13.12.0
ignore: 4.0.6
import-fresh: 3.3.0
js-yaml: 3.14.1
@ -367,7 +371,7 @@ packages:
ajv: 6.12.6
debug: 4.3.2
espree: 9.0.0
globals: 13.11.0
globals: 13.12.0
ignore: 4.0.6
import-fresh: 3.3.0
js-yaml: 3.14.1
@ -422,10 +426,11 @@ packages:
resolution: {integrity: sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==}
dev: true
/@meshtastic/meshtasticjs/0.6.19:
resolution: {integrity: sha512-bdFkgAjjnnBm1J7dJjCxgQ0+ftu6txLAkO698YFodwGRbvb+io+N2ie6fInqvIFvoCPA9R1fUZa6WhGpIiVZGA==}
/@meshtastic/meshtasticjs/0.6.22:
resolution: {integrity: sha512-3G1dwVmwwtrR/TVbCGKcqXDgLDCkUPERiw8P8ZXdYLxYrmlAy2WAZEclzWdQtEmhvBKpXm1+pEBlycN4DXBDXw==}
dependencies:
'@protobuf-ts/runtime': 2.0.7
node-fetch: 3.0.0
sub-events: 1.8.9
dev: false
@ -595,9 +600,9 @@ packages:
immer: 9.0.6
react: 17.0.2
react-redux: 7.2[email protected][email protected]
redux: 4.1.1
redux-thunk: 2.4[email protected].1
reselect: 4.1.0
redux: 4.1.2
redux-thunk: 2.4[email protected].2
reselect: 4.1.1
dev: false
/@rollup/plugin-commonjs/[email protected]:
@ -705,8 +710,8 @@ packages:
react: '>=16.9.0'
react-dom: '>=16.9.0'
dependencies:
'@babel/core': 7.15.8
'@babel/plugin-syntax-class-properties': 7.12.13_@[email protected]5.8
'@babel/core': 7.16.0
'@babel/plugin-syntax-class-properties': 7.12.13_@[email protected]6.0
react: 17.0.2
react-dom: 17.0[email protected]
react-refresh: 0.9.0
@ -806,7 +811,7 @@ packages:
'@types/hoist-non-react-statics': 3.3.1
'@types/react': 17.0.33
hoist-non-react-statics: 3.3.2
redux: 4.1.1
redux: 4.1.2
/@types/react/17.0.33:
resolution: {integrity: sha512-pLWntxXpDPaU+RTAuSGWGSEL2FRTNyRQOjSWDke/rxRg14ncsZvx8AKWMWZqvc1UOaJIAoObdZhAWvRaHFi5rw==}
@ -834,6 +839,14 @@ packages:
resolution: {integrity: sha512-zYzMb2aMyzXW5VgOQHy+FgI8N5tLFb+tIsUqk35CIgSr9pT4pji2GR8BCOTMdniusVuRHIp/DaYQNQGYGLVZHQ==}
dev: true
/@types/w3c-web-serial/1.0.2:
resolution: {integrity: sha512-Ftx4BtLxgAnel7V7GbHylCYjSq827A+jeEE3SnTS7huCGUN0pSwUn+CchTCT9TkZj9w+NVMUq4Bk2R0GvUNmAQ==}
dev: true
/@types/web-bluetooth/0.0.11:
resolution: {integrity: sha512-2CF3Kk2Rcvg/c2QzO7mXUhY7eL9CC3aKzrF+dNWNmp7Q8bmlvjmUM1nFPMSngawdJ+CcIdu8eJlQRytBgAZR9w==}
dev: true
/@typescript-eslint/eslint-plugin/4.33.0_cc617358c89d3f38c52462f6d809db4c:
resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -1300,18 +1313,18 @@ packages:
resolution: {integrity: sha1-x57Zf380y48robyXkLzDZkdLS3k=}
dev: true
/autoprefixer/10.3.7[email protected]:
resolution: {integrity: sha512-EmGpu0nnQVmMhX8ROoJ7Mx8mKYPlcUHuxkwrRYEYMz85lu7H09v8w6R1P0JPdn/hKU32GjpLBFEOuIlDWCRWvg==}
/autoprefixer/10.4.0[email protected]:
resolution: {integrity: sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
peerDependencies:
postcss: ^8.1.0
dependencies:
browserslist: 4.17.5
caniuse-lite: 1.0.30001271
caniuse-lite: 1.0.30001272
fraction.js: 4.1.1
normalize-range: 0.1.2
picocolors: 0.2.1
picocolors: 1.0.0
postcss: 8.3.11
postcss-value-parser: 4.1.0
dev: true
@ -1336,7 +1349,7 @@ packages:
find-babel-config: 1.2.0
glob: 7.2.0
pkg-up: 3.1.0
reselect: 4.1.0
reselect: 4.1.1
resolve: 1.20.0
dev: true
@ -1409,8 +1422,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001271
electron-to-chromium: 1.3.879
caniuse-lite: 1.0.30001272
electron-to-chromium: 1.3.885
escalade: 3.1.1
node-releases: 2.0.1
picocolors: 1.0.0
@ -1497,8 +1510,8 @@ packages:
engines: {node: '>= 6'}
dev: true
/caniuse-lite/1.0.30001271:
resolution: {integrity: sha512-BBruZFWmt3HFdVPS8kceTBIguKxu4f99n5JNp06OlPD/luoAMIaIK5ieV5YjnBLH3Nysai9sxj9rpJj4ZisXOA==}
/caniuse-lite/1.0.30001272:
resolution: {integrity: sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw==}
dev: true
/caseless/0.12.0:
@ -1722,6 +1735,11 @@ packages:
assert-plus: 1.0.0
dev: true
/data-uri-to-buffer/3.0.1:
resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==}
engines: {node: '>= 6'}
dev: false
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
dependencies:
@ -1933,8 +1951,8 @@ packages:
safer-buffer: 2.1.2
dev: true
/electron-to-chromium/1.3.879:
resolution: {integrity: sha512-zJo+D9GwbJvM31IdFmwcGvychhk4KKbKYo2GWlsn+C/dxz2NwmbhGJjWwTfFSF2+eFH7VvfA8MCZ8SOqTrlnpw==}
/electron-to-chromium/1.3.885:
resolution: {integrity: sha512-JXKFJcVWrdHa09n4CNZYfYaK6EW5aAew7/wr3L1OnsD1L+JHL+RCtd7QgIsxUbFPeTwPlvnpqNNTOLkoefmtXg==}
dev: true
/emoji-regex/8.0.0:
@ -2360,7 +2378,7 @@ packages:
file-entry-cache: 6.0.1
functional-red-black-tree: 1.0.1
glob-parent: 5.1.2
globals: 13.11.0
globals: 13.12.0
ignore: 4.0.6
import-fresh: 3.3.0
imurmurhash: 0.1.4
@ -2408,7 +2426,7 @@ packages:
file-entry-cache: 6.0.1
functional-red-black-tree: 1.0.1
glob-parent: 6.0.2
globals: 13.11.0
globals: 13.12.0
ignore: 4.0.6
import-fresh: 3.3.0
imurmurhash: 0.1.4
@ -2558,6 +2576,13 @@ packages:
resolution: {integrity: sha512-IgTtZwL52tx2wqWeuGDzXYTnNsEjNLahZpJw30hCQDyVnoHXwY5acNDnjGImTTL1R0z1PCyLw20VAbE5qLic3Q==}
dev: true
/fetch-blob/3.1.3:
resolution: {integrity: sha512-ax1Y5I9w+9+JiM+wdHkhBoxew+zG4AJ2SvAD1v1szpddUIiPERVGBxrMcB2ZqW0Y3PP8bOWYv2zqQq1Jp2kqUQ==}
engines: {node: ^12.20 || >= 14.13}
dependencies:
web-streams-polyfill: 3.1.1
dev: false
/file-entry-cache/6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -2774,8 +2799,8 @@ packages:
engines: {node: '>=4'}
dev: true
/globals/13.11.0:
resolution: {integrity: sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==}
/globals/13.12.0:
resolution: {integrity: sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==}
engines: {node: '>=8'}
dependencies:
type-fest: 0.20.2
@ -2878,7 +2903,7 @@ packages:
/history/5.0.1:
resolution: {integrity: sha512-5qC/tFUKfVci5kzgRxZxN5Mf1CV8NmJx9ByaPX0YTLx5Vz3Svh7NYp6eA4CpDq4iA9D0C1t8BNIfvQIrUI3mVw==}
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
dev: false
/hoist-non-react-statics/3.3.2:
@ -2969,13 +2994,13 @@ packages:
/i18next-browser-languagedetector/6.1.2:
resolution: {integrity: sha512-YDzIGHhMRvr7M+c8B3EQUKyiMBhfqox4o1qkFvt4QXuu5V2cxf74+NCr+VEkUuU0y+RwcupA238eeolW1Yn80g==}
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
dev: false
/i18next/21.3.3:
resolution: {integrity: sha512-Wv5arCT9pK35nfhOzTdS64T7JpPcoqnkOEidxc4zF0DZ8KetpvmnkO+uWkXy+DFz6zWzPX7U9bIemwBqpFRprw==}
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
dev: false
/iconv-lite/0.6.3:
@ -3725,6 +3750,14 @@ packages:
engines: {node: '>= 0.6'}
dev: true
/node-fetch/3.0.0:
resolution: {integrity: sha512-bKMI+C7/T/SPU1lKnbQbwxptpCrG9ashG+VkytmXCPZyuM9jB6VU+hY0oi4lC8LxTtAeWdckNCTa3nrGsAdA3Q==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
data-uri-to-buffer: 3.0.1
fetch-blob: 3.1.3
dev: false
/node-gyp-build/4.3.0:
resolution: {integrity: sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==}
hasBin: true
@ -4112,7 +4145,7 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
'@babel/code-frame': 7.15.8
'@babel/code-frame': 7.16.0
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.1.6
@ -4168,10 +4201,6 @@ packages:
is-reference: 1.2.1
dev: true
/picocolors/0.2.1:
resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==}
dev: true
/picocolors/1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: true
@ -4444,21 +4473,21 @@ packages:
react-dom: 17.0[email protected]
dev: false
/react-hook-form/7.17.5[email protected]:
resolution: {integrity: sha512-4bPtPGkpVhZlgtTbtMGi0RFphKHgxCj5u3AsGz3SBdleELlG1pDf9zRQOtfGlOGkZlc7u78RzD0xu9kOw7PYdQ==}
/react-hook-form/7.18.0[email protected]:
resolution: {integrity: sha512-aTFs1jXGvpBBv4vYuhheVd9KbAZw/l3DOZhLIadNDyFddaDQmn+yJa63IZ14GDFz4NFgIi+ROkubfGJG2x6q2Q==}
peerDependencies:
react: ^16.8.0 || ^17
dependencies:
react: 17.0.2
dev: false
/react-i18next/11.12[email protected][email protected]:
resolution: {integrity: sha512-M9BT+hqVG03ywrl+L7CK74ugK+4jIo7AeKJ17+g9BoqJz2+/aVbs8SIVXT4KMQ1rjIdcw+GcSRDy1CXjcz6tLQ==}
/react-i18next/11.13[email protected][email protected]:
resolution: {integrity: sha512-AY8ydSqx8LVm1Tn5yXFA0JwCeSWpcFOSr96HrjUXXVAWWbptamZOY2iMxVaGNlGxSLnRY0U2sdCIPVYHcmhBxQ==}
peerDependencies:
i18next: '>= 19.0.0'
react: '>= 16.8.0'
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
html-parse-stringify: 3.0.1
i18next: 21.3.3
react: 17.0.2
@ -4491,7 +4520,7 @@ packages:
react-native:
optional: true
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
'@types/react-redux': 7.1.20
hoist-non-react-statics: 3.3.2
loose-envify: 1.4.0
@ -4554,18 +4583,18 @@ packages:
picomatch: 2.3.0
dev: true
/redux-thunk/[email protected].1:
/redux-thunk/[email protected].2:
resolution: {integrity: sha512-/y6ZKQNU/0u8Bm7ROLq9Pt/7lU93cT0IucYMrubo89ENjxPa7i8pqLKu6V4X7/TvYovQ6x01unTeyeZ9lgXiTA==}
peerDependencies:
redux: ^4
dependencies:
redux: 4.1.1
redux: 4.1.2
dev: false
/redux/4.1.1:
resolution: {integrity: sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw==}
/redux/4.1.2:
resolution: {integrity: sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==}
dependencies:
'@babel/runtime': 7.15.4
'@babel/runtime': 7.16.0
/regenerator-runtime/0.13.9:
resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
@ -4615,8 +4644,8 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/reselect/4.1.0:
resolution: {integrity: sha512-An39mlrk9bnL39pq9M6th54FaL7VaqZe2m8tBb746udYYO6MD7MOIdaqZ+tABkAOmHQSTqtL3NhUNE8HVvVcQQ==}
/reselect/4.1.1:
resolution: {integrity: sha512-Jjt8Us6hAWJpjucyladHvUGR+q1mHHgWtGDXlhvvKyNyIeQ3bjuWLDX0bsTLhbm/gd4iXEACBlODUHBlLWiNnA==}
/resolve-alpn/1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
@ -5098,7 +5127,7 @@ packages:
strip-ansi: 6.0.1
dev: true
/tailwindcss/3.0.0-alpha.1_fa866e6aa6eb85ed70431566fb699b34:
/tailwindcss/3.0.0-alpha.1_0c54bdadaf9d9c9c6c134cb2c6c061a3:
resolution: {integrity: sha512-VweVLyu1tpo/i2MnoyDIunToZHYhHRZLGuKDt9I+nnjFoW07NhDwwHWsUyRHKowP5MZaHduhV+AVlM6Auy7m3A==}
engines: {node: '>=12.13.0'}
hasBin: true
@ -5107,7 +5136,7 @@ packages:
postcss: ^8.0.9
dependencies:
arg: 5.0.1
autoprefixer: 10.3.7[email protected]
autoprefixer: 10.4.0[email protected]
chalk: 4.1.2
chokidar: 3.5.2
color-name: 1.1.4
@ -5358,6 +5387,11 @@ packages:
resolution: {integrity: sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==}
dev: true
/web-streams-polyfill/3.1.1:
resolution: {integrity: sha512-Czi3fG883e96T4DLEPRvufrF2ydhOOW1+1a6c3gNjH2aIh50DNFBdfwh2AKoOf1rXvpvavAoA11Qdq9+BKjE0Q==}
engines: {node: '>= 8'}
dev: false
/which-boxed-primitive/1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
dependencies:

23
src/App.tsx

@ -7,7 +7,7 @@ import { ThemeToggle } from '@components/menu/buttons/ThemeToggle';
import { Logo } from '@components/menu/Logo';
import { MobileNav } from '@components/menu/MobileNav';
import { Navigation } from '@components/menu/Navigation';
import { connection } from '@core/connection';
import { connection, setConnection } from '@core/connection';
import { useRoute } from '@core/router';
import {
addChannel,
@ -20,14 +20,19 @@ import {
setReady,
setUser,
} from '@core/slices/meshtasticSlice';
import { Protobuf, SettingsManager, Types } from '@meshtastic/meshtasticjs';
import {
IHTTPConnection,
Protobuf,
SettingsManager,
Types,
} from '@meshtastic/meshtasticjs';
import { About } from '@pages/About';
import { Messages } from '@pages/Messages';
import { Nodes } from '@pages/Nodes/Index';
import { Settings } from '@pages/settings/Index';
import { NotFound } from './pages/NotFound';
import { Plugins } from './pages/Plugins/Index.jsx';
import { Plugins } from './pages/Plugins/Index';
const App = (): JSX.Element => {
const dispatch = useAppDispatch();
@ -38,6 +43,7 @@ const App = (): JSX.Element => {
const hostOverrideEnabled = useAppSelector(
(state) => state.meshtastic.hostOverrideEnabled,
);
const hostOverride = useAppSelector((state) => state.meshtastic.hostOverride);
const connectionURL = hostOverrideEnabled
@ -50,6 +56,7 @@ const App = (): JSX.Element => {
React.useEffect(() => {
SettingsManager.debugMode = Protobuf.LogRecord_Level.TRACE;
setConnection(new IHTTPConnection());
void connection.connect({
address: connectionURL,
tls: false,
@ -74,8 +81,13 @@ const App = (): JSX.Element => {
dispatch(setMyNodeInfo(nodeInfo));
});
connection.onUserDataPacket.subscribe((user) => {
dispatch(setUser(user));
connection.onUserPacket.subscribe((user) => {
dispatch(
setUser({
nodeNum: user.packet.from,
user: user.data,
}),
);
});
connection.onNodeInfoPacket.subscribe((nodeInfoPacket) =>
@ -117,7 +129,6 @@ const App = (): JSX.Element => {
return (): void => {
connection.onDeviceStatus.cancelAll();
connection.onMyNodeInfo.cancelAll();
connection.onUserDataPacket.cancelAll();
connection.onNodeInfoPacket.cancelAll();
connection.onAdminPacket.cancelAll();
connection.onMeshHeartbeat.cancelAll();

30
src/components/generic/IconButton.tsx

@ -1,47 +1,23 @@
import React from 'react';
import { FiCheck } from 'react-icons/fi';
type DefaulButtonProps = JSX.IntrinsicElements['button'];
export interface IconButtonProps extends DefaulButtonProps {
icon: React.ReactNode;
confirmAction?: () => void;
}
export const IconButton = ({
icon,
confirmAction,
...props
}: IconButtonProps): JSX.Element => {
const [hasConfirmed, setHasConfirmed] = React.useState(false);
const handleConfirm = (): void => {
if (confirmAction) {
if (hasConfirmed) {
void confirmAction();
}
setHasConfirmed(true);
setTimeout(() => {
setHasConfirmed(false);
}, 3000);
}
};
return (
<div
className="my-auto text-gray-500 dark:text-gray-400"
onClick={handleConfirm}
>
<div className="my-auto text-gray-500 dark:text-gray-400">
<button
type="button"
className={`p-2 rounded-md active:scale-95 ${
hasConfirmed
? 'bg-red-500'
: 'hover:bg-gray-200 dark:hover:bg-gray-600'
}`}
className="p-2 rounded-md active:scale-95 hover:bg-gray-200 dark:hover:bg-gray-600"
{...props}
>
{hasConfirmed ? <FiCheck /> : icon}
{icon}
<span className="sr-only">Refresh</span>
</button>
</div>

10
src/core/connection.ts

@ -4,6 +4,10 @@ import {
ISerialConnection,
} from '@meshtastic/meshtasticjs';
export const connection = new IHTTPConnection();
export const bleConnection = new IBLEConnection();
export const serialConnection = new ISerialConnection();
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
export let connection: connectionType = new IHTTPConnection();
export const setConnection = (conn: connectionType): void => {
connection = conn;
};

32
src/core/slices/meshtasticSlice.ts

@ -10,6 +10,11 @@ export interface MessageWithAck {
isSender: boolean;
received: Date;
}
enum connType {
HTTP,
BLE,
SERIAL,
}
interface MeshtasticState {
deviceStatus: Types.DeviceStatusEnum;
@ -24,6 +29,7 @@ interface MeshtasticState {
messages: MessageWithAck[];
hostOverrideEnabled: boolean;
hostOverride: string;
connectionType: connType;
}
const initialState: MeshtasticState = {
@ -40,6 +46,7 @@ const initialState: MeshtasticState = {
hostOverrideEnabled:
localStorage.getItem('hostOverrideEnabled') === 'true' ?? false,
hostOverride: localStorage.getItem('hostOverride') ?? '',
connectionType: parseInt(localStorage.getItem('connectionType') ?? '0'),
};
export const meshtasticSlice = createSlice({
@ -58,8 +65,21 @@ export const meshtasticSlice = createSlice({
setMyNodeInfo: (state, action: PayloadAction<Protobuf.MyNodeInfo>) => {
state.myNodeInfo = action.payload;
},
setUser: (state, action: PayloadAction<Protobuf.User>) => {
state.user = action.payload;
setUser: (
state,
action: PayloadAction<{
nodeNum: number;
user: Protobuf.User;
}>,
) => {
if (action.payload.nodeNum === state.myNodeInfo.myNodeNum) {
state.user = action.payload.user;
} else {
const num = state.nodes.findIndex(
(node) => node.num === action.payload.nodeNum,
);
state.nodes[num].user = action.payload.user;
}
},
addPositionPacket: (state, action: PayloadAction<Types.PositionPacket>) => {
state.positionPackets.push(action.payload);
@ -75,7 +95,6 @@ export const meshtasticSlice = createSlice({
state.nodes.push(action.payload);
}
},
addChannel: (state, action: PayloadAction<Protobuf.Channel>) => {
if (
state.channels.findIndex(
@ -121,6 +140,13 @@ export const meshtasticSlice = createSlice({
connection.disconnect();
}
},
setConnectionType: (state, action: PayloadAction<connType>) => {
state.connectionType = action.payload;
localStorage.setItem('connectionType', String(action.payload));
if (state.connectionType !== action.payload) {
connection.disconnect();
}
},
},
});

16
src/pages/Plugins/Files.tsx

@ -118,14 +118,14 @@ export const Files = ({ navOpen, setNavOpen }: RangeTestProps): JSX.Element => {
</div>
<IconButton
className="mx-2 my-auto"
confirmAction={async (): Promise<void> => {
await fetch(
`http://${connectionURL}/json/spiffs/delete/static?remove=${file.name}`,
{
method: 'DELETE',
},
);
}}
// 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>

1
src/pages/Plugins/Index.tsx

@ -34,7 +34,6 @@ export const Plugins = (): JSX.Element => {
<div className="md:hidden">
<IconButton
icon={<FiXCircle className="w-5 h-5" />}
circle
onClick={(): void => {
setNavOpen(false);
}}

282
src/pages/settings/Connection.tsx

@ -2,39 +2,125 @@ import React from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { FiLink2, FiMenu, FiSave } from 'react-icons/fi';
import { FiCheck, FiMenu, FiSave } from 'react-icons/fi';
import { Card } from '@app/components/generic/Card';
import { EnumSelect } from '@app/components/generic/form/EnumSelect';
import { Input } from '@app/components/generic/form/Input';
import { IconButton } from '@app/components/generic/IconButton.jsx';
import { Tabs } from '@app/components/generic/Tabs';
import { IconButton } from '@app/components/generic/IconButton';
import { Toggle } from '@app/components/generic/Toggle';
import { bleConnection, serialConnection } from '@app/core/connection';
import { useAppSelector } from '@app/hooks/redux';
import { connection, setConnection } from '@app/core/connection';
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import type { Protobuf } from '@meshtastic/meshtasticjs';
import {
IBLEConnection,
IHTTPConnection,
ISerialConnection,
} from '@meshtastic/meshtasticjs';
import type {
BLEConnectionParameters,
HTTPConnectionParameters,
SerialConnectionParameters,
} from '@meshtastic/meshtasticjs/dist/types';
export interface ConnectionProps {
navOpen: boolean;
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
enum connType {
HTTP,
BLE,
SERIAL,
}
export const Connection = ({
navOpen,
setNavOpen,
}: ConnectionProps): JSX.Element => {
const dispatch = useAppDispatch();
const [selectedConnType, setSelectedConnType] = React.useState(connType.HTTP);
const [bleDevices, setBleDevices] = React.useState<BluetoothDevice[]>([]);
const [serialDevices, setSerialDevices] = React.useState<SerialPort[]>([]);
const [httpIpSource, setHttpIpSource] = React.useState<'local' | 'remote'>(
'local',
);
const { t } = useTranslation();
const user = useAppSelector((state) => state.meshtastic.user);
const hostOverrideEnabled = useAppSelector(
(state) => state.meshtastic.hostOverrideEnabled,
);
const hostOverride = useAppSelector((state) => state.meshtastic.hostOverride);
const { register, handleSubmit, formState } = useForm<Protobuf.User>({
defaultValues: user,
const { register, handleSubmit, formState } = useForm<{
method: connType;
}>({
defaultValues: {
method: connType.HTTP,
},
});
const connect = (
connectionType: connType,
params:
| HTTPConnectionParameters
| SerialConnectionParameters
| BLEConnectionParameters,
): void => {
connection.complete();
connection.disconnect();
if (connectionType === connType.BLE) {
setConnection(new IBLEConnection());
} else if (connectionType === connType.HTTP) {
setConnection(new IHTTPConnection());
} else {
setConnection(new ISerialConnection());
}
console.log(params);
// @ts-ignore
connection.connect(params);
console.log(connection);
};
const updateBleDeviceList = async (): Promise<void> => {
const devices = await ble.getDevices();
setBleDevices(devices);
};
const updateSerialDeviceList = async (): Promise<void> => {
const devices = await serial.getPorts();
console.log(devices);
setSerialDevices(devices);
};
React.useEffect(() => {
if (selectedConnType === connType.BLE) {
updateBleDeviceList();
}
if (selectedConnType === connType.SERIAL) {
updateSerialDeviceList();
}
}, [selectedConnType]);
const onSubmit = handleSubmit((data) => {
// void connection.setOwner(data);
});
const connectionURL: string = hostOverrideEnabled
? hostOverride
: import.meta.env.NODE_ENV === 'production'
? window.location.hostname
: (import.meta.env.SNOWPACK_PUBLIC_DEVICE_IP as string) ??
'http://meshtastic.local';
const ble = new IBLEConnection();
const serial = new ISerialConnection();
return (
<PrimaryTemplate
title="Connection"
@ -64,73 +150,127 @@ export const Connection = ({
description="Device name and user parameters"
>
<div className="w-full max-w-3xl p-10 md:max-w-xl">
<div className="flex w-full p-2 mb-2 border dark:border-gray-600 rounded-3xl">
Current connection method:
<div className="px-1 my-auto ml-2 text-sm bg-gray-400 rounded-full dark:bg-primaryDark">
BLE
</div>
</div>
<form className="space-y-2" onSubmit={onSubmit}>
<Tabs
className="mb-10 h-60"
tabs={[
{
name: 'HTTP',
body: (
<div className="space-y-2">
<Input label={'Device URL'} />
<Toggle label="Use TLS?" />
</div>
),
},
{
name: 'Bluetooth',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await bleConnection.getDevices());
<EnumSelect
label="Method"
optionsEnum={connType}
value={selectedConnType}
onChange={(e): void => {
setSelectedConnType(parseInt(e.target.value));
}}
/>
{selectedConnType === connType.HTTP && (
<>
<EnumSelect
label="Host Source"
options={[
{
name: 'Local',
value: 'local',
},
{
name: 'Remote',
value: 'remote',
},
]}
value={httpIpSource}
onChange={(e): void => {
setHttpIpSource(e.target.value as 'local' | 'remote');
}}
/>
{httpIpSource === 'local' ? (
<Input label="Host" value={connectionURL} disabled />
) : (
<Input label="Host" />
)}
<Toggle label="Use TLS?" />
</>
)}
{selectedConnType === connType.BLE && (
<div>
<div className="flex space-x-2">
<Button border onClick={updateBleDeviceList}>
Refresh List
</Button>
<Button
border
onClick={() => {
ble.getDevice();
}}
>
New Device
</Button>
</div>
<div className="space-y-2">
<div>Previously connected devices</div>
{bleDevices.map((device) => (
<div
onClick={() => {
console.log('clicked');
connect(connType.BLE, {
device: device,
});
}}
className="flex justify-between p-2 bg-gray-700 rounded-md"
key={device.id}
>
<div className="my-auto">{device.name}</div>
<IconButton
onClick={() => {
console.log('clicked');
connect(connType.BLE, {
device: device,
});
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<FiLink2 className="w-5 h-5 my-auto mr-2 text-gray-300" />
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<FiLink2 className="w-5 h-5 my-auto mr-2 text-gray-600" />
</div>
icon={<FiCheck />}
/>
</div>
),
},
{
name: 'Serial',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await serialConnection.getPorts());
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<FiLink2 className="w-5 h-5 my-auto mr-2 text-gray-300" />
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<FiLink2 className="w-5 h-5 my-auto mr-2 text-gray-600" />
))}
</div>
</div>
)}
{selectedConnType === connType.SERIAL && (
<div>
<div className="flex space-x-2">
<Button border onClick={updateBleDeviceList}>
Refresh List
</Button>
<Button
border
onClick={() => {
serial.getPort();
}}
>
New Device
</Button>
</div>
<div className="space-y-2">
<div>Previously connected devices</div>
{serialDevices.map((device) => (
<div
className="flex justify-between p-2 bg-gray-700 rounded-md"
key={device.getInfo().usbProductId}
>
<div className="my-auto">
{device.getInfo().usbProductId}
{device.getInfo().usbVendorId}
</div>
<IconButton
onClick={() => {
connect(connType.SERIAL, {
// @ts-ignore
device: device,
});
}}
icon={<FiCheck />}
/>
</div>
),
},
]}
/>
))}
</div>
</div>
)}
</form>
</div>
</Card>

Loading…
Cancel
Save