chore: add English/Turkish changelog cross-links

This commit is contained in:
Erkan IŞIK
2026-06-25 01:33:51 +03:00
parent 7f94c8c0cc
commit 71e2ab3829
14 changed files with 694 additions and 120 deletions
+29 -1
View File
@@ -1,4 +1,32 @@
# Changelog # Changelog — [English](CHANGELOG_en.md)
## [4.0.4] — 2026-06-25
### Added
- Kullanıcı adı doğrulama fonksiyonu `validate_username` (detaylı hata mesajları döndürür)
- Yasaklı sistem kullanıcı adları listesi (root, daemon, bin, sys, vb.)
- Türkçe karakter dönüşümleri büyük harfleri de kapsayacak şekilde genişletildi (Ş, Ğ, İ, Ö, Ü, Ç)
- Locale dosyalarına yeni kullanıcı adı doğrulama anahtarları (username_too_long, username_forbidden, username_invalid_start, username_invalid_chars)
- UsersStep struct'ına `autologin` alanı eklendi
### Changed
- Kullanıcı adı, şifre doğrulama ve hostname input'ları için check/fail iconları input'un yanına alındı
- Hata mesajları inputların altında gösteriliyor (username doğrulama, şifre eşleşme)
- Önyükleyici (bootloader) sayfası form düzeni users sayfasındaki gibi güncellendi (Frame, form_label, form_input_text/password)
- Display manager adımı adım listesinden kaldırıldı (ISO'lar tek masaüstü ile geliyor)
- Autologin özelliği display manager adımından users adımına taşındı
- Display manager yapılandırması otomatik hale getirildi (desktop_environment otomatik tespit ediliyor)
- SDDM/GDM yapılandırmasında masaüstü ortamı seçimi kullanılıyor (xfce.desktop, gnome.desktop vb.)
- Autologin varsayılan değeri false olarak değiştirildi
### Fixed
- Dark modda sidebar metin renginin kaybolması sorunu (SIDEBAR_TEXT beyaz olarak ayarlandı)
- derive_username fonksiyonunda yanlış karakter (ā → ğ) düzeltildi
- unused_mut warning (name değişkeni)
- unused variable warning (err değişkeni)
- unused import warning (DisplayManagerStep)
---
## [4.0.3] — 2026-06-23 ## [4.0.3] — 2026-06-23
+176
View File
@@ -0,0 +1,176 @@
# Changelog — [Türkçe](CHANGELOG.md)
## [4.0.4] — 2026-06-25
### Added
- Username validation function `validate_username` (returns detailed error messages)
- Forbidden system usernames list (root, daemon, bin, sys, etc.)
- Turkish character conversions extended to include uppercase letters (Ş, Ğ, İ, Ö, Ü, Ç)
- New username validation keys in locale files (username_too_long, username_forbidden, username_invalid_start, username_invalid_chars)
- `autologin` field added to UsersStep struct
### Changed
- Check/fail icons for username, password validation, and hostname inputs moved next to input fields
- Error messages shown below inputs (username validation, password mismatch)
- Bootloader page form layout updated to match users page (Frame, form_label, form_input_text/password)
- Display manager step removed from step list (ISOs ship with single desktop environment)
- Autologin feature moved from display manager step to users step
- Display manager configuration made automatic (desktop_environment auto-detected)
- Desktop environment selection used in SDDM/GDM configuration (xfce.desktop, gnome.desktop, etc.)
- Autologin default value changed to false
### Fixed
- Sidebar text color disappearing in dark mode (SIDEBAR_TEXT set to white)
- Incorrect character in derive_username function (ā → ğ)
- unused_mut warning (name variable)
- unused variable warning (err variable)
- unused import warning (DisplayManagerStep)
---
## [4.0.3] — 2026-06-23
### Added
- Searchable keyboard layout/variant selector: egui `TextEdit` + `Area` popup custom implementation
- `color_from_hex(hex: u32)` helper (`combobox_stil.rs`)
- `layout_buf`, `variant_buf` fields (`KeyboardStep`)
### Changed
- `egui-dropdown` dependency removed (no longer used)
- Layout/Variant selectors side-by-side → stacked, label width equalized to longest label
- Popup item height 28px → 32px, gradient background (`draw_gradient_bg`) in `combobox.rs` style
- `DROPDOWN_TEXT_COLOR` off-white → pure white (`color_from_hex(0xFFFFFF)`)
- All color constants converted to hex format (`color_from_hex`)
### Fixed
- Popup not showing all items on first open due to old selection filter — buffer cleared on focus
- `t!()` return type `Cow<str>``String` mismatch (`keyboard.rs`)
### Changed
- Slider maximum value now equals available disk space (excluding other partitions)
- Selected partition capacity included in slider range in edit mode
- `form_input_text` size field directly connected to `add_size_str`, formatted MB display added
- Size label now in `"123.456 MB"` format instead of `"123 MB"` (for parseable values)
### Fixed
- Value written to size input field not written back to `add_size_str` — text edit remained read-only
---
## [4.0.1] — 2026-06-19
### Added
- `c_root_bg()` theme function
- `show_root_password`, `show_root_password_confirm` fields (`UsersStep`)
- `form_input_text` / `form_input_password` wrapped with `Frame` and `.frame(false)`
### Changed
- `form_input_text`: Wrapped in Frame, added stroke/fill/rounding, height 32→10
- `form_input_password`: SVG eye icons (instead of emoji), Frame wrapped, `override_text_color`
- Disk grid selection colors `theme::c_*()` → constant `(237,237,224,1)`
- Disk list header and column headers: `Align::Center``Align::LEFT`, `vertical_centered` removed
- Root password fields raw `TextEdit``form_input_password` (with eye icon + frame)
- User form Frame color `theme::c_bg_widget()``(240,243,198)`
- Manual disk list brand/model label ordering changed
### Fixed
- `users.rs:154``Color32` import error (missing `egui::` prefix)
---
## [4.0.0] — 2026-06-18
### Added
- `CHANGELOG.md`
- `src/ui/combobox.rs` — ComboBox helpers (`show_combo_box`, `selectable_value`, `selectable_value_custom`, `draw_gradient_bg`)
- `src/ui/combobox_stil.rs` — ComboBox visual constants and `apply_visuals()`
- `src/steps/location.rs` — Region/timezone selection step
- `src/steps/network.rs` — Network configuration step
- `src/steps/rescue.rs` — Rescue mode
- `xkbcommon` dependency
- Keyboard visual: XKB keymap → egui drawing (`compile_layout`, `draw_layout`, `keysym_to_label`)
- ISO105 key position mapping (function keys, numpad, navigation included)
- Single character display per key (uppercase preferred)
### Changed
- Keyboard visual: KLE JSON download/parse → direct keymap compilation with xkbcommon
- `Cargo.toml`: `ureq`, `serde_json` removed; `xkbcommon` added
- ComboBox styles moved from `theme.rs``combobox_stil.rs`
- Comment lines added to `secondary_button` gradient colors
- `draw_gradient_bg` moved to `combobox_stil.rs`
- All ComboBox usages updated with `theme::show_combo_box` / `theme::selectable_value`
- Keyboard step (`keyboard.rs`): `ScrollArea`+`selectable_label` → ComboBox
- `TextEdit::multiline` background made with per-widget `Frame::group`
- `locale/` files updated
- Font sizes increased (label 9→12, secondary 7→9)
### Removed
- `ureq`, `serde_json` dependencies
- `assets/keyboards/KLE_*.json` cache files
- `assets/keyboards/KB_*.svg` files
- Old keyboard SVG loading code
- KLE JSON download/cache logic
- Old button examples in demo page
### Fixed
- `set_style`/`set_visuals` order: `set_style` called first
- Region/timezone labels vertically aligned
- Keyboard step `on_enter` not called on first render — layout also initialized in `show()`
- `xkbcommon::Keycode` iteration (conversion with `raw()`)
- `None::<&str>``None::<String>` type mismatch
---
## [4.0.0] — 2026-06-06
### Added
- Rescue mode (rescue step)
- Network configuration step (NetworkManager/Wicd)
- Netinstall step
- LVM and LUKS encryption support
- Demo mode (`--demo`)
- Automatic installation (`--auto-install answer.toml`)
- Multi-language support with `rust-i18n` (Turkish, English)
- Gradient buttons (`gradient_button`, `secondary_button`)
- Language selector (flag + label)
- SVG loading support (`egui_extras` + `image`)
- Slideshow (configurable with branding.toml)
- Step list in sidebar (processed steps green ✔️)
- Real-time installation file tracking
- Advanced partitioning UI (usage bar, LUKS indicator, mount-point selector)
### Changed
- `pspec.xml`/`actions.py` → Cargo-based build
- `comar`/`mudur` calls → `zbus` D-Bus and direct command execution
- Shell-based password management → secure stdin piping (LUKS/GRUB)
- Automatic username derivation (real name → system username)
- Hostname validation/sanitization
- Cleanup operations: user deletion, pool management, boot directory cleanup
- Rsync command with dynamic exclusion
- Version 4.0.1 → 4.0.0 (Cargo.toml compatibility)
### Fixed
- GRUB password writing security
- Dracut/Mkinitcpio LVM module addition
- EFI partition detection and mounting
- Password strength indicator colors
- Automatic partitioning (LVM/LUKS ordering)
---
## [0.1.0] — 2026-05-20
### Added
- First stable release
- Project skeleton (egui + wgpu)
- Step-based installation wizard
- Automatic disk partitioning (GPT/MBR)
- User creation (with password strength check)
- Bootloader configuration (GRUB)
- Display manager selection
- Summary screen
- Basic color theme (light/dark)
- Customizable branding (branding.toml)
- Error screen for rescue purposes
- Job queue (JobQueue / async task management)
- YALI serialization (installer state save/load)
+8 -7
View File
@@ -2,9 +2,12 @@
Rust ve egui ile yeniden yazılmış **Pisi GNU/Linux** kurulum aracı. YALI, canlı ortamdan sistemi kurar, paketleri kurar ve temel yapılandırmayı gerçekleştirir. Orijinal Python/Qt sürümünün modern, hızlı ve bakımı kolay bir yeniden yazımıdır. Rust ve egui ile yeniden yazılmış **Pisi GNU/Linux** kurulum aracı. YALI, canlı ortamdan sistemi kurar, paketleri kurar ve temel yapılandırmayı gerçekleştirir. Orijinal Python/Qt sürümünün modern, hızlı ve bakımı kolay bir yeniden yazımıdır.
- [Changelog](CHANGELOG.md)
- [English README](README_en.md)
## Özellikler ## Özellikler
- **11 adımlı kurulum sihirbazı**: Hoş Geldiniz → Konum → Klavye → Ağ → Disk Bölümleme → Kullanıcılar → Bootloader → Görüntü Yöneticisi → Özet → Kurulum → Bitir - **10 adımlı kurulum sihirbazı**: Hoş Geldiniz → Konum → Klavye → Ağ → Disk Bölümleme → Kullanıcılar → Bootloader → Özet → Kurulum → Bitir
- **İki mod**: Grafik arayüz (varsayılan) ve cevap dosyasıyla otomatik kurulum (`--auto-install answer.toml`) - **İki mod**: Grafik arayüz (varsayılan) ve cevap dosyasıyla otomatik kurulum (`--auto-install answer.toml`)
- **Demo modu**: Sistem kontrollerini atlar, kurulumu simüle eder (`--demo`) - **Demo modu**: Sistem kontrollerini atlar, kurulumu simüle eder (`--demo`)
- **Disk bölümleme**: Otomatik (GPT/MBR) veya manuel, LVM ve LUKS şifreleme desteği - **Disk bölümleme**: Otomatik (GPT/MBR) veya manuel, LVM ve LUKS şifreleme desteği
@@ -56,7 +59,6 @@ sudo cargo run --release -- --auto-install answer.toml
│ │ ├── partition.rs # Disk bölümleme (otomatik + manuel + LVM) │ │ ├── partition.rs # Disk bölümleme (otomatik + manuel + LVM)
│ │ ├── users.rs # Kullanıcı hesabı oluşturma │ │ ├── users.rs # Kullanıcı hesabı oluşturma
│ │ ├── bootloader.rs # GRUB yapılandırması │ │ ├── bootloader.rs # GRUB yapılandırması
│ │ ├── display_manager.rs # Görüntü yöneticisi ve masaüstü seçimi
│ │ ├── summary.rs # Kurulum özeti │ │ ├── summary.rs # Kurulum özeti
│ │ ├── execution.rs # Kurulum yürütme (ilerleme çubuğu, log) │ │ ├── execution.rs # Kurulum yürütme (ilerleme çubuğu, log)
│ │ ├── finish.rs # Tamamlanma ekranı │ │ ├── finish.rs # Tamamlanma ekranı
@@ -86,12 +88,11 @@ sudo cargo run --release -- --auto-install answer.toml
3. **Klavye** — Düzen/varyant seçimi, arama, canlı önizleme (setxkbmap) 3. **Klavye** — Düzen/varyant seçimi, arama, canlı önizleme (setxkbmap)
4. **Ağ** — WiFi tarama, bağlantı, proxy 4. **Ağ** — WiFi tarama, bağlantı, proxy
5. **Disk Bölümleme** — Otomatik (rehberli) veya manuel, LVM, LUKS 5. **Disk Bölümleme** — Otomatik (rehberli) veya manuel, LVM, LUKS
6. **Kullanıcılar** — Hesap oluşturma, parola gücü göstergesi, root parolası 6. **Kullanıcılar** — Hesap oluşturma, parola gücü göstergesi, root parolası, otomatik oturum açma
7. **Bootloader** — GRUB aygıtı, zaman aşımı, parola, çekirdek parametreleri 7. **Bootloader** — GRUB aygıtı, zaman aşımı, parola, çekirdek parametreleri
8. **Görüntü Yöneticisi** — SDDM/LightDM/GDM, masaüstü ortamı, otomatik oturum 8. **Özet** — Tüm seçimlerin gözden geçirilmesi
9. **Özet**Tüm seçimlerin gözden geçirilmesi 9. **Kurulum**Slayt + ilerleme çubuğu + canlı log
10. **Kurulum**Slayt + ilerleme çubuğu + canlı log 10. **Bitir**Başarılı kurulum, yeniden başlat veya canlı masaüstüne dön
11. **Bitir** — Başarılı kurulum, yeniden başlat veya canlı masaüstüne dön
## Bağımlılıklar ## Bağımlılıklar
+114
View File
@@ -0,0 +1,114 @@
# YALI (Yet Another Linux Installer) — Rust / egui
Rust ve egui ile yeniden yazılmış **Pisi GNU/Linux** kurulum aracı. YALI, canlı ortamdan sistemi kurar, paketleri kurar ve temel yapılandırmayı gerçekleştirir. Orijinal Python/Qt sürümünün modern, hızlı ve bakımı kolay bir yeniden yazımıdır.
## Özellikler
- **11 adımlı kurulum sihirbazı**: Hoş Geldiniz → Konum → Klavye → Ağ → Disk Bölümleme → Kullanıcılar → Bootloader → Görüntü Yöneticisi → Özet → Kurulum → Bitir
- **İki mod**: Grafik arayüz (varsayılan) ve cevap dosyasıyla otomatik kurulum (`--auto-install answer.toml`)
- **Demo modu**: Sistem kontrollerini atlar, kurulumu simüle eder (`--demo`)
- **Disk bölümleme**: Otomatik (GPT/MBR) veya manuel, LVM ve LUKS şifreleme desteği
- **Ağ yapılandırması**: WiFi tarama (nmcli), proxy ayarları
- **Önyükleyici**: GRUB aygıt/parola/zaman aşımı ayarları, çekirdek parametreleri
- **Kurtarma modu**: Chroot, GRUB yeniden kurulumu, Pisi geçmişe dönme
- **OEM modu**: Üretici ön kurulumu için ön tanımlı ayarlar
- **Uluslararasılaştırma**: Türkçe ve İngilizce (rust-i18n ile TOML locale dosyaları)
- **Markalama sistemi**: Çalışma zamanında yüklenebilir `branding.toml` ile logo, slayt, renk ayarları
- **Tema**: Koyu/açık tema, atomik renk yönetimi, özel gradient butonlar
- **Asenkron iş kuyruğu**: Tüm kurulum adımları ayrı `tokio` runtime'ında çalışır, `mpsc` kanalı ile UI güncellenir
- **Sistem kontrolleri**: RAM, disk alanı, internet, UEFI, CPU, NVMe gibi 8 ön kontrol
- **Slayt gösterisi**: 9 masaüstü ortamı için özel markalı slaytlar
- **Demo oturum temizliği**: Canlı ortam artifact'lerini kaldırır, üretim deposu ekler
## Kullanım
```bash
# Normal kurulum (root yetkisi gerekir)
sudo cargo run --release
# Demo modu (root gerekmez)
cargo run --release -- --demo
# Otomatik kurulum (cevap dosyası ile)
sudo cargo run --release -- --auto-install answer.toml
```
## Proje Yapısı
```
├── src/
│ ├── main.rs # Giriş noktası, eframe App, GUI düzeni
│ ├── installer.rs # InstallerStep trait'i, GlobalState, WelcomeStep
│ ├── funct.rs # Paylaşılan UI yardımcıları (form alanları, dil seçici)
│ ├── branding.rs # Branding.toml yükleyici (logo, slayt, tema, OEM)
│ ├── ui/
│ │ ├── theme.rs # Renkler, fontlar, Visuals, section_heading, error/warning/success kutuları
│ │ ├── buttons.rs # Gradient butonlar (primary, secondary, danger, vb.)
│ │ ├── combobox.rs # ComboBox yardımcıları (show_combo_box, selectable_value)
│ │ ├── combobox_stil.rs # ComboBox görsel sabitleri (weak_bg, border, text renkleri)
│ │ ├── slideshow.rs # Otomatik ilerleyen slayt gösterisi
│ │ └── error_screen.rs # Hata ekranı (log görüntüleyici, kopyala, yeniden dene)
│ ├── steps/
│ │ ├── location.rs # Konum/saat dilimi + tarih/saat
│ │ ├── license.rs # Lisans sözleşmesi
│ │ ├── keyboard.rs # Klavye düzeni/varyant seçimi
│ │ ├── network.rs # Ağ yapılandırması (WiFi, proxy)
│ │ ├── partition.rs # Disk bölümleme (otomatik + manuel + LVM)
│ │ ├── users.rs # Kullanıcı hesabı oluşturma
│ │ ├── bootloader.rs # GRUB yapılandırması
│ │ ├── display_manager.rs # Görüntü yöneticisi ve masaüstü seçimi
│ │ ├── summary.rs # Kurulum özeti
│ │ ├── execution.rs # Kurulum yürütme (ilerleme çubuğu, log)
│ │ ├── finish.rs # Tamamlanma ekranı
│ │ ├── netinstall.rs # Ek paket grubu seçimi
│ │ └── rescue.rs # Kurtarma modu (chroot, GRUB, Pisi takeback)
│ ├── jobs/mod.rs # Asenkron iş kuyruğu ve tüm kurulum işleri
│ └── autoinstall/
│ ├── mod.rs # Cevap dosyası yükleme ve state uygulama
│ └── checker.rs # Sistem ön kontrolleri
├── locales/
│ ├── tr.toml # Türkçe çeviriler
│ └── en.toml # İngilizce çeviriler
├── assets/
│ ├── icons/ # UI ikonları (YALI_icon_LIGHT.svg, language-icon.svg, vb.)
│ ├── flags/ # Ülke bayrakları (~250 SVG)
│ └── *.png # Slayt ve logo görselleri
├── branding.toml # Varsayılan markalama yapılandırması
├── branding_en.toml # İngilizce markalama
├── branding_tr.toml # Türkçe markalama
└── answer-example.toml # Örnek cevap dosyası
```
## Kurulum İş Akışı
1. **Hoş Geldiniz** — Dil seçimi, sistem kontrolleri, kurtarma modu
2. **Konum / Zaman** — Saat dilimi seçimi (bölge/alan çift ComboBox), GeoIP, NTP veya manuel tarih/saat
3. **Klavye** — Düzen/varyant seçimi, arama, canlı önizleme (setxkbmap)
4. **Ağ** — WiFi tarama, bağlantı, proxy
5. **Disk Bölümleme** — Otomatik (rehberli) veya manuel, LVM, LUKS
6. **Kullanıcılar** — Hesap oluşturma, parola gücü göstergesi, root parolası
7. **Bootloader** — GRUB aygıtı, zaman aşımı, parola, çekirdek parametreleri
8. **Görüntü Yöneticisi** — SDDM/LightDM/GDM, masaüstü ortamı, otomatik oturum
9. **Özet** — Tüm seçimlerin gözden geçirilmesi
10. **Kurulum** — Slayt + ilerleme çubuğu + canlı log
11. **Bitir** — Başarılı kurulum, yeniden başlat veya canlı masaüstüne dön
## Bağımlılıklar
| Bağımlılık | Sürüm | Amaç |
|---|---|---|
| `eframe` | 0.27 (wgpu) | egui çatısı, WebGPU çıktısı |
| `egui_extras` | 0.27 (image, file, svg) | Görsel yükleme, dosya diyalogları, SVG |
| `image` | 0.24 | PNG kod çözme |
| `serde` / `toml` | 1.0 / 0.8 | Branding ve cevap dosyası serileştirme |
| `zbus` | 4.0 | D-Bus iletişimi (COMAR) |
| `tokio` | 1.0 (full) | Asenkron iş kuyruğu |
| `sysinfo` | 0.30 | Sistem bilgisi (RAM, disk, OS) |
| `rust-i18n` | 3.1 | Uluslararasılaştırma |
| `chrono` | 0.4 | Tarih/saat işlemleri |
## Lisans
GNU General Public License v3.0
Bu proje Pisi GNU/Linux ekibi tarafından geliştirilmektedir.
+112
View File
@@ -0,0 +1,112 @@
# YALI (Yet Another Linux Installer) — Rust / egui
A rewritten **Pisi GNU/Linux** installation tool in Rust and egui. YALI installs the system from the live environment, installs packages, and performs basic configuration. It is a modern, fast, and maintainable rewrite of the original Python/Qt version.
## Features
- **10-step installation wizard**: Welcome → Location → Keyboard → Network → Disk Partitioning → Users → Bootloader → Summary → Installation → Finish
- **Two modes**: Graphical interface (default) and automatic installation with answer file (`--auto-install answer.toml`)
- **Demo mode**: Skips system checks, simulates installation (`--demo`)
- **Disk partitioning**: Automatic (GPT/MBR) or manual, LVM and LUKS encryption support
- **Network configuration**: WiFi scanning (nmcli), proxy settings
- **Bootloader**: GRUB device/password/timeout settings, kernel parameters
- **Rescue mode**: Chroot, GRUB reinstallation, Pisi rollback
- **OEM mode**: Predefined settings for manufacturer pre-installation
- **Internationalization**: Turkish and English (with rust-i18n via TOML locale files)
- **Branding system**: Runtime-loadable `branding.toml` for logo, slides, color settings
- **Theme**: Dark/light theme, atomic color management, custom gradient buttons
- **Async job queue**: All installation steps run in separate `tokio` runtime, UI updated via `mpsc` channel
- **System checks**: 8 pre-checks including RAM, disk space, internet, UEFI, CPU, NVMe
- **Slideshow**: Custom branded slides for 9 desktop environments
- **Demo session cleanup**: Removes live environment artifacts, adds production repository
## Usage
```bash
# Normal installation (requires root)
sudo cargo run --release
# Demo mode (no root required)
cargo run --release -- --demo
# Automatic installation (with answer file)
sudo cargo run --release -- --auto-install answer.toml
```
## Project Structure
```
├── src/
│ ├── main.rs # Entry point, eframe App, GUI layout
│ ├── installer.rs # InstallerStep trait, GlobalState, WelcomeStep
│ ├── funct.rs # Shared UI helpers (form fields, language selector)
│ ├── branding.rs # Branding.toml loader (logo, slides, theme, OEM)
│ ├── ui/
│ │ ├── theme.rs # Colors, fonts, Visuals, section_heading, error/warning/success boxes
│ │ ├── buttons.rs # Gradient buttons (primary, secondary, danger, etc.)
│ │ ├── combobox.rs # ComboBox helpers (show_combo_box, selectable_value)
│ │ ├── combobox_stil.rs # ComboBox visual constants (weak_bg, border, text colors)
│ │ ├── slideshow.rs # Auto-advancing slideshow
│ │ └── error_screen.rs # Error screen (log viewer, copy, retry)
│ ├── steps/
│ │ ├── location.rs # Location/timezone + date/time
│ │ ├── license.rs # License agreement
│ │ ├── keyboard.rs # Keyboard layout/variant selection
│ │ ├── network.rs # Network configuration (WiFi, proxy)
│ │ ├── partition.rs # Disk partitioning (automatic + manual + LVM)
│ │ ├── users.rs # User account creation
│ │ ├── bootloader.rs # GRUB configuration
│ │ ├── summary.rs # Installation summary
│ │ ├── execution.rs # Installation execution (progress bar, log)
│ │ ├── finish.rs # Completion screen
│ │ ├── netinstall.rs # Extra package group selection
│ │ └── rescue.rs # Rescue mode (chroot, GRUB, Pisi takeback)
│ ├── jobs/mod.rs # Async job queue and all installation jobs
│ └── autoinstall/
│ ├── mod.rs # Answer file loading and state application
│ └── checker.rs # System pre-checks
├── locales/
│ ├── tr.toml # Turkish translations
│ └── en.toml # English translations
├── assets/
│ ├── icons/ # UI icons (YALI_icon_LIGHT.svg, language-icon.svg, etc.)
│ ├── flags/ # Country flags (~250 SVG)
│ └── *.png # Slide and logo images
├── branding.toml # Default branding configuration
├── branding_en.toml # English branding
├── branding_tr.toml # Turkish branding
└── answer-example.toml # Example answer file
```
## Installation Workflow
1. **Welcome** — Language selection, system checks, rescue mode
2. **Location / Time** — Timezone selection (region/area dual ComboBox), GeoIP, NTP or manual date/time
3. **Keyboard** — Layout/variant selection, search, live preview (setxkbmap)
4. **Network** — WiFi scanning, connection, proxy
5. **Disk Partitioning** — Automatic (guided) or manual, LVM, LUKS
6. **Users** — Account creation, password strength indicator, root password, autologin
7. **Bootloader** — GRUB device, timeout, password, kernel parameters
8. **Summary** — Review all selections
9. **Installation** — Slideshow + progress bar + live log
10. **Finish** — Successful installation, reboot or return to live desktop
## Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| `eframe` | 0.27 (wgpu) | egui framework, WebGPU backend |
| `egui_extras` | 0.27 (image, file, svg) | Image loading, file dialogs, SVG |
| `image` | 0.24 | PNG decoding |
| `serde` / `toml` | 1.0 / 0.8 | Branding and answer file serialization |
| `zbus` | 4.0 | D-Bus communication (COMAR) |
| `tokio` | 1.0 (full) | Async job queue |
| `sysinfo` | 0.30 | System information (RAM, disk, OS) |
| `rust-i18n` | 3.1 | Internationalization |
| `chrono` | 0.4 | Date/time operations |
## License
GNU General Public License v3.0
This project is developed by the Pisi GNU/Linux team.
+4
View File
@@ -61,6 +61,10 @@ password_label = "Password (at least 8 characters...)"
password_confirm_label = "Confirm password" password_confirm_label = "Confirm password"
hostname_label = "Computer name" hostname_label = "Computer name"
username_invalid = "Invalid username. Must start with a lowercase letter or underscore, max 32 characters." username_invalid = "Invalid username. Must start with a lowercase letter or underscore, max 32 characters."
username_too_long = "Username too long (maximum 32 characters)"
username_forbidden = "This username is reserved by the system and is forbidden"
username_invalid_start = "Username must start with a lowercase letter or underscore"
username_invalid_chars = "Only lowercase letters, digits, underscore and hyphen are allowed"
hostname_invalid = "Invalid hostname. Only letters, digits, and hyphens are allowed." hostname_invalid = "Invalid hostname. Only letters, digits, and hyphens are allowed."
passwords_no_match = "Passwords do not match" passwords_no_match = "Passwords do not match"
+4
View File
@@ -61,6 +61,10 @@ password_label = "Parola (en az 8 karakter olmalıdır...)"
password_confirm_label = "Parola (tekrar)" password_confirm_label = "Parola (tekrar)"
hostname_label = "Bilgisayar adı" hostname_label = "Bilgisayar adı"
username_invalid = "Geçersiz kullanıcı adı. Küçük harf veya alt çizgi ile başlamalı, en fazla 32 karakter." username_invalid = "Geçersiz kullanıcı adı. Küçük harf veya alt çizgi ile başlamalı, en fazla 32 karakter."
username_too_long = "Kullanıcı adı çok uzun (maksimum 32 karakter)"
username_forbidden = "Bu kullanıcı adı sistem tarafından kullanılıyor ve yasaklı"
username_invalid_start = "Kullanıcı adı küçük harf veya alt çizgi ile başlamalı"
username_invalid_chars = "Sadece küçük harf, rakam, alt çizgi ve tire kullanılabilir"
hostname_invalid = "Geçersiz bilgisayar adı. Yalnızca harf, rakam ve tire içerebilir." hostname_invalid = "Geçersiz bilgisayar adı. Yalnızca harf, rakam ve tire içerebilir."
passwords_no_match = "Parolalar eşleşmiyor" passwords_no_match = "Parolalar eşleşmiyor"
+1 -1
View File
@@ -303,7 +303,7 @@ impl Default for GlobalState {
oem_password_changed: false, oem_password_changed: false,
selected_package_groups: Vec::new(), selected_package_groups: Vec::new(),
display_manager: "sddm".to_string(), display_manager: "sddm".to_string(),
autologin: true, autologin: false,
desktop_environment: detect_desktop_environment(), desktop_environment: detect_desktop_environment(),
branding_icons: std::collections::HashMap::new(), branding_icons: std::collections::HashMap::new(),
branding_pisi_dark: String::new(), branding_pisi_dark: String::new(),
+28 -4
View File
@@ -1265,10 +1265,22 @@ impl Job for ConfigureDisplayManagerJob {
match dm.as_str() { match dm.as_str() {
"sddm" => { "sddm" => {
let conf = format!("{}/usr/lib/sddm/sddm.conf.d/sddm.conf", self.mount); let conf = format!("{}/usr/lib/sddm/sddm.conf.d/sddm.conf", self.mount);
let session = match self.desktop_environment.as_str() {
"plasma" => "plasmax11.desktop",
"xfce" => "xfce.desktop",
"gnome" => "gnome.desktop",
"cinnamon" => "cinnamon.desktop",
"budgie" => "budgie-desktop.desktop",
"lxde" => "LXDE.desktop",
"lxqt" => "lxqt.desktop",
"mate" => "mate.desktop",
"lumina" => "lumina-desktop.desktop",
_ => "plasmax11.desktop",
};
let content = if self.autologin { let content = if self.autologin {
format!( format!(
"[Autologin]\nUser={}\nSession=plasmax11.desktop\n\n[Theme]\nCurrent=pisilinux24\n", "[Autologin]\nUser={}\nSession={}\n\n[Theme]\nCurrent=pisilinux24\n",
self.username self.username, session
) )
} else { } else {
"[Autologin]\nUser=\nSession=\n\n[Theme]\nCurrent=pisilinux24\n".to_string() "[Autologin]\nUser=\nSession=\n\n[Theme]\nCurrent=pisilinux24\n".to_string()
@@ -1299,10 +1311,22 @@ impl Job for ConfigureDisplayManagerJob {
let dir = format!("{}/etc/gdm", self.mount); let dir = format!("{}/etc/gdm", self.mount);
let _ = tokio::fs::create_dir_all(&dir).await; let _ = tokio::fs::create_dir_all(&dir).await;
let conf = format!("{}/etc/gdm/custom.conf", self.mount); let conf = format!("{}/etc/gdm/custom.conf", self.mount);
let session = match self.desktop_environment.as_str() {
"plasma" => "plasmax11.desktop",
"xfce" => "xfce.desktop",
"gnome" => "gnome.desktop",
"cinnamon" => "cinnamon.desktop",
"budgie" => "budgie-desktop.desktop",
"lxde" => "LXDE.desktop",
"lxqt" => "lxqt.desktop",
"mate" => "mate.desktop",
"lumina" => "lumina-desktop.desktop",
_ => "gnome.desktop",
};
let content = if self.autologin { let content = if self.autologin {
format!( format!(
"[daemon]\nAutomaticLoginEnable=true\nAutomaticLogin={}\n", "[daemon]\nAutomaticLoginEnable=true\nAutomaticLogin={}\nDefaultSession={}\n",
self.username self.username, session
) )
} else { } else {
"[daemon]\n".to_string() "[daemon]\n".to_string()
+1 -2
View File
@@ -7,7 +7,7 @@ mod branding;
mod funct; mod funct;
use installer::{GlobalState, InstallerStep, WelcomeStep}; use installer::{GlobalState, InstallerStep, WelcomeStep};
use steps::{LocationStep, KeyboardStep, UsersStep, SummaryStep, ExecutionStep, FinishStep, PartitionStep, BootloaderStep, NetworkStep, DisplayManagerStep}; use steps::{LocationStep, KeyboardStep, UsersStep, SummaryStep, ExecutionStep, FinishStep, PartitionStep, BootloaderStep, NetworkStep};
use eframe::egui; use eframe::egui;
use rust_i18n::t; use rust_i18n::t;
@@ -231,7 +231,6 @@ impl Default for YaliApp {
Box::new(PartitionStep::default()), Box::new(PartitionStep::default()),
Box::new(UsersStep::default()), Box::new(UsersStep::default()),
Box::new(BootloaderStep::default()), Box::new(BootloaderStep::default()),
Box::new(DisplayManagerStep::default()),
Box::new(SummaryStep), Box::new(SummaryStep),
Box::new(ExecutionStep::default()), Box::new(ExecutionStep::default()),
Box::new(FinishStep), Box::new(FinishStep),
+57 -54
View File
@@ -2,6 +2,7 @@ use eframe::egui;
use rust_i18n::t; use rust_i18n::t;
use crate::installer::{GlobalState, InstallerStep}; use crate::installer::{GlobalState, InstallerStep};
use crate::ui::theme; use crate::ui::theme;
use crate::funct::{form_label, form_input_text, form_input_password};
#[derive(Default)] #[derive(Default)]
pub struct BootloaderStep { pub struct BootloaderStep {
@@ -26,77 +27,79 @@ impl InstallerStep for BootloaderStep {
} }
fn show(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) { fn show(&mut self, ui: &mut egui::Ui, state: &mut GlobalState) {
ui.heading(t!("bootloader_title")); theme::section_heading(ui, &t!("bootloader_title"));
ui.label(t!("bootloader_description")); ui.label(
egui::RichText::new(t!("bootloader_description"))
.color(theme::c_text_dim())
.size(13.0),
);
ui.add_space(12.0); ui.add_space(12.0);
egui::Grid::new("bootloader_grid") // ─── Önyükleyici Formu ──────────────────────────────────
.num_columns(2) egui::Frame::group(ui.style())
.spacing([12.0, 10.0]) .fill(theme::c_bg_widget())
.rounding(6.0)
.inner_margin(egui::Margin::symmetric(10.0, 10.0))
.show(ui, |ui| { .show(ui, |ui| {
// Hedef aygıt ui.set_width(ui.available_width());
ui.label(t!("bootloader_device_label")); ui.vertical(|ui| {
ui.horizontal(|ui| { ui.add_space(10.0);
let mut device_list: Vec<String> = state.available_disks.iter()
.map(|d| d.name.clone()) // Hedef aygıt
.collect(); form_label(ui, &t!("bootloader_device_label"));
if device_list.is_empty() { ui.horizontal(|ui| {
device_list.push(state.bootloader_device.clone()); let mut device_list: Vec<String> = state.available_disks.iter()
} .map(|d| d.name.clone())
let current = if state.bootloader_device.is_empty() { .collect();
device_list[0].clone() if device_list.is_empty() {
} else { device_list.push(state.bootloader_device.clone());
state.bootloader_device.clone()
};
theme::show_combo_box(ui, "boot_device_select", current.as_str(), ui.available_width(), |ui, w| {
for dev in &device_list {
theme::selectable_value(ui, &mut state.bootloader_device, dev.clone(), dev.as_str(), w);
} }
let current = if state.bootloader_device.is_empty() {
device_list[0].clone()
} else {
state.bootloader_device.clone()
};
theme::show_combo_box(ui, "boot_device_select", current.as_str(), ui.available_width(), |ui, w| {
for dev in &device_list {
theme::selectable_value(ui, &mut state.bootloader_device, dev.clone(), dev.as_str(), w);
}
});
}); });
ui.label( ui.label(
egui::RichText::new(t!("bootloader_device_hint")) egui::RichText::new(t!("bootloader_device_hint"))
.size(11.0) .size(11.0)
.color(egui::Color32::from_rgb(120, 120, 140)), .color(theme::c_text_dim()),
); );
}); ui.add_space(6.0);
ui.end_row();
// Timeout // Timeout
ui.label(t!("bootloader_timeout_label")); form_label(ui, &t!("bootloader_timeout_label"));
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.add(egui::Slider::new(&mut state.bootloader_timeout, 0..=60) ui.add(egui::Slider::new(&mut state.bootloader_timeout, 0..=60)
.text(t!("bootloader_timeout_suffix"))); .text(t!("bootloader_timeout_suffix")));
}); });
ui.end_row(); ui.add_space(6.0);
// GRUB şifresi // GRUB şifresi
ui.label(t!("bootloader_password_label")); form_label(ui, &t!("bootloader_password_label"));
ui.horizontal(|ui| { ui.horizontal(|ui| {
if self.show_password { let show_pwd = &mut self.show_password;
ui.text_edit_singleline(&mut state.bootloader_password); form_input_password(ui, &mut state.bootloader_password, show_pwd);
} else { });
ui.add(egui::TextEdit::singleline(&mut state.bootloader_password).password(true)); ui.add_space(6.0);
}
if ui.small_button(if self.show_password { "🙈" } else { "👁" }).clicked() {
self.show_password = !self.show_password;
}
if !state.bootloader_password.is_empty() {
ui.colored_label(egui::Color32::from_rgb(200, 180, 40), "");
}
});
ui.end_row();
// Kernel parametreleri // Kernel parametreleri
ui.label(t!("bootloader_kernel_label")); form_label(ui, &t!("bootloader_kernel_label"));
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.text_edit_singleline(&mut state.kernel_options); form_input_text(ui, &mut state.kernel_options);
});
ui.label( ui.label(
egui::RichText::new(t!("bootloader_kernel_hint")) egui::RichText::new(t!("bootloader_kernel_hint"))
.size(11.0) .size(11.0)
.color(egui::Color32::from_rgb(120, 120, 140)), .color(theme::c_text_dim()),
); );
}); });
ui.end_row();
}); });
} }
+1 -2
View File
@@ -7,7 +7,7 @@ pub mod partition;
pub mod bootloader; pub mod bootloader;
pub mod network; pub mod network;
pub mod rescue; pub mod rescue;
pub mod display_manager; //pub mod display_manager;
pub mod netinstall; pub mod netinstall;
pub mod location; pub mod location;
@@ -20,5 +20,4 @@ pub use partition::PartitionStep;
pub use bootloader::BootloaderStep; pub use bootloader::BootloaderStep;
pub use network::NetworkStep; pub use network::NetworkStep;
pub use rescue::RescueStep; pub use rescue::RescueStep;
pub use display_manager::DisplayManagerStep;
pub use location::LocationStep; pub use location::LocationStep;
+150 -41
View File
@@ -6,16 +6,18 @@ use crate::funct::{ form_input_text, form_input_password, form_label, form_check
/// Kullanıcı adı, şifre, hostname ve yönetici (root) şifresi ayarları adımı. /// Kullanıcı adı, şifre, hostname ve yönetici (root) şifresi ayarları adımı.
pub struct UsersStep { pub struct UsersStep {
use_same_for_admin: bool, use_same_for_admin: bool,
autologin: bool,
show_password: bool, show_password: bool,
show_password_confirm: bool, show_password_confirm: bool,
show_root_password: bool, // <-- Eklendi show_root_password: bool,
show_root_password_confirm: bool, // <-- Eklendi show_root_password_confirm: bool,
} }
impl Default for UsersStep { impl Default for UsersStep {
fn default() -> Self { fn default() -> Self {
Self { Self {
use_same_for_admin: true, use_same_for_admin: true,
autologin: false,
show_password: false, show_password: false,
show_password_confirm: false, show_password_confirm: false,
show_root_password: false, show_root_password: false,
@@ -30,16 +32,22 @@ impl Default for UsersStep {
/// - Boşlukları `-`'ye çevirir /// - Boşlukları `-`'ye çevirir
/// - Geçersiz karakterleri temizler /// - Geçersiz karakterleri temizler
fn derive_username(real_name: &str) -> String { fn derive_username(real_name: &str) -> String {
let mut name = real_name.to_lowercase(); let name = real_name
name = name
.replace('ş', "s") .replace('ş', "s")
.replace('Ş', "s")
.replace('ğ', "g") .replace('ğ', "g")
.replace('Ğ', "g")
.replace('ı', "i") .replace('ı', "i")
.replace('İ', "i")
.replace('ö', "o") .replace('ö', "o")
.replace('Ö', "o")
.replace('ü', "u") .replace('ü', "u")
.replace('Ü', "u")
.replace('ç', "c") .replace('ç', "c")
.replace('Ç', "c")
.replace(' ', "-") .replace(' ', "-")
.replace('_', "-"); .replace('_', "-")
.to_lowercase();
let valid: String = name.chars().filter(|c| c.is_ascii_alphanumeric() || *c == '-' || *c == '_').collect(); let valid: String = name.chars().filter(|c| c.is_ascii_alphanumeric() || *c == '-' || *c == '_').collect();
let trimmed = valid.trim_matches('-').to_string(); let trimmed = valid.trim_matches('-').to_string();
if trimmed.is_empty() { if trimmed.is_empty() {
@@ -54,17 +62,44 @@ fn derive_username(real_name: &str) -> String {
/// Kullanıcı adının geçerliliğini kontrol eder. /// Kullanıcı adının geçerliliğini kontrol eder.
/// Linux kuralları: küçük harf veya alt çizgi ile başlamalı, /// Linux kuralları: küçük harf veya alt çizgi ile başlamalı,
/// en fazla 32 karakter, yalnızca [a-z0-9_-] içermeli. /// en fazla 32 karakter, yalnızca [a-z0-9_-] içermeli.
fn is_valid_username(s: &str) -> bool { /// Ayrıca sistem kullanıcı adları yasaklıdır.
if s.is_empty() || s.len() > 32 { /// Hata varsa hata mesajını döndürür, yoksa None döndürür.
return false; fn validate_username(s: &str) -> Option<String> {
if s.is_empty() {
return None;
} }
if s.len() > 32 {
return Some(t!("username_too_long").to_string());
}
// Yasaklı sistem kullanıcı adları
let forbidden = [
"root", "daemon", "bin", "sys", "sync", "games", "man", "lp",
"mail", "news", "uucp", "proxy", "www-data", "backup", "list",
"irc", "gnats", "nobody", "systemd-timesync", "systemd-network",
"systemd-resolve", "systemd-bus-proxy", "messagebus", "sshd",
"ftp", "apache", "nginx", "mysql", "postgres", "docker",
];
if forbidden.contains(&s) {
return Some(t!("username_forbidden").to_string());
}
let mut chars = s.chars(); let mut chars = s.chars();
// İlk karakter küçük harf veya alt çizgi olmalı // İlk karakter küçük harf veya alt çizgi olmalı
match chars.next() { match chars.next() {
Some(c) if c.is_ascii_lowercase() || c == '_' => {} Some(c) if c.is_ascii_lowercase() || c == '_' => {}
_ => return false, _ => return Some(t!("username_invalid_start").to_string()),
} }
chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-') if !chars.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '-') {
return Some(t!("username_invalid_chars").to_string());
}
None
}
/// Kullanıcı adının geçerliliğini kontrol eder (basit bool versiyonu).
fn is_valid_username(s: &str) -> bool {
validate_username(s).is_none()
} }
/// Hostname kuralları: 1-63 karakter, yalnızca [a-zA-Z0-9-], tire ile başlayamaz/bitemez. /// Hostname kuralları: 1-63 karakter, yalnızca [a-zA-Z0-9-], tire ile başlayamaz/bitemez.
@@ -121,6 +156,9 @@ impl InstallerStep for UsersStep {
} }
fn on_enter(&mut self, state: &mut GlobalState) { fn on_enter(&mut self, state: &mut GlobalState) {
// Autologin senkronizasyonu
self.autologin = state.autologin;
// Gerçek ad varsa ama kullanıcı adı yoksa türet // Gerçek ad varsa ama kullanıcı adı yoksa türet
if !state.real_name.is_empty() && state.username.is_empty() { if !state.real_name.is_empty() && state.username.is_empty() {
state.username = derive_username(&state.real_name); state.username = derive_username(&state.real_name);
@@ -168,27 +206,54 @@ impl InstallerStep for UsersStep {
form_label(ui, &t!("real_name_label")); form_label(ui, &t!("real_name_label"));
{ {
let prev = state.real_name.clone(); let prev = state.real_name.clone();
form_input_text(ui, &mut state.real_name); ui.horizontal(|ui| {
form_input_text(ui, &mut state.real_name);
if !state.real_name.is_empty() {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/check.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_success())
);
}else{
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/fail-icon.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_error())
);
}
});
if state.real_name != prev && !state.real_name.is_empty() { if state.real_name != prev && !state.real_name.is_empty() {
state.username = derive_username(&state.real_name); state.username = derive_username(&state.real_name);
} }
} }
if !state.real_name.is_empty() {
ui.colored_label(theme::c_success(), "");
} else {
ui.colored_label(theme::c_error(), "");
}
ui.add_space(6.0); ui.add_space(6.0);
// Kullanıcı adı (otomatik türetilir, düzenlenebilir) // Kullanıcı adı (otomatik türetilir, düzenlenebilir)
form_label(ui, &t!("username_label")); form_label(ui, &t!("username_label"));
form_input_text(ui, &mut state.username);
if !state.username.is_empty() { ui.horizontal(|ui| {
if is_valid_username(&state.username) { form_input_text(ui, &mut state.username);
ui.colored_label(theme::c_success(), ""); if !state.username.is_empty() {
} else { if let Some(_err) = validate_username(&state.username) {
ui.colored_label(theme::c_warning(), t!("username_invalid")); ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/fail-icon.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_error())
);
} else {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/check.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_success())
);
}
} }
});
if let Some(err) = validate_username(&state.username) {
ui.colored_label(theme::c_error(), err);
} }
ui.add_space(6.0); ui.add_space(6.0);
@@ -221,27 +286,50 @@ impl InstallerStep for UsersStep {
form_label(ui, &t!("password_confirm_label")); form_label(ui, &t!("password_confirm_label"));
{ {
let show_pwd = &mut self.show_password_confirm; let show_pwd = &mut self.show_password_confirm;
form_input_password(ui, &mut state.password_confirm, show_pwd); ui.horizontal(|ui| {
form_input_password(ui, &mut state.password_confirm, show_pwd);
if !state.password_confirm.is_empty() {
if state.password == state.password_confirm {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/check.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_success())
);
} else {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/fail-icon.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_error())
);
}
}
});
} }
if !state.password_confirm.is_empty() { if !state.password_confirm.is_empty() && state.password != state.password_confirm {
if state.password == state.password_confirm { ui.colored_label(theme::c_warning(), t!("passwords_no_match"));
ui.colored_label(theme::c_success(), "");
} else {
ui.colored_label(theme::c_warning(), t!("passwords_no_match"));
}
} }
ui.add_space(6.0); ui.add_space(6.0);
// Hostname // Hostname
form_label(ui, &t!("hostname_label")); form_label(ui, &t!("hostname_label"));
form_input_text(ui, &mut state.hostname); ui.horizontal(|ui| {
if !state.hostname.is_empty() { form_input_text(ui, &mut state.hostname);
if is_valid_hostname(&state.hostname) { if !state.hostname.is_empty() {
ui.colored_label(theme::c_success(), ""); if is_valid_hostname(&state.hostname) {
} else { ui.add(
ui.colored_label(theme::c_warning(), t!("hostname_invalid")); egui::Image::new(egui::include_image!("../../assets/icons/check.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_success())
);
} else {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/fail-icon.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_error())
);
}
} }
} });
}); });
ui.add_space(10.0); ui.add_space(10.0);
@@ -250,9 +338,13 @@ impl InstallerStep for UsersStep {
ui.add_space(14.0); ui.add_space(14.0);
// ─── Otomatik Oturum Açma ───────────────────────────────────────
form_checkbox(ui, &mut self.autologin, &t!("display_manager_autologin"));
ui.add_space(8.0);
// ─── Yönetici (root) Ayarları ───────────────────────────────────── // ─── Yönetici (root) Ayarları ─────────────────────────────────────
form_checkbox(ui, &mut self.use_same_for_admin, &t!("use_same_for_admin")); form_checkbox(ui, &mut self.use_same_for_admin, &t!("use_same_for_admin"));
if self.use_same_for_admin { if self.use_same_for_admin {
state.root_password = state.password.clone(); state.root_password = state.password.clone();
state.root_password_confirm = state.password_confirm.clone(); state.root_password_confirm = state.password_confirm.clone();
@@ -281,16 +373,33 @@ impl InstallerStep for UsersStep {
// DÜZELTME: 3. parametre olarak show_root_password_confirm eklendi // DÜZELTME: 3. parametre olarak show_root_password_confirm eklendi
let show_root_pwd_conf = &mut self.show_root_password_confirm; let show_root_pwd_conf = &mut self.show_root_password_confirm;
form_input_password(ui, &mut state.root_password_confirm, show_root_pwd_conf); ui.horizontal(|ui| {
form_input_password(ui, &mut state.root_password_confirm, show_root_pwd_conf);
if !state.root_password_confirm.is_empty() {
if state.root_password == state.root_password_confirm {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/check.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_success())
);
} else {
ui.add(
egui::Image::new(egui::include_image!("../../assets/icons/fail-icon.svg"))
.max_width(18.0).max_height(18.0)
.tint(theme::c_error())
);
}
}
});
if state.root_password == state.root_password_confirm { if !state.root_password_confirm.is_empty() && state.root_password != state.root_password_confirm {
ui.colored_label(theme::c_success(), "");
} else {
ui.colored_label(theme::c_error(), t!("passwords_no_match")); ui.colored_label(theme::c_error(), t!("passwords_no_match"));
} }
}); });
} }
// Autologin değerini state'e kaydet
state.autologin = self.autologin;
} }
fn is_complete(&self, state: &GlobalState) -> bool { fn is_complete(&self, state: &GlobalState) -> bool {
+9 -8
View File
@@ -60,28 +60,29 @@ pub fn set_theme_mode(is_dark: bool) {
BG_PANEL.store(0x1A1A1E, Ordering::Relaxed); BG_PANEL.store(0x1A1A1E, Ordering::Relaxed);
BG_WIDGET.store(0x242428, Ordering::Relaxed); BG_WIDGET.store(0x242428, Ordering::Relaxed);
BORDER.store(0x323238, Ordering::Relaxed); BORDER.store(0x323238, Ordering::Relaxed);
TEXT.store(0xF3F3F5, Ordering::Relaxed); TEXT.store(0xF3F3F5, Ordering::Relaxed); // #F3F3F5
TEXT_DIM.store(0x9E9EAF, Ordering::Relaxed); TEXT_DIM.store(0x9E9EAF, Ordering::Relaxed); // #9E9EAF
SIDEBAR.store(0x0B0B0D, Ordering::Relaxed); SIDEBAR.store(0x0B0B0D, Ordering::Relaxed);
SIDEBAR_TEXT.store(0xffffff, Ordering::Relaxed);
KEYBOARD_BG.store(0x000000, Ordering::Relaxed); KEYBOARD_BG.store(0x000000, Ordering::Relaxed);
BG_ROOT.store(0x1A1A1E, Ordering::Relaxed); BG_ROOT.store(0x1A1A1E, Ordering::Relaxed);
} else { } else {
BG_FOOTER.store(0xf7f7f7, Ordering::Relaxed); BG_FOOTER.store(0xf7f7f7, Ordering::Relaxed);
BG_DARK.store(0xf7f7f7, Ordering::Relaxed); BG_DARK.store(0xf7f7f7, Ordering::Relaxed);
SIDEBAR.store(0x292f34, Ordering::Relaxed); SIDEBAR.store(0x292f34, Ordering::Relaxed);
TEXT.store(0x000000, Ordering::Relaxed); TEXT.store(0x000000, Ordering::Relaxed); // #000000
TEXT_DIM.store(0x000000, Ordering::Relaxed); TEXT_DIM.store(0x000000, Ordering::Relaxed); // #000000
SIDEBAR_TEXT.store(0xffffff, Ordering::Relaxed); SIDEBAR_TEXT.store(0xffffff, Ordering::Relaxed);
KEYBOARD_BG.store(0xffffff, Ordering::Relaxed); KEYBOARD_BG.store(0xffffff, Ordering::Relaxed);
BG_ROOT.store(0xf7f7f7, Ordering::Relaxed); BG_ROOT.store(0xf7f7f7, Ordering::Relaxed);
BG_DARK.store(0xF0F0F5, Ordering::Relaxed); //BG_DARK.store(0xF0F0F5, Ordering::Relaxed);
BG_PANEL.store(0xFFFFFF, Ordering::Relaxed); BG_PANEL.store(0xFFFFFF, Ordering::Relaxed);
BG_WIDGET.store(0xE8E8EE, Ordering::Relaxed); BG_WIDGET.store(0xE8E8EE, Ordering::Relaxed);
BORDER.store(0xD0D0DA, Ordering::Relaxed); BORDER.store(0xD0D0DA, Ordering::Relaxed);
TEXT.store(0x20202A, Ordering::Relaxed); //TEXT.store(0x20202A, Ordering::Relaxed); // #20202A
TEXT_DIM.store(0x60606A, Ordering::Relaxed); //TEXT_DIM.store(0x60606A, Ordering::Relaxed); // #60606A
SIDEBAR.store(0xE4E4EA, Ordering::Relaxed); //SIDEBAR.store(0xE4E4EA, Ordering::Relaxed);
} }
} }