Merge branch 'master' into feature/node-quick-options

This commit is contained in:
Tilen Komel
2025-01-29 11:50:33 +01:00
23 changed files with 2519 additions and 2842 deletions
+2 -1
View File
@@ -20,7 +20,7 @@ export const getChannelName = (channel: Protobuf.Channel.Channel) =>
? "Primary"
: `Ch ${channel.index}`;
export const ChannelsPage = (): JSX.Element => {
const ChannelsPage = () => {
const { channels, setDialogOpen } = useDevice();
const [activeChannel, setActiveChannel] = useState<Types.ChannelNumber>(
Types.ChannelNumber.Primary,
@@ -69,3 +69,4 @@ export const ChannelsPage = (): JSX.Element => {
</>
);
};
export default ChannelsPage;
+3 -1
View File
@@ -9,7 +9,7 @@ import { ModuleConfig } from "@pages/Config/ModuleConfig.tsx";
import { BoxesIcon, SaveIcon, SettingsIcon } from "lucide-react";
import { useState } from "react";
export const ConfigPage = (): JSX.Element => {
const ConfigPage = (): JSX.Element => {
const { workingConfig, workingModuleConfig, connection } = useDevice();
const [activeConfigSection, setActiveConfigSection] = useState<
"device" | "module"
@@ -72,3 +72,5 @@ export const ConfigPage = (): JSX.Element => {
</>
);
};
export default ConfigPage;
+15 -10
View File
@@ -1,4 +1,5 @@
import { NodeDetail } from "@app/components/PageComponents/Map/NodeDetail";
import { Avatar } from "@app/components/UI/Avatar";
import { Subtle } from "@app/components/UI/Typography/Subtle.tsx";
import { cn } from "@app/core/utils/cn.ts";
import { PageLayout } from "@components/PageLayout.tsx";
@@ -7,7 +8,6 @@ import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx";
import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx";
import { useAppStore } from "@core/stores/appStore.ts";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Hashicon } from "@emeraldpay/hashicon-react";
import type { Protobuf } from "@meshtastic/js";
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
import { bbox, lineString } from "@turf/turf";
@@ -17,11 +17,11 @@ import {
ZoomInIcon,
ZoomOutIcon,
} from "lucide-react";
import { useCallback, useEffect, useState } from "react";
import { type JSX, useCallback, useEffect, useMemo, useState } from "react";
import { AttributionControl, Marker, Popup, useMap } from "react-map-gl";
import MapGl from "react-map-gl/maplibre";
export const MapPage = (): JSX.Element => {
const MapPage = (): JSX.Element => {
const { nodes, waypoints } = useDevice();
const { rasterSources, darkMode } = useAppStore();
const { default: map } = useMap();
@@ -30,7 +30,7 @@ export const MapPage = (): JSX.Element => {
const [selectedNode, setSelectedNode] =
useState<Protobuf.Mesh.NodeInfo | null>(null);
const allNodes = Array.from(nodes.values());
const allNodes = useMemo(() => Array.from(nodes.values()), [nodes]);
const getBBox = useCallback(() => {
if (!map) {
@@ -135,9 +135,7 @@ export const MapPage = (): JSX.Element => {
renderWorldCopies={false}
maxPitch={0}
style={{
filter: darkMode
? "brightness(0.6) invert(1) contrast(3) hue-rotate(200deg) saturate(0.3) brightness(0.7)"
: "",
filter: darkMode ? "brightness(0.8)" : "",
}}
dragRotate={false}
touchZoomRotate={false}
@@ -177,7 +175,7 @@ export const MapPage = (): JSX.Element => {
key={node.num}
longitude={(node.position.longitudeI ?? 0) / 1e7}
latitude={(node.position.latitudeI ?? 0) / 1e7}
style={{ filter: darkMode ? "invert(1)" : "" }}
// style={{ filter: darkMode ? "invert(1)" : "" }}
anchor="bottom"
onClick={() => {
setSelectedNode(node);
@@ -190,8 +188,13 @@ export const MapPage = (): JSX.Element => {
});
}}
>
<div className="flex cursor-pointer gap-2 rounded-md border bg-backgroundPrimary p-1.5">
<Hashicon value={node.num.toString()} size={22} />
<div className="flex cursor-pointer gap-2 rounded-md bg-transparent p-1.5">
<Avatar
text={
node.user?.shortName.toString() ?? node.num.toString()
}
size="sm"
/>
<Subtle className={cn(zoom < 12 && "hidden")}>
{node.user?.longName ||
`!${numberToHexUnpadded(node.num)}`}
@@ -217,3 +220,5 @@ export const MapPage = (): JSX.Element => {
</>
);
};
export default MapPage;
+27 -16
View File
@@ -1,18 +1,18 @@
import { ChannelChat } from "@components/PageComponents/Messages/ChannelChat.tsx";
import { PageLayout } from "@components/PageLayout.tsx";
import { Sidebar } from "@components/Sidebar.tsx";
import { Avatar } from "@components/UI/Avatar.tsx";
import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx";
import { SidebarButton } from "@components/UI/Sidebar/sidebarButton.tsx";
import { useToast } from "@core/hooks/useToast.ts";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Hashicon } from "@emeraldpay/hashicon-react";
import { Device, useDevice, useDeviceStore } from "@core/stores/deviceStore.ts";
import { Protobuf, Types } from "@meshtastic/js";
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
import { getChannelName } from "@pages/Channels.tsx";
import { HashIcon, LockIcon, LockOpenIcon, WaypointsIcon } from "lucide-react";
import { useState } from "react";
export const MessagesPage = (): JSX.Element => {
const MessagesPage = () => {
const { channels, nodes, hardware, messages, traceroutes, connection } =
useDevice();
const [chatType, setChatType] =
@@ -56,18 +56,27 @@ export const MessagesPage = (): JSX.Element => {
))}
</SidebarSection>
<SidebarSection label="Nodes">
{filteredNodes.map((node) => (
<SidebarButton
key={node.num}
label={node.user?.longName ?? `!${numberToHexUnpadded(node.num)}`}
active={activeChat === node.num}
onClick={() => {
setChatType("direct");
setActiveChat(node.num);
}}
element={<Hashicon size={20} value={node.num.toString()} />}
/>
))}
<div className="flex flex-col gap-4">
{filteredNodes.map((node) => (
<SidebarButton
key={node.num}
label={
node.user?.longName ?? `!${numberToHexUnpadded(node.num)}`
}
active={activeChat === node.num}
onClick={() => {
setChatType("direct");
setActiveChat(node.num);
}}
element={
<Avatar
text={node.user?.shortName ?? node.num.toString()}
size="sm"
/>
}
/>
))}
</div>
</SidebarSection>
</Sidebar>
<div className="flex flex-col flex-grow">
@@ -76,7 +85,7 @@ export const MessagesPage = (): JSX.Element => {
chatType === "broadcast" && currentChannel
? getChannelName(currentChannel)
: chatType === "direct" && nodes.get(activeChat)
? nodes.get(activeChat)?.user?.longName ?? nodeHex
? (nodes.get(activeChat)?.user?.longName ?? nodeHex)
: "Loading..."
}`}
actions={
@@ -146,3 +155,5 @@ export const MessagesPage = (): JSX.Element => {
</>
);
};
export default MessagesPage;
+10 -9
View File
@@ -8,11 +8,10 @@ import { Mono } from "@components/generic/Mono.tsx";
import { Table } from "@components/generic/Table/index.tsx";
import { TimeAgo } from "@components/generic/Table/tmp/TimeAgo.tsx";
import { useDevice } from "@core/stores/deviceStore.ts";
import { Hashicon } from "@emeraldpay/hashicon-react";
import { Protobuf, type Types } from "@meshtastic/js";
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
import { LockIcon, LockOpenIcon, TrashIcon } from "lucide-react";
import { Fragment, useCallback, useEffect, useState } from "react";
import { Fragment, type JSX, useCallback, useEffect, useState } from "react";
import { base16 } from "rfc4648";
export interface DeleteNoteDialogProps {
@@ -20,7 +19,7 @@ export interface DeleteNoteDialogProps {
onOpenChange: (open: boolean) => void;
}
export const NodesPage = (): JSX.Element => {
const NodesPage = (): JSX.Element => {
const { nodes, hardware, setDialogOpen, connection } = useDevice();
const { setNodeNumToBeRemoved } = useAppStore();
const [selectedNode, setSelectedNode] = useState<
@@ -66,12 +65,12 @@ export const NodesPage = (): JSX.Element => {
{ title: "Remove", type: "normal", sortable: false },
]}
rows={filteredNodes.map((node) => [
<Hashicon key="icon" size={24} value={node.num.toString()} />,
<h1
className="cursor-pointer"
key="header"
onMouseDown={() => setSelectedNode(node)}
>
<span
key={node.num}
className="h-3 w-3 rounded-full bg-accent"
/>,
<h1 key="header" onMouseDown={() => setSelectedNode(node)}>
{node.user?.longName ??
(node.user?.macaddr
? `Meshtastic ${base16
@@ -147,3 +146,5 @@ export const NodesPage = (): JSX.Element => {
</>
);
};
export default NodesPage;