mirror of
https://github.com/ruvnet/RuView
synced 2026-08-02 19:11:46 +00:00
f49c722764
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.
109 lines
2.7 KiB
TypeScript
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,
|
|
};
|
|
}
|