use eframe::egui; use rust_i18n::t; use crate::installer::{GlobalState, InstallerStep}; #[derive(Default)] pub struct NetworkStep { scan_results: Vec, show_password: Vec, scanning: bool, scan_done: bool, proxy_enabled: bool, } #[derive(Clone, Default)] struct WifiNetwork { ssid: String, signal: String, secured: bool, active: bool, } impl NetworkStep { fn scan_wifi(&mut self) { self.scanning = true; self.scan_done = false; self.scan_results.clear(); if let Ok(out) = std::process::Command::new("nmcli") .args(["-t", "-f", "SSID,SIGNAL,SECURITY,ACTIVE", "dev", "wifi", "list"]) .output() { if out.status.success() { let text = String::from_utf8_lossy(&out.stdout); for line in text.lines() { let parts: Vec<&str> = line.split(':').collect(); if parts.len() >= 3 { let ssid = parts[0].trim().to_string(); if ssid.is_empty() || ssid == "--" { continue; } self.scan_results.push(WifiNetwork { ssid, signal: parts[1].to_string(), secured: !parts[2].is_empty() && parts[2] != "(none)" && parts[2] != "--", active: parts.get(3).map(|s| s.trim() == "yes").unwrap_or(false), }); } } } } self.show_password = vec![false; self.scan_results.len()]; self.scanning = false; self.scan_done = true; } fn connect_wifi(ssid: &str, password: &str) -> Result { let mut args = vec!["dev", "wifi", "connect", ssid]; if !password.is_empty() { args.extend_from_slice(&["password", password]); } let out = std::process::Command::new("nmcli") .args(&args) .output() .map_err(|e| format!("nmcli error: {}", e))?; if out.status.success() { Ok(String::from_utf8_lossy(&out.stdout).trim().to_string()) } else { Err(String::from_utf8_lossy(&out.stderr).trim().to_string()) } } } impl InstallerStep for NetworkStep { fn name(&self) -> String { t!("network").to_string() } fn show(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) { ui.heading(t!("network_title")); ui.label(t!("network_description")); ui.add_space(12.0); // Mevcut bağlantΔ± durumu if let Ok(out) = std::process::Command::new("nmcli") .args(["-t", "-f", "DEVICE,TYPE,STATE,CONNECTION", "dev", "status"]) .output() { let text = String::from_utf8_lossy(&out.stdout); let connected: Vec<&str> = text.lines() .filter(|l| l.contains(":connected:") || l.contains(":connecting:")) .collect(); if !connected.is_empty() { ui.colored_label( egui::Color32::from_rgb(80, 170, 80), format!("{} {}", t!("network_connected"), connected.join(", ")), ); } else { ui.colored_label( egui::Color32::from_rgb(200, 140, 40), t!("network_disconnected"), ); } } ui.add_space(8.0); // Proxy ayarlarΔ± ui.horizontal(|ui| { ui.add(egui::Checkbox::new(&mut self.proxy_enabled, "")); ui.label(t!("network_proxy_label")); }); if self.proxy_enabled { egui::Grid::new("proxy_grid") .num_columns(2) .spacing([12.0, 6.0]) .show(ui, |ui| { ui.label("HTTP:"); ui.text_edit_singleline(&mut state.network_http_proxy); ui.end_row(); ui.label("HTTPS:"); ui.text_edit_singleline(&mut state.network_https_proxy); ui.end_row(); ui.label("FTP:"); ui.text_edit_singleline(&mut state.network_ftp_proxy); ui.end_row(); }); } ui.add_space(12.0); // Wi-Fi tara if !self.scan_done { if ui.add(egui::Button::new(t!("network_scan"))).clicked() { self.scan_wifi(); } } else { ui.horizontal(|ui| { if ui.add(egui::Button::new(t!("network_rescan"))).clicked() { self.scan_done = false; } ui.label( egui::RichText::new(format!("{}: {}", t!("network_scan_count"), self.scan_results.len())) .size(12.0) .color(egui::Color32::from_rgb(120, 120, 140)), ); }); } ui.add_space(6.0); // Wi-Fi listesi if !self.scan_results.is_empty() { egui::ScrollArea::vertical() .max_height(300.0) .show(ui, |ui| { egui::Frame::group(ui.style()) .inner_margin(egui::Margin::same(6.0)) .show(ui, |ui| { for (i, net) in self.scan_results.clone().iter().enumerate() { ui.horizontal(|ui| { let lock = if net.secured { "πŸ”’" } else { "🌐" }; let sig = net.signal.parse::().unwrap_or(0); let bars = if sig > -50 { "β–‚β–„β–†β–ˆ" } else if sig > -67 { "β–‚β–„β–†" } else if sig > -80 { "β–‚β–„" } else { "β–‚" }; let active = if net.active { " βœ“" } else { "" }; ui.label(format!("{} {}{}", lock, net.ssid, active)); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { ui.label( egui::RichText::new(bars) .size(10.0) .color(egui::Color32::from_rgb(120, 120, 140)), ); if net.secured && !net.active { ui.add(egui::TextEdit::singleline(&mut state.network_wifi_password) .password(!self.show_password.get(i).copied().unwrap_or(false)) .hint_text(t!("network_password_hint")) .desired_width(120.0)); if ui.small_button("πŸ‘").clicked() { if self.show_password.len() <= i { self.show_password.resize(i + 1, false); } self.show_password[i] = !self.show_password[i]; } } if !net.active && ui.add(egui::Button::new(t!("network_connect"))).clicked() { let pw = if net.secured { state.network_wifi_password.clone() } else { String::new() }; match Self::connect_wifi(&net.ssid, &pw) { Ok(msg) => { state.install_log.push(format!("Wi-Fi: {} β€” {}", net.ssid, msg)); self.scan_done = false; } Err(e) => { state.install_log.push(format!("Wi-Fi error: {}", e)); } } } }); }); ui.separator(); } }); }); } } fn is_complete(&self, _state: &GlobalState) -> bool { true } }