mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 14:22:09 +03:00
Integrated into release/v3.8.34 (adapted onto #4606's extracted topology section: default-hidden flip + enabled gate on useLiveDashboard)
This commit is contained in:
@@ -196,7 +196,9 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {
|
||||
// Appearance settings for home page pinning
|
||||
const [pinProviderQuotaToHome, setPinProviderQuotaToHome] = useState(false);
|
||||
const [showQuickStartOnHome, setShowQuickStartOnHome] = useState(true); // default on
|
||||
const [showProviderTopologyOnHome, setShowProviderTopologyOnHome] = useState(true); // default on
|
||||
// #4596: default hidden until appearance settings load, so the live-WS
|
||||
// topology connection is never opened before we know the user wants it.
|
||||
const [showProviderTopologyOnHome, setShowProviderTopologyOnHome] = useState(false);
|
||||
const [autoRefreshProviderQuota, setAutoRefreshProviderQuota] = useState(false);
|
||||
const [autoRefreshProviderQuotaInterval, setAutoRefreshProviderQuotaInterval] = useState(180);
|
||||
const [appearanceSettingsLoaded, setAppearanceSettingsLoaded] = useState(false);
|
||||
@@ -1165,6 +1167,7 @@ export default function HomePageClient({ machineId }: HomePageClientProps) {
|
||||
providers={topologyProviders}
|
||||
lastProvider={lastProvider}
|
||||
errorProvider={errorProvider}
|
||||
enabled={showProviderTopologyOnHome}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -19,13 +19,17 @@ export function HomeProviderTopologySection({
|
||||
providers,
|
||||
lastProvider,
|
||||
errorProvider,
|
||||
enabled = true,
|
||||
}: {
|
||||
providers: TopologyProvider[];
|
||||
lastProvider: string;
|
||||
errorProvider: string;
|
||||
enabled?: boolean;
|
||||
}) {
|
||||
const t = useTranslations("home");
|
||||
const { activeRequests: liveActiveRequests } = useLiveRequests();
|
||||
// #4596: gate the live-WS connection so it only opens while the topology
|
||||
// section is actually shown on the home page.
|
||||
const { activeRequests: liveActiveRequests } = useLiveRequests({ enabled });
|
||||
|
||||
return (
|
||||
<Card>
|
||||
|
||||
@@ -50,6 +50,8 @@ export interface DashboardConnectionState {
|
||||
export interface UseLiveDashboardOptions {
|
||||
/** WebSocket URL (default: ws://hostname:20129) */
|
||||
wsUrl?: string;
|
||||
/** Whether the WebSocket connection should be active (default: true) */
|
||||
enabled?: boolean;
|
||||
/** API key for authentication */
|
||||
apiKey?: string;
|
||||
/** Channels to subscribe to */
|
||||
@@ -66,6 +68,7 @@ export interface UseLiveDashboardOptions {
|
||||
*/
|
||||
export function useLiveDashboard({
|
||||
wsUrl = DEFAULT_WS_URL,
|
||||
enabled = true,
|
||||
apiKey,
|
||||
channels = ["requests", "combo", "credentials"],
|
||||
autoReconnect = true,
|
||||
@@ -202,6 +205,23 @@ export function useLiveDashboard({
|
||||
|
||||
// Connect on mount and on reconnect trigger
|
||||
useEffect(() => {
|
||||
mountedRef.current = true;
|
||||
if (!enabled) {
|
||||
if (reconnectTimeoutRef.current) {
|
||||
clearTimeout(reconnectTimeoutRef.current);
|
||||
reconnectTimeoutRef.current = null;
|
||||
}
|
||||
wsRef.current?.close();
|
||||
wsRef.current = null;
|
||||
setConnection({
|
||||
isConnected: false,
|
||||
isConnecting: false,
|
||||
error: null,
|
||||
reconnectAttempt: 0,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
connect();
|
||||
return () => {
|
||||
mountedRef.current = false;
|
||||
@@ -210,7 +230,7 @@ export function useLiveDashboard({
|
||||
}
|
||||
wsRef.current?.close();
|
||||
};
|
||||
}, [connect]);
|
||||
}, [connect, enabled]);
|
||||
|
||||
// Connect (for manual retry)
|
||||
const reconnect = useCallback(() => {
|
||||
|
||||
68
tests/unit/ui/home-topology-hidden-4596.test.tsx
Normal file
68
tests/unit/ui/home-topology-hidden-4596.test.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
// @vitest-environment jsdom
|
||||
import React, { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useLiveRequests } from "../../../src/hooks/useLiveDashboard";
|
||||
|
||||
function LiveRequestsHarness({ enabled }: { enabled: boolean }) {
|
||||
useLiveRequests({ enabled });
|
||||
return null;
|
||||
}
|
||||
|
||||
describe("home topology hidden networking (#4596)", () => {
|
||||
const websocketMock = vi.fn();
|
||||
let root: ReturnType<typeof createRoot> | null = null;
|
||||
let container: HTMLDivElement | null = null;
|
||||
|
||||
beforeEach(() => {
|
||||
(
|
||||
globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
|
||||
).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
websocketMock.mockClear();
|
||||
vi.stubGlobal(
|
||||
"WebSocket",
|
||||
class WebSocketMock {
|
||||
static OPEN = 1;
|
||||
readyState = 0;
|
||||
onopen: (() => void) | null = null;
|
||||
onmessage: ((event: MessageEvent) => void) | null = null;
|
||||
onclose: (() => void) | null = null;
|
||||
onerror: (() => void) | null = null;
|
||||
|
||||
constructor(url: string) {
|
||||
websocketMock(url);
|
||||
}
|
||||
|
||||
send() {}
|
||||
close() {}
|
||||
}
|
||||
);
|
||||
container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
act(() => {
|
||||
root?.unmount();
|
||||
});
|
||||
container?.remove();
|
||||
root = null;
|
||||
container = null;
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("does NOT open a WebSocket when the topology section is disabled", () => {
|
||||
act(() => {
|
||||
root!.render(<LiveRequestsHarness enabled={false} />);
|
||||
});
|
||||
expect(websocketMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("opens a WebSocket when the topology section is enabled", () => {
|
||||
act(() => {
|
||||
root!.render(<LiveRequestsHarness enabled={true} />);
|
||||
});
|
||||
expect(websocketMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user