Fixes
@@ -1,6 +0,0 @@
|
|||||||
[submodule "design"]
|
|
||||||
path = design
|
|
||||||
url = https://github.com/meshtastic/meshtastic-design/
|
|
||||||
[submodule "public/design"]
|
|
||||||
path = public/design
|
|
||||||
url = https://github.com/meshtastic/meshtastic-design/
|
|
||||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 745 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 15 KiB |
@@ -2,7 +2,13 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="/design/web/favicon.ico" />
|
<link rel="shortcut icon" href="favicon.ico" />
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png" />
|
||||||
|
<link rel="manifest" href="site.webmanifest" />
|
||||||
|
<link rel="mask-icon" href="safari-pinned-tab.svg" color="#67ea94" />
|
||||||
|
<meta name="theme-color" content="#67ea94" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="512.000000pt" height="512.000000pt" viewBox="0 0 512.000000 512.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M1090 2655 c-399 -585 -725 -1068 -724 -1072 0 -4 58 -47 129 -95
|
||||||
|
l128 -88 27 38 c60 84 1422 2085 1426 2096 3 9 -244 187 -258 186 -2 0 -329
|
||||||
|
-480 -728 -1065z"/>
|
||||||
|
<path d="M3211 3669 c-18 -4 -45 -16 -60 -26 -30 -23 -1420 -2054 -1414 -2066
|
||||||
|
4 -6 236 -166 254 -175 4 -1 287 409 630 912 343 503 624 914 625 913 1 -1
|
||||||
|
282 -411 624 -912 343 -500 624 -911 625 -912 1 -2 61 38 133 88 111 76 131
|
||||||
|
93 122 107 -43 78 -1391 2029 -1411 2044 -33 25 -85 36 -128 27z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 893 B |
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "Meshtastic",
|
||||||
|
"short_name": "Meshtastic",
|
||||||
|
"start_url": ".",
|
||||||
|
"description": "Meshtastic web app",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#67ea94",
|
||||||
|
"background_color": "#67ea94",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 1115 116" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||||
|
<g transform="matrix(1.05081,0,0,0.602459,-74.3378,-345.171)">
|
||||||
|
<g>
|
||||||
|
<g transform="matrix(0.973838,0,0,1.69858,-1.56777,-229.112)">
|
||||||
|
<path d="M81.582,577.266L148.536,478.804" style="fill:none;stroke:black;stroke-width:14.11px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.961342,0,0,1.67678,882.45,-216.54)">
|
||||||
|
<path d="M81.582,577.266L148.536,478.804" style="fill:none;stroke:black;stroke-width:14.86px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(12.0448,0,0,21.0595,-7445.39,-7644.88)">
|
||||||
|
<text x="640.988px" y="399.072px" style="font-family:'ArialMT', 'Arial', sans-serif;font-size:12px;">ESHT</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.977299,0,0,1.70462,-43.6432,50.5292)">
|
||||||
|
<path d="M187.032,410.85L250.896,317.192L314.907,410.702" style="fill:none;stroke:black;stroke-width:13.85px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.977299,0,0,1.70462,468.182,53.0697)">
|
||||||
|
<path d="M187.032,410.85L250.896,317.192L314.907,410.702" style="fill:none;stroke:black;stroke-width:13.85px;"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.571939,0,0,1,784.482,759.924)">
|
||||||
|
<text x="0px" y="0px" style="font-family:'ArialMT', 'Arial', sans-serif;font-size:252.715px;">ST</text>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.571939,0,0,1,1030.51,760.498)">
|
||||||
|
<text x="0px" y="0px" style="font-family:'ArialMT', 'Arial', sans-serif;font-size:252.715px;">C</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -135,20 +135,21 @@ const App = () => {
|
|||||||
|
|
||||||
connection.onRoutingPacketEvent.subscribe((routingPacket) => {
|
connection.onRoutingPacketEvent.subscribe((routingPacket) => {
|
||||||
console.log(routingPacket);
|
console.log(routingPacket);
|
||||||
|
// console.log(messages);
|
||||||
|
|
||||||
messages.map((message) => {
|
// messages.map((message) => {
|
||||||
console.log(
|
// console.log(
|
||||||
`${
|
// `${
|
||||||
routingPacket.payloadVariant.oneofKind === 'decoded'
|
// routingPacket.payloadVariant.oneofKind === 'decoded'
|
||||||
? routingPacket.payloadVariant.decoded.requestId
|
// ? routingPacket.payloadVariant.decoded.requestId
|
||||||
: null
|
// : null
|
||||||
} === ${message.message.packet.id}: ${
|
// } === ${message.message.packet.id}: ${
|
||||||
routingPacket.payloadVariant.oneofKind === 'decoded'
|
// routingPacket.payloadVariant.oneofKind === 'decoded'
|
||||||
? routingPacket.payloadVariant.decoded.requestId
|
// ? routingPacket.payloadVariant.decoded.requestId
|
||||||
: null === message.message.packet.id
|
// : null === message.message.packet.id
|
||||||
}`,
|
// }`,
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
// messages.find((message) => {
|
// messages.find((message) => {
|
||||||
// message.message.packet.id === routingPacket.decoded.requestId;
|
// message.message.packet.id === routingPacket.decoded.requestId;
|
||||||
// });
|
// });
|
||||||
@@ -156,32 +157,6 @@ const App = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-screen w-screen">
|
<div className="flex flex-col h-screen w-screen">
|
||||||
{/* <Head>
|
|
||||||
<link
|
|
||||||
rel="apple-touch-icon"
|
|
||||||
sizes="180x180"
|
|
||||||
href="/design/web/apple-touch-icon.png"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
type="image/png"
|
|
||||||
sizes="32x32"
|
|
||||||
href="/design/web/favicon-32x32.png"
|
|
||||||
/>
|
|
||||||
<link
|
|
||||||
rel="icon"
|
|
||||||
type="image/png"
|
|
||||||
sizes="16x16"
|
|
||||||
href="/design/web/favicon-16x16.png"
|
|
||||||
/>
|
|
||||||
<link rel="manifest" href="/design/web/site.webmanifest" />
|
|
||||||
<link
|
|
||||||
rel="mask-icon"
|
|
||||||
href="/design/web/safari-pinned-tab.svg"
|
|
||||||
color="#67ea94"
|
|
||||||
/>
|
|
||||||
<meta name="theme-color" content="#67ea94" />
|
|
||||||
</Head> */}
|
|
||||||
<Header
|
<Header
|
||||||
status={deviceStatus}
|
status={deviceStatus}
|
||||||
IsReady={isReady}
|
IsReady={isReady}
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ const Main = (props: MainProps) => {
|
|||||||
Language={props.Language}
|
Language={props.Language}
|
||||||
SetLanguage={props.SetLanguage}
|
SetLanguage={props.SetLanguage}
|
||||||
Translations={props.Translations}
|
Translations={props.Translations}
|
||||||
|
myId={props.MyNodeInfo.myNodeNum}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const Header = (props: HeaderProps) => {
|
|||||||
return (
|
return (
|
||||||
<nav className="w-full shadow-md">
|
<nav className="w-full shadow-md">
|
||||||
<div className="flex w-full container mx-auto justify-between px-6 py-4">
|
<div className="flex w-full container mx-auto justify-between px-6 py-4">
|
||||||
<img src="/design/typelogo/typelogo.svg" height="30" width="200" />
|
<img src="/typelogo.svg" height="30" width="200" />
|
||||||
|
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="flex pl-4">
|
<div className="flex pl-4">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { FaCaretDown, FaCaretRight, FaSpinner } from 'react-icons/fa';
|
|||||||
|
|
||||||
interface NavItemProps {
|
interface NavItemProps {
|
||||||
isDropdown: boolean;
|
isDropdown: boolean;
|
||||||
open?: boolean;
|
open: boolean;
|
||||||
isNested: boolean;
|
isNested: boolean;
|
||||||
titleContent: ReactNode;
|
titleContent: ReactNode;
|
||||||
dropdownContent?: ReactNode;
|
dropdownContent?: ReactNode;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ interface SidebarProps {
|
|||||||
Language: LanguageEnum;
|
Language: LanguageEnum;
|
||||||
SetLanguage: Function;
|
SetLanguage: Function;
|
||||||
Translations: languageTemplate;
|
Translations: languageTemplate;
|
||||||
|
myId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sidebar = (props: SidebarProps) => {
|
const Sidebar = (props: SidebarProps) => {
|
||||||
@@ -37,6 +38,7 @@ const Sidebar = (props: SidebarProps) => {
|
|||||||
IsReady={props.IsReady}
|
IsReady={props.IsReady}
|
||||||
Nodes={props.Nodes}
|
Nodes={props.Nodes}
|
||||||
Translations={props.Translations}
|
Translations={props.Translations}
|
||||||
|
myId={props.myId}
|
||||||
/>
|
/>
|
||||||
<SidebarDeviceSettings
|
<SidebarDeviceSettings
|
||||||
IsReady={props.IsReady}
|
IsReady={props.IsReady}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const SidebarChannels = (props: SidebarChannelsProps) => {
|
|||||||
key={index}
|
key={index}
|
||||||
isDropdown={true}
|
isDropdown={true}
|
||||||
isNested={true}
|
isNested={true}
|
||||||
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{channel.index} - {Protobuf.Channel_Role[channel.role]}
|
{channel.index} - {Protobuf.Channel_Role[channel.role]}
|
||||||
@@ -44,6 +45,7 @@ const SidebarChannels = (props: SidebarChannelsProps) => {
|
|||||||
<NavItem
|
<NavItem
|
||||||
isDropdown={false}
|
isDropdown={false}
|
||||||
isNested={false}
|
isNested={false}
|
||||||
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex justify-between border-b hover:bg-gray-200">
|
<div className="flex justify-between border-b hover:bg-gray-200">
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { FaDesktop, FaUsers } from 'react-icons/fa';
|
import {
|
||||||
|
FaBatteryHalf,
|
||||||
|
FaClock,
|
||||||
|
FaCrown,
|
||||||
|
FaDesktop,
|
||||||
|
FaMapMarkerAlt,
|
||||||
|
FaMountain,
|
||||||
|
FaUsers,
|
||||||
|
} from 'react-icons/fa';
|
||||||
|
|
||||||
import type { Types } from '@meshtastic/meshtasticjs';
|
import type { Types } from '@meshtastic/meshtasticjs';
|
||||||
|
|
||||||
@@ -11,6 +19,7 @@ interface sidebarNodesProps {
|
|||||||
IsReady: boolean;
|
IsReady: boolean;
|
||||||
Nodes: Types.NodeInfoPacket[];
|
Nodes: Types.NodeInfoPacket[];
|
||||||
Translations: languageTemplate;
|
Translations: languageTemplate;
|
||||||
|
myId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SidebarNodes = (props: sidebarNodesProps) => {
|
const SidebarNodes = (props: sidebarNodesProps) => {
|
||||||
@@ -39,7 +48,11 @@ const SidebarNodes = (props: sidebarNodesProps) => {
|
|||||||
open={false}
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<div key={index} className="flex">
|
<div key={index} className="flex">
|
||||||
|
{node.data.num === props.myId ? (
|
||||||
|
<FaCrown className="text-yellow-500 my-auto mr-2" />
|
||||||
|
) : (
|
||||||
<FaDesktop className="my-auto mr-2" />
|
<FaDesktop className="my-auto mr-2" />
|
||||||
|
)}
|
||||||
<div className="m-auto">{node.data.user?.longName}</div>
|
<div className="m-auto">{node.data.user?.longName}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -47,6 +60,7 @@ const SidebarNodes = (props: sidebarNodesProps) => {
|
|||||||
<NavItem
|
<NavItem
|
||||||
isDropdown={false}
|
isDropdown={false}
|
||||||
isNested={true}
|
isNested={true}
|
||||||
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
@@ -58,16 +72,35 @@ const SidebarNodes = (props: sidebarNodesProps) => {
|
|||||||
{node.packet?.rxRssi ? node.packet.rxRssi : 'Unknown'}
|
{node.packet?.rxRssi ? node.packet.rxRssi : 'Unknown'}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Last heard:{' '}
|
{`Last heard: ${
|
||||||
{node.data?.lastHeard ? node.data.lastHeard : 'Unknown'}
|
node.data?.lastHeard
|
||||||
|
? new Date(node.data.lastHeard).toLocaleString()
|
||||||
|
: 'Unknown'
|
||||||
|
}`}{' '}
|
||||||
|
{}
|
||||||
</p>
|
</p>
|
||||||
|
<div className="flex">
|
||||||
|
<FaMapMarkerAlt className="my-auto mr-2" />
|
||||||
<p>
|
<p>
|
||||||
Loc:{' '}
|
{node.data.position?.latitudeI},
|
||||||
{node.data?.position
|
{node.data.position?.longitudeI}
|
||||||
? `alt: ${node.data?.position.altitude}, lat: ${node.data?.position.latitudeI}, lng: ${node.data?.position.longitudeI}, time: ${node.data?.position.time}, batt: ${node.data?.position.batteryLevel}`
|
|
||||||
: 'Unknown'}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="flex">
|
||||||
|
<FaMountain className="my-auto mr-2" />
|
||||||
|
<p>{node.data.position?.altitude}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex">
|
||||||
|
<FaClock className="my-auto mr-2" />
|
||||||
|
<p>{node.data.position?.time}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<FaBatteryHalf className="my-auto mr-2" />
|
||||||
|
<p>{node.data.position?.batteryLevel}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const SidebarUISettings = (props: SidebarUISettingsProps) => {
|
|||||||
<NavItem
|
<NavItem
|
||||||
isDropdown={true}
|
isDropdown={true}
|
||||||
isNested={false}
|
isNested={false}
|
||||||
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<FaCog className="my-auto mr-2" />
|
<FaCog className="my-auto mr-2" />
|
||||||
@@ -30,6 +31,7 @@ const SidebarUISettings = (props: SidebarUISettingsProps) => {
|
|||||||
<NavItem
|
<NavItem
|
||||||
isDropdown={false}
|
isDropdown={false}
|
||||||
isNested={true}
|
isNested={true}
|
||||||
|
open={false}
|
||||||
titleContent={
|
titleContent={
|
||||||
<>
|
<>
|
||||||
<div className="my-auto">
|
<div className="my-auto">
|
||||||
@@ -71,6 +73,7 @@ const SidebarUISettings = (props: SidebarUISettingsProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.SetLanguage(LanguageEnum.ENGLISH);
|
props.SetLanguage(LanguageEnum.ENGLISH);
|
||||||
}}
|
}}
|
||||||
|
open={false}
|
||||||
isDropdown={false}
|
isDropdown={false}
|
||||||
isNested={true}
|
isNested={true}
|
||||||
titleContent={
|
titleContent={
|
||||||
@@ -81,6 +84,7 @@ const SidebarUISettings = (props: SidebarUISettingsProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
props.SetLanguage(LanguageEnum.JAPANESE);
|
props.SetLanguage(LanguageEnum.JAPANESE);
|
||||||
}}
|
}}
|
||||||
|
open={false}
|
||||||
isDropdown={false}
|
isDropdown={false}
|
||||||
isNested={true}
|
isNested={true}
|
||||||
titleContent={
|
titleContent={
|
||||||
|
|||||||