Files
ruvnet--RuView/v2/crates/wifi-densepose-desktop/ui/src/hooks/useServer.ts
T
rUv f49c722764 chore(repo): rename rust-port/wifi-densepose-rs → v2/ (flatten to one level) (#427)
The Rust port lived two directories deep (rust-port/wifi-densepose-rs/)
without any sibling under rust-port/ that warranted the extra level.
Move the whole workspace up to v2/ to match v1/ (Python) at the same
depth and shorten every cd / build command across the repo.

git mv preserves history for all tracked files. 60 files updated for
path references (CI workflows, ADRs, docs, scripts, READMEs, internal
.claude-flow state). Two manual fixes for relative-cd paths in
CLAUDE.md and ADR-043 that became wrong after the depth change
(cd ../.. → cd ..).

Validated:
- cargo check --workspace --no-default-features → clean (after target/
  nuke; the gitignored target/ was carried by the OS rename and had
  hard-coded old paths in build scripts)
- cargo test --workspace --no-default-features → 1,539 passed, 0 failed,
  8 ignored (same totals as pre-rename)
- ESP32-S3 on COM7 → still streaming live CSI (cb #40300, RSSI -64 dBm)

After-merge follow-up: contributors should `rm -rf v2/target` once and
let cargo regenerate from the new path.
2026-04-25 21:28:13 -04:00

109 lines
2.7 KiB
TypeScript

import { useState, useEffect, useCallback, useRef } from "react";
import { invoke } from "@tauri-apps/api/core";
import type { ServerConfig, ServerStatus } from "../types";
const DEFAULT_CONFIG: ServerConfig = {
http_port: 8080,
ws_port: 8765,
udp_port: 5005,
static_dir: null,
model_dir: null,
log_level: "info",
source: "simulate",
};
interface UseServerOptions {
/** Poll interval for status checks in ms. Default: 5000 */
pollInterval?: number;
}
interface UseServerReturn {
status: ServerStatus | null;
isRunning: boolean;
error: string | null;
start: (config?: Partial<ServerConfig>) => Promise<void>;
stop: () => Promise<void>;
refresh: () => Promise<void>;
}
export function useServer(options: UseServerOptions = {}): UseServerReturn {
const { pollInterval = 5000 } = options;
const [status, setStatus] = useState<ServerStatus | null>(null);
const [error, setError] = useState<string | null>(null);
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
const refresh = useCallback(async () => {
try {
const s = await invoke<ServerStatus>("server_status");
setStatus(s);
setError(null);
} catch (err) {
const message =
err instanceof Error ? err.message : String(err);
setError(message);
}
}, []);
const start = useCallback(
async (overrides: Partial<ServerConfig> = {}) => {
setError(null);
const config: ServerConfig = { ...DEFAULT_CONFIG, ...overrides };
try {
await invoke("start_server", { config });
// Allow the server a moment to start, then refresh status
await new Promise((r) => setTimeout(r, 500));
await refresh();
} catch (err) {
const message =
err instanceof Error ? err.message : String(err);
setError(message);
}
},
[refresh]
);
const stop = useCallback(async () => {
setError(null);
try {
await invoke("stop_server");
await new Promise((r) => setTimeout(r, 300));
await refresh();
} catch (err) {
const message =
err instanceof Error ? err.message : String(err);
setError(message);
}
}, [refresh]);
// Initial status check
useEffect(() => {
refresh();
}, [refresh]);
// Polling
useEffect(() => {
if (pollInterval <= 0) return;
intervalRef.current = setInterval(refresh, pollInterval);
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
}, [pollInterval, refresh]);
const isRunning = status?.running ?? false;
return {
status,
isRunning,
error,
start,
stop,
refresh,
};
}