Map logic rework
This commit is contained in:
+4
-5
@@ -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",
|
||||
|
||||
Generated
+86
-140
@@ -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
|
||||
|
||||
+8
-2
@@ -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 => {
|
||||
<div className="flex w-full bg-gray-100 md:shadow-xl md:overflow-hidden dark:bg-secondaryDark md:rounded-b-3xl">
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
{route.name === 'messages' && <Messages />}
|
||||
{route.name === 'nodes' && <Nodes />}
|
||||
{route.name === 'nodes' && (
|
||||
<MapboxProvider>
|
||||
<Nodes />
|
||||
</MapboxProvider>
|
||||
)}
|
||||
{route.name === 'plugins' && <Plugins />}
|
||||
{route.name === 'settings' && <Settings />}
|
||||
{route.name === false && <NotFound />}
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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<HTMLDivElement>(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(
|
||||
<Card>
|
||||
<div className="text-xl font-medium">
|
||||
{node.user?.longName}
|
||||
</div>
|
||||
<ul>
|
||||
<li>ID: {node.number}</li>
|
||||
</ul>
|
||||
</Card>,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
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 (
|
||||
<div className="relative flex w-full h-full">
|
||||
<div className="fixed right-0 z-20 p-2 m-4 space-y-2 bg-white rounded-md shadow-md md:mx-10 dark:bg-primaryDark">
|
||||
@@ -232,7 +85,7 @@ export const Map = (): JSX.Element => {
|
||||
<IconButton icon={<MdRadar />} />
|
||||
</div>
|
||||
<div className="flex w-full h-full">
|
||||
<div className="flex-grow w-full h-full" ref={mapRef} />
|
||||
<div className="flex-grow w-full h-full" ref={ref} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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<HTMLDivElement>(null);
|
||||
|
||||
const [markers, setMarkers] = React.useState<
|
||||
{ id: number; marker: mapbox.Marker }[]
|
||||
>([]);
|
||||
const [markerElements, setMarkerElements] = React.useState<
|
||||
{ id: number; element: JSX.Element; ref: React.RefObject<HTMLDivElement> }[]
|
||||
>([]);
|
||||
|
||||
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<HTMLDivElement>();
|
||||
|
||||
const markerElement = markerElements.find(
|
||||
(element) => element.id === node.number,
|
||||
) ?? {
|
||||
element: (
|
||||
<div ref={tmpRef}>
|
||||
Test
|
||||
<FiAirplay />
|
||||
</div>
|
||||
),
|
||||
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(
|
||||
<Card>
|
||||
<div className="p-2">
|
||||
<div className="text-xl font-medium">
|
||||
{node.user?.longName}
|
||||
</div>
|
||||
<ul>
|
||||
<li>ID: {node.number}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Card>,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
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 (
|
||||
<MapboxContext.Provider value={{ map, ref }}>
|
||||
{children}
|
||||
</MapboxContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
import type mapbox from 'mapbox-gl';
|
||||
|
||||
export interface MapboxContextValue {
|
||||
ref: React.Ref<HTMLDivElement>;
|
||||
map?: mapbox.Map;
|
||||
}
|
||||
|
||||
export const MapboxContext = React.createContext<MapboxContextValue>(
|
||||
{} as MapboxContextValue
|
||||
);
|
||||
@@ -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 {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Button, IconButton } from '@meshtastic/components';
|
||||
export const BLE = (): JSX.Element => {
|
||||
const [bleDevices, setBleDevices] = React.useState<BluetoothDevice[]>([]);
|
||||
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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<SerialPort[]>([]);
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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'];
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<HTMLDivElement>,
|
||||
accessToken: AccessToken,
|
||||
options?: Partial<mapboxgl.MapboxOptions>,
|
||||
): mapboxgl.Map | undefined {
|
||||
const [mapInstance, setMapInstance] = React.useState<mapboxgl.Map>();
|
||||
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;
|
||||
}
|
||||
@@ -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<AppDispatch>();
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
@@ -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<AppDispatch>();
|
||||
@@ -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<RootState> = useSelector;
|
||||
@@ -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<HTMLDivElement>;
|
||||
accessToken: AccessToken;
|
||||
options?: Partial<mapboxgl.MapboxOptions>;
|
||||
}
|
||||
|
||||
export function useCreateMapbox({
|
||||
ref,
|
||||
accessToken,
|
||||
options,
|
||||
}: useMapboxProps): mapboxgl.Map | undefined {
|
||||
const [mapInstance, setMapInstance] = React.useState<mapboxgl.Map>();
|
||||
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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 => {
|
||||
<NodeCard key={node.number} node={node} />
|
||||
))}
|
||||
</Drawer>
|
||||
|
||||
<Map />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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 => {
|
||||
</div>
|
||||
<IconButton
|
||||
disabled={PositionConfidence === 'none'}
|
||||
onClick={() => {
|
||||
onClick={(): void => {
|
||||
if (PositionConfidence !== 'none' && node.currentPosition) {
|
||||
dispatch(
|
||||
setLatLng(
|
||||
new mapboxgl.LngLat(
|
||||
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' ? (
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"@app/*": ["./src/*"],
|
||||
"@pages/*": ["./src/pages/*"],
|
||||
"@components/*": ["./src/components/*"],
|
||||
"@hooks/*": ["./src/hooks/*"],
|
||||
"@core/*": ["./src/core/*"]
|
||||
},
|
||||
"importHelpers": true,
|
||||
|
||||
@@ -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'),
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user