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 ## [4.0.0] — 2026-06-06
### Added ### Added
+61 -21
View File
@@ -18,18 +18,27 @@ pub fn form_input_text(
)-> eframe::egui::Response { )-> eframe::egui::Response {
let width_percent = 0.90; // Mevcut genişliğin %90'ı 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 hesaplanan_genislik = ui.available_width() * width_percent;
let boyut = eframe::egui::vec2(hesaplanan_genislik, height); let boyut = eframe::egui::vec2(hesaplanan_genislik, height);
ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0); 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( ui.add_sized(
boyut, boyut,
eframe::egui::TextEdit::singleline(text) eframe::egui::TextEdit::singleline(text)
.vertical_align(eframe::egui::Align::Center) .vertical_align(eframe::egui::Align::Center)
.frame(false),
) )
}).inner
} }
pub fn form_input_password( pub fn form_input_password(
ui: &mut eframe::egui::Ui, ui: &mut eframe::egui::Ui,
text: &mut String, text: &mut String,
@@ -38,28 +47,59 @@ pub fn form_input_password(
let width_percent = 0.90; let width_percent = 0.90;
let height = 32.0; let height = 32.0;
let toplam_genislik = ui.available_width() * width_percent; let toplam_genislik = ui.available_width() * width_percent;
let dugme_genislik = 40.0;
let alan_genislik = toplam_genislik - dugme_genislik - 4.0; let buton_genislik = 32.0;
let boyut = eframe::egui::vec2(alan_genislik, height); 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| { ui.visuals_mut().override_text_color = Some(eframe::egui::Color32::from_rgb(30, 30, 30));
let r = ui.add_sized(
boyut, // SVG içeriklerini string olarak tanımlıyoruz
eframe::egui::TextEdit::singleline(text) 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>"#;
.password(!*show_password) 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>"#;
.vertical_align(eframe::egui::Align::Center),
); eframe::egui::Frame::none()
let göz = if *show_password { "🙈" } else { "👁" }; .fill(eframe::egui::Color32::WHITE)
if ui.add( .stroke(eframe::egui::Stroke::new(1.0, eframe::egui::Color32::from_rgb(200, 200, 200)))
eframe::egui::Button::new(göz) .rounding(6.0)
.min_size(eframe::egui::vec2(dugme_genislik, height)) .inner_margin(eframe::egui::Margin::symmetric(2.0, 2.0))
).clicked() { .show(ui, |ui| {
*show_password = !*show_password; ui.horizontal(|ui| {
} // 1. Şifre Metin Alanı
r let r = ui.add_sized(
}).inner 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) { pub fn form_label(ui: &mut eframe::egui::Ui, text: &str) {
+22 -18
View File
@@ -415,13 +415,13 @@ impl PartitionStep {
// arka plan // arka plan
egui::Frame::none() egui::Frame::none()
.fill(if selected { .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() { } else if response.hovered() {
egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180) egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
} else if too_small {
egui::Color32::from_rgba_unmultiplied(60, 30, 30, 180)
} else { } 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( .stroke(egui::Stroke::new(
if selected { 2.0 } else { 1.0 }, if selected { 2.0 } else { 1.0 },
@@ -509,15 +509,16 @@ impl PartitionStep {
egui::vec2(tam_genislik * col_widths[j], 30.0), egui::vec2(tam_genislik * col_widths[j], 30.0),
egui::Sense::hover(), 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() egui::Frame::none()
.fill(header_color) .fill(header_color)
.stroke(egui::Stroke::new(1.0, header_color)) .stroke(egui::Stroke::new(1.0, header_color))
.inner_margin(egui::Margin::symmetric(8.0, 4.0)) .inner_margin(egui::Margin::symmetric(8.0, 4.0))
.show(child_ui, |ui| { .show(child_ui, |ui| {
ui.vertical_centered(|ui| { ui.label(egui::RichText::new(h)
ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0)); .strong()
}); .color(header_text)
.size(13.0));
}); });
} }
ui.end_row(); ui.end_row();
@@ -653,11 +654,13 @@ impl PartitionStep {
egui::Frame::none() egui::Frame::none()
.fill(if selected { .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() { } else if response.hovered() {
egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180) egui::Color32::from_rgba_unmultiplied(60, 60, 80, 180)
} else { } 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( .stroke(egui::Stroke::new(
if selected { 2.0 } else { 1.0 }, if selected { 2.0 } else { 1.0 },
@@ -680,17 +683,20 @@ impl PartitionStep {
} else { } else {
&disk.vendor &disk.vendor
}; };
ui.label(
egui::RichText::new(marka)
.size(11.0)
.color(crate::ui::theme::c_text_dim()),
);
ui.label( ui.label(
egui::RichText::new(format!("{} GB", disk.size_gb)) egui::RichText::new(format!("{} GB", disk.size_gb))
.size(14.0) .size(14.0)
.strong() .strong()
.color(crate::ui::theme::c_text()), .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() { if response.clicked() {
@@ -753,9 +759,7 @@ impl PartitionStep {
.stroke(egui::Stroke::new(1.0, header_color)) .stroke(egui::Stroke::new(1.0, header_color))
.inner_margin(egui::Margin::symmetric(8.0, 4.0)) .inner_margin(egui::Margin::symmetric(8.0, 4.0))
.show(child_ui, |ui| { .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(); ui.end_row();
+16 -23
View File
@@ -8,6 +8,8 @@ pub struct UsersStep {
use_same_for_admin: bool, use_same_for_admin: bool,
show_password: bool, show_password: bool,
show_password_confirm: bool, show_password_confirm: bool,
show_root_password: bool, // <-- Eklendi
show_root_password_confirm: bool, // <-- Eklendi
} }
impl Default for UsersStep { impl Default for UsersStep {
@@ -16,6 +18,8 @@ impl Default for UsersStep {
use_same_for_admin: true, use_same_for_admin: true,
show_password: false, show_password: false,
show_password_confirm: 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 ────────────────────────────────── // ─── Kullanıcı Bilgileri Formu ──────────────────────────────────
egui::Frame::group(ui.style()) egui::Frame::group(ui.style())
.fill(theme::c_bg_widget()) .fill(egui::Color32::from_rgb(240, 243, 198))
.rounding(6.0) .rounding(6.0)
.inner_margin(egui::Margin::symmetric(10.0, 10.0)) .inner_margin(egui::Margin::symmetric(10.0, 10.0))
.show(ui, |ui| { .show(ui, |ui| {
@@ -200,6 +204,7 @@ impl InstallerStep for UsersStep {
{ {
let show_pwd = &mut self.show_password; let show_pwd = &mut self.show_password;
let before = state.password.clone(); let before = state.password.clone();
form_input_password(ui, &mut state.password, show_pwd); form_input_password(ui, &mut state.password, show_pwd);
// Kullanıcı şifreyi değiştirdiyse OEM bayrağını kaldır // Kullanıcı şifreyi değiştirdiyse OEM bayrağını kaldır
if state.oem_mode && state.password != before { if state.oem_mode && state.password != before {
@@ -254,7 +259,7 @@ impl InstallerStep for UsersStep {
} else { } else {
ui.add_space(8.0); ui.add_space(8.0);
egui::Frame::group(ui.style()) egui::Frame::group(ui.style())
.fill(theme::c_bg_widget()) .fill(theme::c_root_bg())
.rounding(6.0) .rounding(6.0)
.inner_margin(egui::Margin::same(12.0)) .inner_margin(egui::Margin::same(12.0))
.show(ui, |ui| { .show(ui, |ui| {
@@ -263,33 +268,21 @@ impl InstallerStep for UsersStep {
ui.add_space(8.0); ui.add_space(8.0);
// Root şifresi // Root şifresi
ui.label(egui::RichText::new(t!("admin_password_label")).strong().color(theme::c_text())); ui.label(egui::RichText::new(t!("admin_password_label")).strong().color(theme::c_text()));
ui.horizontal(|ui| {
ui.add( // DÜZELTME: 3. parametre olarak show_root_password eklendi
eframe::egui::TextEdit::singleline(&mut state.root_password) let show_root_pwd = &mut self.show_root_password;
.password(true) form_input_password(ui, &mut state.root_password, show_root_pwd);
.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"));
}
});
ui.add_space(8.0); ui.add_space(8.0);
// Şifre doğrulama // Şifre doğrulama
ui.label(egui::RichText::new(t!("admin_password_confirm_label")).strong().color(theme::c_text())); ui.label(egui::RichText::new(t!("admin_password_confirm_label")).strong().color(theme::c_text()));
ui.horizontal(|ui| { // DÜZELTME: 3. parametre olarak show_root_password_confirm eklendi
ui.add( let show_root_pwd_conf = &mut self.show_root_password_confirm;
eframe::egui::TextEdit::singleline(&mut state.root_password_confirm) form_input_password(ui, &mut state.root_password_confirm, show_root_pwd_conf);
.password(true)
.desired_width(f32::INFINITY)
.min_size(eframe::egui::vec2(0.0, 32.0))
);
});
if state.root_password == state.root_password_confirm { if state.root_password == state.root_password_confirm {
ui.colored_label(theme::c_success(), ""); ui.colored_label(theme::c_success(), "");
} else { } 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() -> 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_sidebar_text() -> Color32 { color_from_hex(SIDEBAR_TEXT.load(Ordering::Relaxed)) }
pub fn c_footer_bg() -> Color32 { color_from_hex(0xf7f7f7) } 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) { pub fn set_theme_mode(is_dark: bool) {
if is_dark { if is_dark {