From 708df41063a5d1afaf4dd9e44074b98a76ca90ed Mon Sep 17 00:00:00 2001 From: Julian Freeman Date: Sat, 18 Apr 2026 16:15:52 -0400 Subject: [PATCH] refactor 6 --- src-tauri/src/commands/app_commands.rs | 16 ---- src-tauri/src/domain/models.rs | 7 -- src-tauri/src/lib.rs | 3 - src-tauri/src/services/essentials_service.rs | 78 +++++++++++++++++++ src-tauri/src/services/mod.rs | 1 + .../src/services/software_state_service.rs | 61 ++++++++++----- src-tauri/src/services/task_event_service.rs | 32 ++++++++ src-tauri/src/tasks/install_queue.rs | 59 ++++---------- src/store/taskRuntime.ts | 25 +++--- 9 files changed, 180 insertions(+), 102 deletions(-) create mode 100644 src-tauri/src/services/task_event_service.rs diff --git a/src-tauri/src/commands/app_commands.rs b/src-tauri/src/commands/app_commands.rs index 063fa87..0a0de46 100644 --- a/src-tauri/src/commands/app_commands.rs +++ b/src-tauri/src/commands/app_commands.rs @@ -5,7 +5,6 @@ use crate::domain::models::{ UpdateCandidate, }; use crate::services::{essentials_service, settings_service, software_state_service}; -use crate::winget::Software; #[tauri::command] pub fn get_settings(app: AppHandle) -> AppSettings { @@ -32,16 +31,6 @@ pub async fn initialize_app(app: AppHandle) -> Result { software_state_service::initialize_app(app).await } -#[tauri::command] -pub async fn get_installed_software(app: AppHandle) -> Vec { - software_state_service::get_installed_software(app).await -} - -#[tauri::command] -pub async fn get_updates(app: AppHandle) -> Vec { - software_state_service::get_updates(app).await -} - #[tauri::command] pub async fn get_dashboard_snapshot(app: AppHandle) -> DashboardSnapshot { software_state_service::get_dashboard_snapshot(app).await @@ -57,11 +46,6 @@ pub async fn get_update_candidates(app: AppHandle) -> Vec { software_state_service::get_update_candidates(app).await } -#[tauri::command] -pub async fn get_software_info(app: AppHandle, id: String) -> Option { - software_state_service::get_software_info(app, id).await -} - #[tauri::command] pub async fn get_software_icon(app: AppHandle, id: String, name: String) -> Option { software_state_service::get_software_icon(app, id, name).await diff --git a/src-tauri/src/domain/models.rs b/src-tauri/src/domain/models.rs index d09fdf2..5002e60 100644 --- a/src-tauri/src/domain/models.rs +++ b/src-tauri/src/domain/models.rs @@ -51,13 +51,6 @@ pub struct SyncEssentialsResult { pub message: String, } -#[derive(Clone, Serialize)] -pub struct InstallProgress { - pub id: String, - pub status: String, - pub progress: f32, -} - #[derive(Clone)] pub struct ResolvedPostInstall { pub software: Software, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b67b876..b1cc1d8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -22,13 +22,10 @@ pub fn run() { commands::app_commands::save_settings, commands::app_commands::sync_essentials, commands::app_commands::get_essentials, - commands::app_commands::get_installed_software, - commands::app_commands::get_updates, commands::app_commands::get_dashboard_snapshot, commands::app_commands::get_essentials_status, commands::app_commands::get_update_candidates, commands::app_commands::get_software_icon, - commands::app_commands::get_software_info, tasks::install_queue::install_software, commands::app_commands::get_logs_history ]) diff --git a/src-tauri/src/services/essentials_service.rs b/src-tauri/src/services/essentials_service.rs index 4ffb57f..b2503a7 100644 --- a/src-tauri/src/services/essentials_service.rs +++ b/src-tauri/src/services/essentials_service.rs @@ -4,9 +4,23 @@ use tauri::AppHandle; use crate::domain::models::{EssentialsRepo, SyncEssentialsResult}; use crate::services::log_service::emit_log; use crate::services::settings_service; +use crate::services::task_event_service::emit_task_event; use crate::storage::{essentials_store, paths}; pub async fn sync_essentials(app: &AppHandle) -> Result { + emit_task_event( + app, + "sync-essentials", + "sync-essentials", + "sync_essentials", + "running", + "starting", + 0.0, + None, + Some("Starting essentials sync".to_string()), + None, + ); + let settings = settings_service::get_settings(app); let url = format!("{}/setup-essentials.json", settings.repo_url.trim_end_matches('/')); let cache_path = paths::get_essentials_path(app); @@ -42,6 +56,20 @@ pub async fn sync_essentials(app: &AppHandle) -> Result Result Result Result { + emit_task_event( + &app, + "env-check", + "env-check", + "initialize_app", + "running", + "checking_environment", + 0.0, + None, + Some("Checking WinGet environment".to_string()), + None, + ); let app_clone = app.clone(); - tokio::task::spawn_blocking(move || winget_client::ensure_environment_ready(&app_clone).map(|_| true)) + let result = tokio::task::spawn_blocking(move || winget_client::ensure_environment_ready(&app_clone).map(|_| true)) .await - .unwrap_or(Err("Initialization Task Panicked".to_string())) -} + .unwrap_or(Err("Initialization Task Panicked".to_string())); -pub async fn get_installed_software(app: AppHandle) -> Vec { - tokio::task::spawn_blocking(move || winget_client::list_installed_packages(&app)) - .await - .unwrap_or_default() -} + match &result { + Ok(_) => emit_task_event( + &app, + "env-check", + "env-check", + "initialize_app", + "completed", + "ready", + 1.0, + None, + Some("WinGet environment ready".to_string()), + None, + ), + Err(err) => emit_task_event( + &app, + "env-check", + "env-check", + "initialize_app", + "failed", + "error", + 1.0, + None, + Some(err.clone()), + None, + ), + } -pub async fn get_updates(app: AppHandle) -> Vec { - tokio::task::spawn_blocking(move || winget_client::list_upgrade_candidates(&app)) - .await - .unwrap_or_default() -} - -pub async fn get_software_info(app: AppHandle, id: String) -> Option { - tokio::task::spawn_blocking(move || winget_client::get_package_by_id(&app, &id)) - .await - .unwrap_or(None) + result } pub async fn get_software_icon(app: AppHandle, id: String, name: String) -> Option { diff --git a/src-tauri/src/services/task_event_service.rs b/src-tauri/src/services/task_event_service.rs new file mode 100644 index 0000000..89461d2 --- /dev/null +++ b/src-tauri/src/services/task_event_service.rs @@ -0,0 +1,32 @@ +use tauri::{AppHandle, Emitter}; + +use crate::domain::models::TaskEventPayload; +use crate::winget::Software; + +pub fn emit_task_event( + handle: &AppHandle, + task_id: &str, + software_id: &str, + task_type: &str, + status: &str, + stage: &str, + progress: f32, + target_version: Option, + message: Option, + software_info: Option, +) { + let _ = handle.emit( + "task-event", + TaskEventPayload { + task_id: task_id.to_string(), + software_id: software_id.to_string(), + task_type: task_type.to_string(), + status: status.to_string(), + stage: stage.to_string(), + progress, + target_version, + message, + software_info, + }, + ); +} diff --git a/src-tauri/src/tasks/install_queue.rs b/src-tauri/src/tasks/install_queue.rs index b9b87d0..56de9f0 100644 --- a/src-tauri/src/tasks/install_queue.rs +++ b/src-tauri/src/tasks/install_queue.rs @@ -11,10 +11,11 @@ use tokio::sync::mpsc; use winreg::enums::*; use winreg::RegKey; -use crate::domain::models::{InstallProgress, InstallTask, TaskEventPayload}; +use crate::domain::models::{InstallTask, TaskEventPayload}; use crate::providers::winget_client; use crate::services::essentials_service; use crate::services::log_service::emit_log; +use crate::services::task_event_service; use crate::winget::{PostInstallStep, Software}; pub struct AppState { @@ -411,14 +412,6 @@ fn spawn_install_stream_reader( let mut is_progress = false; if let Some(caps) = perc_re.captures(clean_line) { if let Ok(p_val) = caps[1].parse::() { - let _ = handle.emit( - "install-status", - InstallProgress { - id: task_id.clone(), - status: "installing".to_string(), - progress: p_val / 100.0, - }, - ); let _ = handle.emit( "task-event", TaskEventPayload { @@ -439,14 +432,6 @@ fn spawn_install_stream_reader( let current = caps[1].parse::().unwrap_or(0.0); let total = caps[2].parse::().unwrap_or(1.0); if total > 0.0 { - let _ = handle.emit( - "install-status", - InstallProgress { - id: task_id.clone(), - status: "installing".to_string(), - progress: (current / total).min(1.0), - }, - ); let _ = handle.emit( "task-event", TaskEventPayload { @@ -488,35 +473,17 @@ fn emit_task_event( message: Option, software_info: Option, ) { - let _ = handle.emit( - "task-event", - TaskEventPayload { - task_id: task_id.to_string(), - software_id: software_id.to_string(), - task_type: task_type.to_string(), - status: status.to_string(), - stage: stage.to_string(), - progress, - target_version: target_version.clone(), - message, - software_info, - }, - ); - - let legacy_status = match status { - "queued" => "pending".to_string(), - "completed" => "success".to_string(), - "failed" => "error".to_string(), - _ => stage.to_string(), - }; - - let _ = handle.emit( - "install-status", - InstallProgress { - id: software_id.to_string(), - status: legacy_status, - progress, - }, + task_event_service::emit_task_event( + handle, + task_id, + software_id, + task_type, + status, + stage, + progress, + target_version.clone(), + message, + software_info, ); } diff --git a/src/store/taskRuntime.ts b/src/store/taskRuntime.ts index 7ad9b5f..5c66fc1 100644 --- a/src/store/taskRuntime.ts +++ b/src/store/taskRuntime.ts @@ -122,7 +122,7 @@ export const useTaskRuntimeStore = defineStore('task-runtime', { this.taskRecords[payload.task_id] = taskRecord if (payload.status === 'completed' || payload.status === 'failed') { - if (payload.status === 'completed') { + if (payload.task_type === 'install' && payload.status === 'completed') { const latestInfo = payload.software_info if (latestInfo) { const installedIndex = catalog.allSoftware.findIndex(s => s.id.toLowerCase() === payload.software_id.toLowerCase()) @@ -154,23 +154,26 @@ export const useTaskRuntimeStore = defineStore('task-runtime', { delete this.taskRecords[payload.task_id] } }, 3000) + } else if (payload.task_type !== 'install') { + setTimeout(() => { + if (this.taskRecords[payload.task_id]?.status === payload.status) { + delete this.taskRecords[payload.task_id] + } + }, 1500) } - const index = this.batchQueue.indexOf(payload.software_id) - if (index !== -1) { - this.batchQueue.splice(index, 1) - if (this.batchQueue.length === 0) { - this.scheduleDataRefresh() + if (payload.task_type === 'install') { + const index = this.batchQueue.indexOf(payload.software_id) + if (index !== -1) { + this.batchQueue.splice(index, 1) + if (this.batchQueue.length === 0) { + this.scheduleDataRefresh() + } } } } }) - listen('install-status', () => { - // Compatibility event is still emitted by the backend, but task-runtime - // now derives runtime state from the richer task-event stream. - }) - listen('log-event', (event: { payload: LogEntry }) => { const payload = event.payload const existingLog = this.logs.find(item => item.id === payload.id)