fix: GPU karakter bozulması için repaint throttle; slideshow emoji ikonları; partition auto FS; çeşitli f32 tip düzeltmeleri

This commit is contained in:
Erkan IŞIK
2026-07-23 17:13:05 +03:00
parent 1e920e0717
commit 20dc937ab8
12 changed files with 130 additions and 43 deletions
-2
View File
@@ -131,8 +131,6 @@ install: release
# .desktop girdisi
install -Dm644 assets/yali.desktop $(DESTDIR)$(DESKTOPDIR)/yali.desktop
# Logo (pixmap)
install -Dm644 assets/yali.png $(DESTDIR)$(PIXMAPDIR)/yali.png
@echo "$(BOLD)$(GREEN)✓ Kurulum tamamlandı$(RESET)"
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

+10 -10
View File
@@ -3,32 +3,32 @@
# ╚══════════════════════════════════════════════════════════════════╝
# Slayt geçiş süresi (saniye)
interval_secs = 6
interval_secs = 12
[[items]]
icon = "slides/img/pisilinux-logo.png"
title = "Pisi GNU/Linux'a Hoş Geldiniz"
description = "Pisi; hız, kararlılık ve kullanım kolaylığını bir araya getiren Türkçe destekli bir GNU/Linux dağıtımıdır."
description = "Pisi GNU/Linux; Türkiye'nin ilk yerli paket yönetim sistemi olan, PiSi tabanlı, özgür yazılım topluluğu tarafından geliştirilen, kolay kurulum, kolay kullanım ve günlük masaüstü gereksinimlerini karşılamaya odaklanan, son kullanıcıya yönelik bir Linux dağıtımıdır."
[[items]]
icon = "slides/img/pisi-software-center.png"
title = "PISI Paket Yöneticisi"
description = "Binlerce pakete tek komutla erişin. `pisi install <paket>` ile ihtiyacınız olan her şeyi kolayca kurabilirsiniz."
title = "Yerli Yazılım Bileşenleri"
description = "Yerli yazılım bileşenleriyle donatılmış olan Pisi GNU/Linux; kurulum yazılımı YALI, ayar sihirbazı KAPTAN, sistemin hızlı açılmasını sağlayan MÜDÜR ve donanım ayarları için kullanılan ÇOMAR gibi özgün teknolojileriyle öne çıkan yerli bir GNU/Linux dağıtımıdır."
[[items]]
icon = "slides/img/community.png"
title = "Topluluk Desteği"
description = "forum.pisilinux.org adresindeki aktif topluluğumuz sorularınızı yanıtlamak için hazır. Wiki sayfalarımız da her an erişilebilir."
title = "Geniş Yazılım Deposu"
description = "Pisi GNU/Linux, geniş yazılım deposu sayesinde kullanıcıların ihtiyaç duyduğu binlerce uygulamayı sunar ve bunları düzenli olarak güncel tutar."
[[items]]
icon = "slides/img/pisi_speed.png"
title = "Hız ve Performans"
description = "Optimize edilmiş çekirdek ve başlangıç servisleri sayesinde PisiLinux saniyeler içinde açılır ve minimum kaynak kullanır."
title = "Modern Masaüstü Deneyimi"
description = "Özgür ve açık kaynaklı Pisi GNU/Linux, varsayılan olarak modern ve kapsamlı özellikler sunan KDE Plasma masaüstü ortamıyla gelir. Daha düşük sistem kaynakları tüketen bir masaüstü tercih eden kullanıcılar için ise hafif, hızlı ve özelleştirilebilir XFCE masaüstü ortamı da alternatif olarak sunulmaktadır."
[[items]]
icon = "slides/img/securety.png"
title = "Güvenlik Önce Gelir"
description = "Düzenli güvenlik güncellemeleri, AppArmor profilleri ve güvenli varsayılan ayarlarla sisteminizi koruyun."
title = "Çok Yönlü Kullanım"
description = "Pisi GNU/Linux; evde, ofiste ve günlük kullanımda rahatlıkla kullanılabilen çok yönlü bir işletim sistemidir. Müzik, film, 3D modelleme, grafik tasarım ve profesyonel uygulamalar için güçlü bir altyapı sunarken, oyun tutkunları için de kapsamlı bir oyun platformu sağlar."
[[items]]
icon = "slides/img/customization.png"
+2 -2
View File
@@ -25,7 +25,7 @@ pub fn form_input_text(
ui.spacing_mut().button_padding = eframe::egui::vec2(10.0, 10.0);
egui::Frame::none()
.fill(egui::Color32::from_rgb(255, 255, 255))
.stroke(egui::Stroke::new(1.0, egui::Color32::from_gray(200)))
.stroke(egui::Stroke::new(1.0_f32, egui::Color32::from_gray(200)))
.rounding(4.0)
.inner_margin(eframe::egui::Margin::symmetric(2.0, 2.0))
.show(ui, |ui| {
@@ -61,7 +61,7 @@ pub fn form_input_password(
eframe::egui::Frame::none()
.fill(eframe::egui::Color32::WHITE)
.stroke(eframe::egui::Stroke::new(1.0, eframe::egui::Color32::from_rgb(200, 200, 200)))
.stroke(eframe::egui::Stroke::new(1.0_f32, eframe::egui::Color32::from_rgb(200, 200, 200)))
.rounding(6.0)
.inner_margin(eframe::egui::Margin::symmetric(2.0, 2.0))
.show(ui, |ui| {
+38 -5
View File
@@ -13,6 +13,7 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc;
use std::time::Instant;
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::process::Command;
use rust_i18n::t;
@@ -39,21 +40,43 @@ pub enum InstallMessage {
}
/// `mpsc::Sender<InstallMessage>` ile `egui::Context` birlikte taşır.
/// Her mesaj gönderiminde `request_repaint()` çağrısı UI'yi uyandırır.
#[derive(Clone)]
/// Mesaj gönderiminde `request_repaint()` çağrısı UI'yi uyandırır,
/// ancak en fazla saniyede ~30 kez (33ms aralıkla) olacak şekilde
/// throttle edilir. Bu, özellikle rsync gibi yoğun I/O işlemleri
/// sırasında Intel tümleşik GPU'lu (UMA) sistemlerde GPU belleği
/// rekabetini önler ve karakter bozulmasını engeller.
pub struct UiSender {
tx: mpsc::Sender<InstallMessage>,
ctx: eframe::egui::Context,
last_repaint: std::sync::Arc<std::sync::Mutex<Instant>>,
}
impl Clone for UiSender {
fn clone(&self) -> Self {
Self {
tx: self.tx.clone(),
ctx: self.ctx.clone(),
last_repaint: self.last_repaint.clone(),
}
}
}
impl UiSender {
pub fn new(tx: mpsc::Sender<InstallMessage>, ctx: eframe::egui::Context) -> Self {
Self { tx, ctx }
Self {
tx,
ctx,
last_repaint: std::sync::Arc::new(std::sync::Mutex::new(Instant::now())),
}
}
pub fn send(&self, msg: InstallMessage) {
let _ = self.tx.send(msg);
self.ctx.request_repaint();
let mut last = self.last_repaint.lock().unwrap();
if last.elapsed() >= std::time::Duration::from_millis(33) {
self.ctx.request_repaint();
*last = Instant::now();
}
}
pub fn log(&self, s: impl Into<String>) {
@@ -301,6 +324,8 @@ impl Job for CopyFilesJob {
let reader = BufReader::new(stdout);
let mut lines = reader.lines();
let mut file_count: u64 = 0;
// Son UI güncellemesi — çok sık güncelleme GPU (özellikle Intel UMA) baskısını azaltır
let mut last_update = Instant::now();
while let Some(line) = lines.next_line().await
.map_err(|e| format!("rsync çıktısı okunamadı: {}", e))?
@@ -311,7 +336,15 @@ impl Job for CopyFilesJob {
}
file_count += 1;
ui.current_file(trimmed);
let now = Instant::now();
if now.duration_since(last_update) >= std::time::Duration::from_millis(50)
|| file_count == 1
|| trimmed.contains("Packages") || trimmed.contains("package")
{
ui.current_file(trimmed);
last_update = now;
}
if total_files > 0 {
let p = (file_count as f32) / (total_files as f32);
+1 -1
View File
@@ -438,7 +438,7 @@ impl eframe::App for YaliApp {
egui::TopBottomPanel::bottom("footer")
.frame(egui::Frame::none()
.fill(ui::theme::c_footer_bg())
.stroke(egui::Stroke::new(1.0, ui::theme::c_footer_bg())))
.stroke(egui::Stroke::new(1.0_f32, ui::theme::c_footer_bg())))
.show(ctx, |ui| {
ui.add_space(10.0);
ui.horizontal(|ui| {
+20 -6
View File
@@ -438,7 +438,7 @@ impl PartitionStep {
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
})
.stroke(egui::Stroke::new(
if selected { 2.0 } else { 1.0 },
if selected { 2.0_f32 } else { 1.0_f32 },
if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
))
.rounding(egui::Rounding::same(8.0))
@@ -538,7 +538,7 @@ impl PartitionStep {
});
egui::Frame::none()
.stroke(egui::Stroke::new(1.0, crate::ui::theme::c_border()))
.stroke(egui::Stroke::new(1.0_f32, crate::ui::theme::c_border()))
.rounding(egui::Rounding::same(6.0))
.show(ui, |ui| {
let tam = ui.available_width();
@@ -673,7 +673,7 @@ impl PartitionStep {
egui::Color32::from_rgba_unmultiplied(237, 237, 224, 1)
})
.stroke(egui::Stroke::new(
if selected { 2.0 } else { 1.0 },
if selected { 2.0_f32 } else { 1.0_f32 },
if selected { crate::ui::theme::c_accent() } else { crate::ui::theme::c_border() },
))
.rounding(egui::Rounding::same(8.0))
@@ -747,7 +747,7 @@ impl PartitionStep {
let tam_genislik = ui.available_width();
let header_color = egui::Color32::from_rgb(33, 37, 41);
let header_text = egui::Color32::WHITE;
let _border_stroke = egui::Stroke::new(1.0, crate::ui::theme::c_border());
let _border_stroke = egui::Stroke::new(1.0_f32, crate::ui::theme::c_border());
// ── Başlık satırı ─────────────────────────────────
let headers: [String; 4] = [
@@ -767,7 +767,7 @@ impl PartitionStep {
let child_ui = &mut ui.child_ui(rect, egui::Layout::top_down(egui::Align::Center));
egui::Frame::none()
.fill(header_color)
.stroke(egui::Stroke::new(1.0, header_color))
.stroke(egui::Stroke::new(1.0_f32, header_color))
.inner_margin(egui::Margin::symmetric(8.0, 4.0))
.show(child_ui, |ui| {
ui.label(egui::RichText::new(h).strong().color(header_text).size(13.0));
@@ -900,7 +900,6 @@ impl PartitionStep {
let next_num = state.custom_partitions.len() + 1;
self.manual.add_size_str.clear();
self.manual.add_mountpoint.clear();
self.manual.add_fstype = 0;
self.manual.add_encrypt = false;
self.manual.add_luks_password.clear();
self.manual.add_mountpoint = match next_num {
@@ -911,6 +910,11 @@ impl PartitionStep {
3 => "/".to_string(),
_ => String::new(),
};
self.manual.add_fstype = match self.manual.add_mountpoint.as_str() {
"swap" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Swap).unwrap_or(0),
"/boot/efi" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Fat32).unwrap_or(0),
_ => 0,
};
}
// Düzenle
@@ -1044,6 +1048,16 @@ impl PartitionStep {
);
});
// mountpoint "swap" seçildiğinde FS tipini otomatik swap yap
let mp = self.manual.add_mountpoint.trim().to_lowercase();
let current_fs = FS_OPTIONS.get(self.manual.add_fstype).map(|x| &x.1);
let idx = |fs: FsType| FS_OPTIONS.iter().position(|(_, t)| *t == fs).unwrap_or(0);
if mp == "swap" && current_fs != Some(&FsType::Swap) {
self.manual.add_fstype = idx(FsType::Swap);
} else if mp == "/boot/efi" && current_fs != Some(&FsType::Fat32) {
self.manual.add_fstype = idx(FsType::Fat32);
}
ui.add_space(6.0);
ui.separator();
+1 -1
View File
@@ -56,7 +56,7 @@ fn gradient_button(ui: &mut egui::Ui, text: &str, top_color: Color32, bottom_col
ui.painter().rect(strip_rect, Rounding::ZERO, c, Stroke::NONE);
}
ui.painter().rect(rect, rounding, Color32::TRANSPARENT, Stroke::new(1.0, actual_border));
ui.painter().rect(rect, rounding, Color32::TRANSPARENT, Stroke::new(1.0_f32, actual_border));
ui.painter().galley(
egui::pos2(rect.center().x - galley.size().x / 2.0, rect.center().y - galley.size().y / 2.0),
+6 -6
View File
@@ -7,13 +7,13 @@ pub fn apply_visuals(v: &mut egui::Visuals) {
v.widgets.hovered.weak_bg_fill = Color32::from_rgb(200, 200, 200);
v.widgets.active.weak_bg_fill = Color32::from_rgb(180, 180, 180);
v.widgets.inactive.fg_stroke = Stroke::new(1.0, Color32::from_rgb(50, 50, 50));
v.widgets.hovered.fg_stroke = Stroke::new(1.5, Color32::WHITE);
v.widgets.active.fg_stroke = Stroke::new(2.0, Color32::WHITE);
v.widgets.inactive.fg_stroke = Stroke::new(1.0_f32, Color32::from_rgb(50, 50, 50));
v.widgets.hovered.fg_stroke = Stroke::new(1.5_f32, Color32::WHITE);
v.widgets.active.fg_stroke = Stroke::new(2.0_f32, Color32::WHITE);
v.widgets.inactive.bg_stroke = Stroke::new(1.0, Color32::from_rgb(155, 155, 155));
v.widgets.hovered.bg_stroke = Stroke::new(1.0, Color32::from_rgb(155, 155, 155));
v.widgets.active.bg_stroke = Stroke::new(1.0, Color32::from_rgb(155, 155, 155));
v.widgets.inactive.bg_stroke = Stroke::new(1.0_f32, Color32::from_rgb(155, 155, 155));
v.widgets.hovered.bg_stroke = Stroke::new(1.0_f32, Color32::from_rgb(155, 155, 155));
v.widgets.active.bg_stroke = Stroke::new(1.0_f32, Color32::from_rgb(155, 155, 155));
}
fn is_dark_ui(ui: &egui::Ui) -> bool {
+1 -1
View File
@@ -68,7 +68,7 @@ impl ErrorScreen {
// ── Hata mesajı ───────────────────────────────
egui::Frame::none()
.fill(egui::Color32::from_rgba_unmultiplied(0xF4, 0x43, 0x36, 18))
.stroke(egui::Stroke::new(1.0, theme::c_error()))
.stroke(egui::Stroke::new(1.0_f32, theme::c_error()))
.rounding(egui::Rounding::same(8.0))
.inner_margin(egui::Margin::same(12.0))
.show(ui, |ui| {
+43 -1
View File
@@ -363,8 +363,50 @@ impl Slideshow {
.rounding(egui::Rounding::same(8.0)),
);
} else {
let emoji = match slide.icon {
"pisilogo" | "pisi" => "\u{1f427}",
"community" => "\u{1f465}",
"pisi_speed" => "\u{26a1}",
"securety" => "\u{1f512}",
"customization" => "\u{1f3a8}",
"budgie" => "\u{1f98e}",
"budgie_applets" => "\u{1f9e9}",
"budgie_raven" => "\u{1f426}",
"budgie_gtk_theme" => "\u{1f3ad}",
"cinnamon" => "\u{1f36e}",
"cinnamon_panel" => "\u{1f4cb}",
"cinnamon_settings" => "\u{2699}\u{fe0f}",
"cinnamon_desklets" => "\u{1f4cc}",
"gnome" => "\u{1f9d1}\u{200d}\u{1f4bb}",
"gnome_search" => "\u{1f50d}",
"gnome_extensions" => "\u{1f9e9}",
"kde" => "\u{1f48e}",
"file_manager" => "\u{1f4c1}",
"kde_connect" => "\u{1f4f1}",
"discover" => "\u{1f6cd}\u{fe0f}",
"lxde" => "\u{1f5a5}\u{fe0f}",
"lxde_openbox" => "\u{1f4e6}",
"lxde_lxpanel" => "\u{1f4ca}",
"lxde_pcmanfm" => "\u{1f4c2}",
"lxqt" => "\u{1f5a5}\u{fe0f}",
"lxqt_panel" => "\u{1f4cb}",
"lxqt_pcmanfm_qt" => "\u{1f4c2}",
"lumina" => "\u{1f31f}",
"lumina_applications" => "\u{1f4f1}",
"lumina_theme" => "\u{1f3a8}",
"lumina_panel" => "\u{1f4cb}",
"mate" => "\u{1f9c9}",
"mate_caja" => "\u{1f4c2}",
"mate_settings" => "\u{2699}\u{fe0f}",
"mate_applications" => "\u{1f4f1}",
"xfce" => "\u{1f42d}",
"xfce_panel" => "\u{1f4cb}",
"xfce_thunar" => "\u{1f4c2}",
"xfce_settings" => "\u{2699}\u{fe0f}",
_ => "\u{1f5bc}\u{fe0f}",
};
ui.label(
egui::RichText::new(slide.icon)
egui::RichText::new(emoji)
.size(48.0),
);
}
+8 -8
View File
@@ -187,7 +187,7 @@ fn build_visuals(is_dark: bool) -> Visuals {
v.override_text_color = None;
// ─── KENARLIKLAR (Calamares Uyumu için İnce İnce Yumuşatıldı) ───────────────────
v.widgets.noninteractive.bg_stroke = Stroke::new(1.0, c_border());
v.widgets.noninteractive.bg_stroke = Stroke::new(1.0_f32, c_border());
// ─── WIDGET DOLGULARI (Burası ComboBox ve Butonların Kaderini Belirliyor) ───────
v.widgets.noninteractive.bg_fill = c_bg_widget();
@@ -205,7 +205,7 @@ fn build_visuals(is_dark: bool) -> Visuals {
crate::ui::combobox_stil::apply_visuals(&mut v);
// ─── METİN RENKLERİ ────────────────────────────────────────────────────────────
v.widgets.noninteractive.fg_stroke = Stroke::new(1.0, c_text());
v.widgets.noninteractive.fg_stroke = Stroke::new(1.0_f32, c_text());
// ─── YUVARLAK KÖŞELER (Zaten 6.0'dı, Tam İstediğin Calamares Kıvamında) ─────────
v.widgets.noninteractive.rounding = Rounding::same(6.0);
@@ -215,13 +215,13 @@ fn build_visuals(is_dark: bool) -> Visuals {
// Seçim rengi
v.selection.bg_fill = c_accent_dim();
v.selection.stroke = Stroke::new(1.0, c_accent());
v.selection.stroke = Stroke::new(1.0_f32, c_accent());
// Hyperlink
v.hyperlink_color = c_accent();
// Pencere kenarlığı
v.window_stroke = Stroke::new(1.0, c_border());
v.window_stroke = Stroke::new(1.0_f32, c_border());
v.window_rounding = Rounding::same(8.0);
v.interact_cursor = Some(egui::CursorIcon::PointingHand);
@@ -268,7 +268,7 @@ pub fn section_heading(ui: &mut egui::Ui, text: &str) {
let (rect, _) = ui.allocate_exact_size(Vec2::new(ui.available_width(), 1.0), egui::Sense::hover());
ui.painter().line_segment(
[rect.left_center(), rect.right_center()],
Stroke::new(1.0, c_accent_dim()),
Stroke::new(1.0_f32, c_accent_dim()),
);
ui.add_space(8.0);
}
@@ -277,7 +277,7 @@ pub fn section_heading(ui: &mut egui::Ui, text: &str) {
pub fn error_box(ui: &mut egui::Ui, msg: &str) {
egui::Frame::none()
.fill(Color32::from_rgba_unmultiplied(0xF4, 0x43, 0x36, 20))
.stroke(Stroke::new(1.0, c_error()))
.stroke(Stroke::new(1.0_f32, c_error()))
.rounding(Rounding::same(6.0))
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {
@@ -294,7 +294,7 @@ pub fn error_box(ui: &mut egui::Ui, msg: &str) {
pub fn warning_box(ui: &mut egui::Ui, msg: &str) {
egui::Frame::none()
.fill(Color32::from_rgba_unmultiplied(0xFF, 0x98, 0x00, 20))
.stroke(Stroke::new(1.0, c_warning()))
.stroke(Stroke::new(1.0_f32, c_warning()))
.rounding(Rounding::same(6.0))
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {
@@ -311,7 +311,7 @@ pub fn warning_box(ui: &mut egui::Ui, msg: &str) {
pub fn success_box(ui: &mut egui::Ui, msg: &str) {
egui::Frame::none()
.fill(Color32::from_rgba_unmultiplied(0x4C, 0xAF, 0x50, 20))
.stroke(Stroke::new(1.0, c_success()))
.stroke(Stroke::new(1.0_f32, c_success()))
.rounding(Rounding::same(6.0))
.inner_margin(egui::Margin::same(10.0))
.show(ui, |ui| {