From a9936c08f6e8b50fe3212df2aeaa6273065175b2 Mon Sep 17 00:00:00 2001 From: ERFouX Date: Tue, 16 Sep 2025 20:57:31 +0330 Subject: [PATCH] Refactor: reorganize helpers, clean UI update, and simplify state initialization --- src/main.rs | 184 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 149 insertions(+), 35 deletions(-) diff --git a/src/main.rs b/src/main.rs index 87eb8da..e2c04e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,10 @@ struct Veltrix { configs: Vec, selected: Option, laptop_model: String, + temperature: String, + current_fan_speed: String, + target_fan_speed: String, + fan_speed_value: u8, } impl Veltrix { @@ -14,63 +18,159 @@ impl Veltrix { } fn new(_cc: &eframe::CreationContext<'_>) -> Self { - let configs = get_nbfc_list(); + let configs = get_config_list(); let laptop_model = read_laptop_model(); - let selected = configs.iter().position(|c| c == &laptop_model); - Self { + let mut app = Self { configs, selected, laptop_model, + temperature: String::new(), + current_fan_speed: String::new(), + target_fan_speed: String::new(), + fan_speed_value: 0, + }; + + app.refresh(); + app + } + + fn refresh(&mut self) { + let status = get_status(); + + self.temperature = status + .iter() + .find(|line| line.contains("Temperature")) + .cloned() + .unwrap_or_else(|| "Unknown Temp".to_string()); + + self.current_fan_speed = status + .iter() + .find(|line| line.contains("Current Fan Speed")) + .cloned() + .unwrap_or_else(|| "Unknown Speed".to_string()); + + self.target_fan_speed = status + .iter() + .find(|line| line.contains("Target Fan Speed")) + .cloned() + .unwrap_or_else(|| "Unknown Speed".to_string()); + } + + fn apply_fan_speed(&self) { + match Command::new("nbfc") + .arg("set") + .arg("-s") + .arg(self.fan_speed_value.to_string()) + .output() + { + Ok(output) if !output.status.success() => { + eprintln!("Failed to apply fan speed: {:?}", output); + } + Err(e) => eprintln!("Error running nbfc: {}", e), + _ => {} } } + + fn set_fan_speed_to_auto(&self) { + Command::new("nbfc") + .arg("set") + .arg("-a") + .output() + .expect("failed to set fan speed to auto"); + } } impl eframe::App for Veltrix { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::CentralPanel::default().show(ctx, |ui| { - ui.heading("Welcome to Veltrix !\n"); - if self.selected.is_none() { - ui.label("Please select a config"); - } else { - ui.label(format!("Laptop model: {}", self.laptop_model)); - } + ui.vertical_centered(|ui| { + ui.heading("Veltrix"); + ui.label("Notebook Fan Controller GUI"); + }); + + ui.add_space(10.0); - if !self.configs.is_empty() { - let selected_text = self - .selected - .map(|i| self.configs[i].as_str()) - .unwrap_or("Select NBFC Config"); - - egui::ComboBox::from_label("Config List\n") - .selected_text(selected_text) - .show_ui(ui, |ui| { - for (i, config) in self.configs.iter().enumerate() { - if ui - .selectable_label(self.selected == Some(i), config) - .clicked() - { - self.selected = Some(i); + // 🔹 Config Section + ui.group(|ui| { + ui.heading("📂 Configuration"); + + if !self.configs.is_empty() { + let selected_text = self + .selected + .map(|i| self.configs[i].as_str()) + .unwrap_or("Select NBFC Config"); + + egui::ComboBox::from_label("Available configs") + .selected_text(selected_text) + .show_ui(ui, |ui| { + for (i, config) in self.configs.iter().enumerate() { + if ui + .selectable_label(self.selected == Some(i), config) + .clicked() + { + self.selected = Some(i); + } } - } - }); + }); - if let Some(i) = self.selected { - ui.colored_label(egui::Color32::GREEN, format!("Selected Config: {}", self.configs[i])); + if let Some(i) = self.selected { + ui.colored_label( + egui::Color32::GREEN, + format!("✅ Selected: {}", self.configs[i]), + ); + } else { + ui.colored_label(egui::Color32::YELLOW, "⚠ No config selected"); + } } else { - ui.colored_label(egui::Color32::YELLOW, "No config selected!"); + ui.colored_label(egui::Color32::RED, "❌ No config found!"); } - } else { - ui.colored_label(egui::Color32::RED, "No config found!"); - } + }); + + ui.add_space(10.0); + + ui.group(|ui| { + ui.heading("📊 System Status"); + ui.label(format!("💻 Laptop: {}", self.laptop_model)); + ui.label(&self.temperature); + ui.label(&self.current_fan_speed); + ui.label(&self.target_fan_speed); + + if ui.button("🔄 Refresh").clicked() { + self.refresh(); + } + }); + + ui.add_space(10.0); + + ui.group(|ui| { + ui.heading("⚡ Fan Control"); + + ui.add( + egui::Slider::new(&mut self.fan_speed_value, 0..=96) + .text("Manual Fan Speed"), + ); + + ui.horizontal(|ui| { + if ui.button("✅ Apply").clicked() { + self.apply_fan_speed(); + self.refresh(); + } + + if ui.button("♻ Set Auto").clicked() { + self.set_fan_speed_to_auto(); + self.refresh(); + } + }); + }); }); } } fn main() -> eframe::Result<()> { let native_options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default().with_inner_size((600.0, 700.0)), + viewport: egui::ViewportBuilder::default().with_inner_size((400.0, 450.0)), ..eframe::NativeOptions::default() }; @@ -88,12 +188,26 @@ fn read_laptop_model() -> String { .to_string() } -fn get_nbfc_list() -> Vec { +fn get_config_list() -> Vec { let output = Command::new("nbfc") .arg("config") .arg("--list") .output() - .expect("failed to execute nbfc"); + .expect("failed to get config list"); + + String::from_utf8_lossy(&output.stdout) + .lines() + .map(|line| line.trim().to_string()) + .filter(|line| !line.is_empty()) + .collect() +} + +fn get_status() -> Vec { + let output = Command::new("nbfc") + .arg("status") + .arg("-a") + .output() + .expect("failed to get status"); String::from_utf8_lossy(&output.stdout) .lines()