chore: fixes from deno linting/formatting
This commit is contained in:
@@ -17,12 +17,12 @@ export const getChannelName = (channel: Protobuf.Channel.Channel) =>
|
||||
channel.settings?.name.length
|
||||
? channel.settings?.name
|
||||
: channel.index === 0
|
||||
? "Primary"
|
||||
: `Ch ${channel.index}`;
|
||||
? "Primary"
|
||||
: `Ch ${channel.index}`;
|
||||
|
||||
const ChannelsPage = () => {
|
||||
const { channels, setDialogOpen } = useDevice();
|
||||
const [activeChannel, setActiveChannel] = useState<Types.ChannelNumber>(
|
||||
const [activeChannel] = useState<Types.ChannelNumber>(
|
||||
Types.ChannelNumber.Primary,
|
||||
);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { LoRa } from "@components/PageComponents/Config/LoRa.tsx";
|
||||
import { Network } from "@components/PageComponents/Config/Network.tsx";
|
||||
import { Position } from "@components/PageComponents/Config/Position.tsx";
|
||||
import { Power } from "@components/PageComponents/Config/Power.tsx";
|
||||
import { Security } from "@components/PageComponents/Config/Security/Security";
|
||||
import { Security } from "../../components/PageComponents/Config/Security/Security.tsx";
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
TabsTrigger,
|
||||
} from "@components/UI/Tabs.tsx";
|
||||
|
||||
export const ModuleConfig = (): JSX.Element => {
|
||||
export const ModuleConfig = () => {
|
||||
const tabs = [
|
||||
{
|
||||
label: "MQTT",
|
||||
|
||||
+13
-11
@@ -1,4 +1,4 @@
|
||||
import { useAppStore } from "@app/core/stores/appStore";
|
||||
import { useAppStore } from "../../core/stores/appStore.ts";
|
||||
import { useDevice } from "@app/core/stores/deviceStore.ts";
|
||||
import { PageLayout } from "@components/PageLayout.tsx";
|
||||
import { Sidebar } from "@components/Sidebar.tsx";
|
||||
@@ -36,9 +36,10 @@ const ConfigPage = () => {
|
||||
connection?.setConfig(config).then(() =>
|
||||
toast({
|
||||
title: "Saving Config",
|
||||
description: `The configuration change ${config.payloadVariant.case} has been saved.`,
|
||||
}),
|
||||
),
|
||||
description:
|
||||
`The configuration change ${config.payloadVariant.case} has been saved.`,
|
||||
})
|
||||
)
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@@ -47,14 +48,15 @@ const ConfigPage = () => {
|
||||
connection?.setModuleConfig(moduleConfig).then(() =>
|
||||
toast({
|
||||
title: "Saving Config",
|
||||
description: `The configuration change ${moduleConfig.payloadVariant.case} has been saved.`,
|
||||
}),
|
||||
),
|
||||
description:
|
||||
`The configuration change ${moduleConfig.payloadVariant.case} has been saved.`,
|
||||
})
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
await connection?.commitEditSettings();
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
toast({
|
||||
title: "Error Saving Config",
|
||||
description: "An error occurred while saving the configuration.",
|
||||
@@ -83,9 +85,9 @@ const ConfigPage = () => {
|
||||
</SidebarSection>
|
||||
</Sidebar>
|
||||
<PageLayout
|
||||
label={
|
||||
activeConfigSection === "device" ? "Radio Config" : "Module Config"
|
||||
}
|
||||
label={activeConfigSection === "device"
|
||||
? "Radio Config"
|
||||
: "Module Config"}
|
||||
actions={[
|
||||
{
|
||||
icon: isError ? SaveOff : SaveIcon,
|
||||
|
||||
@@ -33,74 +33,81 @@ export const Dashboard = () => {
|
||||
<Separator />
|
||||
|
||||
<div className="flex h-[450px] rounded-md border border-dashed border-slate-200 p-3 dark:border-slate-700">
|
||||
{devices.length ? (
|
||||
<ul className="grow divide-y divide-slate-200">
|
||||
{devices.map((device) => {
|
||||
return (
|
||||
<li key={device.id}>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full px-4 py-4 sm:px-6"
|
||||
onClick={() => {
|
||||
setSelectedDevice(device.id);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="truncate text-sm font-medium text-accent">
|
||||
{device.nodes.get(device.hardware.myNodeNum)?.user
|
||||
?.longName ?? "UNK"}
|
||||
</p>
|
||||
<div className="inline-flex w-24 justify-center gap-2 rounded-full bg-slate-100 py-1 text-xs font-semibold text-slate-900 transition-colors hover:bg-slate-700 hover:text-slate-50">
|
||||
{device.connection?.connType === "ble" && (
|
||||
<>
|
||||
<BluetoothIcon size={16} />
|
||||
BLE
|
||||
</>
|
||||
)}
|
||||
{device.connection?.connType === "serial" && (
|
||||
<>
|
||||
<UsbIcon size={16} />
|
||||
Serial
|
||||
</>
|
||||
)}
|
||||
{device.connection?.connType === "http" && (
|
||||
<>
|
||||
<NetworkIcon size={16} />
|
||||
Network
|
||||
</>
|
||||
)}
|
||||
{devices.length
|
||||
? (
|
||||
<ul className="grow divide-y divide-slate-200">
|
||||
{devices.map((device) => {
|
||||
return (
|
||||
<li key={device.id}>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full px-4 py-4 sm:px-6"
|
||||
onClick={() => {
|
||||
setSelectedDevice(device.id);
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="truncate text-sm font-medium text-accent">
|
||||
{device.nodes.get(device.hardware.myNodeNum)?.user
|
||||
?.longName ?? "UNK"}
|
||||
</p>
|
||||
<div className="inline-flex w-24 justify-center gap-2 rounded-full bg-slate-100 py-1 text-xs font-semibold text-slate-900 transition-colors hover:bg-slate-700 hover:text-slate-50">
|
||||
{device.connection?.connType === "ble" && (
|
||||
<>
|
||||
<BluetoothIcon size={16} />
|
||||
BLE
|
||||
</>
|
||||
)}
|
||||
{device.connection?.connType === "serial" && (
|
||||
<>
|
||||
<UsbIcon size={16} />
|
||||
Serial
|
||||
</>
|
||||
)}
|
||||
{device.connection?.connType === "http" && (
|
||||
<>
|
||||
<NetworkIcon size={16} />
|
||||
Network
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 sm:flex sm:justify-between">
|
||||
<div className="flex gap-2 text-sm text-slate-500">
|
||||
<UsersIcon
|
||||
size={20}
|
||||
className="text-slate-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{device.nodes.size === 0 ? 0 : device.nodes.size - 1}
|
||||
<div className="mt-2 sm:flex sm:justify-between">
|
||||
<div className="flex gap-2 text-sm text-slate-500">
|
||||
<UsersIcon
|
||||
size={20}
|
||||
className="text-slate-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{device.nodes.size === 0
|
||||
? 0
|
||||
: device.nodes.size - 1}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
) : (
|
||||
<div className="m-auto flex flex-col gap-3 text-center">
|
||||
<ListPlusIcon size={48} className="mx-auto text-text-secondary" />
|
||||
<H3>No Devices</H3>
|
||||
<Subtle>Connect at least one device to get started</Subtle>
|
||||
<Button
|
||||
className="gap-2 dark:bg-white dark:text-slate-900 dark:hover:text-slate-100"
|
||||
variant={"default"}
|
||||
onClick={() => setConnectDialogOpen(true)}
|
||||
>
|
||||
<PlusIcon size={16} />
|
||||
New Connection
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
: (
|
||||
<div className="m-auto flex flex-col gap-3 text-center">
|
||||
<ListPlusIcon
|
||||
size={48}
|
||||
className="mx-auto text-text-secondary"
|
||||
/>
|
||||
<H3>No Devices</H3>
|
||||
<Subtle>Connect at least one device to get started</Subtle>
|
||||
<Button
|
||||
className="gap-2 dark:bg-white dark:text-slate-900 dark:hover:text-slate-100"
|
||||
variant="default"
|
||||
onClick={() => setConnectDialogOpen(true)}
|
||||
>
|
||||
<PlusIcon size={16} />
|
||||
New Connection
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
+23
-22
@@ -1,14 +1,13 @@
|
||||
import { NodeDetail } from "@app/components/PageComponents/Map/NodeDetail";
|
||||
import { Avatar } from "@app/components/UI/Avatar";
|
||||
import { useTheme } from "@app/core/hooks/useTheme";
|
||||
import { NodeDetail } from "../../components/PageComponents/Map/NodeDetail.tsx";
|
||||
import { Avatar } from "../../components/UI/Avatar.tsx";
|
||||
import { useTheme } from "../../core/hooks/useTheme.ts";
|
||||
import { PageLayout } from "@components/PageLayout.tsx";
|
||||
import { Sidebar } from "@components/Sidebar.tsx";
|
||||
import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import type { Protobuf } from "@meshtastic/core";
|
||||
import { bbox, lineString } from "@turf/turf";
|
||||
import { current } from "immer";
|
||||
import { MapPinIcon } from "lucide-react";
|
||||
import { type JSX, useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
AttributionControl,
|
||||
GeolocateControl,
|
||||
@@ -33,15 +32,16 @@ const convertToLatLng = (position: {
|
||||
longitude: (position.longitudeI ?? 0) / 1e7,
|
||||
});
|
||||
|
||||
const MapPage = (): JSX.Element => {
|
||||
const MapPage = () => {
|
||||
const { nodes, waypoints } = useDevice();
|
||||
const currentTheme = useTheme();
|
||||
const { theme } = useTheme();
|
||||
const { default: map } = useMap();
|
||||
|
||||
const darkMode = currentTheme === "dark";
|
||||
const darkMode = theme === "dark";
|
||||
|
||||
const [selectedNode, setSelectedNode] =
|
||||
useState<Protobuf.Mesh.NodeInfo | null>(null);
|
||||
const [selectedNode, setSelectedNode] = useState<
|
||||
Protobuf.Mesh.NodeInfo | null
|
||||
>(null);
|
||||
|
||||
// Filter out nodes without a valid position
|
||||
const validNodes = useMemo(
|
||||
@@ -140,13 +140,12 @@ const MapPage = (): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<Sidebar />
|
||||
<PageLayout label="Map" noPadding={true} actions={[]}>
|
||||
<PageLayout label="Map" noPadding actions={[]}>
|
||||
<MapGl
|
||||
mapStyle="https://raw.githubusercontent.com/hc-oss/maplibre-gl-styles/master/styles/osm-mapnik/v8/default.json"
|
||||
attributionControl={false}
|
||||
renderWorldCopies={false}
|
||||
maxPitch={0}
|
||||
antialias={true}
|
||||
style={{
|
||||
filter: darkMode ? "brightness(0.9)" : "",
|
||||
}}
|
||||
@@ -185,16 +184,18 @@ const MapPage = (): JSX.Element => {
|
||||
</Marker>
|
||||
))}
|
||||
{markers}
|
||||
{selectedNode ? (
|
||||
<Popup
|
||||
anchor="top"
|
||||
longitude={convertToLatLng(selectedNode.position).longitude}
|
||||
latitude={convertToLatLng(selectedNode.position).latitude}
|
||||
onClose={() => setSelectedNode(null)}
|
||||
>
|
||||
<NodeDetail node={selectedNode} />
|
||||
</Popup>
|
||||
) : null}
|
||||
{selectedNode
|
||||
? (
|
||||
<Popup
|
||||
anchor="top"
|
||||
longitude={convertToLatLng(selectedNode.position).longitude}
|
||||
latitude={convertToLatLng(selectedNode.position).latitude}
|
||||
onClose={() => setSelectedNode(null)}
|
||||
>
|
||||
<NodeDetail node={selectedNode} />
|
||||
</Popup>
|
||||
)
|
||||
: null}
|
||||
</MapGl>
|
||||
</PageLayout>
|
||||
</>
|
||||
|
||||
+33
-39
@@ -1,4 +1,4 @@
|
||||
import { useAppStore } from "@app/core/stores/appStore";
|
||||
import { useAppStore } from "../core/stores/appStore.ts";
|
||||
import { ChannelChat } from "@components/PageComponents/Messages/ChannelChat.tsx";
|
||||
import { PageLayout } from "@components/PageLayout.tsx";
|
||||
import { Sidebar } from "@components/Sidebar.tsx";
|
||||
@@ -10,12 +10,11 @@ import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import { Protobuf, Types } from "@meshtastic/core";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
import { getChannelName } from "@pages/Channels.tsx";
|
||||
import { HashIcon, LockIcon, LockOpenIcon, WaypointsIcon } from "lucide-react";
|
||||
import { HashIcon, LockIcon, LockOpenIcon } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
export const MessagesPage = () => {
|
||||
const { channels, nodes, hardware, messages, traceroutes, connection } =
|
||||
useDevice();
|
||||
const { channels, nodes, hardware, messages } = useDevice();
|
||||
const { activeChat, chatType, setActiveChat, setChatType } = useAppStore();
|
||||
const [searchTerm, setSearchTerm] = useState<string>("");
|
||||
const filteredNodes = Array.from(nodes.values()).filter((node) => {
|
||||
@@ -39,13 +38,11 @@ export const MessagesPage = () => {
|
||||
{filteredChannels.map((channel) => (
|
||||
<SidebarButton
|
||||
key={channel.index}
|
||||
label={
|
||||
channel.settings?.name.length
|
||||
? channel.settings?.name
|
||||
: channel.index === 0
|
||||
? "Primary"
|
||||
: `Ch ${channel.index}`
|
||||
}
|
||||
label={channel.settings?.name.length
|
||||
? channel.settings?.name
|
||||
: channel.index === 0
|
||||
? "Primary"
|
||||
: `Ch ${channel.index}`}
|
||||
active={activeChat === channel.index}
|
||||
onClick={() => {
|
||||
setChatType("broadcast");
|
||||
@@ -69,9 +66,8 @@ export const MessagesPage = () => {
|
||||
{filteredNodes.map((node) => (
|
||||
<SidebarButton
|
||||
key={node.num}
|
||||
label={
|
||||
node.user?.longName ?? `!${numberToHexUnpadded(node.num)}`
|
||||
}
|
||||
label={node.user?.longName ??
|
||||
`!${numberToHexUnpadded(node.num)}`}
|
||||
active={activeChat === node.num}
|
||||
onClick={() => {
|
||||
setChatType("direct");
|
||||
@@ -94,32 +90,30 @@ export const MessagesPage = () => {
|
||||
chatType === "broadcast" && currentChannel
|
||||
? getChannelName(currentChannel)
|
||||
: chatType === "direct" && nodes.get(activeChat)
|
||||
? (nodes.get(activeChat)?.user?.longName ?? nodeHex)
|
||||
: "Loading..."
|
||||
? (nodes.get(activeChat)?.user?.longName ?? nodeHex)
|
||||
: "Loading..."
|
||||
}`}
|
||||
actions={
|
||||
chatType === "direct"
|
||||
? [
|
||||
{
|
||||
icon: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? LockIcon
|
||||
: LockOpenIcon,
|
||||
iconClasses: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? "text-green-600"
|
||||
: "text-yellow-300",
|
||||
async onClick() {
|
||||
const targetNode = nodes.get(activeChat)?.num;
|
||||
if (targetNode === undefined) return;
|
||||
toast({
|
||||
title: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? "Chat is using PKI encryption."
|
||||
: "Chat is using PSK encryption.",
|
||||
});
|
||||
},
|
||||
},
|
||||
]
|
||||
: []
|
||||
}
|
||||
actions={chatType === "direct"
|
||||
? [
|
||||
{
|
||||
icon: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? LockIcon
|
||||
: LockOpenIcon,
|
||||
iconClasses: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? "text-green-600"
|
||||
: "text-yellow-300",
|
||||
onClick() {
|
||||
const targetNode = nodes.get(activeChat)?.num;
|
||||
if (targetNode === undefined) return;
|
||||
toast({
|
||||
title: nodes.get(activeChat)?.user?.publicKey.length
|
||||
? "Chat is using PKI encryption."
|
||||
: "Chat is using PSK encryption.",
|
||||
});
|
||||
},
|
||||
},
|
||||
]
|
||||
: []}
|
||||
>
|
||||
{allChannels.map(
|
||||
(channel) =>
|
||||
|
||||
+22
-22
@@ -1,7 +1,7 @@
|
||||
import { LocationResponseDialog } from "@app/components/Dialog/LocationResponseDialog";
|
||||
import { NodeOptionsDialog } from "@app/components/Dialog/NodeOptionsDialog";
|
||||
import { TracerouteResponseDialog } from "@app/components/Dialog/TracerouteResponseDialog";
|
||||
import Footer from "@app/components/UI/Footer";
|
||||
import { LocationResponseDialog } from "../components/Dialog/LocationResponseDialog.tsx";
|
||||
import { NodeOptionsDialog } from "../components/Dialog/NodeOptionsDialog.tsx";
|
||||
import { TracerouteResponseDialog } from "../components/Dialog/TracerouteResponseDialog.tsx";
|
||||
import Footer from "../components/UI/Footer.tsx";
|
||||
import { Sidebar } from "@components/Sidebar.tsx";
|
||||
import { Avatar } from "@components/UI/Avatar.tsx";
|
||||
import { Mono } from "@components/generic/Mono.tsx";
|
||||
@@ -11,7 +11,7 @@ import { useDevice } from "@core/stores/deviceStore.ts";
|
||||
import { Protobuf, type Types } from "@meshtastic/core";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
import { LockIcon, LockOpenIcon } from "lucide-react";
|
||||
import { Fragment, type JSX, useCallback, useEffect, useState } from "react";
|
||||
import { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { base16 } from "rfc4648";
|
||||
|
||||
export interface DeleteNoteDialogProps {
|
||||
@@ -19,7 +19,7 @@ export interface DeleteNoteDialogProps {
|
||||
onOpenChange: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const NodesPage = (): JSX.Element => {
|
||||
const NodesPage = () => {
|
||||
const { nodes, hardware, connection } = useDevice();
|
||||
const [selectedNode, setSelectedNode] = useState<
|
||||
Protobuf.Mesh.NodeInfo | undefined
|
||||
@@ -107,9 +107,11 @@ const NodesPage = (): JSX.Element => {
|
||||
>
|
||||
{node.user?.shortName ??
|
||||
(node.user?.macaddr
|
||||
? `${base16
|
||||
? `${
|
||||
base16
|
||||
.stringify(node.user?.macaddr.subarray(4, 6) ?? [])
|
||||
.toLowerCase()}`
|
||||
.toLowerCase()
|
||||
}`
|
||||
: `${numberToHexUnpadded(node.num).slice(-4)}`)}
|
||||
</h1>,
|
||||
|
||||
@@ -120,9 +122,11 @@ const NodesPage = (): JSX.Element => {
|
||||
>
|
||||
{node.user?.longName ??
|
||||
(node.user?.macaddr
|
||||
? `Meshtastic ${base16
|
||||
? `Meshtastic ${
|
||||
base16
|
||||
.stringify(node.user?.macaddr.subarray(4, 6) ?? [])
|
||||
.toLowerCase()}`
|
||||
.toLowerCase()
|
||||
}`
|
||||
: `!${numberToHexUnpadded(node.num)}`)}
|
||||
</h1>,
|
||||
|
||||
@@ -136,11 +140,9 @@ const NodesPage = (): JSX.Element => {
|
||||
?.join(":") ?? "UNK"}
|
||||
</Mono>,
|
||||
<Fragment key="lastHeard">
|
||||
{node.lastHeard === 0 ? (
|
||||
<p>Never</p>
|
||||
) : (
|
||||
<TimeAgo timestamp={node.lastHeard * 1000} />
|
||||
)}
|
||||
{node.lastHeard === 0
|
||||
? <p>Never</p>
|
||||
: <TimeAgo timestamp={node.lastHeard * 1000} />}
|
||||
</Fragment>,
|
||||
<Mono key="snr">
|
||||
{node.snr}db/
|
||||
@@ -148,19 +150,17 @@ const NodesPage = (): JSX.Element => {
|
||||
{(node.snr + 10) * 5}raw
|
||||
</Mono>,
|
||||
<Mono key="pki">
|
||||
{node.user?.publicKey && node.user?.publicKey.length > 0 ? (
|
||||
<LockIcon className="text-green-600" />
|
||||
) : (
|
||||
<LockOpenIcon className="text-yellow-300 mx-auto" />
|
||||
)}
|
||||
{node.user?.publicKey && node.user?.publicKey.length > 0
|
||||
? <LockIcon className="text-green-600" />
|
||||
: <LockOpenIcon className="text-yellow-300 mx-auto" />}
|
||||
</Mono>,
|
||||
<Mono key="hops">
|
||||
{node.lastHeard !== 0
|
||||
? node.viaMqtt === false && node.hopsAway === 0
|
||||
? "Direct"
|
||||
: `${node.hopsAway.toString()} ${
|
||||
node.hopsAway > 1 ? "hops" : "hop"
|
||||
} away`
|
||||
node.hopsAway > 1 ? "hops" : "hop"
|
||||
} away`
|
||||
: "-"}
|
||||
{node.viaMqtt === true ? ", via MQTT" : ""}
|
||||
</Mono>,
|
||||
|
||||
Reference in New Issue
Block a user