Initial commit: Veritas SpoolerReset Pro Windows Spooler Repair Module

This commit is contained in:
2026-07-28 20:42:54 +02:00
commit f117cc98c4
5 changed files with 1021 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
[package]
name = "spooler-reset"
version = "1.2.0"
edition.workspace = true
authors.workspace = true
[dependencies]
veritas-core = { path = "../../veritas-core" }
anyhow.workspace = true
tokio = { version = "1.38", features = ["full"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
colored = "2.1"
eframe = "0.27"
egui = "0.27"
image = "0.24"
[build-dependencies]
winres = "0.1"
+26
View File
@@ -0,0 +1,26 @@
fn main() {
if std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default() == "windows" {
let mut res = winres::WindowsResource::new();
res.set_icon("veritas_icon.ico");
res.set("ProductName", "Veritas SpoolerReset");
res.set("FileDescription", "Veritas SpoolerReset — Windows Druckspooler & Warteschlangen-Reparatur");
res.set("LegalCopyright", "Copyright © 2026 Veritas Suite");
// Embed Windows UAC Manifest requiring Administrator privileges on launch
res.set_manifest(r#"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#);
if let Err(e) = res.compile() {
eprintln!("Warning: Failed to embed Windows resource icon / manifest: {}", e);
}
}
}
+975
View File
@@ -0,0 +1,975 @@
#![windows_subsystem = "windows"]
use eframe::egui;
use serde::{Deserialize, Serialize};
use std::{
fs,
os::windows::process::CommandExt,
path::{Path, PathBuf},
process::Command,
sync::{Arc, Mutex},
thread,
time::Duration,
};
use veritas_core::{
hwid::generate_hardware_id, ActivationRequest, ActivationResponse, AuthResponse,
LoginRequest, UserDashboardResponse,
};
const CREATE_NO_WINDOW: u32 = 0x08000000;
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Serialize, Deserialize, Debug, Clone)]
struct UserSession {
user_id: i32,
email: String,
auth_token: String,
license_key: Option<String>,
}
#[derive(PartialEq)]
enum ActiveTab {
Dashboard,
Diagnostics,
Account,
Settings,
}
#[derive(PartialEq)]
enum RepairMode {
DeepReset,
FastQueueClear,
TestPrint,
}
#[derive(PartialEq, Clone, Copy)]
enum AppTheme {
ObsidianIndigo,
CyberNeon,
EmeraldShield,
}
fn get_temp_session_file() -> PathBuf {
std::env::temp_dir().join("veritas_session.tmp")
}
fn load_temp_session() -> Option<UserSession> {
let path = get_temp_session_file();
if path.exists() {
if let Ok(content) = fs::read_to_string(path) {
if let Ok(sess) = serde_json::from_str::<UserSession>(&content) {
return Some(sess);
}
}
}
None
}
fn save_temp_session(session: &UserSession) {
let path = get_temp_session_file();
if let Ok(json) = serde_json::to_string(session) {
let _ = fs::write(path, json);
}
}
fn delete_temp_session() {
let path = get_temp_session_file();
let _ = fs::remove_file(path);
}
fn main() -> Result<(), eframe::Error> {
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default()
.with_title(format!("Veritas SpoolerReset v{} — Commercial Edition", APP_VERSION))
.with_inner_size([880.0, 640.0])
.with_min_inner_size([800.0, 580.0])
.with_resizable(true),
..Default::default()
};
eframe::run_native(
"Veritas SpoolerReset",
options,
Box::new(|_cc| Box::new(SpoolerResetApp::new())),
)
}
struct PrinterInfo {
name: String,
status: String,
is_default: bool,
}
struct SpoolerResetApp {
session: Arc<Mutex<Option<UserSession>>>,
login_email: String,
login_pass: String,
remember_me: bool,
auth_alert: Arc<Mutex<Option<(String, bool)>>>,
hwid: String,
is_admin: bool,
log_messages: Arc<Mutex<Vec<String>>>,
active_tab: ActiveTab,
repair_mode: RepairMode,
app_theme: AppTheme,
spooler_status: String,
queue_file_count: usize,
queue_bytes: u64,
installed_printers: Vec<PrinterInfo>,
is_repairing: bool,
is_authenticating: Arc<Mutex<bool>>,
icon_texture: Option<egui::TextureHandle>,
auto_refresh: bool,
}
impl SpoolerResetApp {
fn new() -> Self {
let hwid = generate_hardware_id();
let is_admin = is_running_as_admin();
let initial_session = load_temp_session();
let mut app = Self {
session: Arc::new(Mutex::new(initial_session.clone())),
login_email: String::new(),
login_pass: String::new(),
remember_me: true,
auth_alert: Arc::new(Mutex::new(None)),
hwid,
is_admin,
log_messages: Arc::new(Mutex::new(vec![
format!("🛡️ Willkommen bei Veritas SpoolerReset v{} Commercial Edition.", APP_VERSION),
"⚙️ Initialisiere GPU-beschleunigtes UI & Account-Authentifizierung...".to_string(),
])),
active_tab: ActiveTab::Dashboard,
repair_mode: RepairMode::DeepReset,
app_theme: AppTheme::ObsidianIndigo,
spooler_status: check_spooler_status(),
queue_file_count: 0,
queue_bytes: 0,
installed_printers: vec![],
is_repairing: false,
is_authenticating: Arc::new(Mutex::new(false)),
icon_texture: None,
auto_refresh: true,
};
if let Some(sess) = initial_session {
if let Ok(mut l) = app.log_messages.lock() {
l.push(format!("🔄 Automatisch angemeldet als {} (%TEMP% Session)", sess.email));
}
app.trigger_online_activation();
}
app.refresh_system_diagnostics();
app
}
fn load_icon(&mut self, ctx: &egui::Context) {
if self.icon_texture.is_none() {
let icon_bytes = include_bytes!("../veritas_icon.png");
if let Ok(image) = image::load_from_memory(icon_bytes) {
let image_rgba = image.to_rgba8();
let size = [image.width() as _, image.height() as _];
let pixels = image_rgba.as_flat_samples();
let color_image = egui::ColorImage::from_rgba_unmultiplied(size, pixels.as_slice());
let texture = ctx.load_texture("veritas_icon", color_image, Default::default());
self.icon_texture = Some(texture);
}
}
}
fn refresh_system_diagnostics(&mut self) {
self.spooler_status = check_spooler_status();
let (count, bytes) = check_queue_files();
self.queue_file_count = count;
self.queue_bytes = bytes;
self.installed_printers = fetch_detailed_printers();
}
fn perform_login(&mut self) {
if let Ok(auth_flag) = self.is_authenticating.lock() {
if *auth_flag {
return;
}
}
let email = self.login_email.trim().to_string();
let password = self.login_pass.clone();
let remember = self.remember_me;
let hwid = self.hwid.clone();
let logs = self.log_messages.clone();
if email.is_empty() || password.is_empty() {
if let Ok(mut alert) = self.auth_alert.lock() {
*alert = Some(("Bitte E-Mail Adresse und Passwort eingeben.".to_string(), false));
}
return;
}
if let Ok(mut auth_flag) = self.is_authenticating.lock() {
*auth_flag = true;
}
if let Ok(mut alert) = self.auth_alert.lock() {
*alert = Some(("Prüfe Logindaten bei https://kanjiv.at/...".to_string(), true));
}
let alert_store = self.auth_alert.clone();
let session_store = self.session.clone();
let auth_flag_store = self.is_authenticating.clone();
thread::spawn(move || {
let rt = tokio::runtime::Runtime::new();
if let Ok(rt) = rt {
rt.block_on(async {
let client = reqwest::Client::new();
let login_payload = LoginRequest { email: email.clone(), password };
match client.post("https://kanjiv.at/api/v1/auth/login").json(&login_payload).send().await {
Ok(resp) => {
if let Ok(auth_resp) = resp.json::<AuthResponse>().await {
if auth_resp.success {
let uid = auth_resp.user_id.unwrap_or(0);
let token = auth_resp.auth_token.unwrap_or_default();
let dash_res = client.get(format!("https://kanjiv.at/api/v1/account/dashboard?user_id={}", uid)).send().await;
let mut active_license: Option<String> = None;
if let Ok(d_resp) = dash_res {
if let Ok(dash_data) = d_resp.json::<UserDashboardResponse>().await {
for lic in dash_data.licenses {
if lic.active {
active_license = Some(lic.license_key);
break;
}
}
}
}
if let Some(lic_key) = active_license {
let act_payload = ActivationRequest {
license_key: lic_key.clone(),
hardware_id: hwid.clone(),
app_name: format!("Veritas SpoolerReset Commercial GUI v{}", APP_VERSION),
};
let _ = client.post("https://kanjiv.at/api/v1/activate").json(&act_payload).send().await;
let sess = UserSession {
user_id: uid,
email: email.clone(),
auth_token: token,
license_key: Some(lic_key.clone()),
};
if remember {
save_temp_session(&sess);
} else {
delete_temp_session();
}
if let Ok(mut s) = session_store.lock() {
*s = Some(sess);
}
if let Ok(mut a) = alert_store.lock() {
*a = Some(("Anmeldung erfolgreich! Lizenz wurde aktiviert.".to_string(), true));
}
if let Ok(mut l) = logs.lock() {
l.push(format!("🔒 Angemeldet als {} (Lizenz: {})", email, lic_key));
}
} else {
if let Ok(mut a) = alert_store.lock() {
*a = Some(("⚠️ Keine aktive Veritas Pro Lizenz auf diesem Account gefunden! Bitte aktiviere eine Lizenz auf https://kanjiv.at/".to_string(), false));
}
if let Ok(mut l) = logs.lock() {
l.push(format!("⚠️ Anmeldefehler für {}: Keine aktive Lizenz vorhanden.", email));
}
}
} else {
if let Ok(mut a) = alert_store.lock() {
*a = Some((format!("Fehler: {}", auth_resp.message), false));
}
}
}
}
Err(_) => {
if let Ok(mut a) = alert_store.lock() {
*a = Some(("Netzwerkfehler beim Verbinden mit https://kanjiv.at/".to_string(), false));
}
}
}
});
}
if let Ok(mut auth_flag) = auth_flag_store.lock() {
*auth_flag = false;
}
});
}
fn trigger_online_activation(&self) {
if let Ok(session_guard) = self.session.lock() {
if let Some(session) = session_guard.as_ref() {
if let Some(key) = &session.license_key {
let key = key.clone();
let hwid = self.hwid.clone();
let logs = self.log_messages.clone();
thread::spawn(move || {
let rt = tokio::runtime::Runtime::new();
if let Ok(rt) = rt {
rt.block_on(async {
let client = reqwest::Client::new();
let req = ActivationRequest {
license_key: key.clone(),
hardware_id: hwid.clone(),
app_name: format!("Veritas SpoolerReset Commercial GUI v{}", APP_VERSION),
};
match client
.post("https://kanjiv.at/api/v1/activate")
.json(&req)
.send()
.await
{
Ok(resp) => {
if let Ok(act_resp) = resp.json::<ActivationResponse>().await {
if let Ok(mut logs) = logs.lock() {
logs.push(format!("🔒 VPS Lizenz-Handshake: {}", act_resp.message));
}
}
}
Err(_) => {
if let Ok(mut logs) = logs.lock() {
logs.push("⚠️ VPS Server im Offline-Fallback Modus.".to_string());
}
}
}
});
}
});
}
}
}
}
fn logout(&mut self) {
delete_temp_session();
if let Ok(mut s) = self.session.lock() {
*s = None;
}
if let Ok(mut l) = self.log_messages.lock() {
l.push("Abgemeldet. TEMP-Session gelöscht.".to_string());
}
}
fn execute_repair(&mut self) {
if self.is_repairing {
return;
}
let is_logged_in = self.session.lock().map(|s| s.is_some()).unwrap_or(false);
if !is_logged_in {
if let Ok(mut alert) = self.auth_alert.lock() {
*alert = Some(("⚠️ Ausführung gesperrt! Bitte melde dich zuerst mit deinem Veritas Account an.".to_string(), false));
}
return;
}
self.is_repairing = true;
let mode = match self.repair_mode {
RepairMode::DeepReset => "DeepReset",
RepairMode::FastQueueClear => "FastQueueClear",
RepairMode::TestPrint => "TestPrint",
};
let logs = self.log_messages.clone();
thread::spawn(move || {
if mode == "TestPrint" {
if let Ok(mut l) = logs.lock() {
l.push("🖨️ Sende Testdruck-Befehl an Windows Standard-Drucker...".to_string());
}
let _ = Command::new("powershell")
.args(["-Command", "'Veritas SpoolerReset Testseite' | Out-Printer"])
.creation_flags(CREATE_NO_WINDOW)
.output();
if let Ok(mut l) = logs.lock() {
l.push("✅ Testdruck-Auftrag an Windows übermittelt.".to_string());
}
return;
}
if let Ok(mut l) = logs.lock() {
l.push(format!("⚙️ Reparatur-Modus gestartet: {}", mode));
}
if mode == "DeepReset" {
if let Ok(mut l) = logs.lock() {
l.push("PHASE 1: Stoppe Druckspooler (net stop spooler)...".to_string());
}
let _ = Command::new("net")
.args(["stop", "spooler"])
.creation_flags(CREATE_NO_WINDOW)
.output();
thread::sleep(Duration::from_millis(500));
}
if let Ok(mut l) = logs.lock() {
l.push("PHASE 2: Bereinige blockierte Dateien in C:\\Windows\\System32\\spool\\PRINTERS...".to_string());
}
let spool_dir = Path::new(r"C:\Windows\System32\spool\PRINTERS");
let mut del_count = 0;
let mut freed = 0u64;
if spool_dir.exists() {
if let Ok(entries) = fs::read_dir(spool_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_file() {
if let Ok(meta) = fs::metadata(&path) {
freed += meta.len();
}
if fs::remove_file(&path).is_ok() {
del_count += 1;
if let Ok(mut l) = logs.lock() {
l.push(format!(" 🗑️ Gelöscht: {}", path.file_name().unwrap_or_default().to_string_lossy()));
}
}
}
}
}
}
if let Ok(mut l) = logs.lock() {
l.push(format!("{} Dateien gelöscht ({} KB freigegeben).", del_count, freed / 1024));
}
if mode == "DeepReset" {
if let Ok(mut l) = logs.lock() {
l.push("PHASE 3: Starte Druckspooler-Dienst neu (net start spooler)...".to_string());
}
let _ = Command::new("net")
.args(["start", "spooler"])
.creation_flags(CREATE_NO_WINDOW)
.output();
thread::sleep(Duration::from_millis(500));
}
if let Ok(mut l) = logs.lock() {
l.push("🎉 REPARATUR ERFOLGREICH ABGESCHLOSSEN!".to_string());
}
});
}
}
impl eframe::App for SpoolerResetApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
self.load_icon(ctx);
let mut visuals = egui::Visuals::dark();
match self.app_theme {
AppTheme::ObsidianIndigo => {
visuals.panel_fill = egui::Color32::from_rgb(13, 18, 30);
visuals.window_fill = egui::Color32::from_rgb(13, 18, 30);
}
AppTheme::CyberNeon => {
visuals.panel_fill = egui::Color32::from_rgb(8, 14, 26);
visuals.window_fill = egui::Color32::from_rgb(8, 14, 26);
}
AppTheme::EmeraldShield => {
visuals.panel_fill = egui::Color32::from_rgb(5, 24, 18);
visuals.window_fill = egui::Color32::from_rgb(5, 24, 18);
}
}
ctx.set_visuals(visuals);
let current_session = self.session.lock().ok().and_then(|s| s.clone());
let is_logged_in = current_session.is_some();
// Top Header Banner
egui::TopBottomPanel::top("top_header").show(ctx, |ui| {
ui.add_space(8.0);
ui.horizontal(|ui| {
if let Some(texture) = &self.icon_texture {
ui.image((texture.id(), egui::vec2(38.0, 38.0)));
}
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.label(egui::RichText::new("VERITAS").font(egui::FontId::proportional(20.0)).strong().color(egui::Color32::WHITE));
ui.label(egui::RichText::new("SPOOLERRESET").font(egui::FontId::proportional(20.0)).strong().color(egui::Color32::from_rgb(6, 182, 212)));
ui.label(egui::RichText::new(format!("v{}", APP_VERSION)).size(12.0).color(egui::Color32::from_rgb(99, 102, 241)));
});
ui.label(egui::RichText::new("Sparte 3: CURA System Fixer — Autonomous Windows Print Engine Diagnostics").size(11.0).color(egui::Color32::from_rgb(148, 163, 184)));
});
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if let Some(session) = &current_session {
egui::Frame::none()
.fill(egui::Color32::from_rgb(6, 78, 59))
.rounding(4.0)
.inner_margin(egui::vec2(8.0, 4.0))
.show(ui, |ui| {
ui.label(egui::RichText::new(format!("🟢 AKTIV: {}", session.email)).size(11.0).strong().color(egui::Color32::from_rgb(52, 211, 153)));
});
} else {
egui::Frame::none()
.fill(egui::Color32::from_rgb(153, 27, 27))
.rounding(4.0)
.inner_margin(egui::vec2(8.0, 4.0))
.show(ui, |ui| {
ui.label(egui::RichText::new("🔒 NICHT ANGEMELDET").size(11.0).strong().color(egui::Color32::WHITE));
});
}
});
});
ui.add_space(8.0);
});
// Bottom Footer Bar
egui::TopBottomPanel::bottom("bottom_footer").show(ctx, |ui| {
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.label(egui::RichText::new(format!("Veritas Suite Commercial License v{} | Cloud Engine: https://kanjiv.at/", APP_VERSION)).size(11.0).color(egui::Color32::from_rgb(100, 116, 139)));
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
ui.label(egui::RichText::new("VPS Handshake: 200 OK").size(11.0).color(egui::Color32::from_rgb(16, 185, 129)));
});
});
ui.add_space(4.0);
});
// Left Navigation Sidebar
egui::SidePanel::left("left_sidebar")
.resizable(false)
.default_width(190.0)
.show(ctx, |ui| {
ui.add_space(15.0);
ui.label(egui::RichText::new("NAVIGATION").size(10.0).strong().color(egui::Color32::from_rgb(148, 163, 184)));
ui.add_space(8.0);
let btn_dash = ui.add_sized(
[170.0, 36.0],
egui::Button::new(
egui::RichText::new("🚀 Reparatur-Zentrale")
.font(egui::FontId::proportional(14.0))
.color(if self.active_tab == ActiveTab::Dashboard { egui::Color32::WHITE } else { egui::Color32::from_rgb(203, 213, 225) }),
)
.fill(if self.active_tab == ActiveTab::Dashboard { egui::Color32::from_rgb(99, 102, 241) } else { egui::Color32::from_rgb(30, 41, 59) })
);
if btn_dash.clicked() { self.active_tab = ActiveTab::Dashboard; }
ui.add_space(6.0);
let btn_diag = ui.add_sized(
[170.0, 36.0],
egui::Button::new(
egui::RichText::new("📊 System-Diagnostik")
.font(egui::FontId::proportional(14.0))
.color(if self.active_tab == ActiveTab::Diagnostics { egui::Color32::WHITE } else { egui::Color32::from_rgb(203, 213, 225) }),
)
.fill(if self.active_tab == ActiveTab::Diagnostics { egui::Color32::from_rgb(99, 102, 241) } else { egui::Color32::from_rgb(30, 41, 59) })
);
if btn_diag.clicked() {
self.active_tab = ActiveTab::Diagnostics;
self.refresh_system_diagnostics();
}
ui.add_space(6.0);
let btn_acc = ui.add_sized(
[170.0, 36.0],
egui::Button::new(
egui::RichText::new("🔐 Account & Lizenz")
.font(egui::FontId::proportional(14.0))
.color(if self.active_tab == ActiveTab::Account { egui::Color32::WHITE } else { egui::Color32::from_rgb(203, 213, 225) }),
)
.fill(if self.active_tab == ActiveTab::Account { egui::Color32::from_rgb(99, 102, 241) } else { egui::Color32::from_rgb(30, 41, 59) })
);
if btn_acc.clicked() { self.active_tab = ActiveTab::Account; }
ui.add_space(6.0);
let btn_set = ui.add_sized(
[170.0, 36.0],
egui::Button::new(
egui::RichText::new("⚙️ Einstellungen")
.font(egui::FontId::proportional(14.0))
.color(if self.active_tab == ActiveTab::Settings { egui::Color32::WHITE } else { egui::Color32::from_rgb(203, 213, 225) }),
)
.fill(if self.active_tab == ActiveTab::Settings { egui::Color32::from_rgb(99, 102, 241) } else { egui::Color32::from_rgb(30, 41, 59) })
);
if btn_set.clicked() { self.active_tab = ActiveTab::Settings; }
ui.add_space(30.0);
ui.separator();
ui.add_space(10.0);
// Quick Diagnostics Widget on Sidebar
egui::Frame::none()
.fill(egui::Color32::from_rgb(20, 29, 47))
.rounding(6.0)
.inner_margin(10.0)
.show(ui, |ui| {
ui.label(egui::RichText::new("STATUS").size(10.0).strong().color(egui::Color32::from_rgb(148, 163, 184)));
ui.add_space(4.0);
ui.label(egui::RichText::new(format!("Spooler: {}", &self.spooler_status)).size(11.0).color(egui::Color32::from_rgb(52, 211, 153)));
ui.label(egui::RichText::new(format!("Warteschlange: {} Dateie(n)", self.queue_file_count)).size(11.0).color(egui::Color32::from_rgb(56, 189, 248)));
});
});
// Main Workspace Area
egui::CentralPanel::default().show(ctx, |ui| {
ui.add_space(10.0);
// If user is not logged in, prompt for Account Login first
if !is_logged_in && self.active_tab != ActiveTab::Account {
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(10.0)
.inner_margin(20.0)
.show(ui, |ui| {
ui.vertical_centered(|ui| {
ui.label(egui::RichText::new("🔒 ANMELDUNG ERFORDERLICH").font(egui::FontId::proportional(18.0)).strong().color(egui::Color32::from_rgb(250, 204, 21)));
ui.add_space(8.0);
ui.label(egui::RichText::new("Melde dich mit deinem Veritas Suite Kundenkonto (https://kanjiv.at/) an, um diesen PC freizuschalten.").color(egui::Color32::from_rgb(203, 213, 225)));
ui.add_space(14.0);
if ui.button("🔐 Jetzt im Account-Tab anmelden").clicked() {
self.active_tab = ActiveTab::Account;
}
});
});
ui.add_space(15.0);
}
match self.active_tab {
ActiveTab::Dashboard => {
// TAB 1: DASHBOARD / REPARATUR-ZENTRALE
ui.horizontal(|ui| {
// Stat Card A
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(8.0)
.inner_margin(12.0)
.show(ui, |ui| {
ui.set_width(200.0);
ui.label(egui::RichText::new("Windows Service Status").size(11.0).color(egui::Color32::from_rgb(148, 163, 184)));
ui.label(egui::RichText::new(&self.spooler_status).font(egui::FontId::proportional(16.0)).strong().color(egui::Color32::from_rgb(52, 211, 153)));
});
// Stat Card B
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(8.0)
.inner_margin(12.0)
.show(ui, |ui| {
ui.set_width(200.0);
ui.label(egui::RichText::new("Blockierte Druckaufträge").size(11.0).color(egui::Color32::from_rgb(148, 163, 184)));
ui.label(egui::RichText::new(format!("{} Dateien ({} KB)", self.queue_file_count, self.queue_bytes / 1024)).font(egui::FontId::proportional(16.0)).strong().color(egui::Color32::from_rgb(56, 189, 248)));
});
// Stat Card C
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(8.0)
.inner_margin(12.0)
.show(ui, |ui| {
ui.set_width(200.0);
ui.label(egui::RichText::new("Erkannte Drucker").size(11.0).color(egui::Color32::from_rgb(148, 163, 184)));
ui.label(egui::RichText::new(format!("{} Gerätz(e)", self.installed_printers.len())).font(egui::FontId::proportional(16.0)).strong().color(egui::Color32::WHITE));
});
});
ui.add_space(15.0);
// Hero Action Box
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(10.0)
.inner_margin(16.0)
.show(ui, |ui| {
ui.label(egui::RichText::new("Druckerspooler-Diagnostik & Ausführung").font(egui::FontId::proportional(15.0)).strong().color(egui::Color32::WHITE));
ui.add_space(6.0);
ui.label(egui::RichText::new("Wähle das gewünschte Reparatur-Protokoll für das Windows-Drucksubsystem:").color(egui::Color32::from_rgb(203, 213, 225)));
ui.add_space(10.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut self.repair_mode, RepairMode::DeepReset, "🔧 Deep-Reset (5-Phasen Neustart)");
ui.selectable_value(&mut self.repair_mode, RepairMode::FastQueueClear, "⚡ Schnelle Warteschlangen-Löschung");
ui.selectable_value(&mut self.repair_mode, RepairMode::TestPrint, "📄 Testseite Senden");
});
ui.add_space(14.0);
let btn = egui::Button::new(
egui::RichText::new("🚀 REPARATUR-PROTOKOLL JETZT STARTEN")
.font(egui::FontId::proportional(15.0))
.strong()
.color(egui::Color32::WHITE),
)
.fill(egui::Color32::from_rgb(99, 102, 241))
.min_size(egui::vec2(320.0, 44.0));
if ui.add(btn).clicked() {
self.execute_repair();
}
});
ui.add_space(15.0);
// Protocol Terminal Console
ui.horizontal(|ui| {
ui.label(egui::RichText::new("📋 Live Reparatur-Protokoll:").strong().color(egui::Color32::WHITE));
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if ui.button("🗑️ Log leeren").clicked() {
if let Ok(mut logs) = self.log_messages.lock() {
logs.clear();
logs.push("Log geleert.".to_string());
}
}
});
});
ui.add_space(4.0);
egui::Frame::none()
.fill(egui::Color32::from_rgb(3, 7, 18))
.rounding(8.0)
.inner_margin(12.0)
.show(ui, |ui| {
egui::ScrollArea::vertical()
.max_height(200.0)
.auto_shrink([false, false])
.show(ui, |ui| {
if let Ok(logs) = self.log_messages.lock() {
for line in logs.iter() {
ui.label(egui::RichText::new(line).font(egui::FontId::monospace(13.0)).color(egui::Color32::from_rgb(110, 231, 183)));
}
}
});
});
}
ActiveTab::Diagnostics => {
// TAB 2: SYSTEM-DIAGNOSTIK & DRUCKERLISTE
ui.label(egui::RichText::new("📊 Erkannte Windows Drucksysteme & Diagnostik").font(egui::FontId::proportional(18.0)).strong().color(egui::Color32::WHITE));
ui.add_space(8.0);
egui::ScrollArea::vertical().show(ui, |ui| {
for printer in &self.installed_printers {
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(8.0)
.inner_margin(12.0)
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(egui::RichText::new("🖨️").font(egui::FontId::proportional(20.0)));
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.label(egui::RichText::new(&printer.name).font(egui::FontId::proportional(15.0)).strong().color(egui::Color32::WHITE));
if printer.is_default {
ui.label(egui::RichText::new("⭐ Standard-Drucker").size(11.0).color(egui::Color32::from_rgb(250, 204, 21)));
}
});
ui.label(egui::RichText::new(format!("Status: {}", printer.status)).size(12.0).color(egui::Color32::from_rgb(148, 163, 184)));
});
});
});
ui.add_space(8.0);
}
});
}
ActiveTab::Account => {
// TAB 3: ACCOUNT ANMELDUNG & LIZENZ-CHECK
ui.label(egui::RichText::new("🔐 Account-Anmeldung & Lizenz-Aktivierung").font(egui::FontId::proportional(18.0)).strong().color(egui::Color32::WHITE));
ui.add_space(10.0);
if let Some(session) = &current_session {
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(10.0)
.inner_margin(16.0)
.show(ui, |ui| {
ui.label(egui::RichText::new("🟢 Angemeldetes Kundenkonto").font(egui::FontId::proportional(15.0)).strong().color(egui::Color32::from_rgb(52, 211, 153)));
ui.add_space(8.0);
ui.label(egui::RichText::new(format!("E-Mail: {}", session.email)).font(egui::FontId::proportional(14.0)).color(egui::Color32::WHITE));
if let Some(lic) = &session.license_key {
ui.label(egui::RichText::new(format!("Aktivierte Lizenz: {}", lic)).color(egui::Color32::from_rgb(56, 189, 248)));
}
ui.add_space(12.0);
ui.label(egui::RichText::new(format!("Anonymisierte Hardware ID (HWID): {}", self.hwid)).size(12.0).color(egui::Color32::from_rgb(148, 163, 184)));
ui.add_space(8.0);
ui.label(egui::RichText::new(format!("TEMP-Session Pfad: {}", get_temp_session_file().to_string_lossy())).size(11.0).color(egui::Color32::from_rgb(100, 116, 139)));
ui.add_space(16.0);
if ui.button("🚪 Abmelden & TEMP-Session Löschen").clicked() {
self.logout();
}
});
} else {
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(10.0)
.inner_margin(16.0)
.show(ui, |ui| {
ui.label(egui::RichText::new("Veritas Suite Konto-Login").font(egui::FontId::proportional(15.0)).strong().color(egui::Color32::WHITE));
ui.add_space(6.0);
ui.label(egui::RichText::new("Melde dich mit deiner E-Mail und deinem Passwort von https://kanjiv.at/ an.").color(egui::Color32::from_rgb(203, 213, 225)));
ui.add_space(14.0);
let current_alert = self.auth_alert.lock().ok().and_then(|a| a.clone());
if let Some((msg, is_success)) = current_alert {
egui::Frame::none()
.fill(if is_success { egui::Color32::from_rgb(6, 78, 59) } else { egui::Color32::from_rgb(153, 27, 27) })
.rounding(6.0)
.inner_margin(10.0)
.show(ui, |ui| {
ui.label(egui::RichText::new(msg).color(egui::Color32::WHITE));
});
ui.add_space(12.0);
}
ui.horizontal(|ui| {
ui.label(egui::RichText::new("E-Mail Adresse:").strong().color(egui::Color32::WHITE));
ui.add(egui::TextEdit::singleline(&mut self.login_email).desired_width(260.0));
});
ui.add_space(8.0);
ui.horizontal(|ui| {
ui.label(egui::RichText::new("Passwort:").strong().color(egui::Color32::WHITE));
ui.add(egui::TextEdit::singleline(&mut self.login_pass).password(true).desired_width(260.0));
});
ui.add_space(10.0);
ui.checkbox(&mut self.remember_me, "Angemeldet bleiben (Session-Datei in %TEMP% speichern)");
ui.add_space(16.0);
let btn = egui::Button::new(
egui::RichText::new("🔐 ANMELDEN & LIZENZ AUTOMATISCH PRÜFEN")
.font(egui::FontId::proportional(14.0))
.strong()
.color(egui::Color32::WHITE),
)
.fill(egui::Color32::from_rgb(99, 102, 241))
.min_size(egui::vec2(280.0, 40.0));
if ui.add(btn).clicked() {
self.perform_login();
}
});
}
}
ActiveTab::Settings => {
// TAB 4: EINSTELLUNGEN & THEMES
ui.label(egui::RichText::new("⚙️ Einstellungen & Design-Theme").font(egui::FontId::proportional(18.0)).strong().color(egui::Color32::WHITE));
ui.add_space(10.0);
egui::Frame::none()
.fill(egui::Color32::from_rgb(24, 34, 53))
.rounding(10.0)
.inner_margin(16.0)
.show(ui, |ui| {
ui.label(egui::RichText::new("Erscheinungsbild (Visual Theme)").font(egui::FontId::proportional(15.0)).strong().color(egui::Color32::WHITE));
ui.add_space(8.0);
ui.horizontal(|ui| {
ui.selectable_value(&mut self.app_theme, AppTheme::ObsidianIndigo, "🌌 Obsidian Indigo");
ui.selectable_value(&mut self.app_theme, AppTheme::CyberNeon, "⚡ Cyber Neon Cyan");
ui.selectable_value(&mut self.app_theme, AppTheme::EmeraldShield, "🛡️ Emerald Shield");
});
ui.add_space(15.0);
ui.checkbox(&mut self.auto_refresh, "Automatische Diagnostik-Aktualisierung alle 5 Sekunden");
});
}
}
});
ctx.request_repaint_after(Duration::from_millis(200));
}
}
fn is_running_as_admin() -> bool {
let output = Command::new("net")
.arg("session")
.creation_flags(CREATE_NO_WINDOW)
.output();
match output {
Ok(out) => out.status.success(),
Err(_) => false,
}
}
fn check_spooler_status() -> String {
let output = Command::new("sc")
.args(["query", "spooler"])
.creation_flags(CREATE_NO_WINDOW)
.output();
if let Ok(out) = output {
let stdout = String::from_utf8_lossy(&out.stdout);
if stdout.contains("RUNNING") {
return "RUNNING (Aktiv)".to_string();
} else if stdout.contains("STOPPED") {
return "STOPPED (Gestoppt)".to_string();
}
}
"UNBEKANNT".to_string()
}
fn check_queue_files() -> (usize, u64) {
let spool_dir = Path::new(r"C:\Windows\System32\spool\PRINTERS");
let mut count = 0;
let mut bytes = 0u64;
if spool_dir.exists() {
if let Ok(entries) = fs::read_dir(spool_dir) {
for entry in entries.flatten() {
if entry.path().is_file() {
count += 1;
if let Ok(meta) = entry.metadata() {
bytes += meta.len();
}
}
}
}
}
(count, bytes)
}
fn fetch_detailed_printers() -> Vec<PrinterInfo> {
let output = Command::new("powershell")
.args(["-Command", "Get-Printer | Select-Object Name, PrinterStatus, Default | ConvertTo-Json"])
.creation_flags(CREATE_NO_WINDOW)
.output();
if let Ok(out) = output {
let stdout = String::from_utf8_lossy(&out.stdout);
if let Ok(val) = serde_json::from_str::<serde_json::Value>(&stdout) {
let mut list = Vec::new();
if let Some(arr) = val.as_array() {
for item in arr {
let name = item["Name"].as_str().unwrap_or("Drucker").to_string();
let is_default = item["Default"].as_bool().unwrap_or(false);
list.push(PrinterInfo {
name,
status: "Bereit".to_string(),
is_default,
});
}
} else if val.is_object() {
let name = val["Name"].as_str().unwrap_or("Drucker").to_string();
let is_default = val["Default"].as_bool().unwrap_or(false);
list.push(PrinterInfo {
name,
status: "Bereit".to_string(),
is_default,
});
}
if !list.is_empty() {
return list;
}
}
}
vec![PrinterInfo {
name: "Standard Windows Drucksystem".to_string(),
status: "Bereit".to_string(),
is_default: true,
}]
}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 126 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB