diff --git a/package.json b/package.json
index 2870eec6..c003bb6a 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
"dependencies": {
"@floating-ui/react-dom": "^0.4.1",
"@headlessui/react": "^1.4.2",
- "@meshtastic/components": "^1.0.12",
+ "@meshtastic/components": "^1.0.13",
"@meshtastic/meshtasticjs": "^0.6.36",
"@reduxjs/toolkit": "^1.7.1",
"base64-js": "^1.5.1",
@@ -27,7 +27,7 @@
"react-error-boundary": "^3.1.4",
"react-file-icon": "^1.1.0",
"react-hook-form": "^7.22.5",
- "react-i18next": "^11.15.2",
+ "react-i18next": "^11.15.3",
"react-icons": "^4.3.1",
"react-json-pretty": "^2.2.0",
"react-qr-code": "^2.0.3",
@@ -40,7 +40,6 @@
"use-breakpoint": "^3.0.0"
},
"devDependencies": {
- "@rollup/plugin-typescript": "^8.3.0",
"@types/mapbox-gl": "^2.6.0",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
@@ -53,12 +52,12 @@
"@vitejs/plugin-react": "^1.1.3",
"autoprefixer": "^10.4.1",
"babel-plugin-module-resolver": "^4.1.0",
- "eslint": "8.5.0",
+ "eslint": "8.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-babel-module": "^5.3.1",
"eslint-import-resolver-typescript": "^2.5.0",
- "eslint-plugin-import": "^2.25.3",
+ "eslint-plugin-import": "^2.25.4",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"gzipper": "^6.2.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 13f3d1f9..82fbc481 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3,10 +3,9 @@ lockfileVersion: 5.3
specifiers:
'@floating-ui/react-dom': ^0.4.1
'@headlessui/react': ^1.4.2
- '@meshtastic/components': ^1.0.12
+ '@meshtastic/components': ^1.0.13
'@meshtastic/meshtasticjs': ^0.6.36
'@reduxjs/toolkit': ^1.7.1
- '@rollup/plugin-typescript': ^8.3.0
'@types/mapbox-gl': ^2.6.0
'@types/react': ^17.0.38
'@types/react-dom': ^17.0.11
@@ -21,12 +20,12 @@ specifiers:
babel-plugin-module-resolver: ^4.1.0
base64-js: ^1.5.1
boring-avatars: ^1.6.1
- eslint: 8.5.0
+ eslint: 8.6.0
eslint-config-prettier: ^8.3.0
eslint-import-resolver-alias: ^1.1.2
eslint-import-resolver-babel-module: ^5.3.1
eslint-import-resolver-typescript: ^2.5.0
- eslint-plugin-import: ^2.25.3
+ eslint-plugin-import: ^2.25.4
eslint-plugin-react: ^7.28.0
eslint-plugin-react-hooks: ^4.3.0
gzipper: ^6.2.1
@@ -40,7 +39,7 @@ specifiers:
react-error-boundary: ^3.1.4
react-file-icon: ^1.1.0
react-hook-form: ^7.22.5
- react-i18next: ^11.15.2
+ react-i18next: ^11.15.3
react-icons: ^4.3.1
react-json-pretty: ^2.2.0
react-qr-code: ^2.0.3
@@ -62,7 +61,7 @@ specifiers:
dependencies:
'@floating-ui/react-dom': 0.4.1_b3482aaf5744fc7c2aeb7941b0e0a78f
'@headlessui/react': 1.4.2_react-dom@17.0.2+react@17.0.2
- '@meshtastic/components': 1.0.12
+ '@meshtastic/components': 1.0.13
'@meshtastic/meshtasticjs': 0.6.36
'@reduxjs/toolkit': 1.7.1_react-redux@7.2.6+react@17.0.2
base64-js: 1.5.1
@@ -75,7 +74,7 @@ dependencies:
react-error-boundary: 3.1.4_react@17.0.2
react-file-icon: 1.1.0_react-dom@17.0.2+react@17.0.2
react-hook-form: 7.22.5_react@17.0.2
- react-i18next: 11.15.2_80acb397921aff391f276c2217c76c9e
+ react-i18next: 11.15.3_80acb397921aff391f276c2217c76c9e
react-icons: 4.3.1_react@17.0.2
react-json-pretty: 2.2.0_react-dom@17.0.2+react@17.0.2
react-qr-code: 2.0.3_react@17.0.2
@@ -88,27 +87,26 @@ dependencies:
use-breakpoint: 3.0.0_react-dom@17.0.2+react@17.0.2
devDependencies:
- '@rollup/plugin-typescript': 8.3.0_typescript@4.5.4
'@types/mapbox-gl': 2.6.0
'@types/react': 17.0.38
'@types/react-dom': 17.0.11
'@types/react-file-icon': 1.0.1
'@types/w3c-web-serial': 1.0.2
'@types/web-bluetooth': 0.0.12
- '@typescript-eslint/eslint-plugin': 5.8.1_3a47348159e115370aa4cba56aba33b6
- '@typescript-eslint/parser': 5.8.1_eslint@8.5.0+typescript@4.5.4
+ '@typescript-eslint/eslint-plugin': 5.8.1_13039593e64cd539d0b4c5c2da390958
+ '@typescript-eslint/parser': 5.8.1_eslint@8.6.0+typescript@4.5.4
'@verypossible/eslint-config': 1.6.1_typescript@4.5.4
'@vitejs/plugin-react': 1.1.3
autoprefixer: 10.4.1_postcss@8.4.5
babel-plugin-module-resolver: 4.1.0
- eslint: 8.5.0
- eslint-config-prettier: 8.3.0_eslint@8.5.0
- eslint-import-resolver-alias: 1.1.2_eslint-plugin-import@2.25.3
+ eslint: 8.6.0
+ eslint-config-prettier: 8.3.0_eslint@8.6.0
+ eslint-import-resolver-alias: 1.1.2_eslint-plugin-import@2.25.4
eslint-import-resolver-babel-module: 5.3.1_e51044130ac762fd207a8cd2109b5344
- eslint-import-resolver-typescript: 2.5.0_f385d671d5f1c72a868db745a891bc1f
- eslint-plugin-import: 2.25.3_eslint@8.5.0
- eslint-plugin-react: 7.28.0_eslint@8.5.0
- eslint-plugin-react-hooks: 4.3.0_eslint@8.5.0
+ eslint-import-resolver-typescript: 2.5.0_b5a36b8c1535387c8dd00eff7ec6b551
+ eslint-plugin-import: 2.25.4_eslint@8.6.0
+ eslint-plugin-react: 7.28.0_eslint@8.6.0
+ eslint-plugin-react-hooks: 4.3.0_eslint@8.6.0
gzipper: 6.2.1
postcss: 8.4.5
prettier: 2.5.1
@@ -1258,7 +1256,7 @@ packages:
babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.7
babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.7
babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.7
- core-js-compat: 3.20.1
+ core-js-compat: 3.20.2
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -1408,7 +1406,7 @@ packages:
dependencies:
ajv: 6.12.6
debug: 4.3.3
- espree: 9.2.0
+ espree: 9.3.0
globals: 13.12.0
ignore: 4.0.6
import-fresh: 3.3.0
@@ -1524,8 +1522,8 @@ packages:
engines: {node: '>=6.0.0'}
dev: false
- /@meshtastic/components/1.0.12:
- resolution: {integrity: sha512-7phiGyKSz2pRDYqscFDhL5lXdLlwY8LQU+hfgd13tEUe4Ch335rPYdyI7Fw+EZAVQTC456RCgMN7MyVfzsRunA==}
+ /@meshtastic/components/1.0.13:
+ resolution: {integrity: sha512-UdRwPVywIMaOYl0httBK51WagSuPhNPAuPG6DbvEq/TBBuJiGrTS/gYWsMb1UJhKzwb9XPKFMqAujowyBGN9cw==}
dependencies:
inter-ui: 3.19.3
react: 17.0.2
@@ -1626,30 +1624,6 @@ packages:
rollup: 2.62.0
dev: true
- /@rollup/plugin-typescript/8.3.0_typescript@4.5.4:
- resolution: {integrity: sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==}
- engines: {node: '>=8.0.0'}
- peerDependencies:
- rollup: ^2.14.0
- tslib: '*'
- typescript: '>=3.7.0'
- dependencies:
- '@rollup/pluginutils': 3.1.0
- resolve: 1.20.0
- typescript: 4.5.4
- dev: true
-
- /@rollup/pluginutils/3.1.0:
- resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
- engines: {node: '>= 8.0.0'}
- peerDependencies:
- rollup: ^1.20.0||^2.0.0
- dependencies:
- '@types/estree': 0.0.39
- estree-walker: 1.0.1
- picomatch: 2.3.0
- dev: true
-
/@rollup/pluginutils/3.1.0_rollup@2.62.0:
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
engines: {node: '>= 8.0.0'}
@@ -1658,7 +1632,7 @@ packages:
dependencies:
'@types/estree': 0.0.39
estree-walker: 1.0.1
- picomatch: 2.3.0
+ picomatch: 2.3.1
rollup: 2.62.0
dev: true
@@ -1667,7 +1641,7 @@ packages:
engines: {node: '>= 8.0.0'}
dependencies:
estree-walker: 2.0.2
- picomatch: 2.3.0
+ picomatch: 2.3.1
dev: true
/@surma/rollup-plugin-off-main-thread/2.2.3:
@@ -1712,8 +1686,8 @@ packages:
'@types/geojson': 7946.0.8
dev: true
- /@types/node/17.0.5:
- resolution: {integrity: sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==}
+ /@types/node/17.0.7:
+ resolution: {integrity: sha512-1QUk+WAUD4t8iR+Oj+UgI8oJa6yyxaB8a8pHaC8uqM6RrS1qbL7bf3Pwl5rHv0psm2CuDErgho6v5N+G+5fwtQ==}
dev: true
/@types/parse-json/4.0.0:
@@ -1760,7 +1734,7 @@ packages:
/@types/resolve/1.17.1:
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
dependencies:
- '@types/node': 17.0.5
+ '@types/node': 17.0.7
dev: true
/@types/scheduler/0.16.2:
@@ -1804,7 +1778,7 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/eslint-plugin/5.8.1_3a47348159e115370aa4cba56aba33b6:
+ /@typescript-eslint/eslint-plugin/5.8.1_13039593e64cd539d0b4c5c2da390958:
resolution: {integrity: sha512-wTZ5oEKrKj/8/366qTM366zqhIKAp6NCMweoRONtfuC07OAU9nVI2GZZdqQ1qD30WAAtcPdkH+npDwtRFdp4Rw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -1815,11 +1789,11 @@ packages:
typescript:
optional: true
dependencies:
- '@typescript-eslint/experimental-utils': 5.8.1_eslint@8.5.0+typescript@4.5.4
- '@typescript-eslint/parser': 5.8.1_eslint@8.5.0+typescript@4.5.4
+ '@typescript-eslint/experimental-utils': 5.8.1_eslint@8.6.0+typescript@4.5.4
+ '@typescript-eslint/parser': 5.8.1_eslint@8.6.0+typescript@4.5.4
'@typescript-eslint/scope-manager': 5.8.1
debug: 4.3.3
- eslint: 8.5.0
+ eslint: 8.6.0
functional-red-black-tree: 1.0.1
ignore: 5.2.0
regexpp: 3.2.0
@@ -1848,7 +1822,7 @@ packages:
- typescript
dev: true
- /@typescript-eslint/experimental-utils/5.8.1_eslint@8.5.0+typescript@4.5.4:
+ /@typescript-eslint/experimental-utils/5.8.1_eslint@8.6.0+typescript@4.5.4:
resolution: {integrity: sha512-fbodVnjIDU4JpeXWRDsG5IfIjYBxEvs8EBO8W1+YVdtrc2B9ppfof5sZhVEDOtgTfFHnYQJDI8+qdqLYO4ceww==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -1858,9 +1832,9 @@ packages:
'@typescript-eslint/scope-manager': 5.8.1
'@typescript-eslint/types': 5.8.1
'@typescript-eslint/typescript-estree': 5.8.1_typescript@4.5.4
- eslint: 8.5.0
+ eslint: 8.6.0
eslint-scope: 5.1.1
- eslint-utils: 3.0.0_eslint@8.5.0
+ eslint-utils: 3.0.0_eslint@8.6.0
transitivePeerDependencies:
- supports-color
- typescript
@@ -1886,7 +1860,7 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/parser/5.8.1_eslint@8.5.0+typescript@4.5.4:
+ /@typescript-eslint/parser/5.8.1_eslint@8.6.0+typescript@4.5.4:
resolution: {integrity: sha512-K1giKHAjHuyB421SoXMXFHHVI4NdNY603uKw92++D3qyxSeYvC10CBJ/GE5Thpo4WTUvu1mmJI2/FFkz38F2Gw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -1900,7 +1874,7 @@ packages:
'@typescript-eslint/types': 5.8.1
'@typescript-eslint/typescript-estree': 5.8.1_typescript@4.5.4
debug: 4.3.3
- eslint: 8.5.0
+ eslint: 8.6.0
typescript: 4.5.4
transitivePeerDependencies:
- supports-color
@@ -1999,8 +1973,8 @@ packages:
eslint: 7.32.0
eslint-config-prettier: 8.3.0_eslint@7.32.0
eslint-import-resolver-babel-module: 5.3.1_e51044130ac762fd207a8cd2109b5344
- eslint-import-resolver-typescript: 2.5.0_a820dc868cc8cd66d8297be6779b9035
- eslint-plugin-import: 2.25.3_eslint@7.32.0
+ eslint-import-resolver-typescript: 2.5.0_157002f9dff1b62f2b20650d7e8bf1eb
+ eslint-plugin-import: 2.25.4_eslint@7.32.0
eslint-plugin-react: 7.28.0_eslint@7.32.0
eslint-plugin-react-hooks: 4.3.0_eslint@7.32.0
prettier: 2.5.1
@@ -2119,7 +2093,7 @@ packages:
engines: {node: '>= 8'}
dependencies:
normalize-path: 3.0.0
- picomatch: 2.3.0
+ picomatch: 2.3.1
dev: true
/aproba/1.2.0:
@@ -2203,7 +2177,7 @@ packages:
postcss: ^8.1.0
dependencies:
browserslist: 4.19.1
- caniuse-lite: 1.0.30001294
+ caniuse-lite: 1.0.30001295
fraction.js: 4.1.2
normalize-range: 0.1.2
picocolors: 1.0.0
@@ -2253,7 +2227,7 @@ packages:
dependencies:
'@babel/core': 7.16.7
'@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.7
- core-js-compat: 3.20.1
+ core-js-compat: 3.20.2
transitivePeerDependencies:
- supports-color
dev: true
@@ -2312,8 +2286,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
- caniuse-lite: 1.0.30001294
- electron-to-chromium: 1.4.30
+ caniuse-lite: 1.0.30001295
+ electron-to-chromium: 1.4.31
escalade: 3.1.1
node-releases: 2.0.1
picocolors: 1.0.0
@@ -2352,8 +2326,8 @@ packages:
engines: {node: '>= 6'}
dev: true
- /caniuse-lite/1.0.30001294:
- resolution: {integrity: sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==}
+ /caniuse-lite/1.0.30001295:
+ resolution: {integrity: sha512-lSP16vcyC0FEy0R4ECc9duSPoKoZy+YkpGkue9G4D81OfPnliopaZrU10+qtPdT8PbGXad/PNx43TIQrOmJZSQ==}
dev: true
/chalk/2.4.2:
@@ -2460,8 +2434,8 @@ packages:
safe-buffer: 5.1.2
dev: true
- /core-js-compat/3.20.1:
- resolution: {integrity: sha512-AVhKZNpqMV3Jz8hU0YEXXE06qoxtQGsAqU0u1neUngz5IusDJRX/ZJ6t3i7mS7QxNyEONbCo14GprkBrxPlTZA==}
+ /core-js-compat/3.20.2:
+ resolution: {integrity: sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg==}
dependencies:
browserslist: 4.19.1
semver: 7.0.0
@@ -2672,8 +2646,8 @@ packages:
jake: 10.8.2
dev: true
- /electron-to-chromium/1.4.30:
- resolution: {integrity: sha512-609z9sIMxDHg+TcR/VB3MXwH+uwtrYyeAwWc/orhnr90ixs6WVGSrt85CDLGUdNnLqCA7liv426V20EecjvflQ==}
+ /electron-to-chromium/1.4.31:
+ resolution: {integrity: sha512-t3XVQtk+Frkv6aTD4RRk0OqosU+VLe1dQFW83MDer78ZD6a52frgXuYOIsLYTQiH2Lm+JB2OKYcn7zrX+YGAiQ==}
dev: true
/emoji-regex/8.0.0:
@@ -2931,22 +2905,22 @@ packages:
eslint: 7.32.0
dev: true
- /eslint-config-prettier/8.3.0_eslint@8.5.0:
+ /eslint-config-prettier/8.3.0_eslint@8.6.0:
resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
- eslint: 8.5.0
+ eslint: 8.6.0
dev: true
- /eslint-import-resolver-alias/1.1.2_eslint-plugin-import@2.25.3:
+ /eslint-import-resolver-alias/1.1.2_eslint-plugin-import@2.25.4:
resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==}
engines: {node: '>= 4'}
peerDependencies:
eslint-plugin-import: '>=1.4.0'
dependencies:
- eslint-plugin-import: 2.25.3_eslint@8.5.0
+ eslint-plugin-import: 2.25.4_eslint@8.6.0
dev: true
/eslint-import-resolver-babel-module/5.3.1_e51044130ac762fd207a8cd2109b5344:
@@ -2968,7 +2942,7 @@ packages:
resolve: 1.20.0
dev: true
- /eslint-import-resolver-typescript/2.5.0_a820dc868cc8cd66d8297be6779b9035:
+ /eslint-import-resolver-typescript/2.5.0_157002f9dff1b62f2b20650d7e8bf1eb:
resolution: {integrity: sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==}
engines: {node: '>=4'}
peerDependencies:
@@ -2977,7 +2951,7 @@ packages:
dependencies:
debug: 4.3.3
eslint: 7.32.0
- eslint-plugin-import: 2.25.3_eslint@7.32.0
+ eslint-plugin-import: 2.25.4_eslint@7.32.0
glob: 7.2.0
is-glob: 4.0.3
resolve: 1.20.0
@@ -2986,7 +2960,7 @@ packages:
- supports-color
dev: true
- /eslint-import-resolver-typescript/2.5.0_f385d671d5f1c72a868db745a891bc1f:
+ /eslint-import-resolver-typescript/2.5.0_b5a36b8c1535387c8dd00eff7ec6b551:
resolution: {integrity: sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==}
engines: {node: '>=4'}
peerDependencies:
@@ -2994,8 +2968,8 @@ packages:
eslint-plugin-import: '*'
dependencies:
debug: 4.3.3
- eslint: 8.5.0
- eslint-plugin-import: 2.25.3_eslint@8.5.0
+ eslint: 8.6.0
+ eslint-plugin-import: 2.25.4_eslint@8.6.0
glob: 7.2.0
is-glob: 4.0.3
resolve: 1.20.0
@@ -3004,17 +2978,16 @@ packages:
- supports-color
dev: true
- /eslint-module-utils/2.7.1:
- resolution: {integrity: sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==}
+ /eslint-module-utils/2.7.2:
+ resolution: {integrity: sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==}
engines: {node: '>=4'}
dependencies:
debug: 3.2.7
find-up: 2.1.0
- pkg-dir: 2.0.0
dev: true
- /eslint-plugin-import/2.25.3_eslint@7.32.0:
- resolution: {integrity: sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==}
+ /eslint-plugin-import/2.25.4_eslint@7.32.0:
+ resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
@@ -3025,7 +2998,7 @@ packages:
doctrine: 2.1.0
eslint: 7.32.0
eslint-import-resolver-node: 0.3.6
- eslint-module-utils: 2.7.1
+ eslint-module-utils: 2.7.2
has: 1.0.3
is-core-module: 2.8.0
is-glob: 4.0.3
@@ -3035,8 +3008,8 @@ packages:
tsconfig-paths: 3.12.0
dev: true
- /eslint-plugin-import/2.25.3_eslint@8.5.0:
- resolution: {integrity: sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==}
+ /eslint-plugin-import/2.25.4_eslint@8.6.0:
+ resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
@@ -3045,9 +3018,9 @@ packages:
array.prototype.flat: 1.2.5
debug: 2.6.9
doctrine: 2.1.0
- eslint: 8.5.0
+ eslint: 8.6.0
eslint-import-resolver-node: 0.3.6
- eslint-module-utils: 2.7.1
+ eslint-module-utils: 2.7.2
has: 1.0.3
is-core-module: 2.8.0
is-glob: 4.0.3
@@ -3066,13 +3039,13 @@ packages:
eslint: 7.32.0
dev: true
- /eslint-plugin-react-hooks/4.3.0_eslint@8.5.0:
+ /eslint-plugin-react-hooks/4.3.0_eslint@8.6.0:
resolution: {integrity: sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
dependencies:
- eslint: 8.5.0
+ eslint: 8.6.0
dev: true
/eslint-plugin-react/7.28.0_eslint@7.32.0:
@@ -3098,7 +3071,7 @@ packages:
string.prototype.matchall: 4.0.6
dev: true
- /eslint-plugin-react/7.28.0_eslint@8.5.0:
+ /eslint-plugin-react/7.28.0_eslint@8.6.0:
resolution: {integrity: sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==}
engines: {node: '>=4'}
peerDependencies:
@@ -3107,7 +3080,7 @@ packages:
array-includes: 3.1.4
array.prototype.flatmap: 1.2.5
doctrine: 2.1.0
- eslint: 8.5.0
+ eslint: 8.6.0
estraverse: 5.3.0
jsx-ast-utils: 3.2.1
minimatch: 3.0.4
@@ -3154,13 +3127,13 @@ packages:
eslint-visitor-keys: 2.1.0
dev: true
- /eslint-utils/3.0.0_eslint@8.5.0:
+ /eslint-utils/3.0.0_eslint@8.6.0:
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
peerDependencies:
eslint: '>=5'
dependencies:
- eslint: 8.5.0
+ eslint: 8.6.0
eslint-visitor-keys: 2.1.0
dev: true
@@ -3228,8 +3201,8 @@ packages:
- supports-color
dev: true
- /eslint/8.5.0:
- resolution: {integrity: sha512-tVGSkgNbOfiHyVte8bCM8OmX+xG9PzVG/B4UCF60zx7j61WIVY/AqJECDgpLD4DbbESD0e174gOg3ZlrX15GDg==}
+ /eslint/8.6.0:
+ resolution: {integrity: sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
@@ -3243,9 +3216,9 @@ packages:
enquirer: 2.3.6
escape-string-regexp: 4.0.0
eslint-scope: 7.1.0
- eslint-utils: 3.0.0_eslint@8.5.0
+ eslint-utils: 3.0.0_eslint@8.6.0
eslint-visitor-keys: 3.1.0
- espree: 9.2.0
+ espree: 9.3.0
esquery: 1.4.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
@@ -3284,8 +3257,8 @@ packages:
eslint-visitor-keys: 1.3.0
dev: true
- /espree/9.2.0:
- resolution: {integrity: sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==}
+ /espree/9.3.0:
+ resolution: {integrity: sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.7.0
@@ -3689,13 +3662,6 @@ packages:
resolution: {integrity: sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==}
dev: false
- /import-cwd/3.0.0:
- resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==}
- engines: {node: '>=8'}
- dependencies:
- import-from: 3.0.0
- dev: true
-
/import-fresh/3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -3704,13 +3670,6 @@ packages:
resolve-from: 4.0.0
dev: true
- /import-from/3.0.0:
- resolution: {integrity: sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==}
- engines: {node: '>=8'}
- dependencies:
- resolve-from: 5.0.0
- dev: true
-
/imurmurhash/0.1.4:
resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=}
engines: {node: '>=0.8.19'}
@@ -3953,7 +3912,7 @@ packages:
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
engines: {node: '>= 10.13.0'}
dependencies:
- '@types/node': 17.0.5
+ '@types/node': 17.0.7
merge-stream: 2.0.0
supports-color: 7.2.0
dev: true
@@ -4179,7 +4138,7 @@ packages:
engines: {node: '>=8.6'}
dependencies:
braces: 3.0.2
- picomatch: 2.3.0
+ picomatch: 2.3.1
dev: true
/mimic-response/2.1.0:
@@ -4497,18 +4456,11 @@ packages:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: true
- /picomatch/2.3.0:
- resolution: {integrity: sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==}
+ /picomatch/2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
dev: true
- /pkg-dir/2.0.0:
- resolution: {integrity: sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=}
- engines: {node: '>=4'}
- dependencies:
- find-up: 2.1.0
- dev: true
-
/pkg-up/3.1.0:
resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
engines: {node: '>=8'}
@@ -4524,8 +4476,8 @@ packages:
postcss: 8.4.5
dev: true
- /postcss-load-config/3.1.0:
- resolution: {integrity: sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==}
+ /postcss-load-config/3.1.1:
+ resolution: {integrity: sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==}
engines: {node: '>= 10'}
peerDependencies:
ts-node: '>=9.0.0'
@@ -4533,7 +4485,6 @@ packages:
ts-node:
optional: true
dependencies:
- import-cwd: 3.0.0
lilconfig: 2.0.4
yaml: 1.10.2
dev: true
@@ -4731,8 +4682,8 @@ packages:
react: 17.0.2
dev: false
- /react-i18next/11.15.2_80acb397921aff391f276c2217c76c9e:
- resolution: {integrity: sha512-28WlZ6tr57RQoIM1x4/gTzvzh3Vvr+YeZwJHTOqV/sLXMFbR+xzjgSMdLnOCDxmlQ0irGN2uM+HT+mYK+3bg6g==}
+ /react-i18next/11.15.3_80acb397921aff391f276c2217c76c9e:
+ resolution: {integrity: sha512-RSUEM4So3Tu2JHV0JsZ5Yje+4nz66YViMfPZoywxOy0xyn3L7tE2CHvJ7Y9LUsrTU7vGmZ5bwb8PpjnkatdIxg==}
peerDependencies:
i18next: '>= 19.0.0'
react: '>= 16.8.0'
@@ -4883,7 +4834,7 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
dependencies:
- picomatch: 2.3.0
+ picomatch: 2.3.1
dev: true
/redux-thunk/2.4.1_redux@4.1.2:
@@ -4969,11 +4920,6 @@ packages:
engines: {node: '>=4'}
dev: true
- /resolve-from/5.0.0:
- resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
- engines: {node: '>=8'}
- dev: true
-
/resolve-protobuf-schema/2.1.0:
resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==}
dependencies:
@@ -5382,7 +5328,7 @@ packages:
object-hash: 2.2.0
postcss: 8.4.5
postcss-js: 3.0.3
- postcss-load-config: 3.1.0
+ postcss-load-config: 3.1.1
postcss-nested: 5.0.6_postcss@8.4.5
postcss-selector-parser: 6.0.8
postcss-value-parser: 4.2.0
diff --git a/src/App.tsx b/src/App.tsx
index 10077f9d..357e1879 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -4,7 +4,6 @@ import { ErrorBoundary } from 'react-error-boundary';
import { FiBell } from 'react-icons/fi';
import { DeviceStatus } from '@app/components/menu/buttons/DeviceStatus';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Connection } from '@components/Connection';
import { MobileNavToggle } from '@components/menu/buttons/MobileNavToggle';
import { Notifications } from '@components/menu/buttons/Notifications';
@@ -14,6 +13,8 @@ import { MobileNav } from '@components/menu/MobileNav';
import { Navigation } from '@components/menu/Navigation';
import { useRoute } from '@core/router';
import { requestNotificationPermission } from '@core/utils/notifications';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Messages } from '@pages/Messages';
import { Nodes } from '@pages/Nodes/Index';
import { NotFound } from '@pages/NotFound';
@@ -21,6 +22,7 @@ import { Plugins } from '@pages/Plugins/Index';
import { Settings } from '@pages/settings/Index';
import { ErrorFallback } from './components/ErrorFallback';
+import { MapboxProvider } from './components/MapBox/MapboxProvider';
import { addNotification, removeNotification } from './core/slices/appSlice';
export const App = (): JSX.Element => {
@@ -86,7 +88,11 @@ export const App = (): JSX.Element => {
{route.name === 'messages' && }
- {route.name === 'nodes' && }
+ {route.name === 'nodes' && (
+
+
+
+ )}
{route.name === 'plugins' && }
{route.name === 'settings' && }
{route.name === false && }
diff --git a/src/components/Connection.tsx b/src/components/Connection.tsx
index 2ec42a11..d8033a42 100644
--- a/src/components/Connection.tsx
+++ b/src/components/Connection.tsx
@@ -1,6 +1,5 @@
import React from 'react';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { BLE } from '@components/connection/BLE';
import { HTTP } from '@components/connection/HTTP';
import { Serial } from '@components/connection/Serial';
@@ -12,6 +11,8 @@ import {
setConnectionParams,
setConnType,
} from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Button, Card, Select } from '@meshtastic/components';
import { Types } from '@meshtastic/meshtasticjs';
diff --git a/src/components/Map/index.tsx b/src/components/Map/index.tsx
index 0f823d8e..01069d51 100644
--- a/src/components/Map/index.tsx
+++ b/src/components/Map/index.tsx
@@ -1,22 +1,17 @@
import React from 'react';
-import mapboxgl from 'mapbox-gl';
-import { renderToString } from 'react-dom/server';
import { FaDirections, FaGlobeAfrica, FaMountain } from 'react-icons/fa';
import { MdFullscreen, MdRadar, MdWbShade } from 'react-icons/md';
-import { useMapbox } from '@app/hooks/mapbox';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import {
- setBearing,
setExaggeration,
setHillShade,
- setLatLng,
setMapStyle,
- setPitch,
- setZoom,
} from '@core/slices/mapSlice';
-import { Card, IconButton } from '@meshtastic/components';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
+import { useMapbox } from '@hooks/useMapbox';
+import { IconButton } from '@meshtastic/components';
import type { MapStyle } from './styles';
import { MapStyles } from './styles';
@@ -24,63 +19,10 @@ import { MapStyles } from './styles';
export const Map = (): JSX.Element => {
const dispatch = useAppDispatch();
const darkMode = useAppSelector((state) => state.app.darkMode);
- const nodes = useAppSelector((state) => state.meshtastic.nodes);
- const mapState = useAppSelector((state) => state.map);
- const [markers, setMarkers] = React.useState<
- { id: number; marker: mapboxgl.Marker }[]
- >([]);
- const mapRef = React.useRef(null);
-
- const map = useMapbox(mapRef, mapState.accessToken, {
- center: mapState.latLng,
- zoom: mapState.zoom,
- bearing: mapState.bearing,
- pitch: mapState.pitch,
- style: mapState.style.url,
- });
-
- const updateNodes = React.useCallback(() => {
- nodes.map((node) => {
- if (map?.loaded() && node.currentPosition) {
- const existingMarker = markers.find(
- (marker) => marker.id === node.number,
- )?.marker;
- const marker =
- existingMarker ??
- new mapboxgl.Marker({}).setLngLat([0, 0]).addTo(map);
- marker
- .setLngLat([
- node.currentPosition.longitudeI / 1e7,
- node.currentPosition.latitudeI / 1e7,
- ])
- .setPopup(
- new mapboxgl.Popup().setHTML(
- renderToString(
-
-
- {node.user?.longName}
-
-
- ,
- ),
- ),
- );
+ const mapState = useAppSelector((state) => state.map);
- if (!existingMarker) {
- setMarkers((markers) => [
- ...markers,
- {
- id: node.number,
- marker,
- },
- ]);
- }
- }
- });
- }, [markers, map, nodes]);
+ const { ref } = useMapbox();
const ChangeMapStyle = React.useCallback(
(styleName: string, style: MapStyle) => {
@@ -97,95 +39,6 @@ export const Map = (): JSX.Element => {
[dispatch, darkMode, mapState.style.title],
);
- React.useEffect(() => {
- map?.on('load', () => {
- updateNodes();
- });
- map?.on('styledata', () => {
- if (!map.getSource('mapbox-dem')) {
- map.addSource('mapbox-dem', {
- type: 'raster-dem',
- url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
- tileSize: 512,
- maxzoom: 14,
- });
- }
- map.setTerrain({
- source: 'mapbox-dem',
- exaggeration: mapState.exaggeration ? 1.5 : 0,
- });
- });
- map?.on('dragend', (e) => {
- dispatch(setLatLng(e.target.getCenter()));
- });
- map?.on('zoomend', (e) => {
- dispatch(setZoom(e.target.getZoom()));
- });
- map?.on('rotate', (e) => {
- dispatch(setBearing(e.target.getBearing()));
- });
- map?.on('pitch', (e) => {
- dispatch(setPitch(e.target.getPitch()));
- });
- }, [dispatch, map, updateNodes, mapState.exaggeration]);
-
- React.useEffect(() => {
- const center = map?.getCenter();
- if (center !== mapState.latLng) {
- map?.setCenter(mapState.latLng);
- }
- }, [map, mapState.latLng]);
-
- /**
- * Hill Shading
- */
- React.useEffect(() => {
- if (map?.loaded()) {
- if (mapState.hillShade) {
- map.addLayer(
- {
- id: 'hillshading',
- source: 'mapbox-dem',
- type: 'hillshade',
- // insert below waterway-river-canal-shadow;
- // where hillshading sits in the Mapbox Outdoors style
- },
- 'waterway-river-canal-shadow',
- );
- } else {
- map.removeLayer('hillshading');
- }
- }
- }, [map, mapState.hillShade]);
-
- /**
- * Exaggeration
- */
- React.useEffect(() => {
- if (map?.loaded()) {
- map.setTerrain({
- source: 'mapbox-dem',
- exaggeration: mapState.exaggeration ? 1.5 : 0,
- });
- }
- }, [map, mapState.exaggeration]);
-
- /**
- * Map Style
- */
- React.useEffect(() => {
- if (map?.loaded()) {
- map.setStyle(mapState.style.url);
- }
- }, [map, mapState.style]);
-
- /**
- * Markers
- */
- React.useEffect(() => {
- updateNodes();
- }, [nodes, updateNodes]);
-
return (
@@ -232,7 +85,7 @@ export const Map = (): JSX.Element => {
} />
);
diff --git a/src/components/MapBox/MapboxProvider.tsx b/src/components/MapBox/MapboxProvider.tsx
new file mode 100644
index 00000000..b895a603
--- /dev/null
+++ b/src/components/MapBox/MapboxProvider.tsx
@@ -0,0 +1,224 @@
+import React from 'react';
+
+import mapbox from 'mapbox-gl';
+import { renderToString } from 'react-dom/server';
+import { FiAirplay } from 'react-icons/fi';
+
+import {
+ setBearing,
+ setLatLng,
+ setMapStyle,
+ setPitch,
+ setZoom,
+} from '@core/slices/mapSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
+import { useCreateMapbox } from '@hooks/useCreateMapbox';
+import { Card } from '@meshtastic/components';
+
+import { MapStyles } from '../Map/styles';
+import { MapboxContext } from './mapboxContext';
+
+export type MapboxProviderProps = {
+ children: React.ReactNode;
+};
+
+export const MapboxProvider = ({
+ children,
+}: MapboxProviderProps): JSX.Element => {
+ const darkMode = useAppSelector((state) => state.app.darkMode);
+ const mapState = useAppSelector((state) => state.map);
+ const nodes = useAppSelector((state) => state.meshtastic.nodes);
+ const dispatch = useAppDispatch();
+ const ref = React.useRef(null);
+
+ const [markers, setMarkers] = React.useState<
+ { id: number; marker: mapbox.Marker }[]
+ >([]);
+ const [markerElements, setMarkerElements] = React.useState<
+ { id: number; element: JSX.Element; ref: React.RefObject }[]
+ >([]);
+
+ const map = useCreateMapbox({
+ ref,
+ accessToken:
+ 'pk.eyJ1Ijoic2FjaGF3IiwiYSI6ImNrNW9meXozZjBsdW0zbHBjM2FnNnV6cmsifQ.3E4n8eFGD9ZOFo-XDVeZnQ',
+ options: {
+ center: mapState.latLng,
+ zoom: mapState.zoom,
+ bearing: mapState.bearing,
+ pitch: mapState.pitch,
+ style: mapState.style.url,
+ },
+ });
+
+ const updateNodes = React.useCallback(() => {
+ nodes.map((node) => {
+ if (map?.loaded() && node.currentPosition) {
+ const existingMarker = markers.find(
+ (marker) => marker.id === node.number,
+ )?.marker;
+
+ const tmpRef = React.createRef();
+
+ const markerElement = markerElements.find(
+ (element) => element.id === node.number,
+ ) ?? {
+ element: (
+
+ Test
+
+
+ ),
+ id: node.number,
+ ref: tmpRef,
+ };
+
+ console.log(markerElement);
+
+ const marker =
+ existingMarker ??
+ new mapbox.Marker(markerElement.ref.current ?? undefined, {})
+ .setLngLat([0, 0])
+ .addTo(map);
+
+ marker
+ .setLngLat([
+ node.currentPosition.longitudeI / 1e7,
+ node.currentPosition.latitudeI / 1e7,
+ ])
+ .setPopup(
+ new mapbox.Popup().setHTML(
+ renderToString(
+
+
+
+ {node.user?.longName}
+
+
+
+ ,
+ ),
+ ),
+ );
+
+ if (!existingMarker) {
+ setMarkers((markers) => [
+ ...markers,
+ {
+ id: node.number,
+ marker,
+ },
+ ]);
+ setMarkerElements((markerElements) => [
+ ...markerElements,
+ markerElement,
+ ]);
+ }
+ }
+ });
+ }, [markers, markerElements, map, nodes]);
+
+ React.useEffect(() => {
+ map?.on('load', () => {
+ updateNodes();
+ });
+ map?.on('styledata', () => {
+ if (!map.getSource('mapbox-dem')) {
+ map.addSource('mapbox-dem', {
+ type: 'raster-dem',
+ url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
+ tileSize: 512,
+ maxzoom: 14,
+ });
+ }
+ map.setTerrain({
+ source: 'mapbox-dem',
+ exaggeration: mapState.exaggeration ? 1.5 : 0,
+ });
+ });
+ map?.on('dragend', (e) => {
+ dispatch(setLatLng(e.target.getCenter()));
+ });
+ map?.on('zoomend', (e) => {
+ dispatch(setZoom(e.target.getZoom()));
+ });
+ map?.on('rotate', (e) => {
+ dispatch(setBearing(e.target.getBearing()));
+ });
+ map?.on('pitch', (e) => {
+ dispatch(setPitch(e.target.getPitch()));
+ });
+ }, [dispatch, map, updateNodes, mapState.exaggeration]);
+
+ React.useEffect(() => {
+ const center = map?.getCenter();
+ if (center !== mapState.latLng) {
+ map?.setCenter(mapState.latLng);
+ }
+ }, [map, mapState.latLng]);
+
+ React.useEffect(() => {
+ if (['Light', 'Dark'].includes(mapState.style.title)) {
+ dispatch(setMapStyle(darkMode ? MapStyles.Dark : MapStyles.Light));
+ }
+ }, [dispatch, darkMode, mapState.style.title]);
+
+ /**
+ * Hill Shading
+ */
+ React.useEffect(() => {
+ if (map?.loaded()) {
+ if (mapState.hillShade) {
+ map.addLayer(
+ {
+ id: 'hillshading',
+ source: 'mapbox-dem',
+ type: 'hillshade',
+ // insert below waterway-river-canal-shadow;
+ // where hillshading sits in the Mapbox Outdoors style
+ },
+ 'waterway-river-canal-shadow',
+ );
+ } else {
+ map.removeLayer('hillshading');
+ }
+ }
+ }, [map, mapState.hillShade]);
+
+ /**
+ * Exaggeration
+ */
+ React.useEffect(() => {
+ if (map?.loaded()) {
+ map.setTerrain({
+ source: 'mapbox-dem',
+ exaggeration: mapState.exaggeration ? 1.5 : 0,
+ });
+ }
+ }, [map, mapState.exaggeration]);
+
+ /**
+ * Map Style
+ */
+ React.useEffect(() => {
+ if (map?.loaded()) {
+ map.setStyle(mapState.style.url);
+ }
+ }, [map, mapState.style]);
+
+ /**
+ * Markers
+ */
+ React.useEffect(() => {
+ updateNodes();
+ }, [nodes, updateNodes]);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/components/MapBox/mapboxContext.ts b/src/components/MapBox/mapboxContext.ts
new file mode 100644
index 00000000..14b42751
--- /dev/null
+++ b/src/components/MapBox/mapboxContext.ts
@@ -0,0 +1,12 @@
+import React from 'react';
+
+import type mapbox from 'mapbox-gl';
+
+export interface MapboxContextValue {
+ ref: React.Ref;
+ map?: mapbox.Map;
+}
+
+export const MapboxContext = React.createContext(
+ {} as MapboxContextValue
+);
diff --git a/src/components/chat/MessageBar.tsx b/src/components/chat/MessageBar.tsx
index 8684eed0..1c06832e 100644
--- a/src/components/chat/MessageBar.tsx
+++ b/src/components/chat/MessageBar.tsx
@@ -3,9 +3,10 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { FiSend } from 'react-icons/fi';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { connection } from '@core/connection';
import { ackMessage } from '@core/slices/meshtasticSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { IconButton, Input, Select } from '@meshtastic/components';
export interface MessageBarProps {
diff --git a/src/components/connection/BLE.tsx b/src/components/connection/BLE.tsx
index 13a8a0ec..fd995aa4 100644
--- a/src/components/connection/BLE.tsx
+++ b/src/components/connection/BLE.tsx
@@ -10,7 +10,7 @@ import { Button, IconButton } from '@meshtastic/components';
export const BLE = (): JSX.Element => {
const [bleDevices, setBleDevices] = React.useState([]);
- const { register, handleSubmit, control } = useForm<{
+ const { handleSubmit } = useForm<{
device?: BluetoothDevice;
}>();
@@ -23,7 +23,7 @@ export const BLE = (): JSX.Element => {
void updateBleDeviceList();
}, [updateBleDeviceList]);
- const onSubmit = handleSubmit(async (data) => {
+ const onSubmit = handleSubmit(async () => {
await setConnection(connType.BLE);
});
diff --git a/src/components/connection/HTTP.tsx b/src/components/connection/HTTP.tsx
index 92478a41..45d024bc 100644
--- a/src/components/connection/HTTP.tsx
+++ b/src/components/connection/HTTP.tsx
@@ -2,9 +2,9 @@ import type React from 'react';
import { useForm, useWatch } from 'react-hook-form';
-import { useAppDispatch } from '@app/hooks/redux.js';
import { connectionUrl, setConnection } from '@core/connection';
import { connType, setConnectionParams } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
import { Button, Checkbox, Input, Select } from '@meshtastic/components';
export const HTTP = (): JSX.Element => {
diff --git a/src/components/connection/Serial.tsx b/src/components/connection/Serial.tsx
index f5578df4..5629a279 100644
--- a/src/components/connection/Serial.tsx
+++ b/src/components/connection/Serial.tsx
@@ -3,16 +3,16 @@ import React from 'react';
import { useForm } from 'react-hook-form';
import { FiCheck } from 'react-icons/fi';
-import { useAppDispatch } from '@app/hooks/redux';
import { serial, setConnection } from '@core/connection';
import { connType, setConnectionParams } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
import { Button, IconButton } from '@meshtastic/components';
export const Serial = (): JSX.Element => {
const [serialDevices, setSerialDevices] = React.useState([]);
const dispatch = useAppDispatch();
- const { register, handleSubmit, control } = useForm<{
+ const { handleSubmit } = useForm<{
device?: SerialPort;
}>();
@@ -25,7 +25,7 @@ export const Serial = (): JSX.Element => {
void updateSerialDeviceList();
}, [updateSerialDeviceList]);
- const onSubmit = handleSubmit(async (data) => {
+ const onSubmit = handleSubmit(async () => {
await setConnection(connType.SERIAL);
});
diff --git a/src/components/generic/Modal.tsx b/src/components/generic/Modal.tsx
index f1df40d8..ca0d13fd 100644
--- a/src/components/generic/Modal.tsx
+++ b/src/components/generic/Modal.tsx
@@ -1,7 +1,7 @@
import type React from 'react';
-import { useAppSelector } from '@app/hooks/redux';
import { Dialog } from '@headlessui/react';
+import { useAppSelector } from '@hooks/useAppSelector';
type DefaultDivProps = JSX.IntrinsicElements['div'];
diff --git a/src/components/generic/form/BitwiseSelect.tsx b/src/components/generic/form/BitwiseSelect.tsx
index 2b778881..9d4c3fdc 100644
--- a/src/components/generic/form/BitwiseSelect.tsx
+++ b/src/components/generic/form/BitwiseSelect.tsx
@@ -5,7 +5,7 @@ import type { Theme } from 'react-select';
import ReactSelect from 'react-select';
import { bitwiseDecode, bitwiseEncode } from '@app/core/utils/bitwise';
-import { useAppSelector } from '@app/hooks/redux.js';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Label } from './Label';
diff --git a/src/components/menu/MobileNav.tsx b/src/components/menu/MobileNav.tsx
index 27516320..73fa7565 100644
--- a/src/components/menu/MobileNav.tsx
+++ b/src/components/menu/MobileNav.tsx
@@ -1,8 +1,9 @@
import type React from 'react';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { Drawer } from '@components/generic/Drawer';
import { closeMobileNav } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Logo } from './Logo';
import { Navigation } from './Navigation';
diff --git a/src/components/menu/buttons/DeviceStatus.tsx b/src/components/menu/buttons/DeviceStatus.tsx
index 3f4339c9..95c65e88 100644
--- a/src/components/menu/buttons/DeviceStatus.tsx
+++ b/src/components/menu/buttons/DeviceStatus.tsx
@@ -2,8 +2,9 @@ import type React from 'react';
import { FiBluetooth, FiCpu, FiWifi } from 'react-icons/fi';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { connType, openConnectionModal } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Button } from '@meshtastic/components';
import { Types } from '@meshtastic/meshtasticjs';
diff --git a/src/components/menu/buttons/MobileNavToggle.tsx b/src/components/menu/buttons/MobileNavToggle.tsx
index 9be69191..38134642 100644
--- a/src/components/menu/buttons/MobileNavToggle.tsx
+++ b/src/components/menu/buttons/MobileNavToggle.tsx
@@ -3,10 +3,9 @@ import type React from 'react';
import { FiMenu } from 'react-icons/fi';
import { openMobileNav } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
import { IconButton } from '@meshtastic/components';
-import { useAppDispatch } from '../../../hooks/redux';
-
export const MobileNavToggle = (): JSX.Element => {
const dispatch = useAppDispatch();
diff --git a/src/components/menu/buttons/Notifications.tsx b/src/components/menu/buttons/Notifications.tsx
index 95e357c9..9f9c8b5c 100644
--- a/src/components/menu/buttons/Notifications.tsx
+++ b/src/components/menu/buttons/Notifications.tsx
@@ -2,9 +2,9 @@ import React from 'react';
import { FiBell, FiX } from 'react-icons/fi';
-import { useAppSelector } from '@app/hooks/redux';
import { shift, useFloating } from '@floating-ui/react-dom';
import { Popover } from '@headlessui/react';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Button, IconButton } from '@meshtastic/components';
export const Notifications = (): JSX.Element => {
diff --git a/src/components/menu/buttons/ThemeToggle.tsx b/src/components/menu/buttons/ThemeToggle.tsx
index 3c6c0da8..7cfb731f 100644
--- a/src/components/menu/buttons/ThemeToggle.tsx
+++ b/src/components/menu/buttons/ThemeToggle.tsx
@@ -2,8 +2,9 @@ import type React from 'react';
import { FiMoon, FiSun } from 'react-icons/fi';
-import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
import { setDarkModeEnabled } from '@core/slices/appSlice';
+import { useAppDispatch } from '@hooks/useAppDispatch';
+import { useAppSelector } from '@hooks/useAppSelector';
import { IconButton } from '@meshtastic/components';
export const ThemeToggle = (): JSX.Element => {
diff --git a/src/components/templates/PageLayout.tsx b/src/components/templates/PageLayout.tsx
index ee8afe67..bf85b870 100644
--- a/src/components/templates/PageLayout.tsx
+++ b/src/components/templates/PageLayout.tsx
@@ -2,11 +2,11 @@ import React from 'react';
import { FiXCircle } from 'react-icons/fi';
-import { useBreakpoint } from '@app/hooks/breakpoint';
import { Drawer } from '@components/generic/Drawer';
import type { SidebarItemProps } from '@components/generic/SidebarItem';
import { SidebarItem } from '@components/generic/SidebarItem';
import { Tab } from '@headlessui/react';
+import { useBreakpoint } from '@hooks/useBreakpoint';
import { IconButton } from '@meshtastic/components';
export interface PageLayoutProps {
diff --git a/src/core/connection.ts b/src/core/connection.ts
index 646ed8ce..790e6682 100644
--- a/src/core/connection.ts
+++ b/src/core/connection.ts
@@ -23,7 +23,7 @@ import {
Types,
} from '@meshtastic/meshtasticjs';
-import { showNotification } from './utils/notifications.js';
+import { showNotification } from './utils/notifications';
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
diff --git a/src/hooks/mapbox.ts b/src/hooks/mapbox.ts
deleted file mode 100644
index 175c851e..00000000
--- a/src/hooks/mapbox.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import 'mapbox-gl/dist/mapbox-gl.css';
-
-import React from 'react';
-
-import mapboxgl from 'mapbox-gl';
-
-type AccessToken = string;
-
-export function useMapbox(
- ref: React.RefObject,
- accessToken: AccessToken,
- options?: Partial,
-): mapboxgl.Map | undefined {
- const [mapInstance, setMapInstance] = React.useState();
- React.useEffect(() => {
- const container = ref.current;
- if (mapInstance || !container) {
- return;
- }
-
- mapboxgl.accessToken = accessToken;
- const mergedOptions = { container, ...options };
- const map = new mapboxgl.Map(mergedOptions);
- setMapInstance(map);
- }, [ref, accessToken, options, mapInstance]);
-
- return mapInstance;
-}
diff --git a/src/hooks/redux.ts b/src/hooks/redux.ts
deleted file mode 100644
index 404c34cf..00000000
--- a/src/hooks/redux.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
-/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
-import type { TypedUseSelectorHook } from 'react-redux';
-import { useDispatch, useSelector } from 'react-redux';
-
-import type { AppDispatch, RootState } from '@core/store';
-
-export const useAppDispatch = () => useDispatch();
-export const useAppSelector: TypedUseSelectorHook = useSelector;
diff --git a/src/hooks/useAppDispatch.ts b/src/hooks/useAppDispatch.ts
new file mode 100644
index 00000000..bc57197a
--- /dev/null
+++ b/src/hooks/useAppDispatch.ts
@@ -0,0 +1,7 @@
+/* eslint-disable @typescript-eslint/explicit-function-return-type */
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
+import { useDispatch } from 'react-redux';
+
+import type { AppDispatch } from '@core/store';
+
+export const useAppDispatch = () => useDispatch();
diff --git a/src/hooks/useAppSelector.ts b/src/hooks/useAppSelector.ts
new file mode 100644
index 00000000..c752e3d6
--- /dev/null
+++ b/src/hooks/useAppSelector.ts
@@ -0,0 +1,6 @@
+import type { TypedUseSelectorHook } from 'react-redux';
+import { useSelector } from 'react-redux';
+
+import type { RootState } from '@core/store';
+
+export const useAppSelector: TypedUseSelectorHook = useSelector;
diff --git a/src/hooks/breakpoint.ts b/src/hooks/useBreakpoint.ts
similarity index 100%
rename from src/hooks/breakpoint.ts
rename to src/hooks/useBreakpoint.ts
diff --git a/src/hooks/useCreateMapbox.ts b/src/hooks/useCreateMapbox.ts
new file mode 100644
index 00000000..80cf5f0b
--- /dev/null
+++ b/src/hooks/useCreateMapbox.ts
@@ -0,0 +1,36 @@
+import 'mapbox-gl/dist/mapbox-gl.css';
+
+import React from 'react';
+
+import mapboxgl from 'mapbox-gl';
+
+type AccessToken = string;
+
+export interface useMapboxProps {
+ ref: React.RefObject;
+ accessToken: AccessToken;
+ options?: Partial;
+}
+
+export function useCreateMapbox({
+ ref,
+ accessToken,
+ options,
+}: useMapboxProps): mapboxgl.Map | undefined {
+ const [mapInstance, setMapInstance] = React.useState();
+ React.useEffect(() => {
+ const container = ref.current as HTMLDivElement;
+ if (mapInstance || !container) {
+ return;
+ }
+ mapboxgl.accessToken = accessToken;
+ const map = new mapboxgl.Map({
+ container,
+ antialias: true,
+ ...options,
+ });
+ setMapInstance(map);
+ }, []);
+
+ return mapInstance;
+}
diff --git a/src/hooks/useMapbox.ts b/src/hooks/useMapbox.ts
new file mode 100644
index 00000000..46c0c3d3
--- /dev/null
+++ b/src/hooks/useMapbox.ts
@@ -0,0 +1,8 @@
+import React from 'react';
+
+import type { MapboxContextValue } from '@components/MapBox/mapboxContext';
+import { MapboxContext } from '@components/MapBox/mapboxContext';
+
+export const useMapbox = (): MapboxContextValue => {
+ return React.useContext(MapboxContext);
+};
diff --git a/src/index.css b/src/index.css
index 9253a59f..9b3ee91e 100644
--- a/src/index.css
+++ b/src/index.css
@@ -21,3 +21,15 @@
::-webkit-scrollbar-thumb:hover {
background-color: #a8bbbf;
}
+
+.mapboxgl-popup-close-button,
+.mapboxgl-popup-tip {
+ display: none;
+}
+
+.mapboxgl-popup-content {
+ background: transparent !important;
+ border-radius: 0 !important;
+ box-sizing: unset !important;
+ padding: 0 !important;
+}
diff --git a/src/pages/Messages.tsx b/src/pages/Messages.tsx
index b9af2929..b9a93081 100644
--- a/src/pages/Messages.tsx
+++ b/src/pages/Messages.tsx
@@ -4,11 +4,10 @@ import { FiHash } from 'react-icons/fi';
import { Message } from '@components/chat/Message';
import { MessageBar } from '@components/chat/MessageBar';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Select } from '@meshtastic/components';
import { Protobuf } from '@meshtastic/meshtasticjs';
-import { useAppSelector } from '../hooks/redux';
-
export const Messages = (): JSX.Element => {
const nodes = useAppSelector((state) => state.meshtastic.nodes);
const channels = useAppSelector((state) => state.meshtastic.radio.channels);
diff --git a/src/pages/Nodes/Index.tsx b/src/pages/Nodes/Index.tsx
index ed925ab3..c343ccb8 100644
--- a/src/pages/Nodes/Index.tsx
+++ b/src/pages/Nodes/Index.tsx
@@ -2,10 +2,10 @@ import React from 'react';
import { FiXCircle } from 'react-icons/fi';
-import { useBreakpoint } from '@app/hooks/breakpoint';
-import { useAppSelector } from '@app/hooks/redux';
import { Drawer } from '@components/generic/Drawer';
import { Map } from '@components/Map';
+import { useAppSelector } from '@hooks/useAppSelector';
+import { useBreakpoint } from '@hooks/useBreakpoint';
import { IconButton } from '@meshtastic/components';
import { NodeCard } from './NodeCard';
@@ -60,6 +60,7 @@ export const Nodes = (): JSX.Element => {
))}
+
);
diff --git a/src/pages/Nodes/NodeCard.tsx b/src/pages/Nodes/NodeCard.tsx
index 54d4df46..862efe74 100644
--- a/src/pages/Nodes/NodeCard.tsx
+++ b/src/pages/Nodes/NodeCard.tsx
@@ -16,10 +16,9 @@ import {
} from 'react-icons/md';
import TimeAgo from 'timeago-react';
-import { setLatLng } from '@app/core/slices/mapSlice.js';
-import { useAppDispatch } from '@app/hooks/redux.js';
import type { Node } from '@core/slices/meshtasticSlice';
import { Disclosure } from '@headlessui/react';
+import { useMapbox } from '@hooks/useMapbox';
import { IconButton } from '@meshtastic/components';
import { Protobuf } from '@meshtastic/meshtasticjs';
@@ -32,9 +31,10 @@ export interface NodeCardProps {
}
export const NodeCard = ({ node, myNodeInfo }: NodeCardProps): JSX.Element => {
- const dispatch = useAppDispatch();
const [snrAverage, setSnrAverage] = React.useState(0);
const [satsAverage, setSatsAverage] = React.useState(0);
+ const { map } = useMapbox();
+
React.useEffect(() => {
setSnrAverage(
node.snr
@@ -119,17 +119,26 @@ export const NodeCard = ({ node, myNodeInfo }: NodeCardProps): JSX.Element => {
{
+ onClick={(): void => {
if (PositionConfidence !== 'none' && node.currentPosition) {
- dispatch(
- setLatLng(
- new mapboxgl.LngLat(
- node.currentPosition.longitudeI / 1e7,
- node.currentPosition.latitudeI / 1e7,
- ),
+ map?.flyTo({
+ center: new mapboxgl.LngLat(
+ node.currentPosition.longitudeI / 1e7,
+ node.currentPosition.latitudeI / 1e7,
),
- );
+ zoom: 16,
+ });
}
+ // if (PositionConfidence !== 'none' && node.currentPosition) {
+ // dispatch(
+ // setLatLng(
+ // new mapboxgl.LngLat(
+ // node.currentPosition.longitudeI / 1e7,
+ // node.currentPosition.latitudeI / 1e7,
+ // ),
+ // ),
+ // );
+ // }
}}
icon={
PositionConfidence === 'high' ? (
diff --git a/src/pages/Plugins/ExternalNotification.tsx b/src/pages/Plugins/ExternalNotification.tsx
index 50a5ef2f..8bd2483d 100644
--- a/src/pages/Plugins/ExternalNotification.tsx
+++ b/src/pages/Plugins/ExternalNotification.tsx
@@ -4,9 +4,9 @@ import { useForm, useWatch } from 'react-hook-form';
import { FiMenu } from 'react-icons/fi';
import { FormFooter } from '@app/components/FormFooter';
-import { useAppSelector } from '@app/hooks/redux';
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';
diff --git a/src/pages/Plugins/RangeTest.tsx b/src/pages/Plugins/RangeTest.tsx
index 50dbc57b..24624ce2 100644
--- a/src/pages/Plugins/RangeTest.tsx
+++ b/src/pages/Plugins/RangeTest.tsx
@@ -3,10 +3,10 @@ import React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { FiMenu } from 'react-icons/fi';
-import { useAppSelector } from '@app/hooks/redux';
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';
diff --git a/src/pages/Plugins/Serial.tsx b/src/pages/Plugins/Serial.tsx
index 642b8811..1bd705c4 100644
--- a/src/pages/Plugins/Serial.tsx
+++ b/src/pages/Plugins/Serial.tsx
@@ -3,10 +3,10 @@ import React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { FiMenu } from 'react-icons/fi';
-import { useAppSelector } from '@app/hooks/redux';
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';
diff --git a/src/pages/Plugins/StoreAndForward.tsx b/src/pages/Plugins/StoreAndForward.tsx
index 0a2fed71..9fefea6c 100644
--- a/src/pages/Plugins/StoreAndForward.tsx
+++ b/src/pages/Plugins/StoreAndForward.tsx
@@ -3,10 +3,10 @@ import React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { FiMenu } from 'react-icons/fi';
-import { useAppSelector } from '@app/hooks/redux';
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';
diff --git a/src/pages/settings/Channels.tsx b/src/pages/settings/Channels.tsx
index 479757a3..53e575cc 100644
--- a/src/pages/settings/Channels.tsx
+++ b/src/pages/settings/Channels.tsx
@@ -4,13 +4,13 @@ import { useForm, useWatch } from 'react-hook-form';
import { FiCode, FiMenu } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
-import { useAppSelector } from '@app/hooks/redux';
import { Channel } from '@components/Channel';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
import { Loading } from '@components/generic/Loading';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { connection } from '@core/connection';
+import { useAppSelector } from '@hooks/useAppSelector';
import {
Card,
Checkbox,
diff --git a/src/pages/settings/Index.tsx b/src/pages/settings/Index.tsx
index 29786cab..f81431e3 100644
--- a/src/pages/settings/Index.tsx
+++ b/src/pages/settings/Index.tsx
@@ -10,7 +10,7 @@ import {
FiZap,
} from 'react-icons/fi';
-import type { SidebarItemProps } from '@app/components/generic/SidebarItem.js';
+import type { SidebarItemProps } from '@app/components/generic/SidebarItem';
import { PageLayout } from '@components/templates/PageLayout';
import { Channels } from './Channels';
diff --git a/src/pages/settings/Position.tsx b/src/pages/settings/Position.tsx
index bf3ef23f..bb905080 100644
--- a/src/pages/settings/Position.tsx
+++ b/src/pages/settings/Position.tsx
@@ -6,12 +6,12 @@ import JSONPretty from 'react-json-pretty';
import type { Theme } from 'react-select';
import ReactSelect from 'react-select';
-import { useAppSelector } from '@app/hooks/redux';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
import { Label } from '@components/generic/form/Label';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { connection } from '@core/connection';
+import { useAppSelector } from '@hooks/useAppSelector';
import {
Card,
Checkbox,
diff --git a/src/pages/settings/Power.tsx b/src/pages/settings/Power.tsx
index 09eb2fd3..eca15374 100644
--- a/src/pages/settings/Power.tsx
+++ b/src/pages/settings/Power.tsx
@@ -4,11 +4,11 @@ import { useForm } from 'react-hook-form';
import { FiCode, FiMenu } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
-import { useAppSelector } from '@app/hooks/redux';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { connection } from '@core/connection';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Card, Checkbox, IconButton, Select } from '@meshtastic/components';
import { Protobuf } from '@meshtastic/meshtasticjs';
diff --git a/src/pages/settings/Radio.tsx b/src/pages/settings/Radio.tsx
index f2c67ea0..f7cf1ea2 100644
--- a/src/pages/settings/Radio.tsx
+++ b/src/pages/settings/Radio.tsx
@@ -4,11 +4,11 @@ import { useForm } from 'react-hook-form';
import { FiCode, FiMenu } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
-import { useAppSelector } from '@app/hooks/redux';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { connection } from '@core/connection';
+import { useAppSelector } from '@hooks/useAppSelector';
import { Card, Checkbox, IconButton, Select } from '@meshtastic/components';
import { Protobuf } from '@meshtastic/meshtasticjs';
diff --git a/src/pages/settings/User.tsx b/src/pages/settings/User.tsx
index c6d888c9..9a4876eb 100644
--- a/src/pages/settings/User.tsx
+++ b/src/pages/settings/User.tsx
@@ -5,11 +5,11 @@ import { FiCode, FiMenu } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
import { base16 } from 'rfc4648';
-import { useAppSelector } from '@app/hooks/redux';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
import { connection } from '@core/connection';
+import { useAppSelector } from '@hooks/useAppSelector';
import {
Card,
Checkbox,
diff --git a/src/pages/settings/WiFi.tsx b/src/pages/settings/WiFi.tsx
index 4809ef7e..ea84d474 100644
--- a/src/pages/settings/WiFi.tsx
+++ b/src/pages/settings/WiFi.tsx
@@ -5,11 +5,11 @@ import { useTranslation } from 'react-i18next';
import { FiCode, FiMenu } from 'react-icons/fi';
import JSONPretty from 'react-json-pretty';
-import { useAppSelector } from '@app/hooks/redux';
import { FormFooter } from '@components/FormFooter';
import { Cover } from '@components/generic/Cover';
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 { Protobuf } from '@meshtastic/meshtasticjs';
diff --git a/tsconfig.json b/tsconfig.json
index f4b4a7b8..20b176b1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -21,6 +21,7 @@
"@app/*": ["./src/*"],
"@pages/*": ["./src/pages/*"],
"@components/*": ["./src/components/*"],
+ "@hooks/*": ["./src/hooks/*"],
"@core/*": ["./src/core/*"]
},
"importHelpers": true,
diff --git a/vite.config.ts b/vite.config.ts
index 267e3781..7c7d417b 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -67,6 +67,7 @@ export default defineConfig({
'@app': path.resolve(__dirname, './src'),
'@pages': path.resolve(__dirname, './src/pages'),
'@components': path.resolve(__dirname, './src/components'),
+ '@hooks': path.resolve(__dirname, './src/hooks'),
'@core': path.resolve(__dirname, './src/core'),
},
},