2025-10-15 22:30:49 +08:00
|
|
|
import { useState, useEffect } from 'react';
|
|
|
|
|
import { invoke } from '@tauri-apps/api/core';
|
2025-10-18 20:21:43 +08:00
|
|
|
import { X, Server, WifiOff, Wifi } from 'lucide-react';
|
|
|
|
|
import { SettingsService } from '../services/SettingsService';
|
2025-12-09 11:07:44 +08:00
|
|
|
import { getProfilerService } from '../services/getService';
|
2025-10-15 22:30:49 +08:00
|
|
|
import '../styles/PortManager.css';
|
|
|
|
|
|
|
|
|
|
interface PortManagerProps {
|
|
|
|
|
onClose: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function PortManager({ onClose }: PortManagerProps) {
|
2025-11-02 23:50:41 +08:00
|
|
|
const [isServerRunning, setIsServerRunning] = useState(false);
|
|
|
|
|
const [serverPort, setServerPort] = useState<string>('8080');
|
|
|
|
|
const [isChecking, setIsChecking] = useState(false);
|
|
|
|
|
const [isStopping, setIsStopping] = useState(false);
|
|
|
|
|
const [isStarting, setIsStarting] = useState(false);
|
2025-10-18 20:21:43 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
const settings = SettingsService.getInstance();
|
2025-12-01 22:28:51 +08:00
|
|
|
const savedPort = settings.get('profiler.port', 8080);
|
|
|
|
|
console.log('[PortManager] Initial port from settings:', savedPort);
|
|
|
|
|
setServerPort(String(savedPort));
|
2025-10-18 20:21:43 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
const handleSettingsChange = ((event: CustomEvent) => {
|
2025-12-01 22:28:51 +08:00
|
|
|
console.log('[PortManager] settings:changed event received:', event.detail);
|
2025-11-02 23:50:41 +08:00
|
|
|
const newPort = event.detail['profiler.port'];
|
2025-12-01 22:28:51 +08:00
|
|
|
if (newPort !== undefined) {
|
|
|
|
|
console.log('[PortManager] Updating port to:', newPort);
|
|
|
|
|
setServerPort(String(newPort));
|
2025-11-02 23:50:41 +08:00
|
|
|
}
|
|
|
|
|
}) as EventListener;
|
2025-10-18 20:21:43 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
window.addEventListener('settings:changed', handleSettingsChange);
|
2025-10-18 20:21:43 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('settings:changed', handleSettingsChange);
|
|
|
|
|
};
|
|
|
|
|
}, []);
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
useEffect(() => {
|
|
|
|
|
checkServerStatus();
|
|
|
|
|
}, []);
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
const checkServerStatus = async () => {
|
|
|
|
|
setIsChecking(true);
|
|
|
|
|
try {
|
|
|
|
|
const status = await invoke<boolean>('get_profiler_status');
|
|
|
|
|
setIsServerRunning(status);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('[PortManager] Failed to check server status:', error);
|
|
|
|
|
setIsServerRunning(false);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsChecking(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
const handleStopServer = async () => {
|
|
|
|
|
setIsStopping(true);
|
|
|
|
|
try {
|
2025-12-09 11:07:44 +08:00
|
|
|
const profilerService = getProfilerService();
|
2025-11-02 23:50:41 +08:00
|
|
|
if (profilerService) {
|
|
|
|
|
await profilerService.manualStopServer();
|
|
|
|
|
setIsServerRunning(false);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('[PortManager] Failed to stop server:', error);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsStopping(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-18 20:21:43 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
const handleStartServer = async () => {
|
|
|
|
|
setIsStarting(true);
|
|
|
|
|
try {
|
2025-12-09 11:07:44 +08:00
|
|
|
const profilerService = getProfilerService();
|
2025-11-02 23:50:41 +08:00
|
|
|
if (profilerService) {
|
|
|
|
|
await profilerService.manualStartServer();
|
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
|
|
|
await checkServerStatus();
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('[PortManager] Failed to start server:', error);
|
|
|
|
|
} finally {
|
|
|
|
|
setIsStarting(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
return (
|
|
|
|
|
<div className="port-manager-overlay" onClick={onClose}>
|
|
|
|
|
<div className="port-manager" onClick={(e) => e.stopPropagation()}>
|
|
|
|
|
<div className="port-manager-header">
|
|
|
|
|
<div className="port-manager-title">
|
|
|
|
|
<Server size={20} />
|
|
|
|
|
<h2>Port Manager</h2>
|
|
|
|
|
</div>
|
|
|
|
|
<button className="port-manager-close" onClick={onClose} title="Close">
|
|
|
|
|
<X size={20} />
|
|
|
|
|
</button>
|
2025-10-15 22:30:49 +08:00
|
|
|
</div>
|
|
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
<div className="port-manager-content">
|
|
|
|
|
<div className="port-section">
|
|
|
|
|
<h3>Profiler Server</h3>
|
|
|
|
|
<div className="port-info">
|
|
|
|
|
<div className="port-item">
|
|
|
|
|
<span className="port-label">Status:</span>
|
|
|
|
|
<span className={`port-status ${isServerRunning ? 'running' : 'stopped'}`}>
|
|
|
|
|
{isChecking ? 'Checking...' : isServerRunning ? 'Running' : 'Stopped'}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
{isServerRunning && (
|
|
|
|
|
<div className="port-item">
|
|
|
|
|
<span className="port-label">Port:</span>
|
|
|
|
|
<span className="port-value">{serverPort}</span>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
{isServerRunning && (
|
|
|
|
|
<div className="port-actions">
|
|
|
|
|
<button
|
|
|
|
|
className="action-btn danger"
|
|
|
|
|
onClick={handleStopServer}
|
|
|
|
|
disabled={isStopping}
|
|
|
|
|
>
|
|
|
|
|
<WifiOff size={16} />
|
|
|
|
|
<span>{isStopping ? 'Stopping...' : 'Stop Server'}</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-10-15 22:30:49 +08:00
|
|
|
|
2025-11-02 23:50:41 +08:00
|
|
|
{!isServerRunning && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="port-actions">
|
|
|
|
|
<button
|
|
|
|
|
className="action-btn primary"
|
|
|
|
|
onClick={handleStartServer}
|
|
|
|
|
disabled={isStarting}
|
|
|
|
|
>
|
|
|
|
|
<Wifi size={16} />
|
|
|
|
|
<span>{isStarting ? 'Starting...' : 'Start Server'}</span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="port-hint">
|
|
|
|
|
<p>No server is currently running.</p>
|
|
|
|
|
<p className="hint-text">Click "Start Server" to start the profiler server.</p>
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="port-tips">
|
|
|
|
|
<h4>Tips</h4>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Use this when the Profiler server port is stuck and cannot be restarted</li>
|
|
|
|
|
<li>The server will automatically stop when the Profiler window is closed</li>
|
|
|
|
|
<li>Current configured port: {serverPort}</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-10-15 22:30:49 +08:00
|
|
|
</div>
|
2025-11-02 23:50:41 +08:00
|
|
|
);
|
2025-10-15 22:30:49 +08:00
|
|
|
}
|