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} -
-
    -
  • ID: {node.number}
  • -
-
, - ), - ), - ); + 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} +
+
    +
  • ID: {node.number}
  • +
+
+
, + ), + ), + ); + + 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'), }, },