Files
XCDesktop/src/modules/opencode/OpenCodePage.tsx

87 lines
2.4 KiB
TypeScript

import React, { useEffect, useState, useRef } from 'react'
export const OpenCodePage: React.FC = () => {
const [isHealthy, setIsHealthy] = useState(false)
const [port, setPort] = useState<number>(9999)
const startedRef = useRef(false)
const restartingRef = useRef(false)
const webviewRef = useRef<HTMLWebViewElement>(null)
useEffect(() => {
let mounted = true
const start = async () => {
try {
const portResult = await window.electronAPI.xcOpenCodeWebGetPort()
if (mounted) {
setPort(portResult.port)
}
const result = await window.electronAPI.xcOpenCodeWebStart()
if (!result.success && mounted) {
console.error('Failed to start XCOpenCodeWeb:', result.error)
}
restartingRef.current = false
} catch (err) {
console.error('Failed to start XCOpenCodeWeb:', err)
restartingRef.current = false
}
}
const checkStatus = async () => {
try {
const status = await window.electronAPI.xcOpenCodeWebGetStatus()
if (mounted) {
setIsHealthy(status.running)
if (!status.running && !restartingRef.current) {
restartingRef.current = true
start()
}
}
} catch (err) {
if (mounted) {
setIsHealthy(false)
if (!restartingRef.current) {
restartingRef.current = true
start()
}
}
}
}
if (!startedRef.current) {
startedRef.current = true
start()
}
const interval = setInterval(checkStatus, 2000)
return () => {
mounted = false
clearInterval(interval)
window.electronAPI.xcOpenCodeWebStop()
startedRef.current = false
}
}, [])
return (
<div className="h-full w-full relative">
<span className={`absolute bottom-2 right-2 z-10 w-1.5 h-1.5 rounded-full ${isHealthy ? 'bg-green-500' : 'bg-red-500'}`} />
{!isHealthy && (
<div className="absolute inset-0 flex items-center justify-center">
<div className="w-8 h-8 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" />
</div>
)}
{isHealthy && (
<webview
ref={webviewRef}
src={`http://localhost:${port}`}
style={{ width: '100%', height: '100%', border: 'none' }}
allowpopups={true}
webpreferences="contextIsolation=no"
/>
)}
</div>
)
}