From 523cdbc8f9be3fc128417627bee8ace605fe8d03 Mon Sep 17 00:00:00 2001 From: tpaulsoncdw Date: Fri, 13 Jun 2025 17:16:41 +0000 Subject: [PATCH] Remove HTTP server status checking - Remove automatic server status checking from HTTP components - Eliminate status tracking overhead in HTTPServerSection and HTTP tab - Simplify persistent server list by removing status indicators - Clean up unused imports and status-related functions - Replace || with ?? for nullish coalescing consistency --- src/components/Dashboard/BluetoothSection.tsx | 10 +- .../Dashboard/HTTPServerSection.tsx | 105 +----------------- src/components/Dashboard/SerialSection.tsx | 12 +- .../PageComponents/Connect/HTTP.test.tsx | 51 ++++++--- .../PageComponents/Connect/HTTP.tsx | 79 +------------ 5 files changed, 48 insertions(+), 209 deletions(-) diff --git a/src/components/Dashboard/BluetoothSection.tsx b/src/components/Dashboard/BluetoothSection.tsx index bfd8838b..e2f0ba69 100644 --- a/src/components/Dashboard/BluetoothSection.tsx +++ b/src/components/Dashboard/BluetoothSection.tsx @@ -61,7 +61,7 @@ export const BluetoothSection = ({ onConnect }: BluetoothSectionProps) => { onConnect?.(); } catch (error) { console.error("Bluetooth connection error:", error); - setConnectionError(`Failed to connect to ${bleDevice.name || "device"}`); + setConnectionError(`Failed to connect to ${bleDevice.name ?? "device"}`); } finally { setConnectingToDevice(null); } @@ -102,11 +102,11 @@ export const BluetoothSection = ({ onConnect }: BluetoothSectionProps) => { return ( ); - } else if (isConnected) { + } + if (isConnected) { return ; - } else { - return ; } + return ; }; const getStatusText = (device: BluetoothDevice) => { @@ -148,7 +148,7 @@ export const BluetoothSection = ({ onConnect }: BluetoothSectionProps) => {
- {device.name || "Unknown Device"} + {device.name ?? "Unknown Device"}
diff --git a/src/components/Dashboard/HTTPServerSection.tsx b/src/components/Dashboard/HTTPServerSection.tsx index 683bc842..cdb44290 100644 --- a/src/components/Dashboard/HTTPServerSection.tsx +++ b/src/components/Dashboard/HTTPServerSection.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import { Button } from "@components/UI/Button.tsx"; import { Input } from "@components/UI/Input.tsx"; import { Label } from "@components/UI/Label.tsx"; @@ -18,14 +18,12 @@ import { TransportHTTP } from "@meshtastic/transport-http"; import { useForm } from "react-hook-form"; import { AlertTriangle, - Circle, Clock, Lock, LockOpen, Plus, Server, Trash2, - Users, Wifi, } from "lucide-react"; import { useMessageStore } from "@core/stores/messageStore/index.ts"; @@ -56,7 +54,6 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { addSavedServer, removeSavedServer, clearSavedServers, - updateServerStatus, getSavedServers, } = useAppStore(); @@ -77,48 +74,6 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { const secureValue = watch("secure"); - // Auto-check server status on component mount - useEffect(() => { - savedServers.forEach((server) => { - if (server.status !== "checking") { - checkServerStatus(server); - } - }); - }, []); - - const checkServerStatus = async (server: SavedServer) => { - updateServerStatus(server.url, "checking"); - - try { - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 8000); - - const response = await fetch(`${server.url}/api/v1/fromradio?all=false`, { - method: "GET", - mode: "cors", - signal: controller.signal, - }); - - clearTimeout(timeoutId); - - if (response.ok) { - updateServerStatus(server.url, "online"); - } else { - const fallbackResponse = await fetch(`${server.url}/`, { - method: "GET", - mode: "cors", - signal: AbortSignal.timeout(3000), - }); - updateServerStatus( - server.url, - fallbackResponse.ok ? "online" : "offline", - ); - } - } catch { - updateServerStatus(server.url, "offline"); - } - }; - const connectToServer = async (server: SavedServer) => { setConnectingToServer(server.url); setConnectionError(null); @@ -137,13 +92,11 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { subscribeAll(device, connection, messageStore); addSavedServer(server.host, server.protocol); - updateServerStatus(server.url, "online"); onConnect?.(); } catch (error) { console.error("Connection error:", error); setConnectionError(`Failed to connect to ${server.host}`); - updateServerStatus(server.url, "offline"); } finally { setConnectingToServer(null); } @@ -177,40 +130,12 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { } }); - const getStatusIcon = (status?: string) => { - switch (status) { - case "online": - return ; - case "offline": - return ; - case "checking": - return ( - - ); - default: - return ; - } - }; - const getSecurityIcon = (protocol: "http" | "https") => { return protocol === "https" ? : ; }; - const getStatusText = (status?: string) => { - switch (status) { - case "online": - return "Online"; - case "offline": - return "Offline"; - case "checking": - return "Checking..."; - default: - return "Unknown"; - } - }; - return ( <>
@@ -249,11 +174,6 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { key={server.url} className="flex items-center gap-3 p-3 rounded-lg bg-white dark:bg-slate-700 border border-slate-200 dark:border-slate-600 hover:shadow-sm transition-shadow" > - {/* Status */} -
- {getStatusIcon(server.status)} -
- {/* Server Info */}
@@ -262,29 +182,6 @@ export const HTTPServerSection = ({ onConnect }: HTTPServerSectionProps) => { {getSecurityIcon(server.protocol)}
- -
- {getStatusText(server.status)} - - {server.deviceInfo?.model && ( - <> - - - {server.deviceInfo.model} - - - )} - - {server.deviceInfo?.nodeCount && ( - <> - - - - {server.deviceInfo.nodeCount} - - - )} -
{/* Actions */} diff --git a/src/components/Dashboard/SerialSection.tsx b/src/components/Dashboard/SerialSection.tsx index 8b9a8060..0bef441f 100644 --- a/src/components/Dashboard/SerialSection.tsx +++ b/src/components/Dashboard/SerialSection.tsx @@ -27,7 +27,7 @@ export const SerialSection = ({ onConnect }: SerialSectionProps) => { const updateSerialPortList = useCallback(async () => { try { - setSerialPorts(await navigator?.serial?.getPorts() || []); + setSerialPorts((await navigator?.serial?.getPorts()) ?? []); } catch (error) { console.error("Error getting serial ports:", error); } @@ -111,11 +111,11 @@ export const SerialSection = ({ onConnect }: SerialSectionProps) => { return ( ); - } else if (isConnected) { + } + if (isConnected) { return ; - } else { - return ; } + return ; }; const getStatusText = (port: SerialPort) => { @@ -145,7 +145,9 @@ export const SerialSection = ({ onConnect }: SerialSectionProps) => { : ( serialPorts.map((port, index) => (
{/* Status */} diff --git a/src/components/PageComponents/Connect/HTTP.test.tsx b/src/components/PageComponents/Connect/HTTP.test.tsx index 4422c949..197b4bad 100644 --- a/src/components/PageComponents/Connect/HTTP.test.tsx +++ b/src/components/PageComponents/Connect/HTTP.test.tsx @@ -5,7 +5,13 @@ import { TransportHTTP } from "@meshtastic/transport-http"; import { describe, expect, it, vi } from "vitest"; vi.mock("@core/stores/appStore.ts", () => ({ - useAppStore: vi.fn(() => ({ setSelectedDevice: vi.fn() })), + useAppStore: vi.fn(() => ({ + setSelectedDevice: vi.fn(), + addSavedServer: vi.fn(), + removeSavedServer: vi.fn(), + clearSavedServers: vi.fn(), + getSavedServers: vi.fn(() => []), + })), })); vi.mock("@core/stores/deviceStore.ts", () => ({ @@ -14,10 +20,18 @@ vi.mock("@core/stores/deviceStore.ts", () => ({ })), })); +vi.mock("@core/stores/messageStore/index.ts", () => ({ + useMessageStore: vi.fn(() => ({})), +})); + vi.mock("@core/utils/randId.ts", () => ({ randId: vi.fn(() => "mock-id"), })); +vi.mock("@core/subscriptions.ts", () => ({ + subscribeAll: vi.fn(), +})); + vi.mock("@meshtastic/transport-http", () => ({ TransportHTTP: { create: vi.fn(() => Promise.resolve({})), @@ -33,34 +47,35 @@ vi.mock("@meshtastic/core", () => ({ describe("HTTP Component", () => { it("renders correctly", () => { render(); - expect(screen.getByText("IP Address/Hostname")).toBeInTheDocument(); - expect(screen.getByRole("textbox")).toBeInTheDocument(); - expect(screen.getByPlaceholderText("000.000.000.000 / meshtastic.local")) - .toBeInTheDocument(); - expect(screen.getByText("Use HTTPS")).toBeInTheDocument(); - expect(screen.getByRole("button", { name: "Connect" })).toBeInTheDocument(); + expect(screen.getByText("Meshtastic Servers")).toBeInTheDocument(); + expect(screen.getByText("Add New Server")).toBeInTheDocument(); + expect(screen.getByText("No saved servers yet")).toBeInTheDocument(); }); - it("allows input field to be updated", () => { + it("opens dialog when add new server is clicked", () => { render(); - const inputField = screen.getByRole("textbox"); - fireEvent.change(inputField, { target: { value: "meshtastic.local" } }); - expect(screen.getByPlaceholderText("000.000.000.000 / meshtastic.local")) + const addButton = screen.getByText("Add New Server"); + fireEvent.click(addButton); + expect(screen.getByText("Hostname or IP Address")).toBeInTheDocument(); + expect(screen.getByPlaceholderText("meshtastic.local or 192.168.1.100")) .toBeInTheDocument(); }); - it("toggles HTTPS switch and updates prefix", () => { + it("toggles HTTPS switch in dialog", () => { render(); + // Open the dialog first + const addButton = screen.getByText("Add New Server"); + fireEvent.click(addButton); + const switchInput = screen.getByRole("switch"); - expect(screen.getByText("http://")).toBeInTheDocument(); + expect(screen.getByText("Use HTTPS (Secure)")).toBeInTheDocument(); fireEvent.click(switchInput); - expect(screen.getByText("https://")).toBeInTheDocument(); + expect(switchInput).toBeChecked(); fireEvent.click(switchInput); expect(switchInput).not.toBeChecked(); - expect(screen.getByText("http://")).toBeInTheDocument(); }); it("enables HTTPS toggle when location protocol is https", () => { @@ -71,10 +86,12 @@ describe("HTTP Component", () => { render(); + // Open the dialog first + const addButton = screen.getByText("Add New Server"); + fireEvent.click(addButton); + const switchInput = screen.getByRole("switch"); expect(switchInput).toBeChecked(); - - expect(screen.getByText("https://")).toBeInTheDocument(); }); it.skip("submits form and triggers connection process", async () => { diff --git a/src/components/PageComponents/Connect/HTTP.tsx b/src/components/PageComponents/Connect/HTTP.tsx index b8ff9e6c..9db11fab 100644 --- a/src/components/PageComponents/Connect/HTTP.tsx +++ b/src/components/PageComponents/Connect/HTTP.tsx @@ -15,7 +15,7 @@ import { subscribeAll } from "@core/subscriptions.ts"; import { randId } from "@core/utils/randId.ts"; import { MeshDevice } from "@meshtastic/core"; import { TransportHTTP } from "@meshtastic/transport-http"; -import { useCallback, useEffect, useState } from "react"; +import { useState } from "react"; import { useForm } from "react-hook-form"; import { AlertTriangle, @@ -54,7 +54,6 @@ export const HTTP = ({ closeDialog }: TabElementProps) => { addSavedServer, removeSavedServer, clearSavedServers, - updateServerStatus, getSavedServers, } = useAppStore(); @@ -75,80 +74,6 @@ export const HTTP = ({ closeDialog }: TabElementProps) => { const secureValue = watch("secure"); - const checkServerStatus = useCallback( - async (server: SavedServer) => { - updateServerStatus(server.url, "checking"); - - try { - const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), 8000); - - // Try to get actual device info from fromradio endpoint - const response = await fetch( - `${server.url}/api/v1/fromradio?all=false`, - { - method: "GET", - mode: "cors", - signal: controller.signal, - }, - ); - - clearTimeout(timeoutId); - - if (response.ok) { - // Try to get basic device info if available - try { - // First check if we can get a simple status response - const statusResponse = await fetch( - `${server.url}/api/v1/fromradio`, - { - method: "GET", - mode: "cors", - signal: AbortSignal.timeout(3000), - }, - ); - - if (statusResponse.ok) { - // For now, just mark as online - we could parse protobuf later for device details - updateServerStatus(server.url, "online"); - - // TODO: Parse protobuf response to get device info - // This would require proper protobuf decoding which is complex - // For now, we'll show it as online and get device info after connection - } else { - updateServerStatus(server.url, "offline"); - } - } catch { - // If fromradio fails, try the simpler status endpoint - const fallbackResponse = await fetch(`${server.url}/`, { - method: "GET", - mode: "cors", - signal: AbortSignal.timeout(3000), - }); - updateServerStatus( - server.url, - fallbackResponse.ok ? "online" : "offline", - ); - } - } else { - updateServerStatus(server.url, "offline"); - } - } catch { - updateServerStatus(server.url, "offline"); - } - }, - [updateServerStatus], - ); - - // Auto-check server status on component mount - useEffect(() => { - for (const server of savedServers) { - if (server.status !== "checking") { - checkServerStatus(server); - } - } - }, [savedServers, checkServerStatus]); - const connectToServer = async (server: SavedServer) => { setConnectingToServer(server.url); setConnectionError(null); @@ -168,13 +93,11 @@ export const HTTP = ({ closeDialog }: TabElementProps) => { // Update last used time addSavedServer(server.host, server.protocol); - updateServerStatus(server.url, "online"); closeDialog(); } catch (error) { console.error("Connection error:", error); setConnectionError(`Failed to connect to ${server.host}`); - updateServerStatus(server.url, "offline"); } finally { setConnectingToServer(null); }