fix: stabilize process targeting with search/pinning and fix targeted report data isolation
This commit is contained in:
43
src/App.tsx
43
src/App.tsx
@@ -99,6 +99,8 @@ function App() {
|
||||
const [stats, setStats] = useState<SystemStats | null>(null);
|
||||
const [history, setHistory] = useState<{ time: string; cpu: number }[]>([]);
|
||||
const [report, setReport] = useState<ProfilingReport | null>(null);
|
||||
const [searchTerm, setSearchBar] = useState("");
|
||||
const [pinnedPid, setPinnedPid] = useState<number | null>(null);
|
||||
|
||||
// Initial report check
|
||||
useEffect(() => {
|
||||
@@ -161,9 +163,13 @@ function App() {
|
||||
const reportData = await invoke<ProfilingReport>('stop_profiling');
|
||||
setReport(reportData);
|
||||
setView('report');
|
||||
} else {
|
||||
if (pinnedPid) {
|
||||
await invoke('start_targeted_profiling', { pid: pinnedPid });
|
||||
} else {
|
||||
await invoke('start_profiling');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const startTargeted = async (pid: number) => {
|
||||
@@ -213,6 +219,11 @@ function App() {
|
||||
const avgCpu = stats.cpu_usage.reduce((a, b) => a + b, 0) / stats.cpu_usage.length;
|
||||
const memoryPercent = (stats.used_memory / stats.total_memory) * 100;
|
||||
|
||||
const filteredLiveProcs = stats.processes.filter(p =>
|
||||
p.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
p.pid.toString().includes(searchTerm)
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-base text-text">
|
||||
<div data-tauri-drag-region className="titlebar shrink-0">
|
||||
@@ -239,7 +250,7 @@ function App() {
|
||||
onClick={toggleRecording}
|
||||
>
|
||||
{stats.is_recording ? <Square size={12} fill="currentColor" /> : <Play size={12} fill="currentColor" />}
|
||||
{stats.is_recording ? `STOP (${formatDuration(stats.recording_duration)})` : "START PROFILING"}
|
||||
{stats.is_recording ? `STOP (${formatDuration(stats.recording_duration)})` : (pinnedPid ? "PROFILE TARGET" : "START GLOBAL")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -327,16 +338,27 @@ function App() {
|
||||
</div>
|
||||
|
||||
<div className="card flex-1 flex flex-col min-h-0 overflow-hidden shadow-[0_35px_60px_-15px_rgba(0,0,0,0.5)] border border-surface1/50">
|
||||
<div className="flex justify-between items-center mb-6 px-2">
|
||||
<div className="flex justify-between items-center mb-6 px-2 shrink-0">
|
||||
<h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
|
||||
<Activity size={24} className="text-red" strokeWidth={3} />
|
||||
Live Feed
|
||||
</h3>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="SEARCH PROCESS..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchBar(e.target.value)}
|
||||
className="bg-surface1/50 border border-surface2 rounded-xl px-4 py-2 text-xs font-bold text-text placeholder:text-overlay1 focus:outline-none focus:ring-2 focus:ring-blue/30 w-64 transition-all"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-[10px] bg-red/10 text-red border border-red/20 px-3 py-1.5 rounded-full font-black uppercase tracking-widest flex items-center gap-1.5">
|
||||
<div className="w-1.5 h-1.5 rounded-full bg-red animate-pulse" />
|
||||
Real-time
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-[1fr_80px_100px_120px_120px] gap-4 px-6 py-4 bg-surface1/50 rounded-2xl font-black uppercase tracking-widest text-[10px] text-overlay1 mb-2">
|
||||
<div>Process</div>
|
||||
@@ -347,12 +369,19 @@ function App() {
|
||||
</div>
|
||||
|
||||
<div className="overflow-y-auto flex-1 custom-scrollbar px-2">
|
||||
{stats.processes.map((proc) => (
|
||||
<div key={proc.pid} className="grid grid-cols-[1fr_80px_100px_120px_120px] gap-4 px-4 py-4 border-b border-surface1/20 group hover:bg-surface1/20 transition-all rounded-xl">
|
||||
{filteredLiveProcs.map((proc) => (
|
||||
<div
|
||||
key={proc.pid}
|
||||
className={cn(
|
||||
"grid grid-cols-[1fr_80px_100px_120px_120px] gap-4 px-4 py-4 border-b border-surface1/20 group hover:bg-surface1/20 transition-all rounded-xl cursor-pointer",
|
||||
pinnedPid === proc.pid ? "bg-blue/10 border-blue/30" : ""
|
||||
)}
|
||||
onClick={() => setPinnedPid(pinnedPid === proc.pid ? null : proc.pid)}
|
||||
>
|
||||
<div className="font-black text-text truncate text-sm flex items-center gap-3" title={proc.name}>
|
||||
<div className={cn(
|
||||
"w-2 h-2 rounded-full transition-colors",
|
||||
proc.is_syspulse ? "bg-mauve" : "bg-surface2 group-hover:bg-blue"
|
||||
proc.is_syspulse ? "bg-mauve" : (pinnedPid === proc.pid ? "bg-blue" : "bg-surface2 group-hover:bg-blue")
|
||||
)} />
|
||||
{proc.name}
|
||||
</div>
|
||||
@@ -361,14 +390,14 @@ function App() {
|
||||
<div className="text-mauve font-black text-sm text-right self-center tabular-nums">{formatBytes(proc.memory, 0)}</div>
|
||||
<div className="flex justify-center items-center gap-2">
|
||||
<button
|
||||
onClick={() => startTargeted(proc.pid)}
|
||||
onClick={(e) => { e.stopPropagation(); startTargeted(proc.pid); }}
|
||||
className="opacity-0 group-hover:opacity-100 p-2 hover:bg-blue/20 text-blue rounded-xl transition-all hover:scale-110 active:scale-90"
|
||||
title="Target Profile"
|
||||
>
|
||||
<Target size={16} strokeWidth={2.5} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => killProcess(proc.pid)}
|
||||
onClick={(e) => { e.stopPropagation(); killProcess(proc.pid); }}
|
||||
className="opacity-0 group-hover:opacity-100 p-2 hover:bg-red/20 text-red rounded-xl transition-all hover:scale-110 active:scale-90"
|
||||
title="Terminate"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user