|
|
|
@ -1,16 +1,12 @@ |
|
|
|
import type React from "react"; |
|
|
|
|
|
|
|
import { base16 } from "rfc4648"; |
|
|
|
|
|
|
|
import { Hashicon } from "@emeraldpay/hashicon-react"; |
|
|
|
import { useDevice } from "@app/core/providers/useDevice.js"; |
|
|
|
import { |
|
|
|
EllipsisHorizontalCircleIcon, |
|
|
|
EllipsisHorizontalIcon, |
|
|
|
UserGroupIcon, |
|
|
|
} from "@heroicons/react/24/outline"; |
|
|
|
import type { Protobuf } from "@meshtastic/meshtasticjs"; |
|
|
|
|
|
|
|
import { Card } from "../Card.js"; |
|
|
|
import { Dropdown } from "../Dropdown.js"; |
|
|
|
import { IconButton } from "../IconButton.js"; |
|
|
|
import { Mono } from "../Mono.js"; |
|
|
|
|
|
|
|
@ -19,45 +15,36 @@ export interface PeersWidgetProps { |
|
|
|
} |
|
|
|
|
|
|
|
export const PeersWidget = ({ peers }: PeersWidgetProps): JSX.Element => { |
|
|
|
const { setActivePage } = useDevice(); |
|
|
|
|
|
|
|
return ( |
|
|
|
<Card className="flex-col"> |
|
|
|
<Dropdown |
|
|
|
title="Peers" |
|
|
|
stat={peers.length} |
|
|
|
icon={<UserGroupIcon className="h-4" />} |
|
|
|
> |
|
|
|
<div className="flex flex-col p-3"> |
|
|
|
{peers.map((peer) => ( |
|
|
|
<div |
|
|
|
className="flex gap-2 rounded-md p-2 hover:bg-slate-100" |
|
|
|
key={peer.num} |
|
|
|
> |
|
|
|
<span className="my-auto shrink-0"> |
|
|
|
<Hashicon value={peer.num.toString()} size={28} /> |
|
|
|
</span> |
|
|
|
<div className="flex flex-col"> |
|
|
|
<span className="font-medium">{peer.user?.longName}</span> |
|
|
|
<Mono> |
|
|
|
{base16 |
|
|
|
.stringify(peer.user?.macaddr ?? []) |
|
|
|
.match(/.{1,2}/g) |
|
|
|
?.join(":") ?? ""} |
|
|
|
</Mono> |
|
|
|
</div> |
|
|
|
<div className="my-auto ml-auto"> |
|
|
|
<IconButton |
|
|
|
variant="secondary" |
|
|
|
size="sm" |
|
|
|
icon={<EllipsisHorizontalCircleIcon className="h-4" />} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
))} |
|
|
|
{peers.length === 0 && ( |
|
|
|
<Mono className="m-auto">No devices discovered yet.</Mono> |
|
|
|
<div className="flex gap-3 overflow-hidden rounded-lg bg-white p-3 shadow"> |
|
|
|
<div className="rounded-md bg-emerald-500 p-3"> |
|
|
|
<UserGroupIcon className="h-6 text-white" /> |
|
|
|
</div> |
|
|
|
<div> |
|
|
|
<p className="truncate text-sm font-medium text-gray-500"> |
|
|
|
Connected Peers |
|
|
|
</p> |
|
|
|
<div className="flex gap-1"> |
|
|
|
{peers.length > 0 ? ( |
|
|
|
<p className="text-lg font-semibold text-gray-900"> |
|
|
|
{`${peers.length} ${peers.length > 1 ? "Peers" : "Peer"}`} |
|
|
|
</p> |
|
|
|
) : ( |
|
|
|
<Mono className="m-auto">None Discovered.</Mono> |
|
|
|
)} |
|
|
|
</div> |
|
|
|
</Dropdown> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
<IconButton |
|
|
|
className="my-auto ml-auto" |
|
|
|
variant="secondary" |
|
|
|
size="sm" |
|
|
|
onClick={() => { |
|
|
|
setActivePage("peers"); |
|
|
|
}} |
|
|
|
icon={<EllipsisHorizontalIcon className="h-4" />} |
|
|
|
/> |
|
|
|
</div> |
|
|
|
); |
|
|
|
}; |
|
|
|
|