small fixes

This commit is contained in:
Abdenasser 2024-11-13 18:32:44 +01:00
parent 821f67105b
commit a93ae705df
3 changed files with 170 additions and 143 deletions

View File

@ -13,12 +13,10 @@
export let show = false; export let show = false;
export let process: Process | null = null; export let process: Process | null = null;
export let onClose: () => void; export let onClose: () => void;
$: currentProcess = process;
</script> </script>
<Modal {show} title="Process Details" maxWidth="700px" {onClose}> <Modal {show} title="Process Details" maxWidth="700px" {onClose}>
{#if currentProcess} {#if process}
<div class="process-details"> <div class="process-details">
<!-- Basic Info Section --> <!-- Basic Info Section -->
<section class="detail-section"> <section class="detail-section">
@ -26,23 +24,23 @@
<div class="detail-grid"> <div class="detail-grid">
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">Name:</span> <span class="detail-label">Name:</span>
<span class="detail-value">{currentProcess.name}</span> <span class="detail-value">{process.name}</span>
</div> </div>
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">PID:</span> <span class="detail-label">PID:</span>
<span class="detail-value">{currentProcess.pid}</span> <span class="detail-value">{process.pid}</span>
</div> </div>
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">Parent PID:</span> <span class="detail-label">Parent PID:</span>
<span class="detail-value">{currentProcess.ppid}</span> <span class="detail-value">{process.ppid}</span>
</div> </div>
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">User:</span> <span class="detail-label">User:</span>
<span class="detail-value">{currentProcess.user}</span> <span class="detail-value">{process.user}</span>
</div> </div>
<div class="detail-row"> <div class="detail-row">
<span class="detail-label">Status:</span> <span class="detail-label">Status:</span>
<span class="detail-value">{currentProcess.status}</span> <span class="detail-value">{process.status}</span>
</div> </div>
</div> </div>
</section> </section>
@ -61,12 +59,12 @@
<div class="progress-bar"> <div class="progress-bar">
<div <div
class="progress-fill" class="progress-fill"
style="width: {currentProcess.cpu_usage}%" style="width: {process.cpu_usage}%"
class:high={currentProcess.cpu_usage > 50} class:high={process.cpu_usage > 50}
class:critical={currentProcess.cpu_usage > 80} class:critical={process.cpu_usage > 80}
></div> ></div>
</div> </div>
<span>{currentProcess.cpu_usage.toFixed(1)}%</span> <span>{process.cpu_usage.toFixed(1)}%</span>
</div> </div>
</div> </div>
@ -77,8 +75,8 @@
<span>Memory Usage</span> <span>Memory Usage</span>
</div> </div>
<div class="resource-stats"> <div class="resource-stats">
<div>Physical: {formatBytes(currentProcess.memory_usage)}</div> <div>Physical: {formatBytes(process.memory_usage)}</div>
<div>Virtual: {formatBytes(currentProcess.virtual_memory)}</div> <div>Virtual: {formatBytes(process.virtual_memory)}</div>
</div> </div>
</div> </div>
@ -89,8 +87,8 @@
<span>Disk I/O</span> <span>Disk I/O</span>
</div> </div>
<div class="resource-stats"> <div class="resource-stats">
<div>Read: {formatBytes(currentProcess.disk_usage[0])}</div> <div>Read: {formatBytes(process.disk_usage[0])}</div>
<div>Written: {formatBytes(currentProcess.disk_usage[1])}</div> <div>Written: {formatBytes(process.disk_usage[1])}</div>
</div> </div>
</div> </div>
@ -101,8 +99,8 @@
<span>Time Information</span> <span>Time Information</span>
</div> </div>
<div class="resource-stats"> <div class="resource-stats">
<div>Started: {formatDate(currentProcess.start_time)}</div> <div>Started: {formatDate(process.start_time)}</div>
<div>Running: {formatUptime(currentProcess.run_time)}</div> <div>Running: {formatUptime(process.run_time)}</div>
</div> </div>
</div> </div>
</div> </div>
@ -114,17 +112,17 @@
<div class="detail-grid"> <div class="detail-grid">
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="detail-label">Command:</span> <span class="detail-label">Command:</span>
<span class="detail-value command">{currentProcess.command}</span> <span class="detail-value command">{process.command}</span>
</div> </div>
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="detail-label">Root:</span> <span class="detail-label">Root:</span>
<span class="detail-value path">{currentProcess.root}</span> <span class="detail-value path">{process.root}</span>
</div> </div>
{#if currentProcess.environ.length > 0} {#if process.environ.length > 0}
<div class="detail-row full-width"> <div class="detail-row full-width">
<span class="detail-label">Environment:</span> <span class="detail-label">Environment:</span>
<div class="detail-value env-vars"> <div class="detail-value env-vars">
{#each currentProcess.environ as env} {#each process.environ as env}
<div class="env-var">{env}</div> <div class="env-var">{env}</div>
{/each} {/each}
</div> </div>

View File

@ -47,46 +47,56 @@ const initialState: ProcessStore = {
function createProcessStore() { function createProcessStore() {
const { subscribe, set, update } = writable<ProcessStore>(initialState); const { subscribe, set, update } = writable<ProcessStore>(initialState);
return { // Define all methods first
subscribe, const setIsLoading = (isLoading: boolean) =>
set, update((state) => ({ ...state, isLoading }));
update,
setIsLoading: (isLoading: boolean) => const getProcesses = async () => {
update((state) => ({ ...state, isLoading })),
async getProcesses() {
try { try {
const result = await invoke<[Process[], SystemStats]>("get_processes"); const result = await invoke<[Process[], SystemStats]>("get_processes");
update((state) => ({ update((state) => {
let updatedSelectedProcess = state.selectedProcess;
if (state.selectedProcessPid) {
updatedSelectedProcess =
result[0].find((p) => p.pid === state.selectedProcessPid) || null;
}
return {
...state, ...state,
processes: result[0], processes: result[0],
systemStats: result[1], systemStats: result[1],
error: null, error: null,
})); selectedProcess: updatedSelectedProcess,
};
});
} catch (e: unknown) { } catch (e: unknown) {
update((state) => ({ update((state) => ({
...state, ...state,
error: e instanceof Error ? e.message : String(e), error: e instanceof Error ? e.message : String(e),
})); }));
} }
}, };
async killProcess(pid: number) { const killProcess = async (pid: number) => {
try { try {
update((state) => ({ ...state, isKilling: true }));
const success = await invoke<boolean>("kill_process", { pid }); const success = await invoke<boolean>("kill_process", { pid });
if (success) { if (success) {
await this.getProcesses(); await getProcesses();
} else {
throw new Error("Failed to kill process");
} }
} catch (e: unknown) { } catch (e: unknown) {
update((state) => ({ update((state) => ({
...state, ...state,
error: e instanceof Error ? e.message : String(e), error: e instanceof Error ? e.message : String(e),
})); }));
} finally {
update((state) => ({ ...state, isKilling: false }));
} }
}, };
toggleSort(field: keyof Process) { const toggleSort = (field: keyof Process) => {
update((state) => ({ update((state) => ({
...state, ...state,
sortConfig: { sortConfig: {
@ -99,9 +109,9 @@ function createProcessStore() {
: "desc", : "desc",
}, },
})); }));
}, };
togglePin(command: string) { const togglePin = (command: string) => {
update((state) => { update((state) => {
const newPinnedProcesses = new Set(state.pinnedProcesses); const newPinnedProcesses = new Set(state.pinnedProcesses);
if (newPinnedProcesses.has(command)) { if (newPinnedProcesses.has(command)) {
@ -111,75 +121,97 @@ function createProcessStore() {
} }
return { ...state, pinnedProcesses: newPinnedProcesses }; return { ...state, pinnedProcesses: newPinnedProcesses };
}); });
}, };
setSearchTerm: (searchTerm: string) => const setSearchTerm = (searchTerm: string) =>
update((state) => ({ ...state, searchTerm, currentPage: 1 })), update((state) => ({ ...state, searchTerm, currentPage: 1 }));
setIsFrozen: (isFrozen: boolean) =>
update((state) => ({ ...state, isFrozen })),
setCurrentPage: (currentPage: number) =>
update((state) => ({ ...state, currentPage })),
showProcessDetails(process: Process) { const setIsFrozen = (isFrozen: boolean) =>
update((state) => ({ ...state, isFrozen }));
const setCurrentPage = (currentPage: number) =>
update((state) => ({ ...state, currentPage }));
const showProcessDetails = (process: Process) => {
update((state) => ({ update((state) => ({
...state, ...state,
selectedProcessPid: process.pid, selectedProcessPid: process.pid,
selectedProcess: process, selectedProcess: process,
showInfoModal: true, showInfoModal: true,
})); }));
}, };
closeProcessDetails() { const closeProcessDetails = () => {
update((state) => ({ update((state) => ({
...state, ...state,
showInfoModal: false, showInfoModal: false,
selectedProcess: null, selectedProcess: null,
selectedProcessPid: null, selectedProcessPid: null,
})); }));
}, };
confirmKillProcess(process: Process) { const confirmKillProcess = (process: Process) => {
update((state) => ({ update((state) => ({
...state, ...state,
processToKill: process, processToKill: process,
showConfirmModal: true, showConfirmModal: true,
})); }));
}, };
closeConfirmKill() { const closeConfirmKill = () => {
update((state) => ({ update((state) => ({
...state, ...state,
showConfirmModal: false, showConfirmModal: false,
processToKill: null, processToKill: null,
})); }));
}, };
async handleConfirmKill() { const handleConfirmKill = async () => {
update((state) => ({ ...state, isKilling: true })); let processToKill: Process | null = null;
let currentState: ProcessStore | undefined;
const unsubscribe = subscribe((state) => {
currentState = state;
});
unsubscribe();
if (currentState?.processToKill && "pid" in currentState.processToKill) {
processToKill = currentState.processToKill;
}
if (!processToKill?.pid) {
return;
}
try { try {
const pid = this.getState().processToKill?.pid; await killProcess(processToKill.pid);
if (pid) {
await this.killProcess(pid);
}
} finally { } finally {
update((state) => ({ update((state) => ({
...state, ...state,
isKilling: false,
showConfirmModal: false, showConfirmModal: false,
processToKill: null, processToKill: null,
})); }));
} }
}, };
// Helper to get current state // Return all methods
getState() { return {
let currentState: ProcessStore | undefined; subscribe,
subscribe((state) => { set,
currentState = state; update,
})(); setIsLoading,
return currentState!; getProcesses,
}, killProcess,
toggleSort,
togglePin,
setSearchTerm,
setIsFrozen,
setCurrentPage,
showProcessDetails,
closeProcessDetails,
confirmKillProcess,
closeConfirmKill,
handleConfirmKill,
}; };
} }

View File

@ -121,19 +121,16 @@ export function sortProcesses(
sortConfig: SortConfig, sortConfig: SortConfig,
pinnedProcesses: Set<string>, pinnedProcesses: Set<string>,
): Process[] { ): Process[] {
// Clear the cache before sorting
isPinned.clear();
return [...processes].sort((a, b) => { return [...processes].sort((a, b) => {
// Cache pinned status // Cache pinned status
let aPin = isPinned.get(a.command); let aPin = pinnedProcesses.has(a.command);
if (aPin === undefined) {
aPin = pinnedProcesses.has(a.command);
isPinned.set(a.command, aPin); isPinned.set(a.command, aPin);
}
let bPin = isPinned.get(b.command); let bPin = pinnedProcesses.has(b.command);
if (bPin === undefined) {
bPin = pinnedProcesses.has(b.command);
isPinned.set(b.command, bPin); isPinned.set(b.command, bPin);
}
// Quick pin comparison // Quick pin comparison
if (aPin !== bPin) { if (aPin !== bPin) {