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
This commit is contained in:
Erkan IŞIK
2026-06-19 02:56:42 +03:00
parent 0b108be414
commit 8bb7116194
5 changed files with 121 additions and 62 deletions
+21
View File
@@ -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
+61 -21
View File
@@ -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<eframe::egui::Response> = 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#"<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" /><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" /></svg>"#;
let goz_kapali_svg = r#"<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" /></svg>"#;
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) {
+22 -18
View File
@@ -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();
+16 -23
View File
@@ -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 {
+1
View File
@@ -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 {