Skip to content

Commit

Permalink
more refactoring, and documenting
Browse files Browse the repository at this point in the history
  • Loading branch information
Abdenasser committed Nov 12, 2024
1 parent 30c5962 commit 38073aa
Show file tree
Hide file tree
Showing 14 changed files with 591 additions and 347 deletions.
28 changes: 14 additions & 14 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "macos-task-manager"
name = "neohtop"
version = "1.1.0"
description = "A Tauri App"
description = "A cross-platform system monitor"
authors = ["you"]
edition = "2021"

Expand Down
184 changes: 47 additions & 137 deletions src-tauri/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,156 +1,66 @@
//! Tauri command handlers
//!
//! This module contains the command handlers that are exposed to the frontend
//! through Tauri's IPC mechanism. These commands provide the interface between
//! the frontend and the system monitoring functionality.
use crate::monitoring::{ProcessInfo, ProcessMonitor, SystemStats};
use crate::state::AppState;
use crate::system::collect_system_stats;
use crate::types::{ProcessInfo, ProcessStaticInfo, SystemStats};
use std::time::{SystemTime, UNIX_EPOCH};
use sysinfo::{PidExt, ProcessExt, ProcessStatus, SystemExt};
use sysinfo::SystemExt;
use tauri::State;

/// Retrieves the current list of processes and system statistics
///
/// # Arguments
///
/// * `state` - The application state containing system monitoring components
///
/// # Returns
///
/// A tuple containing:
/// * A vector of process information
/// * Current system statistics
///
/// # Errors
///
/// Returns an error string if:
/// * Failed to acquire locks on system state
/// * Failed to collect process information
#[tauri::command]
pub async fn get_processes(
state: State<'_, AppState>,
) -> Result<(Vec<ProcessInfo>, SystemStats), String> {
let processes_data;
let system_stats;

let current_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|e| format!("Failed to get system time: {}", e))?
.as_secs();

let mut sys = state
.sys
.lock()
.map_err(|e| format!("Failed to lock system state: {}", e))?;

let mut sys = state.sys.lock().map_err(|e| e.to_string())?;
sys.refresh_all();
sys.refresh_networks_list();
sys.refresh_disks_list();

processes_data = collect_process_data(&sys, current_time);
let mut process_monitor = state.process_monitor.lock().map_err(|e| e.to_string())?;
let mut system_monitor = state.system_monitor.lock().map_err(|e| e.to_string())?;

system_stats = collect_system_stats(&mut sys, &state)
.map_err(|e| format!("Failed to collect system stats: {}", e))?;

let mut process_cache = state
.process_cache
.lock()
.map_err(|e| format!("Failed to lock process cache: {}", e))?;

let processes = build_process_info(processes_data, &mut process_cache);
let processes = process_monitor.collect_processes(&sys)?;
let system_stats = system_monitor.collect_stats(&sys);

Ok((processes, system_stats))
}

/// Attempts to kill a process with the specified PID
///
/// # Arguments
///
/// * `pid` - Process ID to kill
/// * `state` - The application state
///
/// # Returns
///
/// * `true` if the process was successfully killed
/// * `false` if the process couldn't be killed or wasn't found
///
/// # Errors
///
/// Returns an error string if failed to acquire lock on system state
#[tauri::command]
pub async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
let sys = state
.sys
.lock()
.map_err(|e| format!("Failed to lock system state for process termination: {}", e))?;

if let Some(process) = sys.process(sysinfo::Pid::from(pid as usize)) {
Ok(process.kill())
} else {
Ok(false)
}
}

// Helper functions
fn collect_process_data(sys: &sysinfo::System, current_time: u64) -> Vec<ProcessData> {
sys.processes()
.iter()
.map(|(pid, process)| {
let start_time = process.start_time();
let run_time = if start_time > 0 {
current_time.saturating_sub(start_time)
} else {
0
};

ProcessData {
pid: pid.as_u32(),
name: process.name().to_string(),
cmd: process.cmd().to_vec(),
user_id: process.user_id().map(|uid| uid.to_string()),
cpu_usage: process.cpu_usage(),
memory: process.memory(),
status: process.status(),
ppid: process.parent().map(|p| p.as_u32()),
environ: process.environ().to_vec(),
root: process.root().to_string_lossy().into_owned(),
virtual_memory: process.virtual_memory(),
start_time,
run_time,
disk_read: process.disk_usage().read_bytes,
disk_written: process.disk_usage().written_bytes,
session_id: process.session_id().map(|id| id.as_u32()),
}
})
.collect()
}

// Helper struct for intermediate process data
struct ProcessData {
pid: u32,
name: String,
cmd: Vec<String>,
user_id: Option<String>,
cpu_usage: f32,
memory: u64,
status: ProcessStatus,
ppid: Option<u32>,
environ: Vec<String>,
root: String,
virtual_memory: u64,
start_time: u64,
run_time: u64,
disk_read: u64,
disk_written: u64,
session_id: Option<u32>,
}

// Helper function to build process info
fn build_process_info(
processes: Vec<ProcessData>,
process_cache: &mut std::collections::HashMap<u32, ProcessStaticInfo>,
) -> Vec<ProcessInfo> {
processes
.into_iter()
.map(|data| {
// Update or get from cache
let cached_info = process_cache
.entry(data.pid)
.or_insert_with(|| ProcessStaticInfo {
name: data.name.clone(),
command: data.cmd.join(" "),
user: data.user_id.clone().unwrap_or_else(|| "-".to_string()),
});

let status_str = match data.status {
ProcessStatus::Run => "Running",
ProcessStatus::Sleep => "Sleeping",
ProcessStatus::Idle => "Idle",
_ => "Unknown",
};

ProcessInfo {
pid: data.pid,
ppid: data.ppid.unwrap_or(0),
name: cached_info.name.clone(),
cpu_usage: data.cpu_usage,
memory_usage: data.memory,
status: status_str.to_string(),
user: cached_info.user.clone(),
command: cached_info.command.clone(),
threads: None,
environ: data.environ,
root: data.root,
virtual_memory: data.virtual_memory,
start_time: data.start_time,
run_time: data.run_time,
disk_usage: (data.disk_read, data.disk_written),
session_id: data.session_id,
}
})
.collect()
let sys = state.sys.lock().map_err(|e| e.to_string())?;
Ok(ProcessMonitor::kill_process(&sys, pid))
}
22 changes: 16 additions & 6 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
//! NeoHtop - A modern system monitor built with Tauri
//!
//! This is the main entry point for the application. It sets up the Tauri
//! application, initializes plugins, and configures window effects.
mod commands;
mod monitoring;
mod state;
mod system;
mod types;
mod window;
mod ui;

use state::AppState;
use tauri::Manager;
use window::setup_window_effects;

/// Main entry point for the application
///
/// # Panics
///
/// Will panic if:
/// - Unable to create the main window
/// - Failed to apply window effects
/// - Failed to initialize the application state
fn main() {
tauri::Builder::default()
.setup(|app| {
let window = app.get_webview_window("main").unwrap();
setup_window_effects(&window).expect("Failed to apply window effects");
ui::setup_window_effects(&window).expect("Failed to apply window effects");
Ok(())
})
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_os::init())
.manage(AppState::new())
.invoke_handler(tauri::generate_handler![
commands::get_processes,
commands::kill_process
commands::kill_process,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
13 changes: 13 additions & 0 deletions src-tauri/src/monitoring/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! System monitoring functionality
//!
//! This module provides types and functionality for monitoring system resources
//! and processes. It includes process monitoring, system statistics collection,
//! and data structures for representing system state.
mod process_monitor;
mod system_monitor;
mod types;

pub use process_monitor::ProcessMonitor;
pub use system_monitor::SystemMonitor;
pub use types::*; // Re-export all types
Loading

0 comments on commit 38073aa

Please sign in to comment.