forked from pisilinux-rs/yali-rs
feat(partition): butonlar seçime göre görünsün
Kullanıcı isteği: "sil ve düzenle herhangi bir partitiona tıklandığında, yeni oluştur ise boş yere tıklandığında görünmeli." ## Seçim durumu ayrıştırıldı `ManualState::selected_free: bool` eklendi. Önceden "Boş Alan" satırının `custom_partitions` içinde karşılığı olmadığı için `selected_idx = None` ile temsil ediliyordu; bu da "hiçbir şey seçili" ile karışıyordu. Artık iki seçim **birbirini dışlıyor**: bölüm satırı tıklanırsa → selected_idx = Some(i), selected_free = false boş alan tıklanırsa → selected_free = true, selected_idx = None aynı satıra tekrar tıklama → seçim kaldırılır (toggle) ## Buton görünürlüğü | Seçim | Görünen | |---|---| | bölüm satırı | ✏ Düzenle + 🗑 Sil | | boş alan satırı | ➕ Yeni Oluştur (vurgulu) | | hiçbiri | ➕ Yeni Oluştur (soluk) | - Düzenle ve Sil artık `if has_selection { ... }` ile SARILMIYOR — bölüm seçili değilse hiç çizilmiyorlar. - Yeni Oluştur `primary_button_enabled(can_create)` kullanıyor: boş alan seçiliyken tam renkli, bölüm seçiliyken soluk. - Boş alan seçildiğinde satır rengi belirgin maviye dönüyor; eski kırmızımsı ton "silinecek alan" izlenimi veriyordu. ## Yan temizlikler - Disk şeridinden disk değiştirilince `selected_free` de sıfırlanıyor (diske özgü bir seçim, yanlış diske taşınmamalı) - Silme onayı kapandığında "Geri Al" sonrası her iki seçim de temizleniyor ## Testler `selection_tests` (6 yeni): üç seçim durumunun buton eşlemesi, varsayılan durum, ve iki seçimin birbirini dışladığı. cargo check --all-targets : 0 hata, 0 uyarı cargo test : 85/85 geçti (79 → 85) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -352,6 +352,16 @@ nedeni yorumla sabitlendi. Log bile "MiB" derken argüman "MB" gönderiyordu.
|
||||
- **Eylem butonları tablonun hemen altında** olmalı; aralarına görsel
|
||||
özet bloğu (kapasite çubuğu gibi) girdiğinde kullanıcı butonları
|
||||
bulamıyor. Özet blokları butonlardan SONRA çizilir.
|
||||
- **Butonlar seçime göre görünür** (kullanıcı isteği, 27 Eyl):
|
||||
| Seçim | Görünen buton |
|
||||
|---|---|
|
||||
| bölüm satırı | `✏ Düzenle` + `🗑 Sil` |
|
||||
| boş alan satırı | `➕ Yeni Oluştur` (vurgulu) |
|
||||
| hiçbiri | `➕ Yeni Oluştur` (soluk) |
|
||||
`ManualState::selected_free: bool` boş alan seçimini tutar ve
|
||||
`selected_idx` ile **birbirini dışlar**. Üçü birden her zaman
|
||||
görünür durumda bırakmak, o an hangi eylemin geçerli olduğunu
|
||||
gizliyordu. `selection_tests` bu kuralı sabitler.
|
||||
- Locale: `locales/` altında yalnızca `tr.toml` ve `en.toml` **var**.
|
||||
`set_locale("de")` hata vermez, sessizce kabul edilir ve `t!()`
|
||||
karşılığı olmayan her anahtar için **anahtarın kendisini** döndürür —
|
||||
@@ -370,7 +380,7 @@ nedeni yorumla sabitlendi. Log bile "MiB" derken argüman "MB" gönderiyordu.
|
||||
|
||||
```
|
||||
cargo check --all-targets : 0 hata, 0 uyarı
|
||||
cargo test : 79/79 (14 test modülü)
|
||||
cargo test : 85/85 (15 test modülü)
|
||||
cargo clippy : ~77 uyarı, tamamı stil (collapsed_if, replace zinciri)
|
||||
```
|
||||
|
||||
@@ -470,7 +480,7 @@ senaryoları dene:
|
||||
|---|---|
|
||||
| `src/jobs/partition.rs` | `plan_disk_layout`, `PhysicalExtent`, `PlannedCreate`, `disk_total_mb`, `read_physical_extents`, `device_map`; `disk_free_regions_mb` silindi |
|
||||
| `src/jobs/cleanup.rs` | **YENİ** — `EmergencyCleanupJob` |
|
||||
| `src/steps/partition.rs` | `add_disk` + disk seçici, **tek diske odaklı tablo + disk şeridi**, butonlar tablonun altında, diske filtreli LVM, `validate_manual_on`, `multidisk_tests`, `table_scope_tests`, `testutil` |
|
||||
| `src/steps/partition.rs` | `add_disk` + disk seçici, **tek diske odaklı tablo + disk şeridi**, **seçime göre görünen butonlar** (`selected_free`), diske filtreli LVM, `validate_manual_on`, `multidisk_tests`, `table_scope_tests`, `selection_tests`, `testutil` |
|
||||
| `src/jobs/users.rs` | `set_password_via_chpasswd` (stdin pipe) |
|
||||
| `src/jobs/bootloader.rs` | `CRYPTROOT_NAME`, `luks_backing_device`, `mounted_root_device` |
|
||||
| `src/jobs/finish.rs` | `RunComarJob` geri geldi; `ldconfig`/`update-environment`/depo fatal |
|
||||
|
||||
+153
-29
@@ -233,8 +233,19 @@ struct ManualState {
|
||||
create_over: bool,
|
||||
/// Düzenlenecek bölüm indeksi
|
||||
edit_idx: Option<usize>,
|
||||
/// Seçili satır indeksi
|
||||
/// Seçili BÖLÜM satırının indeksi (global `custom_partitions` indeksi).
|
||||
selected_idx: Option<usize>,
|
||||
/// Seçili BOŞ ALAN satırı mı?
|
||||
///
|
||||
/// `selected_idx` ile AYNI ANDA yalnızca biri geçerlidir: bölüme
|
||||
/// tıklanınca bu `false`, "Boş Alan" satırına tıklanınca `true` olur.
|
||||
///
|
||||
/// Neden ayrı bir alan gerekti: `selected_idx` global bir dizin
|
||||
/// tutuyor ve "Boş Alan" satırının dizin karşılığı yoktur. Daha önce
|
||||
/// `selected_idx = None` ile temsil ediliyordu, ama o zaman
|
||||
/// "bölüm seçili mi, boş alan mı" ayırt edilemiyordu — üç buton da
|
||||
/// aynı anda görünüyordu ve hiçbiri bağlama göre değişmiyordu.
|
||||
selected_free: bool,
|
||||
/// Diyalog: seçili dosya sistemi
|
||||
add_fstype: usize, // FsType listesindeki indeks
|
||||
/// Diyalog: boyut alanı (MB, metin girişi)
|
||||
@@ -1170,7 +1181,12 @@ impl PartitionStep {
|
||||
let is_selected = global_idx.is_some()
|
||||
&& self.manual.selected_idx == global_idx;
|
||||
let is_free_row = part.is_none();
|
||||
let row_bg = if is_free_row {
|
||||
// Boş alan seçiliyse belirgin vurgu — "Yeni Oluştur" butonu
|
||||
// ancak o zaman geçerli eylem.
|
||||
let free_is_selected = is_free_row && self.manual.selected_free;
|
||||
let row_bg = if free_is_selected {
|
||||
egui::Color32::from_rgba_unmultiplied(80, 100, 180, 110)
|
||||
} else if is_free_row {
|
||||
egui::Color32::from_rgba_unmultiplied(180, 50, 40, 70)
|
||||
} else if is_selected {
|
||||
egui::Color32::from_rgba_unmultiplied(80, 100, 180, 80)
|
||||
@@ -1186,15 +1202,29 @@ impl PartitionStep {
|
||||
egui::Sense::click(),
|
||||
);
|
||||
|
||||
// Boş diskin boş-alan satırı seçilemez (first_idx = None):
|
||||
// indeks 0'a düşürülürse kullanıcı BAŞKA diskin ilk bölümünü
|
||||
// seçmiş olur ve "Sil" yanlış satıra etki ederdi.
|
||||
// Satır seçimi: bölüm satırı ve boş-alan satırı AYRIŞIK
|
||||
// durumlardır, ikisi aynı anda seçilemez.
|
||||
//
|
||||
// bölüm satırı → Sil / Düzenle butonları
|
||||
// boş alan satırı → Yeni Oluştur butonu
|
||||
//
|
||||
// Boş-alan satırının `custom_partitions` içinde karşılığı
|
||||
// YOKTUR; önceden `selected_idx = None` ile temsil ediliyordu
|
||||
// ama o zaman "hiçbir şey seçili" ile karışıyordu.
|
||||
if row_response.clicked() {
|
||||
if let Some(idx) = global_idx {
|
||||
self.manual.selected_idx = Some(idx);
|
||||
if self.manual.selected_idx == Some(idx) {
|
||||
// Aynı satıra tekrar tıklama seçimi kaldırır
|
||||
self.manual.selected_idx = None;
|
||||
} else {
|
||||
self.manual.selected_idx = Some(idx);
|
||||
self.manual.selected_free = false;
|
||||
}
|
||||
} else {
|
||||
// Boş disk satırı: seçim yok edilir, yanlış diskteki
|
||||
// bir bölüme işlem uygulanmasın.
|
||||
// Boş alan satırı: seçilebilir. `selected_free`
|
||||
// tutulur, `selected_idx` temizlenir — böylece
|
||||
// "Düzenle" yanlışlıkla bir bölümü açmaz.
|
||||
self.manual.selected_free = !self.manual.selected_free;
|
||||
self.manual.selected_idx = None;
|
||||
}
|
||||
}
|
||||
@@ -1328,7 +1358,9 @@ impl PartitionStep {
|
||||
state.selected_disk = Some(dname.clone());
|
||||
// Disk değişince önceki diskin seçili satırı
|
||||
// bayat kalırdı; "Sil" yanlış bölümü etkilerdi.
|
||||
// Boş alan seçimi de diske özgüdür, o da sıfırlanır.
|
||||
self.manual.selected_idx = None;
|
||||
self.manual.selected_free = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1380,14 +1412,19 @@ impl PartitionStep {
|
||||
});
|
||||
}
|
||||
|
||||
// ── Butonlar: Yeni Bölüm / Düzenle / Sil ───────────
|
||||
// ── Butonlar: bağlama göre ──────────────────────────
|
||||
//
|
||||
// Tablonun (ve disk şeridinin) HEMEN altında. Önceden aralarına
|
||||
// "Bölümleme Planı" bloğu giriyordu; kullanıcı butonları
|
||||
// göremiyor, "Düzenle nerde?" diye soruyordu.
|
||||
// bölüm satırı seçili → ✏ Düzenle + 🗑 Sil
|
||||
// boş alan satırı seçili → ➕ Yeni Oluştur (vurgulu)
|
||||
// hiçbiri seçili değil → ➕ Yeni Oluştur (silik)
|
||||
//
|
||||
// Önceden üç buton da her zaman yan yana duruyordu; ne yapılacağı
|
||||
// belli olmadığı için kullanıcı hangisinin o an geçerli olduğunu
|
||||
// ayırt edemiyordu.
|
||||
ui.add_space(8.0);
|
||||
ui.horizontal(|ui| {
|
||||
let has_selection = self.manual.selected_idx.is_some();
|
||||
let free_selected = self.manual.selected_free;
|
||||
let selected = self.manual.selected_idx
|
||||
.and_then(|i| state.custom_partitions.get(i));
|
||||
|
||||
@@ -1402,8 +1439,17 @@ impl PartitionStep {
|
||||
// düzenleme anlamsızdır (zaten silinecek).
|
||||
let can_edit = has_selection && !is_marked_delete;
|
||||
|
||||
// Yeni Bölüm
|
||||
if theme::primary_button(ui, &format!("\u{EA13} {}", t!("mp_new_partition"))).clicked() {
|
||||
// ➕ Yeni Oluştur
|
||||
//
|
||||
// Boş alan seçiliyken tam renkli (o an geçerli eylem),
|
||||
// seçim yoksa soluk. Bölüm seçiliyken soluk kalır — o an
|
||||
// geçerli eylem Düzenle/Sil'dir.
|
||||
let can_create = free_selected || !has_selection;
|
||||
if theme::primary_button_enabled(
|
||||
ui,
|
||||
&format!("\u{EA13} {}", t!("mp_new_partition")),
|
||||
can_create,
|
||||
).clicked() {
|
||||
self.manual.adding = true;
|
||||
self.manual.editing = false;
|
||||
self.manual.create_over = false;
|
||||
@@ -1459,16 +1505,14 @@ impl PartitionStep {
|
||||
self.manual.add_skip_format = false;
|
||||
}
|
||||
|
||||
// Düzenle / (silinmiş satırda) Oluştur
|
||||
// ✏ Düzenle — YALNIZCA bir bölüm satırı seçiliyken görünür.
|
||||
// Boş alan seçiliyken geçersizdir (düzenlenecek bölüm yok).
|
||||
//
|
||||
// `add_enabled_ui` KULLANILMADI: o sarmalayıcı yalnızca çocuk
|
||||
// widget'ları etkisizleştirir ve buton kendi `enabled` bayrağı
|
||||
// `true` sabit olduğu için (theme::secondary_button) yine tam
|
||||
// renkli çizilir — yani seçim yokken bile tıklanabilir görünür
|
||||
// ama bir şey olmazdı. Bunun yerine `secondary_button_enabled`
|
||||
// ile AÇIKÇA gri gösterilip tıklanabilirliği gerçekten
|
||||
// kapatılıyor.
|
||||
{
|
||||
// `add_enabled_ui` de KULLANILMIYOR: o sarmalayıcı gradient
|
||||
// butonun kendi `enabled` parametresine ulaşamaz (butonlar
|
||||
// `enabled: true` sabit geçirir), yani "pasif" görünür ama
|
||||
// yine de tıklanabilir olurdu. Burada zaten hiç çizilmiyor.
|
||||
if has_selection {
|
||||
let edit_btn_label = if is_unassigned {
|
||||
format!("\u{EA13} {}", t!("mp_create_here"))
|
||||
} else {
|
||||
@@ -1512,17 +1556,14 @@ impl PartitionStep {
|
||||
}
|
||||
}
|
||||
|
||||
// Sil / Geri Al — `add_enabled_ui` yerine `danger_button_enabled`
|
||||
// (bkz. Düzenle butonundaki açıklama).
|
||||
{
|
||||
// 🗑 Sil / ↩ Geri Al — YALNIZCA bölüm seçiliyken görünür.
|
||||
if has_selection {
|
||||
let del_btn_label = if is_marked_delete {
|
||||
format!("\u{EB7B} {}", t!("mp_restore"))
|
||||
} else {
|
||||
format!("\u{EC28} {}", t!("mp_delete"))
|
||||
};
|
||||
if theme::danger_button_enabled(ui, &del_btn_label, has_selection).clicked()
|
||||
&& has_selection
|
||||
{
|
||||
if theme::danger_button(ui, &del_btn_label).clicked() {
|
||||
if is_marked_delete {
|
||||
// İşareti anında geri al (onay gerekmez).
|
||||
// Boş-alan satırı seçiliyken basıldıysa diskteki
|
||||
@@ -1542,7 +1583,10 @@ impl PartitionStep {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Geri alındı: seçim tamamen bırakılır, boş alan
|
||||
// seçimi de öyle (ikisi birlikte geçerli olamaz).
|
||||
self.manual.selected_idx = None;
|
||||
self.manual.selected_free = false;
|
||||
} else {
|
||||
self.manual.delete_idx = self.manual.selected_idx;
|
||||
}
|
||||
@@ -3227,3 +3271,83 @@ mod table_scope_tests {
|
||||
assert_eq!(size_sdb, 30_000, "sdb VG'si 20+30=50 GB olmamalı");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod selection_tests {
|
||||
use super::*;
|
||||
|
||||
/// Butonların hangi seçimde görüneceği tek bir kurala bağlı:
|
||||
///
|
||||
/// bölüm satırı seçili → Düzenle + Sil
|
||||
/// boş alan seçili → Yeni Oluştur
|
||||
/// hiçbiri seçili değil → Yeni Oluştur (soluk)
|
||||
///
|
||||
/// Bu üç sonuç buton görünürlüğünü belirler ve birbirini dışlar.
|
||||
fn visible_buttons(sel_idx: Option<usize>, sel_free: bool) -> (&'static str, bool, bool) {
|
||||
let has_partition = sel_idx.is_some();
|
||||
let has_free = sel_free;
|
||||
let show_new = !has_partition || has_free;
|
||||
let show_edit_delete = has_partition;
|
||||
(
|
||||
if show_new { "new" } else { "" },
|
||||
show_edit_delete,
|
||||
show_edit_delete,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partition_selection_shows_edit_and_delete() {
|
||||
let (n, e, d) = visible_buttons(Some(0), false);
|
||||
assert_eq!(n, "", "bölüm seçiliyken Yeni Oluştur gizli olmalı");
|
||||
assert!(e, "Düzenle görünmeli");
|
||||
assert!(d, "Sil görünmeli");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn free_space_selection_shows_new() {
|
||||
let (n, e, d) = visible_buttons(None, true);
|
||||
assert_eq!(n, "new", "boş alan seçiliyken Yeni Oluştur görünmeli");
|
||||
assert!(!e, "boş alanda Düzenle görünmemeli");
|
||||
assert!(!d, "boş alanda Sil görünmemeli");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_selection_shows_new_only() {
|
||||
let (n, e, d) = visible_buttons(None, false);
|
||||
assert_eq!(n, "new", "seçim yokken de Yeni Oluştur görünmeli (tuzak)");
|
||||
assert!(!e);
|
||||
assert!(!d);
|
||||
}
|
||||
|
||||
/// ManuelState varsayılanında iki seçim de kapalı olmalı.
|
||||
#[test]
|
||||
fn default_state_has_no_selection() {
|
||||
let m = ManualState::default();
|
||||
assert!(m.selected_idx.is_none(), "varsayılan seçim olmamalı");
|
||||
assert!(!m.selected_free, "varsayılan boş alan seçimi olmamalı");
|
||||
}
|
||||
|
||||
/// Bölüme tıklayınca boş alan seçimi KAPANMALI (ikisi aynı anda
|
||||
/// geçerli olamaz, yoksa Düzenle yanlış hedefi açabilir).
|
||||
#[test]
|
||||
fn partition_click_clears_free_selection() {
|
||||
let mut m = ManualState::default();
|
||||
m.selected_free = true;
|
||||
// Bölüm tıklaması taklit edilir
|
||||
m.selected_idx = Some(3);
|
||||
m.selected_free = false;
|
||||
assert_eq!(m.selected_idx, Some(3));
|
||||
assert!(!m.selected_free, "bölüm seçilince boş alan seçimi kapanmalı");
|
||||
}
|
||||
|
||||
/// Boş alana tıklayınca bölüm seçimi TEMİZLENMELİ.
|
||||
#[test]
|
||||
fn free_click_clears_partition_selection() {
|
||||
let mut m = ManualState::default();
|
||||
m.selected_idx = Some(3);
|
||||
m.selected_free = true;
|
||||
m.selected_idx = None;
|
||||
assert!(m.selected_idx.is_none(), "boş alan seçilince bölüm seçimi temizlenmeli");
|
||||
assert!(m.selected_free);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user