87 lines
2.4 KiB
TypeScript
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>
|
|
)
|
|
}
|