Skip to content

Commit e4acae4

Browse files
authored
Merge pull request #2 from ERFouX/dev
Refactor: reorganize helpers, clean UI update, and simplify state ini…
2 parents 31d541e + a9936c0 commit e4acae4

File tree

1 file changed

+149
-35
lines changed

1 file changed

+149
-35
lines changed

src/main.rs

Lines changed: 149 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ struct Veltrix {
66
configs: Vec<String>,
77
selected: Option<usize>,
88
laptop_model: String,
9+
temperature: String,
10+
current_fan_speed: String,
11+
target_fan_speed: String,
12+
fan_speed_value: u8,
913
}
1014

1115
impl Veltrix {
@@ -14,63 +18,159 @@ impl Veltrix {
1418
}
1519

1620
fn new(_cc: &eframe::CreationContext<'_>) -> Self {
17-
let configs = get_nbfc_list();
21+
let configs = get_config_list();
1822
let laptop_model = read_laptop_model();
19-
2023
let selected = configs.iter().position(|c| c == &laptop_model);
2124

22-
Self {
25+
let mut app = Self {
2326
configs,
2427
selected,
2528
laptop_model,
29+
temperature: String::new(),
30+
current_fan_speed: String::new(),
31+
target_fan_speed: String::new(),
32+
fan_speed_value: 0,
33+
};
34+
35+
app.refresh();
36+
app
37+
}
38+
39+
fn refresh(&mut self) {
40+
let status = get_status();
41+
42+
self.temperature = status
43+
.iter()
44+
.find(|line| line.contains("Temperature"))
45+
.cloned()
46+
.unwrap_or_else(|| "Unknown Temp".to_string());
47+
48+
self.current_fan_speed = status
49+
.iter()
50+
.find(|line| line.contains("Current Fan Speed"))
51+
.cloned()
52+
.unwrap_or_else(|| "Unknown Speed".to_string());
53+
54+
self.target_fan_speed = status
55+
.iter()
56+
.find(|line| line.contains("Target Fan Speed"))
57+
.cloned()
58+
.unwrap_or_else(|| "Unknown Speed".to_string());
59+
}
60+
61+
fn apply_fan_speed(&self) {
62+
match Command::new("nbfc")
63+
.arg("set")
64+
.arg("-s")
65+
.arg(self.fan_speed_value.to_string())
66+
.output()
67+
{
68+
Ok(output) if !output.status.success() => {
69+
eprintln!("Failed to apply fan speed: {:?}", output);
70+
}
71+
Err(e) => eprintln!("Error running nbfc: {}", e),
72+
_ => {}
2673
}
2774
}
75+
76+
fn set_fan_speed_to_auto(&self) {
77+
Command::new("nbfc")
78+
.arg("set")
79+
.arg("-a")
80+
.output()
81+
.expect("failed to set fan speed to auto");
82+
}
2883
}
2984

3085
impl eframe::App for Veltrix {
3186
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
3287
egui::CentralPanel::default().show(ctx, |ui| {
33-
ui.heading("Welcome to Veltrix !\n");
34-
if self.selected.is_none() {
35-
ui.label("Please select a config");
36-
} else {
37-
ui.label(format!("Laptop model: {}", self.laptop_model));
38-
}
88+
ui.vertical_centered(|ui| {
89+
ui.heading("Veltrix");
90+
ui.label("Notebook Fan Controller GUI");
91+
});
92+
93+
ui.add_space(10.0);
3994

40-
if !self.configs.is_empty() {
41-
let selected_text = self
42-
.selected
43-
.map(|i| self.configs[i].as_str())
44-
.unwrap_or("Select NBFC Config");
45-
46-
egui::ComboBox::from_label("Config List\n")
47-
.selected_text(selected_text)
48-
.show_ui(ui, |ui| {
49-
for (i, config) in self.configs.iter().enumerate() {
50-
if ui
51-
.selectable_label(self.selected == Some(i), config)
52-
.clicked()
53-
{
54-
self.selected = Some(i);
95+
// 🔹 Config Section
96+
ui.group(|ui| {
97+
ui.heading("📂 Configuration");
98+
99+
if !self.configs.is_empty() {
100+
let selected_text = self
101+
.selected
102+
.map(|i| self.configs[i].as_str())
103+
.unwrap_or("Select NBFC Config");
104+
105+
egui::ComboBox::from_label("Available configs")
106+
.selected_text(selected_text)
107+
.show_ui(ui, |ui| {
108+
for (i, config) in self.configs.iter().enumerate() {
109+
if ui
110+
.selectable_label(self.selected == Some(i), config)
111+
.clicked()
112+
{
113+
self.selected = Some(i);
114+
}
55115
}
56-
}
57-
});
116+
});
58117

59-
if let Some(i) = self.selected {
60-
ui.colored_label(egui::Color32::GREEN, format!("Selected Config: {}", self.configs[i]));
118+
if let Some(i) = self.selected {
119+
ui.colored_label(
120+
egui::Color32::GREEN,
121+
format!("✅ Selected: {}", self.configs[i]),
122+
);
123+
} else {
124+
ui.colored_label(egui::Color32::YELLOW, "⚠ No config selected");
125+
}
61126
} else {
62-
ui.colored_label(egui::Color32::YELLOW, "No config selected!");
127+
ui.colored_label(egui::Color32::RED, "No config found!");
63128
}
64-
} else {
65-
ui.colored_label(egui::Color32::RED, "No config found!");
66-
}
129+
});
130+
131+
ui.add_space(10.0);
132+
133+
ui.group(|ui| {
134+
ui.heading("📊 System Status");
135+
ui.label(format!("💻 Laptop: {}", self.laptop_model));
136+
ui.label(&self.temperature);
137+
ui.label(&self.current_fan_speed);
138+
ui.label(&self.target_fan_speed);
139+
140+
if ui.button("🔄 Refresh").clicked() {
141+
self.refresh();
142+
}
143+
});
144+
145+
ui.add_space(10.0);
146+
147+
ui.group(|ui| {
148+
ui.heading("⚡ Fan Control");
149+
150+
ui.add(
151+
egui::Slider::new(&mut self.fan_speed_value, 0..=96)
152+
.text("Manual Fan Speed"),
153+
);
154+
155+
ui.horizontal(|ui| {
156+
if ui.button("✅ Apply").clicked() {
157+
self.apply_fan_speed();
158+
self.refresh();
159+
}
160+
161+
if ui.button("♻ Set Auto").clicked() {
162+
self.set_fan_speed_to_auto();
163+
self.refresh();
164+
}
165+
});
166+
});
67167
});
68168
}
69169
}
70170

71171
fn main() -> eframe::Result<()> {
72172
let native_options = eframe::NativeOptions {
73-
viewport: egui::ViewportBuilder::default().with_inner_size((600.0, 700.0)),
173+
viewport: egui::ViewportBuilder::default().with_inner_size((400.0, 450.0)),
74174
..eframe::NativeOptions::default()
75175
};
76176

@@ -88,12 +188,26 @@ fn read_laptop_model() -> String {
88188
.to_string()
89189
}
90190

91-
fn get_nbfc_list() -> Vec<String> {
191+
fn get_config_list() -> Vec<String> {
92192
let output = Command::new("nbfc")
93193
.arg("config")
94194
.arg("--list")
95195
.output()
96-
.expect("failed to execute nbfc");
196+
.expect("failed to get config list");
197+
198+
String::from_utf8_lossy(&output.stdout)
199+
.lines()
200+
.map(|line| line.trim().to_string())
201+
.filter(|line| !line.is_empty())
202+
.collect()
203+
}
204+
205+
fn get_status() -> Vec<String> {
206+
let output = Command::new("nbfc")
207+
.arg("status")
208+
.arg("-a")
209+
.output()
210+
.expect("failed to get status");
97211

98212
String::from_utf8_lossy(&output.stdout)
99213
.lines()

0 commit comments

Comments
 (0)