mirror of
https://github.com/kunkunsh/kunkun-ext-neohtop.git
synced 2025-06-06 18:45:03 +00:00
more refactoring, and documenting
This commit is contained in:
parent
30c5962b26
commit
38073aa1b2
28
src-tauri/Cargo.lock
generated
28
src-tauri/Cargo.lock
generated
@ -1660,20 +1660,6 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "macos-task-manager"
|
|
||||||
version = "1.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"sysinfo",
|
|
||||||
"tauri",
|
|
||||||
"tauri-build",
|
|
||||||
"tauri-plugin-os",
|
|
||||||
"tauri-plugin-shell",
|
|
||||||
"window-vibrancy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "malloc_buf"
|
name = "malloc_buf"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
@ -1796,6 +1782,20 @@ dependencies = [
|
|||||||
"jni-sys",
|
"jni-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "neohtop"
|
||||||
|
version = "1.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sysinfo",
|
||||||
|
"tauri",
|
||||||
|
"tauri-build",
|
||||||
|
"tauri-plugin-os",
|
||||||
|
"tauri-plugin-shell",
|
||||||
|
"window-vibrancy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "new_debug_unreachable"
|
name = "new_debug_unreachable"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "macos-task-manager"
|
name = "neohtop"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
description = "A Tauri App"
|
description = "A cross-platform system monitor"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
@ -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::state::AppState;
|
||||||
use crate::system::collect_system_stats;
|
use sysinfo::SystemExt;
|
||||||
use crate::types::{ProcessInfo, ProcessStaticInfo, SystemStats};
|
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
|
||||||
use sysinfo::{PidExt, ProcessExt, ProcessStatus, SystemExt};
|
|
||||||
use tauri::State;
|
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]
|
#[tauri::command]
|
||||||
pub async fn get_processes(
|
pub async fn get_processes(
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<(Vec<ProcessInfo>, SystemStats), String> {
|
) -> Result<(Vec<ProcessInfo>, SystemStats), String> {
|
||||||
let processes_data;
|
let mut sys = state.sys.lock().map_err(|e| e.to_string())?;
|
||||||
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))?;
|
|
||||||
|
|
||||||
sys.refresh_all();
|
sys.refresh_all();
|
||||||
sys.refresh_networks_list();
|
sys.refresh_networks_list();
|
||||||
sys.refresh_disks_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)
|
let processes = process_monitor.collect_processes(&sys)?;
|
||||||
.map_err(|e| format!("Failed to collect system stats: {}", e))?;
|
let system_stats = system_monitor.collect_stats(&sys);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
Ok((processes, system_stats))
|
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]
|
#[tauri::command]
|
||||||
pub async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
|
pub async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result<bool, String> {
|
||||||
let sys = state
|
let sys = state.sys.lock().map_err(|e| e.to_string())?;
|
||||||
.sys
|
Ok(ProcessMonitor::kill_process(&sys, pid))
|
||||||
.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()
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,30 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![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 commands;
|
||||||
|
mod monitoring;
|
||||||
mod state;
|
mod state;
|
||||||
mod system;
|
mod ui;
|
||||||
mod types;
|
|
||||||
mod window;
|
|
||||||
|
|
||||||
use state::AppState;
|
use state::AppState;
|
||||||
use tauri::Manager;
|
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() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let window = app.get_webview_window("main").unwrap();
|
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(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
@ -22,7 +32,7 @@ fn main() {
|
|||||||
.manage(AppState::new())
|
.manage(AppState::new())
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
commands::get_processes,
|
commands::get_processes,
|
||||||
commands::kill_process
|
commands::kill_process,
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
13
src-tauri/src/monitoring/mod.rs
Normal file
13
src-tauri/src/monitoring/mod.rs
Normal file
@ -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
|
167
src-tauri/src/monitoring/process_monitor.rs
Normal file
167
src-tauri/src/monitoring/process_monitor.rs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
//! Process monitoring functionality
|
||||||
|
//!
|
||||||
|
//! This module handles monitoring and managing system processes, including
|
||||||
|
//! collecting process information and managing process lifecycle.
|
||||||
|
|
||||||
|
use super::{ProcessData, ProcessInfo, ProcessStaticInfo};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
use sysinfo::{PidExt, ProcessExt, ProcessStatus, SystemExt};
|
||||||
|
|
||||||
|
/// Monitors and manages system processes
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ProcessMonitor {
|
||||||
|
/// Cache for static process information to avoid redundant allocations
|
||||||
|
process_cache: HashMap<u32, ProcessStaticInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProcessMonitor {
|
||||||
|
/// Creates a new process monitor instance
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
process_cache: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collects information about all running processes
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `sys` - System information provider
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A vector of process information, or an error string if collection failed
|
||||||
|
pub fn collect_processes(&mut self, sys: &sysinfo::System) -> Result<Vec<ProcessInfo>, String> {
|
||||||
|
let current_time = Self::get_current_time()?;
|
||||||
|
let processes_data = self.collect_process_data(sys, current_time);
|
||||||
|
Ok(self.build_process_info(processes_data))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to kill a process
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `sys` - System information provider
|
||||||
|
/// * `pid` - Process ID to kill
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Boolean indicating whether the process was successfully killed
|
||||||
|
pub fn kill_process(sys: &sysinfo::System, pid: u32) -> bool {
|
||||||
|
sys.process(sysinfo::Pid::from(pid as usize))
|
||||||
|
.map(|process| process.kill())
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the current system time in seconds since UNIX epoch
|
||||||
|
fn get_current_time() -> Result<u64, String> {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.map(|d| d.as_secs())
|
||||||
|
.map_err(|e| format!("Failed to get system time: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collects raw process data from the system
|
||||||
|
fn collect_process_data(&self, sys: &sysinfo::System, current_time: u64) -> Vec<ProcessData> {
|
||||||
|
sys.processes()
|
||||||
|
.iter()
|
||||||
|
.map(|(pid, process)| {
|
||||||
|
let start_time = process.start_time();
|
||||||
|
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: if start_time > 0 {
|
||||||
|
current_time.saturating_sub(start_time)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
},
|
||||||
|
disk_usage: process.disk_usage(),
|
||||||
|
session_id: process.session_id().map(|id| id.as_u32()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds process information from raw process data
|
||||||
|
fn build_process_info(&mut self, processes: Vec<ProcessData>) -> Vec<ProcessInfo> {
|
||||||
|
processes
|
||||||
|
.into_iter()
|
||||||
|
.map(|data| {
|
||||||
|
let cached_info =
|
||||||
|
self.process_cache
|
||||||
|
.entry(data.pid)
|
||||||
|
.or_insert_with(|| ProcessStaticInfo {
|
||||||
|
name: data.name.clone(),
|
||||||
|
command: data.cmd.join(" "),
|
||||||
|
user: data.user_id.unwrap_or_else(|| "-".to_string()),
|
||||||
|
});
|
||||||
|
|
||||||
|
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: Self::format_status(data.status),
|
||||||
|
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_usage.read_bytes, data.disk_usage.written_bytes),
|
||||||
|
session_id: data.session_id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Formats process status into a human-readable string
|
||||||
|
pub fn format_status(status: ProcessStatus) -> String {
|
||||||
|
match status {
|
||||||
|
ProcessStatus::Run => "Running",
|
||||||
|
ProcessStatus::Sleep => "Sleeping",
|
||||||
|
ProcessStatus::Idle => "Idle",
|
||||||
|
_ => "Unknown",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use sysinfo::System;
|
||||||
|
|
||||||
|
/// Tests creation of a new process monitor
|
||||||
|
#[test]
|
||||||
|
fn test_process_monitor_creation() {
|
||||||
|
let monitor = ProcessMonitor::new();
|
||||||
|
assert!(monitor.process_cache.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tests process collection functionality
|
||||||
|
#[test]
|
||||||
|
fn test_process_collection() {
|
||||||
|
let mut monitor = ProcessMonitor::new();
|
||||||
|
let mut sys = System::new();
|
||||||
|
sys.refresh_all();
|
||||||
|
|
||||||
|
let result = monitor.collect_processes(&sys);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
}
|
146
src-tauri/src/monitoring/system_monitor.rs
Normal file
146
src-tauri/src/monitoring/system_monitor.rs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
//! System statistics monitoring
|
||||||
|
//!
|
||||||
|
//! This module handles collection and monitoring of system-wide statistics
|
||||||
|
//! including CPU, memory, network, and disk usage.
|
||||||
|
|
||||||
|
use super::SystemStats;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::time::Instant;
|
||||||
|
use sysinfo::{CpuExt, Disk, DiskExt, NetworkExt, NetworksExt, SystemExt};
|
||||||
|
|
||||||
|
/// Monitors system-wide statistics
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SystemMonitor {
|
||||||
|
/// Tracks network usage between updates
|
||||||
|
last_network_update: (Instant, u64, u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SystemMonitor {
|
||||||
|
/// Creates a new system monitor instance
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `sys` - System information provider for initial readings
|
||||||
|
pub fn new(sys: &sysinfo::System) -> Self {
|
||||||
|
let initial_rx: u64 = sys
|
||||||
|
.networks()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, data)| data.total_received())
|
||||||
|
.sum();
|
||||||
|
let initial_tx: u64 = sys
|
||||||
|
.networks()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, data)| data.total_transmitted())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
last_network_update: (Instant::now(), initial_rx, initial_tx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collects current system statistics
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `sys` - System information provider
|
||||||
|
pub fn collect_stats(&mut self, sys: &sysinfo::System) -> SystemStats {
|
||||||
|
let (network_rx, network_tx) = self.calculate_network_stats(sys);
|
||||||
|
let (disk_total, disk_used, disk_free) = self.calculate_disk_stats(sys);
|
||||||
|
|
||||||
|
SystemStats {
|
||||||
|
cpu_usage: sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(),
|
||||||
|
memory_total: sys.total_memory(),
|
||||||
|
memory_used: sys.used_memory(),
|
||||||
|
memory_free: sys.total_memory() - sys.used_memory(),
|
||||||
|
memory_cached: sys.total_memory()
|
||||||
|
- (sys.used_memory() + (sys.total_memory() - sys.used_memory())),
|
||||||
|
uptime: sys.uptime(),
|
||||||
|
load_avg: [
|
||||||
|
sys.load_average().one,
|
||||||
|
sys.load_average().five,
|
||||||
|
sys.load_average().fifteen,
|
||||||
|
],
|
||||||
|
network_rx_bytes: network_rx,
|
||||||
|
network_tx_bytes: network_tx,
|
||||||
|
disk_total_bytes: disk_total,
|
||||||
|
disk_used_bytes: disk_used,
|
||||||
|
disk_free_bytes: disk_free,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Filters disks based on platform-specific criteria
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
fn filter_disks(disks: &[Disk]) -> Vec<&Disk> {
|
||||||
|
disks
|
||||||
|
.iter()
|
||||||
|
.filter(|disk| disk.mount_point() == Path::new("/"))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Windows-specific disk filtering
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn filter_disks(disks: &[Disk]) -> Vec<&Disk> {
|
||||||
|
disks.iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates network usage rates
|
||||||
|
fn calculate_network_stats(&mut self, sys: &sysinfo::System) -> (u64, u64) {
|
||||||
|
let current_rx: u64 = sys
|
||||||
|
.networks()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, data)| data.total_received())
|
||||||
|
.sum();
|
||||||
|
let current_tx: u64 = sys
|
||||||
|
.networks()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, data)| data.total_transmitted())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
let elapsed = self.last_network_update.0.elapsed().as_secs_f64();
|
||||||
|
let rx_rate = ((current_rx - self.last_network_update.1) as f64 / elapsed) as u64;
|
||||||
|
let tx_rate = ((current_tx - self.last_network_update.2) as f64 / elapsed) as u64;
|
||||||
|
|
||||||
|
self.last_network_update = (Instant::now(), current_rx, current_tx);
|
||||||
|
(rx_rate, tx_rate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates disk usage statistics
|
||||||
|
fn calculate_disk_stats(&self, sys: &sysinfo::System) -> (u64, u64, u64) {
|
||||||
|
let disks = Self::filter_disks(sys.disks());
|
||||||
|
let total: u64 = disks.iter().map(|disk| disk.total_space()).sum();
|
||||||
|
let used: u64 = disks
|
||||||
|
.iter()
|
||||||
|
.map(|disk| disk.total_space() - disk.available_space())
|
||||||
|
.sum();
|
||||||
|
let free: u64 = disks.iter().map(|disk| disk.available_space()).sum();
|
||||||
|
(total, used, free)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use sysinfo::System;
|
||||||
|
|
||||||
|
/// Tests creation of system monitor
|
||||||
|
#[test]
|
||||||
|
fn test_system_monitor_creation() {
|
||||||
|
let sys = System::new();
|
||||||
|
let monitor = SystemMonitor::new(&sys);
|
||||||
|
assert!(monitor.last_network_update.1 >= 0);
|
||||||
|
assert!(monitor.last_network_update.2 >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tests system statistics collection
|
||||||
|
#[test]
|
||||||
|
fn test_stats_collection() {
|
||||||
|
let mut sys = System::new();
|
||||||
|
let mut monitor = SystemMonitor::new(&sys);
|
||||||
|
sys.refresh_all();
|
||||||
|
|
||||||
|
let stats = monitor.collect_stats(&sys);
|
||||||
|
assert!(!stats.cpu_usage.is_empty());
|
||||||
|
assert!(stats.memory_total > 0);
|
||||||
|
}
|
||||||
|
}
|
119
src-tauri/src/monitoring/types.rs
Normal file
119
src-tauri/src/monitoring/types.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use sysinfo::{DiskUsage, ProcessStatus};
|
||||||
|
|
||||||
|
/// Internal representation of process data collected from the system
|
||||||
|
/// This struct is used internally and not exposed directly to the frontend
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct ProcessData {
|
||||||
|
/// Process ID
|
||||||
|
pub pid: u32,
|
||||||
|
/// Name of the process
|
||||||
|
pub name: String,
|
||||||
|
/// Complete command line arguments
|
||||||
|
pub cmd: Vec<String>,
|
||||||
|
/// User ID that owns the process
|
||||||
|
pub user_id: Option<String>,
|
||||||
|
/// CPU usage as percentage (0-100)
|
||||||
|
pub cpu_usage: f32,
|
||||||
|
/// Physical memory usage in bytes
|
||||||
|
pub memory: u64,
|
||||||
|
/// Current process status
|
||||||
|
pub status: ProcessStatus,
|
||||||
|
/// Parent process ID
|
||||||
|
pub ppid: Option<u32>,
|
||||||
|
/// Environment variables
|
||||||
|
pub environ: Vec<String>,
|
||||||
|
/// Root directory of the process
|
||||||
|
pub root: String,
|
||||||
|
/// Virtual memory usage in bytes
|
||||||
|
pub virtual_memory: u64,
|
||||||
|
/// Process start time (Unix timestamp)
|
||||||
|
pub start_time: u64,
|
||||||
|
/// Process running time in seconds
|
||||||
|
pub run_time: u64,
|
||||||
|
/// Disk I/O statistics
|
||||||
|
pub disk_usage: DiskUsage,
|
||||||
|
/// Session ID of the process
|
||||||
|
pub session_id: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Static information about a process that doesn't change frequently
|
||||||
|
/// Used for caching purposes to avoid frequent updates of stable data
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ProcessStaticInfo {
|
||||||
|
/// Process name
|
||||||
|
pub name: String,
|
||||||
|
/// Full command string
|
||||||
|
pub command: String,
|
||||||
|
/// Username of the process owner
|
||||||
|
pub user: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process information exposed to the frontend via Tauri
|
||||||
|
/// Contains formatted and filtered process data for UI consumption
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
pub struct ProcessInfo {
|
||||||
|
/// Process ID
|
||||||
|
pub pid: u32,
|
||||||
|
/// Parent process ID
|
||||||
|
pub ppid: u32,
|
||||||
|
/// Process name
|
||||||
|
pub name: String,
|
||||||
|
/// CPU usage as percentage (0-100)
|
||||||
|
pub cpu_usage: f32,
|
||||||
|
/// Physical memory usage in bytes
|
||||||
|
pub memory_usage: u64,
|
||||||
|
/// Process status as string
|
||||||
|
pub status: String,
|
||||||
|
/// Username of the process owner
|
||||||
|
pub user: String,
|
||||||
|
/// Full command string
|
||||||
|
pub command: String,
|
||||||
|
/// Number of threads (if available)
|
||||||
|
pub threads: Option<u32>,
|
||||||
|
/// Environment variables
|
||||||
|
pub environ: Vec<String>,
|
||||||
|
/// Root directory of the process
|
||||||
|
pub root: String,
|
||||||
|
/// Virtual memory usage in bytes
|
||||||
|
pub virtual_memory: u64,
|
||||||
|
/// Process start time (Unix timestamp)
|
||||||
|
pub start_time: u64,
|
||||||
|
/// Process running time in seconds
|
||||||
|
pub run_time: u64,
|
||||||
|
/// Disk I/O statistics (read bytes, written bytes)
|
||||||
|
pub disk_usage: (u64, u64),
|
||||||
|
/// Session ID of the process
|
||||||
|
pub session_id: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// System-wide statistics exposed to the frontend
|
||||||
|
/// Provides overall system resource usage and performance metrics
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
pub struct SystemStats {
|
||||||
|
/// CPU usage per core as percentage (0-100)
|
||||||
|
pub cpu_usage: Vec<f32>,
|
||||||
|
/// Total physical memory in bytes
|
||||||
|
pub memory_total: u64,
|
||||||
|
/// Used physical memory in bytes
|
||||||
|
pub memory_used: u64,
|
||||||
|
/// Free physical memory in bytes
|
||||||
|
pub memory_free: u64,
|
||||||
|
/// Cached memory in bytes
|
||||||
|
pub memory_cached: u64,
|
||||||
|
/// System uptime in seconds
|
||||||
|
pub uptime: u64,
|
||||||
|
/// Load averages for 1, 5, and 15 minutes
|
||||||
|
pub load_avg: [f64; 3],
|
||||||
|
/// Total bytes received over network
|
||||||
|
pub network_rx_bytes: u64,
|
||||||
|
/// Total bytes transmitted over network
|
||||||
|
pub network_tx_bytes: u64,
|
||||||
|
/// Total disk space in bytes
|
||||||
|
pub disk_total_bytes: u64,
|
||||||
|
/// Used disk space in bytes
|
||||||
|
pub disk_used_bytes: u64,
|
||||||
|
/// Free disk space in bytes
|
||||||
|
pub disk_free_bytes: u64,
|
||||||
|
}
|
@ -1,35 +1,41 @@
|
|||||||
use crate::types::ProcessStaticInfo;
|
//! Application state management
|
||||||
use std::collections::HashMap;
|
//!
|
||||||
use std::sync::Mutex;
|
//! This module handles the global application state, including system monitoring
|
||||||
use std::time::Instant;
|
//! and process tracking capabilities.
|
||||||
use sysinfo::{NetworkExt, NetworksExt, System, SystemExt};
|
|
||||||
|
|
||||||
|
use crate::monitoring::{ProcessMonitor, SystemMonitor};
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use sysinfo::{System, SystemExt};
|
||||||
|
|
||||||
|
/// Global application state
|
||||||
|
///
|
||||||
|
/// Maintains thread-safe access to system information and monitoring components
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
/// System information handler
|
||||||
pub sys: Mutex<System>,
|
pub sys: Mutex<System>,
|
||||||
pub process_cache: Mutex<HashMap<u32, ProcessStaticInfo>>,
|
/// Process monitoring component
|
||||||
pub last_network_update: Mutex<(Instant, u64, u64)>,
|
pub process_monitor: Mutex<ProcessMonitor>,
|
||||||
|
/// System statistics monitoring component
|
||||||
|
pub system_monitor: Mutex<SystemMonitor>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
|
/// Creates a new instance of the application state
|
||||||
|
///
|
||||||
|
/// Initializes system monitoring and process tracking components
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// A new `AppState` instance with initialized monitors
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut sys = System::new();
|
let mut sys = System::new();
|
||||||
sys.refresh_all();
|
sys.refresh_all();
|
||||||
|
|
||||||
let initial_rx = sys
|
|
||||||
.networks()
|
|
||||||
.iter()
|
|
||||||
.map(|(_, data)| data.total_received())
|
|
||||||
.sum();
|
|
||||||
let initial_tx = sys
|
|
||||||
.networks()
|
|
||||||
.iter()
|
|
||||||
.map(|(_, data)| data.total_transmitted())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
process_monitor: Mutex::new(ProcessMonitor::new()),
|
||||||
|
system_monitor: Mutex::new(SystemMonitor::new(&sys)),
|
||||||
sys: Mutex::new(sys),
|
sys: Mutex::new(sys),
|
||||||
process_cache: Mutex::new(HashMap::new()),
|
|
||||||
last_network_update: Mutex::new((Instant::now(), initial_rx, initial_tx)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
use crate::state::AppState;
|
|
||||||
use crate::types::SystemStats;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::time::Instant;
|
|
||||||
use sysinfo::{CpuExt, Disk, DiskExt, NetworkExt, NetworksExt, SystemExt};
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
pub fn filter_disks(disks: &[Disk]) -> Vec<&sysinfo::Disk> {
|
|
||||||
disks
|
|
||||||
.iter()
|
|
||||||
.filter(|disk| {
|
|
||||||
// Filter for physical disks - typically those mounted at "/"
|
|
||||||
disk.mount_point() == Path::new("/")
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub fn filter_disks(disks: &[Disk]) -> Vec<&sysinfo::Disk> {
|
|
||||||
disks.iter().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_network_stats(
|
|
||||||
sys: &sysinfo::System,
|
|
||||||
last_update: &mut (Instant, u64, u64),
|
|
||||||
elapsed: f64,
|
|
||||||
) -> (u64, u64) {
|
|
||||||
let current_rx: u64 = sys
|
|
||||||
.networks()
|
|
||||||
.iter()
|
|
||||||
.map(|(_, data)| data.total_received())
|
|
||||||
.sum();
|
|
||||||
let current_tx: u64 = sys
|
|
||||||
.networks()
|
|
||||||
.iter()
|
|
||||||
.map(|(_, data)| data.total_transmitted())
|
|
||||||
.sum();
|
|
||||||
|
|
||||||
let rx_rate = ((current_rx - last_update.1) as f64 / elapsed) as u64;
|
|
||||||
let tx_rate = ((current_tx - last_update.2) as f64 / elapsed) as u64;
|
|
||||||
|
|
||||||
last_update.0 = Instant::now();
|
|
||||||
last_update.1 = current_rx;
|
|
||||||
last_update.2 = current_tx;
|
|
||||||
|
|
||||||
(rx_rate, tx_rate)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn calculate_disk_stats(sys: &sysinfo::System) -> (u64, u64, u64) {
|
|
||||||
let disks = filter_disks(sys.disks());
|
|
||||||
let total: u64 = disks.iter().map(|disk| disk.total_space()).sum();
|
|
||||||
let used: u64 = disks
|
|
||||||
.iter()
|
|
||||||
.map(|disk| disk.total_space() - disk.available_space())
|
|
||||||
.sum();
|
|
||||||
let free: u64 = disks.iter().map(|disk| disk.available_space()).sum();
|
|
||||||
(total, used, free)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn collect_system_stats(
|
|
||||||
sys: &mut sysinfo::System,
|
|
||||||
state: &AppState,
|
|
||||||
) -> Result<SystemStats, String> {
|
|
||||||
let mut last_update = state
|
|
||||||
.last_network_update
|
|
||||||
.lock()
|
|
||||||
.map_err(|e| format!("Failed to lock network state: {}", e))?;
|
|
||||||
|
|
||||||
let elapsed = last_update.0.elapsed().as_secs_f64();
|
|
||||||
|
|
||||||
let (network_rx, network_tx) = calculate_network_stats(sys, &mut last_update, elapsed);
|
|
||||||
let (disk_total, disk_used, disk_free) = calculate_disk_stats(sys);
|
|
||||||
|
|
||||||
Ok(SystemStats {
|
|
||||||
cpu_usage: sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(),
|
|
||||||
memory_total: sys.total_memory(),
|
|
||||||
memory_used: sys.used_memory(),
|
|
||||||
memory_free: sys.total_memory() - sys.used_memory(),
|
|
||||||
memory_cached: sys.total_memory()
|
|
||||||
- (sys.used_memory() + (sys.total_memory() - sys.used_memory())),
|
|
||||||
uptime: sys.uptime(),
|
|
||||||
load_avg: [
|
|
||||||
sys.load_average().one,
|
|
||||||
sys.load_average().five,
|
|
||||||
sys.load_average().fifteen,
|
|
||||||
],
|
|
||||||
network_rx_bytes: network_rx,
|
|
||||||
network_tx_bytes: network_tx,
|
|
||||||
disk_total_bytes: disk_total,
|
|
||||||
disk_used_bytes: disk_used,
|
|
||||||
disk_free_bytes: disk_free,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ProcessStaticInfo {
|
|
||||||
pub name: String,
|
|
||||||
pub command: String,
|
|
||||||
pub user: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct ProcessInfo {
|
|
||||||
pub pid: u32,
|
|
||||||
pub ppid: u32,
|
|
||||||
pub name: String,
|
|
||||||
pub cpu_usage: f32,
|
|
||||||
pub memory_usage: u64,
|
|
||||||
pub status: String,
|
|
||||||
pub user: String,
|
|
||||||
pub command: String,
|
|
||||||
pub threads: Option<u32>,
|
|
||||||
pub environ: Vec<String>,
|
|
||||||
pub root: String,
|
|
||||||
pub virtual_memory: u64,
|
|
||||||
pub start_time: u64,
|
|
||||||
pub run_time: u64,
|
|
||||||
pub disk_usage: (u64, u64),
|
|
||||||
pub session_id: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct SystemStats {
|
|
||||||
pub cpu_usage: Vec<f32>,
|
|
||||||
pub memory_total: u64,
|
|
||||||
pub memory_used: u64,
|
|
||||||
pub memory_free: u64,
|
|
||||||
pub memory_cached: u64,
|
|
||||||
pub uptime: u64,
|
|
||||||
pub load_avg: [f64; 3],
|
|
||||||
pub network_rx_bytes: u64,
|
|
||||||
pub network_tx_bytes: u64,
|
|
||||||
pub disk_total_bytes: u64,
|
|
||||||
pub disk_used_bytes: u64,
|
|
||||||
pub disk_free_bytes: u64,
|
|
||||||
}
|
|
7
src-tauri/src/ui/mod.rs
Normal file
7
src-tauri/src/ui/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! User interface functionality
|
||||||
|
//!
|
||||||
|
//! This module handles UI-specific functionality, including window effects
|
||||||
|
//! and platform-specific visual customizations.
|
||||||
|
|
||||||
|
mod window;
|
||||||
|
pub use window::setup_window_effects;
|
35
src-tauri/src/ui/window.rs
Normal file
35
src-tauri/src/ui/window.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//! Window effects and customization
|
||||||
|
//!
|
||||||
|
//! Provides platform-specific window effects like transparency and vibrancy.
|
||||||
|
|
||||||
|
use tauri::WebviewWindow;
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use window_vibrancy::apply_acrylic;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial, NSVisualEffectState};
|
||||||
|
|
||||||
|
/// Applies Windows-specific window effects
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn setup_window_effects(window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
apply_acrylic(window, Some((0, 0, 25, 125)))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies macOS-specific window effects
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub fn setup_window_effects(window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
apply_vibrancy(
|
||||||
|
window,
|
||||||
|
NSVisualEffectMaterial::HudWindow,
|
||||||
|
Some(NSVisualEffectState::Active),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// No-op for platforms without specific window effects
|
||||||
|
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
|
||||||
|
pub fn setup_window_effects(_window: &WebviewWindow) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,32 +0,0 @@
|
|||||||
#[cfg(target_os = "windows")]
|
|
||||||
use window_vibrancy::apply_acrylic;
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
use window_vibrancy::{apply_vibrancy, NSVisualEffectMaterial, NSVisualEffectState};
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub fn setup_window_effects(
|
|
||||||
window: &tauri::WebviewWindow,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
apply_acrylic(window, Some((0, 0, 25, 125)))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
pub fn setup_window_effects(
|
|
||||||
window: &tauri::WebviewWindow,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
apply_vibrancy(
|
|
||||||
window,
|
|
||||||
NSVisualEffectMaterial::HudWindow,
|
|
||||||
Some(NSVisualEffectState::Active),
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "windows", target_os = "macos")))]
|
|
||||||
pub fn setup_window_effects(
|
|
||||||
_window: &tauri::WebviewWindow,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user