mirror of
https://github.com/meshtastic/web.git
synced 2026-07-31 23:16:37 -04:00
refactor(web): rename node legacy adapters to *AsProto
The "Legacy" suffix on the node-adapter hooks reads as if the hook itself is deprecated, when in fact the hook is the bridge: it converts SDK Node domain entities into Protobuf.Mesh.NodeInfo so consumer templates that destructure proto fields keep working during the migration. - useNodesLegacy → useNodesAsProto - useNodeLegacy → useNodeAsProto - useMyNodeLegacy → useMyNodeAsProto - File renamed to packages/web/src/core/hooks/useNodesAsProto.ts. All 16 call sites updated. Test mock in packages/web/src/components/PageComponents/Messages/TraceRoute.test.tsx updated to the new module path. Behaviour unchanged. 295 tests still green; production Vite build clean. (useChatLegacy follows the same pattern but maps to a hand-written web type, not a proto — it stays as-is for now and is queued for renaming once the broader chat-store cleanup lands.)
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
||||
CommandList,
|
||||
} from "@components/UI/Command.tsx";
|
||||
import { usePinnedItems } from "@core/hooks/usePinnedItems.ts";
|
||||
import { useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useAppStore, useDevice, useDeviceStore } from "@core/stores";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
@@ -62,7 +62,7 @@ export const CommandPalette = () => {
|
||||
useAppStore();
|
||||
const { getDevices } = useDeviceStore();
|
||||
const { setDialogOpen, connection } = useDevice();
|
||||
const allNodes = useNodesLegacy();
|
||||
const allNodes = useNodesAsProto();
|
||||
const getNode = (n: number) => allNodes.find((node) => node.num === n);
|
||||
const { pinnedItems, togglePinnedItem } = usePinnedItems({
|
||||
storageName: "pinnedCommandMenuGroups",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import type { Protobuf, Types } from "@meshtastic/sdk";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -23,7 +23,7 @@ export const LocationResponseDialog = ({
|
||||
onOpenChange,
|
||||
}: LocationResponseDialogProps) => {
|
||||
const { t } = useTranslation("dialog");
|
||||
const from = useNodeLegacy(location?.from ?? 0);
|
||||
const from = useNodeAsProto(location?.from ?? 0);
|
||||
const longName =
|
||||
from?.user?.longName ?? (from ? `!${numberToHexUnpadded(from?.num)}` : t("unknown.shortName"));
|
||||
const shortName =
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { useFavoriteNode } from "@core/hooks/useFavoriteNode.ts";
|
||||
import { useIgnoreNode } from "@core/hooks/useIgnoreNode.ts";
|
||||
import { toast } from "@core/hooks/useToast.ts";
|
||||
import { useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useAppStore, useDevice } from "@core/stores";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
import { Protobuf } from "@meshtastic/sdk";
|
||||
@@ -59,7 +59,7 @@ export const NodeDetailsDialog = ({ open, onOpenChange }: NodeDetailsDialogProps
|
||||
const { updateFavorite } = useFavoriteNode();
|
||||
const { updateIgnored } = useIgnoreNode();
|
||||
|
||||
const node = useNodeLegacy(nodeNumDetails);
|
||||
const node = useNodeAsProto(nodeNumDetails);
|
||||
|
||||
const [isFavoriteState, setIsFavoriteState] = useState<boolean>(node?.isFavorite ?? false);
|
||||
const [isIgnoredState, setIsIgnoredState] = useState<boolean>(node?.isIgnored ?? false);
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@components/UI/Dialog.tsx";
|
||||
import { useMyNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useMyNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useDevice } from "@core/stores";
|
||||
import { fromByteArray } from "base64-js";
|
||||
import { DownloadIcon, PrinterIcon } from "lucide-react";
|
||||
@@ -23,7 +23,7 @@ export interface PkiBackupDialogProps {
|
||||
export const PkiBackupDialog = ({ open, onOpenChange }: PkiBackupDialogProps) => {
|
||||
const { t } = useTranslation("dialog");
|
||||
const { config, setDialogOpen } = useDevice();
|
||||
const myNode = useMyNodeLegacy();
|
||||
const myNode = useMyNodeAsProto();
|
||||
const privateKey = config.security?.privateKey;
|
||||
const publicKey = config.security?.publicKey;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Label } from "@components/UI/Label.tsx";
|
||||
import { useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useAppStore, useDevice, useNodeDB } from "@core/stores";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { DialogWrapper } from "./DialogWrapper.tsx";
|
||||
@@ -14,7 +14,7 @@ export const RemoveNodeDialog = ({ open, onOpenChange }: RemoveNodeDialogProps)
|
||||
const { connection } = useDevice();
|
||||
const { removeNode } = useNodeDB();
|
||||
const { nodeNumToBeRemoved } = useAppStore();
|
||||
const node = useNodeLegacy(nodeNumToBeRemoved);
|
||||
const node = useNodeAsProto(nodeNumToBeRemoved);
|
||||
|
||||
const handleConfirm = () => {
|
||||
connection?.removeNodeByNum(nodeNumToBeRemoved);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import type { Protobuf, Types } from "@meshtastic/sdk";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -29,14 +29,14 @@ export const TracerouteResponseDialog = ({
|
||||
const routeBack: number[] = traceroute?.data.routeBack ?? [];
|
||||
const snrTowards = (traceroute?.data.snrTowards ?? []).map((snr) => snr / 4);
|
||||
const snrBack = (traceroute?.data.snrBack ?? []).map((snr) => snr / 4);
|
||||
const from = useNodeLegacy(traceroute?.to ?? 0); // The origin of the traceroute = the "to" node of the mesh packet
|
||||
const from = useNodeAsProto(traceroute?.to ?? 0); // The origin of the traceroute = the "to" node of the mesh packet
|
||||
const fromLongName =
|
||||
from?.user?.longName ?? (from ? `!${numberToHexUnpadded(from?.num)}` : t("unknown.shortName"));
|
||||
const fromShortName =
|
||||
from?.user?.shortName ??
|
||||
(from ? `${numberToHexUnpadded(from?.num).substring(0, 4)}` : t("unknown.shortName"));
|
||||
|
||||
const toUser = useNodeLegacy(traceroute?.from ?? 0); // The destination of the traceroute = the "from" node of the mesh packet
|
||||
const toUser = useNodeAsProto(traceroute?.from ?? 0); // The destination of the traceroute = the "from" node of the mesh packet
|
||||
|
||||
if (!toUser || !from) {
|
||||
return null;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { TimeAgo } from "@components/generic/TimeAgo";
|
||||
import { Separator } from "@components/UI/Separator.tsx";
|
||||
import { useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import type { WaypointWithMetadata } from "@core/stores";
|
||||
import { bearingDegrees, distanceMeters, hasPos, toLngLat } from "@core/utils/geo";
|
||||
import type { Protobuf } from "@meshtastic/sdk";
|
||||
@@ -24,7 +24,7 @@ interface WaypointDetailProps {
|
||||
|
||||
export const WaypointDetail = ({ waypoint, myNode }: WaypointDetailProps) => {
|
||||
const { t } = useTranslation("map");
|
||||
const lockedToNode = useNodeLegacy(waypoint.lockedTo ?? 0);
|
||||
const lockedToNode = useNodeAsProto(waypoint.lockedTo ?? 0);
|
||||
|
||||
const waypointLngLat = toLngLat({
|
||||
latitudeI: waypoint.latitudeI,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@components/UI/Tooltip.tsx";
|
||||
import { useMyNodeLegacy, useNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useMyNodeAsProto, useNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { MessageState, useAppStore, useDevice } from "@core/stores";
|
||||
import type { Message } from "@core/stores/messageStore/types.ts";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
@@ -25,7 +25,7 @@ const myNodePromises = new Map<string, Promise<Protobuf.Mesh.NodeInfo>>();
|
||||
// gap between mount and first onMyNodeInfo packet on a fresh connect.
|
||||
function useSuspendingMyNode() {
|
||||
const selectedDeviceId = useAppStore((s) => s.selectedDeviceId);
|
||||
const myNode = useMyNodeLegacy();
|
||||
const myNode = useMyNodeAsProto();
|
||||
|
||||
if (!myNode) {
|
||||
const deviceKey = `device-${selectedDeviceId}`;
|
||||
@@ -44,7 +44,7 @@ function useSuspendingMyNode() {
|
||||
return;
|
||||
}
|
||||
// Resolve a no-op promise to retrigger the Suspense boundary;
|
||||
// the next render will call useMyNodeLegacy again.
|
||||
// the next render will call useMyNodeAsProto again.
|
||||
resolve({} as Protobuf.Mesh.NodeInfo);
|
||||
myNodePromises.delete(deviceKey);
|
||||
};
|
||||
@@ -94,7 +94,7 @@ interface MessageItemProps {
|
||||
export const MessageItem = ({ message }: MessageItemProps) => {
|
||||
const { config } = useDevice();
|
||||
const { t, i18n } = useTranslation("messages");
|
||||
const messageUserNode = useNodeLegacy(message.from ?? 0);
|
||||
const messageUserNode = useNodeAsProto(message.from ?? 0);
|
||||
|
||||
// This will suspend if myNode is not available yet
|
||||
const myNode = useSuspendingMyNode();
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { TraceRoute } from "@components/PageComponents/Messages/TraceRoute.tsx";
|
||||
import { useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { Protobuf } from "@meshtastic/sdk";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("@core/hooks/useNodesLegacy.ts");
|
||||
vi.mock("@core/hooks/useNodesAsProto.ts");
|
||||
|
||||
describe("TraceRoute", () => {
|
||||
const fromUser = {
|
||||
@@ -64,7 +64,7 @@ describe("TraceRoute", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
vi.mocked(useNodesLegacy).mockReturnValue(Array.from(mockNodes.values()));
|
||||
vi.mocked(useNodesAsProto).mockReturnValue(Array.from(mockNodes.values()));
|
||||
});
|
||||
|
||||
it("renders the route to destination with SNR values", () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import type { Protobuf } from "@meshtastic/sdk";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -23,7 +23,7 @@ interface RoutePathProps {
|
||||
}
|
||||
|
||||
const RoutePath = ({ title, from, to, path, snr }: RoutePathProps) => {
|
||||
const allNodes = useNodesLegacy();
|
||||
const allNodes = useNodesAsProto();
|
||||
const getNode = (n: number) => allNodes.find((node) => node.num === n);
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type UserValidation, UserValidationSchema } from "@app/validation/config/user.ts";
|
||||
import { create } from "@bufbuild/protobuf";
|
||||
import { DynamicForm, type DynamicFormFormInit } from "@components/Form/DynamicForm.tsx";
|
||||
import { useMyNodeLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useMyNodeAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useDevice } from "@core/stores";
|
||||
import { Protobuf } from "@meshtastic/sdk";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -14,7 +14,7 @@ export const User = ({ onFormInit }: UserConfigProps) => {
|
||||
const { getChange, connection } = useDevice();
|
||||
const { t } = useTranslation("config");
|
||||
|
||||
const myNode = useMyNodeLegacy();
|
||||
const myNode = useMyNodeAsProto();
|
||||
const defaultUser = myNode?.user ?? {
|
||||
id: "",
|
||||
longName: "",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { SidebarButton } from "@components/UI/Sidebar/SidebarButton.tsx";
|
||||
import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx";
|
||||
import { Spinner } from "@components/UI/Spinner.tsx";
|
||||
import { Subtle } from "@components/UI/Typography/Subtle.tsx";
|
||||
import { useMyNodeLegacy, useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useMyNodeAsProto, useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import {
|
||||
type Page,
|
||||
useActiveConnection,
|
||||
@@ -68,9 +68,9 @@ const CollapseToggleButton = () => {
|
||||
|
||||
export const Sidebar = ({ children }: SidebarProps) => {
|
||||
const { metadata, unreadCounts, setDialogOpen } = useDevice();
|
||||
const allNodes = useNodesLegacy();
|
||||
const allNodes = useNodesAsProto();
|
||||
const { setCommandPaletteOpen } = useAppStore();
|
||||
const myNode = useMyNodeLegacy();
|
||||
const myNode = useMyNodeAsProto();
|
||||
const getNodesLength = () => allNodes.length;
|
||||
const { isCollapsed } = useSidebar();
|
||||
const { t } = useTranslation("ui");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useNodeLegacy } from "@app/core/hooks/useNodesLegacy.ts";
|
||||
import { useNodeAsProto } from "@app/core/hooks/useNodesAsProto.ts";
|
||||
import { getColorFromNodeNum, isLightColor } from "@app/core/utils/color";
|
||||
import {
|
||||
Tooltip,
|
||||
@@ -28,7 +28,7 @@ export const Avatar = ({
|
||||
className,
|
||||
}: AvatarProps) => {
|
||||
const { t } = useTranslation();
|
||||
const node = useNodeLegacy(nodeNum);
|
||||
const node = useNodeAsProto(nodeNum);
|
||||
|
||||
if (!nodeNum) {
|
||||
return null;
|
||||
|
||||
@@ -13,12 +13,12 @@ import { useMemo } from "react";
|
||||
* every consumer reads `Node` from the SDK directly.
|
||||
*/
|
||||
|
||||
export function useNodesLegacy(): Protobuf.Mesh.NodeInfo[] {
|
||||
export function useNodesAsProto(): Protobuf.Mesh.NodeInfo[] {
|
||||
const nodes = useNodes();
|
||||
return useMemo(() => nodes.map(toNodeInfo), [nodes]);
|
||||
}
|
||||
|
||||
export function useNodeLegacy(nodeNum: number): Protobuf.Mesh.NodeInfo | undefined {
|
||||
export function useNodeAsProto(nodeNum: number): Protobuf.Mesh.NodeInfo | undefined {
|
||||
const nodes = useNodes();
|
||||
return useMemo(() => {
|
||||
const found = nodes.find((n) => n.num === nodeNum);
|
||||
@@ -31,7 +31,7 @@ export function useNodeLegacy(nodeNum: number): Protobuf.Mesh.NodeInfo | undefin
|
||||
* NodeInfo packet has been observed yet. Returns undefined while the
|
||||
* device is still configuring.
|
||||
*/
|
||||
export function useMyNodeLegacy(): Protobuf.Mesh.NodeInfo | undefined {
|
||||
export function useMyNodeAsProto(): Protobuf.Mesh.NodeInfo | undefined {
|
||||
const { myNodeNum } = useMeshDevice();
|
||||
const nodes = useNodes();
|
||||
return useMemo(() => {
|
||||
@@ -22,7 +22,7 @@ import type { PopupState } from "@components/PageComponents/Map/Popups/PopupWrap
|
||||
import { PageLayout } from "@components/PageLayout.tsx";
|
||||
import { Sidebar } from "@components/Sidebar.tsx";
|
||||
import { useMapFitting } from "@core/hooks/useMapFitting.ts";
|
||||
import { useMyNodeLegacy, useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useMyNodeAsProto, useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
import { hasPos, toLngLat } from "@core/utils/geo.ts";
|
||||
import type { Protobuf } from "@meshtastic/sdk";
|
||||
@@ -34,13 +34,13 @@ import { type MapLayerMouseEvent, useMap } from "react-map-gl/maplibre";
|
||||
|
||||
const MapPage = () => {
|
||||
const { t } = useTranslation("map");
|
||||
const allNodes = useNodesLegacy();
|
||||
const allNodes = useNodesAsProto();
|
||||
const getNode = useCallback((n: number) => allNodes.find((node) => node.num === n), [allNodes]);
|
||||
const validNodes = useMemo(
|
||||
() => allNodes.filter((n): n is Protobuf.Mesh.NodeInfo => Boolean(n.position?.latitudeI)),
|
||||
[allNodes],
|
||||
);
|
||||
const myNode = useMyNodeLegacy();
|
||||
const myNode = useMyNodeAsProto();
|
||||
const { nodeFilter, defaultFilterValues, isFilterDirty } = useFilterNode();
|
||||
const { default: mapRef } = useMap();
|
||||
const { focusLngLat, fitToNodes } = useMapFitting(mapRef);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Input } from "@components/UI/Input.tsx";
|
||||
import { SidebarButton } from "@components/UI/Sidebar/SidebarButton.tsx";
|
||||
import { SidebarSection } from "@components/UI/Sidebar/SidebarSection.tsx";
|
||||
import { useChatLegacy } from "@core/hooks/useChatLegacy.ts";
|
||||
import { useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useToast } from "@core/hooks/useToast.ts";
|
||||
import { MessageType, useDevice, useNodeDB, useSidebar } from "@core/stores";
|
||||
import { cn } from "@core/utils/cn.ts";
|
||||
@@ -34,7 +34,7 @@ function SelectMessageChat() {
|
||||
export const MessagesPage = () => {
|
||||
const { channels, getUnreadCount, resetUnread } = useDevice();
|
||||
const { hasNodeError } = useNodeDB();
|
||||
const allNodes = useNodesLegacy();
|
||||
const allNodes = useNodesAsProto();
|
||||
const getNode = (n: number) => allNodes.find((node) => node.num === n);
|
||||
const meshClient = useActiveClient();
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Sidebar } from "@components/Sidebar.tsx";
|
||||
import { Avatar } from "@components/UI/Avatar.tsx";
|
||||
import { Input } from "@components/UI/Input.tsx";
|
||||
import useLang from "@core/hooks/useLang.ts";
|
||||
import { useNodesLegacy } from "@core/hooks/useNodesLegacy.ts";
|
||||
import { useNodesAsProto } from "@core/hooks/useNodesAsProto.ts";
|
||||
import { useAppStore, useDevice, useNodeDB } from "@core/stores";
|
||||
import { Protobuf, type Types } from "@meshtastic/sdk";
|
||||
import { numberToHexUnpadded } from "@noble/curves/abstract/utils";
|
||||
@@ -53,7 +53,7 @@ const NodesPage = (): JSX.Element => {
|
||||
// Nodes come from the SDK NodesClient (signals + sqlocal-backed history).
|
||||
// hasNodeError still lives on the legacy nodeDB store — node-validation /
|
||||
// PKI-error tracking has not been migrated to the SDK yet.
|
||||
const allSdkNodes = useNodesLegacy();
|
||||
const allSdkNodes = useNodesAsProto();
|
||||
const filteredNodes = useMemo(() => allSdkNodes.filter(predicate), [allSdkNodes, predicate]);
|
||||
const { hasNodeError } = useNodeDB(
|
||||
(db) => ({
|
||||
|
||||
Reference in New Issue
Block a user