COnnection modal fix & notification basics
This commit is contained in:
+2
-1
@@ -1 +1,2 @@
|
|||||||
VITE_PUBLIC_DEVICE_IP=
|
VITE_PUBLIC_DEVICE_IP=
|
||||||
|
VITE_PUBLIC_HOSTED=
|
||||||
+4
-4
@@ -14,7 +14,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.4.2",
|
"@headlessui/react": "^1.4.2",
|
||||||
"@meshtastic/meshtasticjs": "^0.6.35",
|
"@meshtastic/meshtasticjs": "^0.6.35",
|
||||||
"@reduxjs/toolkit": "^1.7.0",
|
"@reduxjs/toolkit": "^1.7.1",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"boring-avatars": "^1.5.8",
|
"boring-avatars": "^1.5.8",
|
||||||
"i18next": "^21.6.0",
|
"i18next": "^21.6.0",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.6",
|
||||||
"react-select": "^5.2.1",
|
"react-select": "^5.2.1",
|
||||||
"rfc4648": "^1.5.0",
|
"rfc4648": "^1.5.0",
|
||||||
"swr": "^1.1.1",
|
"swr": "^1.1.2-beta.0",
|
||||||
"timeago-react": "^3.0.4",
|
"timeago-react": "^3.0.4",
|
||||||
"type-route": "^0.6.0",
|
"type-route": "^0.6.0",
|
||||||
"use-breakpoint": "^3.0.0"
|
"use-breakpoint": "^3.0.0"
|
||||||
@@ -60,12 +60,12 @@
|
|||||||
"gzipper": "^6.0.0",
|
"gzipper": "^6.0.0",
|
||||||
"postcss": "^8.4.5",
|
"postcss": "^8.4.5",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"tailwindcss": "^3.0.2",
|
"tailwindcss": "^3.0.5",
|
||||||
"tar": "^6.1.11",
|
"tar": "^6.1.11",
|
||||||
"typescript": "^4.5.4",
|
"typescript": "^4.5.4",
|
||||||
"vite": "^2.7.2",
|
"vite": "^2.7.2",
|
||||||
"vite-plugin-cdn-import": "^0.3.5",
|
"vite-plugin-cdn-import": "^0.3.5",
|
||||||
"vite-plugin-pwa": "^0.11.11",
|
"vite-plugin-pwa": "^0.11.12",
|
||||||
"workbox-window": "^6.4.2"
|
"workbox-window": "^6.4.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+31
-31
@@ -3,7 +3,7 @@ lockfileVersion: 5.3
|
|||||||
specifiers:
|
specifiers:
|
||||||
'@headlessui/react': ^1.4.2
|
'@headlessui/react': ^1.4.2
|
||||||
'@meshtastic/meshtasticjs': ^0.6.35
|
'@meshtastic/meshtasticjs': ^0.6.35
|
||||||
'@reduxjs/toolkit': ^1.7.0
|
'@reduxjs/toolkit': ^1.7.1
|
||||||
'@types/mapbox-gl': ^2.6.0
|
'@types/mapbox-gl': ^2.6.0
|
||||||
'@types/react': ^17.0.37
|
'@types/react': ^17.0.37
|
||||||
'@types/react-dom': ^17.0.11
|
'@types/react-dom': ^17.0.11
|
||||||
@@ -43,8 +43,8 @@ specifiers:
|
|||||||
react-redux: ^7.2.6
|
react-redux: ^7.2.6
|
||||||
react-select: ^5.2.1
|
react-select: ^5.2.1
|
||||||
rfc4648: ^1.5.0
|
rfc4648: ^1.5.0
|
||||||
swr: ^1.1.1
|
swr: ^1.1.2-beta.0
|
||||||
tailwindcss: ^3.0.2
|
tailwindcss: ^3.0.5
|
||||||
tar: ^6.1.11
|
tar: ^6.1.11
|
||||||
timeago-react: ^3.0.4
|
timeago-react: ^3.0.4
|
||||||
type-route: ^0.6.0
|
type-route: ^0.6.0
|
||||||
@@ -52,13 +52,13 @@ specifiers:
|
|||||||
use-breakpoint: ^3.0.0
|
use-breakpoint: ^3.0.0
|
||||||
vite: ^2.7.2
|
vite: ^2.7.2
|
||||||
vite-plugin-cdn-import: ^0.3.5
|
vite-plugin-cdn-import: ^0.3.5
|
||||||
vite-plugin-pwa: ^0.11.11
|
vite-plugin-pwa: ^0.11.12
|
||||||
workbox-window: ^6.4.2
|
workbox-window: ^6.4.2
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@headlessui/react': 1.4.2_react-dom@17.0.2+react@17.0.2
|
'@headlessui/react': 1.4.2_react-dom@17.0.2+react@17.0.2
|
||||||
'@meshtastic/meshtasticjs': 0.6.35
|
'@meshtastic/meshtasticjs': 0.6.35
|
||||||
'@reduxjs/toolkit': 1.7.0_react-redux@7.2.6+react@17.0.2
|
'@reduxjs/toolkit': 1.7.1_react-redux@7.2.6+react@17.0.2
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
boring-avatars: 1.5.8
|
boring-avatars: 1.5.8
|
||||||
i18next: 21.6.0
|
i18next: 21.6.0
|
||||||
@@ -75,7 +75,7 @@ dependencies:
|
|||||||
react-redux: 7.2.6_react-dom@17.0.2+react@17.0.2
|
react-redux: 7.2.6_react-dom@17.0.2+react@17.0.2
|
||||||
react-select: 5.2.1_5539cae010396b202b015f3568914e95
|
react-select: 5.2.1_5539cae010396b202b015f3568914e95
|
||||||
rfc4648: 1.5.0
|
rfc4648: 1.5.0
|
||||||
swr: 1.1.1_react@17.0.2
|
swr: 1.1.2-beta.0_react@17.0.2
|
||||||
timeago-react: 3.0.4_react@17.0.2
|
timeago-react: 3.0.4_react@17.0.2
|
||||||
type-route: 0.6.0
|
type-route: 0.6.0
|
||||||
use-breakpoint: 3.0.0_react-dom@17.0.2+react@17.0.2
|
use-breakpoint: 3.0.0_react-dom@17.0.2+react@17.0.2
|
||||||
@@ -104,12 +104,12 @@ devDependencies:
|
|||||||
gzipper: 6.0.0
|
gzipper: 6.0.0
|
||||||
postcss: 8.4.5
|
postcss: 8.4.5
|
||||||
prettier: 2.5.1
|
prettier: 2.5.1
|
||||||
tailwindcss: 3.0.2_16a290f6d0e3717bf6d2667234aebd30
|
tailwindcss: 3.0.5_16a290f6d0e3717bf6d2667234aebd30
|
||||||
tar: 6.1.11
|
tar: 6.1.11
|
||||||
typescript: 4.5.4
|
typescript: 4.5.4
|
||||||
vite: 2.7.2
|
vite: 2.7.2
|
||||||
vite-plugin-cdn-import: 0.3.5
|
vite-plugin-cdn-import: 0.3.5
|
||||||
vite-plugin-pwa: 0.11.11_vite@2.7.2
|
vite-plugin-pwa: 0.11.12_vite@2.7.2
|
||||||
workbox-window: 6.4.2
|
workbox-window: 6.4.2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
@@ -1249,7 +1249,7 @@ packages:
|
|||||||
babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.5
|
babel-plugin-polyfill-corejs2: 0.3.0_@babel+core@7.16.5
|
||||||
babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.5
|
babel-plugin-polyfill-corejs3: 0.4.0_@babel+core@7.16.5
|
||||||
babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.5
|
babel-plugin-polyfill-regenerator: 0.3.0_@babel+core@7.16.5
|
||||||
core-js-compat: 3.19.3
|
core-js-compat: 3.20.0
|
||||||
semver: 6.3.0
|
semver: 6.3.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -1523,8 +1523,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-HZwkgJW9SGiE9+0lWKr1X997tmG01/40j+hr9yBVk+hTQcm7Hsf77XhMNtsDjWUOcspG6GBXu8o3g4i3kD5/zQ==}
|
resolution: {integrity: sha512-HZwkgJW9SGiE9+0lWKr1X997tmG01/40j+hr9yBVk+hTQcm7Hsf77XhMNtsDjWUOcspG6GBXu8o3g4i3kD5/zQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@reduxjs/toolkit/1.7.0_react-redux@7.2.6+react@17.0.2:
|
/@reduxjs/toolkit/1.7.1_react-redux@7.2.6+react@17.0.2:
|
||||||
resolution: {integrity: sha512-iApo4zS+8kWnIn4xucTDWpqRjDNkXruFIyJQWwThIEIbMj5kwqvbMaQcEgd2a305B68Z+4bvZqAqJSATeddaJA==}
|
resolution: {integrity: sha512-wXwXYjBVz/ItxB7SMzEAMmEE/FBiY1ze18N+VVVX7NtVbRUrdOGKhpQMHivIJfkbJvSdLUU923a/yAagJQzY0Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.9.0 || ^17.0.0 || 18.0.0-beta
|
react: ^16.9.0 || ^17.0.0 || 18.0.0-beta
|
||||||
react-redux: ^7.2.1 || ^8.0.0-beta
|
react-redux: ^7.2.1 || ^8.0.0-beta
|
||||||
@@ -1646,8 +1646,8 @@ packages:
|
|||||||
'@types/geojson': 7946.0.8
|
'@types/geojson': 7946.0.8
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/node/16.11.13:
|
/@types/node/17.0.0:
|
||||||
resolution: {integrity: sha512-eUXZzHLHoZqj1frtUetNkUetYoJ6X55UmrVnFD4DMhVeAmwLjniZhtBmsRiemQh4uq4G3vUra/Ws/hs9vEvL3Q==}
|
resolution: {integrity: sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/parse-json/4.0.0:
|
/@types/parse-json/4.0.0:
|
||||||
@@ -1694,7 +1694,7 @@ packages:
|
|||||||
/@types/resolve/1.17.1:
|
/@types/resolve/1.17.1:
|
||||||
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 16.11.13
|
'@types/node': 17.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/scheduler/0.16.2:
|
/@types/scheduler/0.16.2:
|
||||||
@@ -2121,7 +2121,7 @@ packages:
|
|||||||
postcss: ^8.1.0
|
postcss: ^8.1.0
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.19.1
|
browserslist: 4.19.1
|
||||||
caniuse-lite: 1.0.30001286
|
caniuse-lite: 1.0.30001287
|
||||||
fraction.js: 4.1.2
|
fraction.js: 4.1.2
|
||||||
normalize-range: 0.1.2
|
normalize-range: 0.1.2
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
@@ -2171,7 +2171,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.16.5
|
'@babel/core': 7.16.5
|
||||||
'@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.5
|
'@babel/helper-define-polyfill-provider': 0.3.0_@babel+core@7.16.5
|
||||||
core-js-compat: 3.19.3
|
core-js-compat: 3.20.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
@@ -2223,8 +2223,8 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001286
|
caniuse-lite: 1.0.30001287
|
||||||
electron-to-chromium: 1.4.18
|
electron-to-chromium: 1.4.20
|
||||||
escalade: 3.1.1
|
escalade: 3.1.1
|
||||||
node-releases: 2.0.1
|
node-releases: 2.0.1
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
@@ -2256,8 +2256,8 @@ packages:
|
|||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/caniuse-lite/1.0.30001286:
|
/caniuse-lite/1.0.30001287:
|
||||||
resolution: {integrity: sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ==}
|
resolution: {integrity: sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/chalk/2.4.2:
|
/chalk/2.4.2:
|
||||||
@@ -2342,8 +2342,8 @@ packages:
|
|||||||
safe-buffer: 5.1.2
|
safe-buffer: 5.1.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/core-js-compat/3.19.3:
|
/core-js-compat/3.20.0:
|
||||||
resolution: {integrity: sha512-59tYzuWgEEVU9r+SRgceIGXSSUn47JknoiXW6Oq7RW8QHjXWz3/vp8pa7dbtuVu40sewz3OP3JmQEcDdztrLhA==}
|
resolution: {integrity: sha512-relrah5h+sslXssTTOkvqcC/6RURifB0W5yhYBdBkaPYa5/2KBMiog3XiD+s3TwEHWxInWVv4Jx2/Lw0vng+IQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.19.1
|
browserslist: 4.19.1
|
||||||
semver: 7.0.0
|
semver: 7.0.0
|
||||||
@@ -2509,8 +2509,8 @@ packages:
|
|||||||
jake: 10.8.2
|
jake: 10.8.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/electron-to-chromium/1.4.18:
|
/electron-to-chromium/1.4.20:
|
||||||
resolution: {integrity: sha512-i7nKjGGBE1+YUIbfLObA1EZPmN7J1ITEllbhusDk+KIk6V6gUxN9PFe36v+Sd+8Cg0k3cgUv9lQhQZalr8rggw==}
|
resolution: {integrity: sha512-N7ZVNrdzX8NE90OXEFBMsBf3fp8P/vVDUER3WCUZjzC7OkNTXHVoF6W9qVhq8+dA8tGnbDajzUpj2ISNVVyj+Q==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/emoji-regex/8.0.0:
|
/emoji-regex/8.0.0:
|
||||||
@@ -3730,7 +3730,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
|
resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==}
|
||||||
engines: {node: '>= 10.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 16.11.13
|
'@types/node': 17.0.0
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 7.2.0
|
supports-color: 7.2.0
|
||||||
dev: true
|
dev: true
|
||||||
@@ -4885,8 +4885,8 @@ packages:
|
|||||||
has-flag: 4.0.0
|
has-flag: 4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/swr/1.1.1_react@17.0.2:
|
/swr/1.1.2-beta.0_react@17.0.2:
|
||||||
resolution: {integrity: sha512-ZpUHyU3N3snj2QGFeE2Fd3BXl1CVS6YQIQGb1ttPAkTmvwZqDyV3GRMNPsaeAYCBM74tfn4XbKx28FVQR0mS7Q==}
|
resolution: {integrity: sha512-e7ZcPCrEvGX+s4jDtBwV9c+HKqHzG1secuwU8bYjnnGkSJMneyn7OaabJKtRh922DH5a3k2vvBdhftoSL8bHJQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0
|
react: ^16.11.0 || ^17.0.0 || ^18.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4904,8 +4904,8 @@ packages:
|
|||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/tailwindcss/3.0.2_16a290f6d0e3717bf6d2667234aebd30:
|
/tailwindcss/3.0.5_16a290f6d0e3717bf6d2667234aebd30:
|
||||||
resolution: {integrity: sha512-i1KpjYnGYftjzdAth6jA5iMPjhxpUkk5L6DafhfnQs+KiiWaThYxmk47Weh4oFH1mZqP6MuiQNHxtoRVPOraLg==}
|
resolution: {integrity: sha512-59pNgzx2o+wkAk7IZGIH7H9eNS53gzZGrO3+NPyOEWHDbquHgiLL/c993T5t1vPSAeBxox4X5OgZwNuRvXVf+g==}
|
||||||
engines: {node: '>=12.13.0'}
|
engines: {node: '>=12.13.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -5170,8 +5170,8 @@ packages:
|
|||||||
- rollup
|
- rollup
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-pwa/0.11.11_vite@2.7.2:
|
/vite-plugin-pwa/0.11.12_vite@2.7.2:
|
||||||
resolution: {integrity: sha512-/nSLS7VfGN5UrL4a1ALGEQAyga/H0hYZjEkwPehiEFW1PM1DTi1A8GkPCsmevKwR6vt10P+5wS1wrvSgwQemzw==}
|
resolution: {integrity: sha512-XqFmA4y9C4RBb5osSsa26GVwOSwbzf2GNVcT5+06KYYdguqLpuI9FW7iV/akZqg0OUNUpH4tHfme8SnHA4PIXA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.0.0
|
vite: ^2.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
+10
-4
@@ -1,4 +1,4 @@
|
|||||||
import type React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DeviceStatus } from '@app/components/menu/buttons/DeviceStatus';
|
import { DeviceStatus } from '@app/components/menu/buttons/DeviceStatus';
|
||||||
import { useAppSelector } from '@app/hooks/redux';
|
import { useAppSelector } from '@app/hooks/redux';
|
||||||
@@ -9,17 +9,23 @@ import { Logo } from '@components/menu/Logo';
|
|||||||
import { MobileNav } from '@components/menu/MobileNav';
|
import { MobileNav } from '@components/menu/MobileNav';
|
||||||
import { Navigation } from '@components/menu/Navigation';
|
import { Navigation } from '@components/menu/Navigation';
|
||||||
import { useRoute } from '@core/router';
|
import { useRoute } from '@core/router';
|
||||||
|
import { requestNotificationPermission } from '@core/utils/notifications';
|
||||||
import { Messages } from '@pages/Messages';
|
import { Messages } from '@pages/Messages';
|
||||||
import { Nodes } from '@pages/Nodes/Index';
|
import { Nodes } from '@pages/Nodes/Index';
|
||||||
|
import { NotFound } from '@pages/NotFound';
|
||||||
|
import { Plugins } from '@pages/Plugins/Index';
|
||||||
import { Settings } from '@pages/settings/Index';
|
import { Settings } from '@pages/settings/Index';
|
||||||
|
|
||||||
import { NotFound } from './pages/NotFound';
|
|
||||||
import { Plugins } from './pages/Plugins/Index';
|
|
||||||
|
|
||||||
export const App = (): JSX.Element => {
|
export const App = (): JSX.Element => {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const darkMode = useAppSelector((state) => state.app.darkMode);
|
const darkMode = useAppSelector((state) => state.app.darkMode);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
requestNotificationPermission().catch((e) => {
|
||||||
|
console.log(e);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`h-screen w-screen ${darkMode ? 'dark' : ''}`}>
|
<div className={`h-screen w-screen ${darkMode ? 'dark' : ''}`}>
|
||||||
<Connection />
|
<Connection />
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { useAppDispatch, useAppSelector } from '@app/hooks/redux';
|
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';
|
import { Serial } from '@components/connection/Serial';
|
||||||
import { Button } from '@components/generic/Button';
|
import { Button } from '@components/generic/Button';
|
||||||
import { Card } from '@components/generic/Card';
|
import { Card } from '@components/generic/Card';
|
||||||
import { Select } from '@components/generic/form/Select';
|
import { Select } from '@components/generic/form/Select';
|
||||||
import { Modal } from '@components/generic/Modal';
|
import { Modal } from '@components/generic/Modal';
|
||||||
import { DeviceStatus } from '@components/menu/buttons/DeviceStatus';
|
|
||||||
import { connection, connectionUrl, setConnection } from '@core/connection';
|
import { connection, connectionUrl, setConnection } from '@core/connection';
|
||||||
import {
|
import {
|
||||||
closeConnectionModal,
|
closeConnectionModal,
|
||||||
@@ -16,9 +17,6 @@ import {
|
|||||||
} from '@core/slices/appSlice';
|
} from '@core/slices/appSlice';
|
||||||
import { Types } from '@meshtastic/meshtasticjs';
|
import { Types } from '@meshtastic/meshtasticjs';
|
||||||
|
|
||||||
import { BLE } from './connection/BLE';
|
|
||||||
import { HTTP } from './connection/HTTP';
|
|
||||||
|
|
||||||
export const Connection = (): JSX.Element => {
|
export const Connection = (): JSX.Element => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@@ -58,23 +56,25 @@ export const Connection = (): JSX.Element => {
|
|||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<div className="w-full max-w-3xl p-10">
|
<div className="w-full max-w-3xl p-10">
|
||||||
<div className="flex justify-between w-full border rounded-md">
|
{state.deviceStatus === Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
|
||||||
<div className="p-2">
|
<div className="space-y-2">
|
||||||
<DeviceStatus />
|
<Select
|
||||||
|
label="Connection Method"
|
||||||
|
optionsEnum={connType}
|
||||||
|
value={appState.connType}
|
||||||
|
onChange={(e): void => {
|
||||||
|
dispatch(setConnType(parseInt(e.target.value)));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{appState.connType === connType.HTTP && <HTTP />}
|
||||||
|
{appState.connType === connType.BLE && <BLE />}
|
||||||
|
{appState.connType === connType.SERIAL && <Serial />}
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 my-auto">
|
) : (
|
||||||
|
<div>
|
||||||
|
<span>Connecting...</span>
|
||||||
{state.deviceStatus ===
|
{state.deviceStatus ===
|
||||||
Types.DeviceStatusEnum.DEVICE_DISCONNECTED ? (
|
Types.DeviceStatusEnum.DEVICE_CONNECTED && (
|
||||||
<Button
|
|
||||||
padding={2}
|
|
||||||
border
|
|
||||||
onClick={async (): Promise<void> => {
|
|
||||||
await setConnection(appState.connType);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Connect
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
<Button
|
||||||
padding={2}
|
padding={2}
|
||||||
border
|
border
|
||||||
@@ -86,22 +86,6 @@ export const Connection = (): JSX.Element => {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{state.deviceStatus ===
|
|
||||||
Types.DeviceStatusEnum.DEVICE_DISCONNECTED && (
|
|
||||||
<form className="space-y-2">
|
|
||||||
<Select
|
|
||||||
label="Method"
|
|
||||||
optionsEnum={connType}
|
|
||||||
value={appState.connType}
|
|
||||||
onChange={(e): void => {
|
|
||||||
dispatch(setConnType(parseInt(e.target.value)));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{appState.connType === connType.HTTP && <HTTP />}
|
|
||||||
{appState.connType === connType.BLE && <BLE />}
|
|
||||||
{appState.connType === connType.SERIAL && <Serial />}
|
|
||||||
</form>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { FiCheck } from 'react-icons/fi';
|
import { FiCheck } from 'react-icons/fi';
|
||||||
|
|
||||||
import { connType } from '@app/core/slices/appSlice';
|
import { connType } from '@app/core/slices/appSlice';
|
||||||
|
import { Button } from '@components/generic/Button';
|
||||||
import { IconButton } from '@components/generic/IconButton';
|
import { IconButton } from '@components/generic/IconButton';
|
||||||
import { ble, setConnection } from '@core/connection';
|
import { ble, setConnection } from '@core/connection';
|
||||||
|
|
||||||
export const BLE = (): JSX.Element => {
|
export const BLE = (): JSX.Element => {
|
||||||
const [bleDevices, setBleDevices] = React.useState<BluetoothDevice[]>([]);
|
const [bleDevices, setBleDevices] = React.useState<BluetoothDevice[]>([]);
|
||||||
|
|
||||||
|
const { register, handleSubmit, control } = useForm<{
|
||||||
|
device?: BluetoothDevice;
|
||||||
|
}>();
|
||||||
|
|
||||||
const updateBleDeviceList = React.useCallback(async (): Promise<void> => {
|
const updateBleDeviceList = React.useCallback(async (): Promise<void> => {
|
||||||
const devices = await ble.getDevices();
|
const devices = await ble.getDevices();
|
||||||
setBleDevices(devices);
|
setBleDevices(devices);
|
||||||
@@ -18,8 +24,12 @@ export const BLE = (): JSX.Element => {
|
|||||||
void updateBleDeviceList();
|
void updateBleDeviceList();
|
||||||
}, [updateBleDeviceList]);
|
}, [updateBleDeviceList]);
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
|
await setConnection(connType.BLE);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<form onSubmit={onSubmit} className="space-y-2">
|
||||||
{bleDevices.map((device, index) => (
|
{bleDevices.map((device, index) => (
|
||||||
<div
|
<div
|
||||||
onClick={async (): Promise<void> => {
|
onClick={async (): Promise<void> => {
|
||||||
@@ -37,6 +47,9 @@ export const BLE = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
<Button type="submit" className="mt-2 ml-auto" border>
|
||||||
|
Connect
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,52 @@
|
|||||||
import React from 'react';
|
import type React from 'react';
|
||||||
|
|
||||||
|
import { useForm, useWatch } from 'react-hook-form';
|
||||||
|
|
||||||
|
import { useAppDispatch } from '@app/hooks/redux.js';
|
||||||
|
import { Button } from '@components/generic/Button';
|
||||||
import { Checkbox } from '@components/generic/form/Checkbox';
|
import { Checkbox } from '@components/generic/form/Checkbox';
|
||||||
import { Input } from '@components/generic/form/Input';
|
import { Input } from '@components/generic/form/Input';
|
||||||
import { Select } from '@components/generic/form/Select';
|
import { Select } from '@components/generic/form/Select';
|
||||||
import { connectionUrl } from '@core/connection';
|
import { connectionUrl, setConnection } from '@core/connection';
|
||||||
|
import { connType, setConnectionParams } from '@core/slices/appSlice';
|
||||||
|
|
||||||
export const HTTP = (): JSX.Element => {
|
export const HTTP = (): JSX.Element => {
|
||||||
const [httpIpSource, setHttpIpSource] = React.useState<'local' | 'remote'>(
|
const dispatch = useAppDispatch();
|
||||||
'local',
|
|
||||||
);
|
const { register, handleSubmit, control } = useForm<{
|
||||||
|
ipSource: 'local' | 'remote';
|
||||||
|
ip?: string;
|
||||||
|
tls: boolean;
|
||||||
|
}>({
|
||||||
|
defaultValues: {
|
||||||
|
ipSource: 'local',
|
||||||
|
ip: connectionUrl,
|
||||||
|
tls: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const watchIpSource = useWatch({
|
||||||
|
control,
|
||||||
|
name: 'ipSource',
|
||||||
|
defaultValue: 'local',
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
|
dispatch(
|
||||||
|
setConnectionParams({
|
||||||
|
type: connType.HTTP,
|
||||||
|
params: {
|
||||||
|
address: data.ip ?? connectionUrl,
|
||||||
|
tls: data.tls,
|
||||||
|
fetchInterval: 2000,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
await setConnection(connType.HTTP);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<form onSubmit={onSubmit}>
|
||||||
<Select
|
<Select
|
||||||
label="Host Source"
|
label="Host Source"
|
||||||
options={[
|
options={[
|
||||||
@@ -24,17 +59,17 @@ export const HTTP = (): JSX.Element => {
|
|||||||
value: 'remote',
|
value: 'remote',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
value={httpIpSource}
|
{...register('ipSource')}
|
||||||
onChange={(e): void => {
|
|
||||||
setHttpIpSource(e.target.value as 'local' | 'remote');
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
{httpIpSource === 'local' ? (
|
{watchIpSource === 'local' ? (
|
||||||
<Input label="Host" value={connectionUrl} disabled />
|
<Input label="Host" value={connectionUrl} disabled />
|
||||||
) : (
|
) : (
|
||||||
<Input label="Host" />
|
<Input label="Host" {...register('ip')} />
|
||||||
)}
|
)}
|
||||||
<Checkbox label="Use TLS?" />
|
<Checkbox label="Use TLS?" {...register('tls')} />
|
||||||
</div>
|
<Button type="submit" className="mt-2 ml-auto" border>
|
||||||
|
Connect
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
import { FiCheck } from 'react-icons/fi';
|
import { FiCheck } from 'react-icons/fi';
|
||||||
|
|
||||||
|
import { Button } from '@components/generic/Button';
|
||||||
import { IconButton } from '@components/generic/IconButton';
|
import { IconButton } from '@components/generic/IconButton';
|
||||||
import { serial, setConnection } from '@core/connection';
|
import { serial, setConnection } from '@core/connection';
|
||||||
import { connType } from '@core/slices/appSlice';
|
import { connType } from '@core/slices/appSlice';
|
||||||
@@ -9,6 +11,10 @@ import { connType } from '@core/slices/appSlice';
|
|||||||
export const Serial = (): JSX.Element => {
|
export const Serial = (): JSX.Element => {
|
||||||
const [serialDevices, setSerialDevices] = React.useState<SerialPort[]>([]);
|
const [serialDevices, setSerialDevices] = React.useState<SerialPort[]>([]);
|
||||||
|
|
||||||
|
const { register, handleSubmit, control } = useForm<{
|
||||||
|
device?: SerialPort;
|
||||||
|
}>();
|
||||||
|
|
||||||
const updateSerialDeviceList = React.useCallback(async (): Promise<void> => {
|
const updateSerialDeviceList = React.useCallback(async (): Promise<void> => {
|
||||||
const devices = await serial.getPorts();
|
const devices = await serial.getPorts();
|
||||||
setSerialDevices(devices);
|
setSerialDevices(devices);
|
||||||
@@ -18,8 +24,12 @@ export const Serial = (): JSX.Element => {
|
|||||||
void updateSerialDeviceList();
|
void updateSerialDeviceList();
|
||||||
}, [updateSerialDeviceList]);
|
}, [updateSerialDeviceList]);
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (data) => {
|
||||||
|
await setConnection(connType.SERIAL);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<form onSubmit={onSubmit} className="space-y-2">
|
||||||
{serialDevices.map((device, index) => (
|
{serialDevices.map((device, index) => (
|
||||||
<div
|
<div
|
||||||
className="flex justify-between p-2 bg-gray-700 rounded-md"
|
className="flex justify-between p-2 bg-gray-700 rounded-md"
|
||||||
@@ -41,6 +51,9 @@ export const Serial = (): JSX.Element => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
<Button type="submit" className="mt-2 ml-auto" border>
|
||||||
|
Connect
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import {
|
|||||||
Types,
|
Types,
|
||||||
} from '@meshtastic/meshtasticjs';
|
} from '@meshtastic/meshtasticjs';
|
||||||
|
|
||||||
|
import { showNotification } from './utils/notifications.js';
|
||||||
|
|
||||||
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
|
type connectionType = IBLEConnection | IHTTPConnection | ISerialConnection;
|
||||||
|
|
||||||
export let connection: connectionType = new IHTTPConnection();
|
export let connection: connectionType = new IHTTPConnection();
|
||||||
@@ -151,6 +153,7 @@ const registerListeners = (): void => {
|
|||||||
|
|
||||||
connection.onTextPacket.subscribe((message) => {
|
connection.onTextPacket.subscribe((message) => {
|
||||||
const myNodeNum = store.getState().meshtastic.radio.hardware.myNodeNum;
|
const myNodeNum = store.getState().meshtastic.radio.hardware.myNodeNum;
|
||||||
|
showNotification('New message', message.data);
|
||||||
|
|
||||||
store.dispatch(
|
store.dispatch(
|
||||||
addMessage({
|
addMessage({
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export const requestNotificationPermission = async (): Promise<void> => {
|
||||||
|
if (window.Notification && Notification.permission !== 'denied') {
|
||||||
|
await Notification.requestPermission();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const showNotification = (title: string, body: string): void => {
|
||||||
|
new Notification(title, {
|
||||||
|
body,
|
||||||
|
icon: 'android-512.png',
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user