From c7db122ee8bde52e1a0140765cf66678f363dd26 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 25 Apr 2026 21:03:52 -0400 Subject: [PATCH] refactor(web): NodesPage reads node list from SDK signals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First consumer migration off the legacy Zustand nodeDBStore onto SDK-managed nodes. Pages/Nodes/index.tsx now pulls the full node array through useNodesLegacy() — which subscribes to the SDK NodesClient signal underneath — and applies the existing nodeFilter predicate client-side via useMemo. Behavior parity: - Same Protobuf.Mesh.NodeInfo shape rendered in the table (the legacy adapter ensures channel / viaMqtt / hopsAway / publicKey survive). - Same debounce semantics — only the underlying source changed. - hasNodeError + nodeErrors continue to come from the Zustand nodeDBStore until PKI-error tracking is migrated to the SDK in a follow-up commit (validation logic still in packages/web/src/core/stores/nodeDBStore/nodeValidation.ts). The legacy nodeDBStore still populates from subscriptions.ts, so this rewrite is reversible and runs alongside the SDK source. Web tests (295) still green; production Vite build clean. --- packages/web/src/pages/Nodes/index.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/web/src/pages/Nodes/index.tsx b/packages/web/src/pages/Nodes/index.tsx index e234d73c..e8f22640 100644 --- a/packages/web/src/pages/Nodes/index.tsx +++ b/packages/web/src/pages/Nodes/index.tsx @@ -10,11 +10,12 @@ 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 { useAppStore, useDevice, useNodeDB } from "@core/stores"; import { Protobuf, type Types } from "@meshtastic/sdk"; import { numberToHexUnpadded } from "@noble/curves/abstract/utils"; import { LockIcon, LockOpenIcon } from "lucide-react"; -import { type JSX, useCallback, useDeferredValue, useEffect, useState } from "react"; +import { type JSX, useCallback, useDeferredValue, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { base16 } from "rfc4648"; @@ -49,12 +50,15 @@ const NodesPage = (): JSX.Element => { [nodeFilter, deferredFilterState], ); - // subscribe to actual data (nodes array) and to nodeErrors ref for badge updates - const { nodes: filteredNodes, hasNodeError } = useNodeDB( + // 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 filteredNodes = useMemo(() => allSdkNodes.filter(predicate), [allSdkNodes, predicate]); + const { hasNodeError } = useNodeDB( (db) => ({ - nodes: db.getNodes(predicate, true), hasNodeError: db.hasNodeError, - _errorsRef: db.nodeErrors, // include the Map ref so UI also re-renders on error changes + _errorsRef: db.nodeErrors, }), { debounce: NODEDB_DEBOUNCE_MS }, );