feat: implement web mode for process detail fetching and management, enhance server routing for SPA

This commit is contained in:
Jonathan Atta
2026-03-12 09:29:37 +01:00
parent 3ad8bf68a4
commit 748e589159
2 changed files with 59 additions and 7 deletions

View File

@@ -5,6 +5,13 @@ import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Progress } from '@/components/ui/progress'
import { cn } from '@/lib/utils'
// Detect if running inside Wails desktop or as a standalone web app
const isWeb = !(window as any).__wails_ipc_active &&
typeof (window as any)['go'] === 'undefined'
// Base URL for web mode: same origin as the page
const apiBase = `${window.location.protocol}//${window.location.host}`
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
@@ -188,8 +195,9 @@ function ProcessDetailPanel({
const load = useCallback(async () => {
try {
// Use low-level Wails IPC — binding will be regenerated automatically
const d = await (window as any)['go']['main']['App']['GetProcessDetail'](pid) as ProcessDetail
const d: ProcessDetail = isWeb
? await fetch(`${apiBase}/api/process/${pid}`).then(r => { if (!r.ok) throw new Error(); return r.json() })
: await (window as any)['go']['main']['App']['GetProcessDetail'](pid) as ProcessDetail
setDetail(d)
} catch {
setDetail(null)
@@ -208,7 +216,12 @@ function ProcessDetailPanel({
setKilling(true)
setKillError(null)
try {
await (window as any)['go']['main']['App']['KillProcess'](pid, force)
if (isWeb) {
const res = await fetch(`${apiBase}/api/process/${pid}/kill${force ? '?force=true' : ''}`, { method: 'POST' })
if (!res.ok) throw new Error(await res.text())
} else {
await (window as any)['go']['main']['App']['KillProcess'](pid, force)
}
// stop refreshing — process is gone
if (intervalRef.current) clearInterval(intervalRef.current)
onClose()
@@ -231,10 +244,18 @@ function ProcessDetailPanel({
lastManNameRef.current = detail.name
setManPageLoading(true)
setManPage(null)
;(window as any)['go']['main']['App']['GetManPage'](detail.name)
.then((text: string) => { setManPage(text || null) })
.catch(() => setManPage(null))
.finally(() => setManPageLoading(false))
if (isWeb) {
fetch(`${apiBase}/api/man/${encodeURIComponent(detail.name)}`)
.then(r => r.ok ? r.text() : Promise.reject())
.then(text => setManPage(text || null))
.catch(() => setManPage(null))
.finally(() => setManPageLoading(false))
} else {
;(window as any)['go']['main']['App']['GetManPage'](detail.name)
.then((text: string) => { setManPage(text || null) })
.catch(() => setManPage(null))
.finally(() => setManPageLoading(false))
}
}, [detail?.name])
return (
@@ -541,6 +562,15 @@ export default function App() {
const [pageSize, setPageSize] = useState(20)
useEffect(() => {
if (isWeb) {
// Web mode: connect to SSE stream
const es = new EventSource(`${apiBase}/api/metrics/stream`)
es.onmessage = (e) => {
try { setMetrics(JSON.parse(e.data) as Metrics) } catch {}
}
return () => es.close()
}
// Wails desktop mode: listen to pushed events
const handler = (m: Metrics) => setMetrics(m)
EventsOn('metrics', handler)
return () => EventsOff('metrics')