From 8bb71161945f5952c55ef59d053e4725d14d30f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erkan=20I=C5=9EIK?= Date: Fri, 19 Jun 2026 02:56:42 +0300 Subject: [PATCH] feat: form input styling, root password toggle, partition UI fixes - form_input_text: Frame wrapper with stroke/fill/rounding, .frame(false) - form_input_password: SVG eye icons instead of emoji, Frame wrapper - Partition disk grid: hardcoded colors, left-aligned headers - Users: root password show/hide toggle, colored form frames - Add c_root_bg() theme function --- CHANGELOG.md | 21 +++++++++++ src/funct.rs | 82 +++++++++++++++++++++++++++++++----------- src/steps/partition.rs | 40 +++++++++++---------- src/steps/users.rs | 39 +++++++++----------- src/ui/theme.rs | 1 + 5 files changed, 121 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd3dd19..6261196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,27 @@ --- +## [4.0.1] — 2026-06-19 + +### Added +- `c_root_bg()` tema fonksiyonu +- `show_root_password`, `show_root_password_confirm` alanları (`UsersStep`) +- `form_input_text` / `form_input_password`'a `Frame` sarmalı ve `.frame(false)` + +### Changed +- `form_input_text`: Frame içine alındı, stroke/fill/rounding eklendi, yükseklik 32→10 +- `form_input_password`: SVG göz ikonları (emoji yerine), Frame sarmalı, `override_text_color` +- Disk grid seçim renkleri `theme::c_*()` → sabit `(237,237,224,1)` +- Disk listesi header ve sütun başlıkları: `Align::Center` → `Align::LEFT`, `vertical_centered` kaldırıldı +- Root şifre alanları raw `TextEdit` → `form_input_password` (göz ikonu + frame ile) +- Kullanıcı formu Frame rengi `theme::c_bg_widget()` → `(240,243,198)` +- Manuel disk listesinde marka/model etiketi sıralaması değiştirildi + +### Fixed +- `users.rs:154` — `Color32` import hatası (missing `egui::` prefix) + +--- + ## [4.0.0] — 2026-06-06 ### Added diff --git a/src/funct.rs b/src/funct.rs index 44d960e..7e60b90 100644 --- a/src/funct.rs +++ b/src/funct.rs @@ -18,18 +18,27 @@ pub fn form_input_text( )-> eframe::egui::Response { let width_percent = 0.90; // Mevcut genişliğin %90'ı - let height = 32.0; // Standart yükseklik + let height = 10.0; // Standart yükseklik let hesaplanan_genislik = ui.available_width() * width_percent; let boyut = eframe::egui::vec2(hesaplanan_genislik, height); ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0); + egui::Frame::none() + .fill(egui::Color32::from_rgb(255, 255, 255)) + .stroke(egui::Stroke::new(1.0, egui::Color32::from_gray(200))) + .rounding(4.0) + .inner_margin(eframe::egui::Margin::symmetric(2.0, 2.0)) + .show(ui, |ui| { ui.add_sized( boyut, eframe::egui::TextEdit::singleline(text) .vertical_align(eframe::egui::Align::Center) + .frame(false), ) + }).inner } + pub fn form_input_password( ui: &mut eframe::egui::Ui, text: &mut String, @@ -38,28 +47,59 @@ pub fn form_input_password( let width_percent = 0.90; let height = 32.0; let toplam_genislik = ui.available_width() * width_percent; - let dugme_genislik = 40.0; - let alan_genislik = toplam_genislik - dugme_genislik - 4.0; - let boyut = eframe::egui::vec2(alan_genislik, height); + + let buton_genislik = 32.0; + let alan_genislik = toplam_genislik - buton_genislik - 4.0; - ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0); + let mut response: Option = None; - ui.horizontal(|ui| { - let r = ui.add_sized( - boyut, - eframe::egui::TextEdit::singleline(text) - .password(!*show_password) - .vertical_align(eframe::egui::Align::Center), - ); - let göz = if *show_password { "🙈" } else { "👁" }; - if ui.add( - eframe::egui::Button::new(göz) - .min_size(eframe::egui::vec2(dugme_genislik, height)) - ).clicked() { - *show_password = !*show_password; - } - r - }).inner + ui.visuals_mut().override_text_color = Some(eframe::egui::Color32::from_rgb(30, 30, 30)); + + // SVG içeriklerini string olarak tanımlıyoruz + let goz_acik_svg = r#""#; + let goz_kapali_svg = r#""#; + + eframe::egui::Frame::none() + .fill(eframe::egui::Color32::WHITE) + .stroke(eframe::egui::Stroke::new(1.0, eframe::egui::Color32::from_rgb(200, 200, 200))) + .rounding(6.0) + .inner_margin(eframe::egui::Margin::symmetric(2.0, 2.0)) + .show(ui, |ui| { + ui.horizontal(|ui| { + // 1. Şifre Metin Alanı + let r = ui.add_sized( + eframe::egui::vec2(alan_genislik, height), + eframe::egui::TextEdit::singleline(text) + .password(!*show_password) + .frame(false) + ); + response = Some(r); + + // Duruma göre ilgili SVG string'ini seçip byte dizisine (&[u8]) çeviriyoruz + let (uri, svg_bytes) = if *show_password { + ("bytes://goz_acik.svg", goz_acik_svg.as_bytes()) + } else { + ("bytes://goz_kapali.svg", goz_kapali_svg.as_bytes()) + }; + + // Image::from_bytes kullanarak imajı güvenli bir şekilde yüklüyoruz + let svg_gosterici = eframe::egui::Image::from_bytes(uri, svg_bytes) + .tint(eframe::egui::Color32::from_rgb(120, 120, 120)) + .max_width(18.0) + .max_height(18.0); + + // 2. SVG İkonlu Buton + let btn = eframe::egui::Button::image(svg_gosterici) + .frame(false) + .min_size(eframe::egui::vec2(buton_genislik, height)); + + if ui.add(btn).on_hover_cursor(eframe::egui::CursorIcon::PointingHand).clicked() { + *show_password = !*show_password; + } + }); + }); + + response.expect("Metin alanı yüklenemedi") } pub fn form_label(ui: &mut eframe::egui::Ui, text: &str) { diff --git a/src/steps/partition.rs b/src/steps/partition.rs index be09a15..716f3ac 100644 --- a/src/steps/partition.rs +++ b/src/steps/partition.rs @@ -415,13 +415,13 @@ impl PartitionStep { // arka plan egui::Frame::none() .fill(if selected { - crate::ui::theme::c_accent_dim() + //crate::ui::theme::c_accent_dim() + egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1) } else if response.hovered() { egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180) - } else if too_small { - egui::Color32::from_rgba_unmultiplied(60, 30, 30, 180) } else { - crate::ui::theme::c_bg_widget() + //crate::ui::theme::c_bg_widget() + egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1) }) .stroke(egui::Stroke::new( if selected { 2.0 } else { 1.0 }, @@ -509,15 +509,16 @@ impl PartitionStep { egui::vec2(tam_genislik * col_widths[j], 30.0), egui::Sense::hover(), ); - let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center)); + let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::LEFT)); egui::Frame::none() .fill(header_color) .stroke(egui::Stroke::new(1.0, header_color)) .inner_margin(egui::Margin::symmetric(8.0, 4.0)) .show(child_ui, |ui| { - ui.vertical_centered(|ui| { - ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0)); - }); + ui.label(egui::RichText::new(h) + .strong() + .color(header_text) + .size(13.0)); }); } ui.end_row(); @@ -653,11 +654,13 @@ impl PartitionStep { egui::Frame::none() .fill(if selected { - crate::ui::theme::c_accent_dim() + //crate::ui::theme::c_accent_dim() + egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1) } else if response.hovered() { egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180) } else { - crate::ui::theme::c_bg_widget() + //crate::ui::theme::c_bg_widget() + egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1) }) .stroke(egui::Stroke::new( if selected { 2.0 } else { 1.0 }, @@ -680,17 +683,20 @@ impl PartitionStep { } else { &disk.vendor }; + + ui.label( + egui::RichText::new(marka) + .size(11.0) + .color(crate::ui::theme::c_text_dim()), + ); + ui.label( egui::RichText::new(format!("{} GB", disk.size_gb)) .size(14.0) .strong() .color(crate::ui::theme::c_text()), ); - ui.label( - egui::RichText::new(marka) - .size(11.0) - .color(crate::ui::theme::c_text_dim()), - ); + }); if response.clicked() { @@ -753,9 +759,7 @@ impl PartitionStep { .stroke(egui::Stroke::new(1.0, header_color)) .inner_margin(egui::Margin::symmetric(8.0, 4.0)) .show(child_ui, |ui| { - ui.vertical_centered(|ui| { - ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0)); - }); + ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0)); }); } ui.end_row(); diff --git a/src/steps/users.rs b/src/steps/users.rs index af3aace..83550b0 100644 --- a/src/steps/users.rs +++ b/src/steps/users.rs @@ -8,6 +8,8 @@ pub struct UsersStep { use_same_for_admin: bool, show_password: bool, show_password_confirm: bool, + show_root_password: bool, // <-- Eklendi + show_root_password_confirm: bool, // <-- Eklendi } impl Default for UsersStep { @@ -16,6 +18,8 @@ impl Default for UsersStep { use_same_for_admin: true, show_password: false, show_password_confirm: false, + show_root_password: false, + show_root_password_confirm: false, } } } @@ -151,7 +155,7 @@ impl InstallerStep for UsersStep { // ─── Kullanıcı Bilgileri Formu ────────────────────────────────── egui::Frame::group(ui.style()) - .fill(theme::c_bg_widget()) + .fill(egui::Color32::from_rgb(240, 243, 198)) .rounding(6.0) .inner_margin(egui::Margin::symmetric(10.0, 10.0)) .show(ui, |ui| { @@ -200,6 +204,7 @@ impl InstallerStep for UsersStep { { let show_pwd = &mut self.show_password; let before = state.password.clone(); + form_input_password(ui, &mut state.password, show_pwd); // Kullanıcı şifreyi değiştirdiyse OEM bayrağını kaldır if state.oem_mode && state.password != before { @@ -254,7 +259,7 @@ impl InstallerStep for UsersStep { } else { ui.add_space(8.0); egui::Frame::group(ui.style()) - .fill(theme::c_bg_widget()) + .fill(theme::c_root_bg()) .rounding(6.0) .inner_margin(egui::Margin::same(12.0)) .show(ui, |ui| { @@ -263,33 +268,21 @@ impl InstallerStep for UsersStep { ui.add_space(8.0); // Root şifresi - ui.label(egui::RichText::new(t!("admin_password_label")).strong().color(theme::c_text())); - ui.horizontal(|ui| { - ui.add( - eframe::egui::TextEdit::singleline(&mut state.root_password) - .password(true) - .desired_width(f32::INFINITY) - .min_size(eframe::egui::vec2(0.0, 32.0)) - ); - - if !state.root_password.is_empty() && state.root_password.len() < 8 { - ui.colored_label(theme::c_error(), t!("admin_password_short")); - } - }); + + // DÜZELTME: 3. parametre olarak show_root_password eklendi + let show_root_pwd = &mut self.show_root_password; + form_input_password(ui, &mut state.root_password, show_root_pwd); + ui.add_space(8.0); // Şifre doğrulama ui.label(egui::RichText::new(t!("admin_password_confirm_label")).strong().color(theme::c_text())); - ui.horizontal(|ui| { - ui.add( - eframe::egui::TextEdit::singleline(&mut state.root_password_confirm) - .password(true) - .desired_width(f32::INFINITY) - .min_size(eframe::egui::vec2(0.0, 32.0)) - ); - }); + // DÜZELTME: 3. parametre olarak show_root_password_confirm eklendi + let show_root_pwd_conf = &mut self.show_root_password_confirm; + form_input_password(ui, &mut state.root_password_confirm, show_root_pwd_conf); + if state.root_password == state.root_password_confirm { ui.colored_label(theme::c_success(), "✅"); } else { diff --git a/src/ui/theme.rs b/src/ui/theme.rs index 592d47b..504d741 100644 --- a/src/ui/theme.rs +++ b/src/ui/theme.rs @@ -47,6 +47,7 @@ pub fn c_error() -> Color32 { color_from_hex(ERROR.load(Ordering::Relaxed)) pub fn c_sidebar() -> Color32 { color_from_hex(SIDEBAR.load(Ordering::Relaxed)) } pub fn c_sidebar_text() -> Color32 { color_from_hex(SIDEBAR_TEXT.load(Ordering::Relaxed)) } pub fn c_footer_bg() -> Color32 { color_from_hex(0xf7f7f7) } +pub fn c_root_bg() -> Color32 { color_from_hex(0xf7f7f7) } pub fn set_theme_mode(is_dark: bool) { if is_dark {