mirror of
https://gitlab.com/erkanisik/yali-rs.git
synced 2026-07-30 18:59:02 +00:00
chore: add English/Turkish changelog cross-links
This commit is contained in:
+29
-1
@@ -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
@@ -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`)
|
||||||
|
- ISO‑105 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)
|
||||||
@@ -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
@@ -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
@@ -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.
|
||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user