fix: stabilize process targeting with search/pinning and fix targeted report data isolation

This commit is contained in:
2026-02-23 18:29:48 +01:00
parent 122532c2f7
commit c7adb2af17

View File

@@ -99,6 +99,8 @@ function App() {
const [stats, setStats] = useState<SystemStats | null>(null); const [stats, setStats] = useState<SystemStats | null>(null);
const [history, setHistory] = useState<{ time: string; cpu: number }[]>([]); const [history, setHistory] = useState<{ time: string; cpu: number }[]>([]);
const [report, setReport] = useState<ProfilingReport | null>(null); const [report, setReport] = useState<ProfilingReport | null>(null);
const [searchTerm, setSearchBar] = useState("");
const [pinnedPid, setPinnedPid] = useState<number | null>(null);
// Initial report check // Initial report check
useEffect(() => { useEffect(() => {
@@ -161,9 +163,13 @@ function App() {
const reportData = await invoke<ProfilingReport>('stop_profiling'); const reportData = await invoke<ProfilingReport>('stop_profiling');
setReport(reportData); setReport(reportData);
setView('report'); setView('report');
} else {
if (pinnedPid) {
await invoke('start_targeted_profiling', { pid: pinnedPid });
} else { } else {
await invoke('start_profiling'); await invoke('start_profiling');
} }
}
}; };
const startTargeted = async (pid: number) => { 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 avgCpu = stats.cpu_usage.reduce((a, b) => a + b, 0) / stats.cpu_usage.length;
const memoryPercent = (stats.used_memory / stats.total_memory) * 100; 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 ( return (
<div className="flex flex-col h-screen bg-base text-text"> <div className="flex flex-col h-screen bg-base text-text">
<div data-tauri-drag-region className="titlebar shrink-0"> <div data-tauri-drag-region className="titlebar shrink-0">
@@ -239,7 +250,7 @@ function App() {
onClick={toggleRecording} onClick={toggleRecording}
> >
{stats.is_recording ? <Square size={12} fill="currentColor" /> : <Play size={12} fill="currentColor" />} {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> </button>
</div> </div>
</div> </div>
@@ -327,16 +338,27 @@ function App() {
</div> </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="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"> <h3 className="text-xl font-black tracking-tighter uppercase italic flex items-center gap-2">
<Activity size={24} className="text-red" strokeWidth={3} /> <Activity size={24} className="text-red" strokeWidth={3} />
Live Feed Live Feed
</h3> </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="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" /> <div className="w-1.5 h-1.5 rounded-full bg-red animate-pulse" />
Real-time Real-time
</div> </div>
</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 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> <div>Process</div>
@@ -347,12 +369,19 @@ function App() {
</div> </div>
<div className="overflow-y-auto flex-1 custom-scrollbar px-2"> <div className="overflow-y-auto flex-1 custom-scrollbar px-2">
{stats.processes.map((proc) => ( {filteredLiveProcs.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"> <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="font-black text-text truncate text-sm flex items-center gap-3" title={proc.name}>
<div className={cn( <div className={cn(
"w-2 h-2 rounded-full transition-colors", "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} {proc.name}
</div> </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="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"> <div className="flex justify-center items-center gap-2">
<button <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" 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" title="Target Profile"
> >
<Target size={16} strokeWidth={2.5} /> <Target size={16} strokeWidth={2.5} />
</button> </button>
<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" 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" title="Terminate"
> >