diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c1c0b4e..7629350 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -26,6 +26,8 @@ pub struct EssentialsRepo { pub struct InstallTask { pub id: String, pub version: Option, + pub use_manifest: bool, + pub manifest_url: Option, } impl Default for AppSettings { @@ -165,8 +167,14 @@ async fn get_updates(app: AppHandle) -> Vec { } #[tauri::command] -async fn install_software(id: String, version: Option, state: State<'_, AppState>) -> Result<(), String> { - state.install_tx.send(InstallTask { id, version }).await.map_err(|e| e.to_string()) +async fn install_software( + id: String, + version: Option, + use_manifest: bool, + manifest_url: Option, + state: State<'_, AppState> +) -> Result<(), String> { + state.install_tx.send(InstallTask { id, version, use_manifest, manifest_url }).await.map_err(|e| e.to_string()) } #[tauri::command] @@ -196,6 +204,8 @@ pub fn run() { while let Some(task) = rx.recv().await { let id = task.id; let version = task.version; + let use_manifest = task.use_manifest; + let manifest_url = task.manifest_url; let log_id = format!("install-{}", id); let _ = handle.emit("install-status", InstallProgress { @@ -204,31 +214,44 @@ pub fn run() { progress: 0.0, }); - let display_cmd = match &version { - Some(v) => format!("Winget Install: {} (v{})", id, v), - None => format!("Winget Install: {}", id), - }; - emit_log(&handle, &log_id, &display_cmd, "Starting...", "info"); + let mut args = vec!["install".to_string()]; + let display_cmd: String; - let id_for_cmd = id.clone(); - let h = handle.clone(); - - let mut args = vec![ - "install".to_string(), - "--id".to_string(), id_for_cmd.clone(), - "-e".to_string(), + if use_manifest && manifest_url.is_some() { + let url = manifest_url.unwrap(); + args.push("--manifest".to_string()); + args.push(url.clone()); + display_cmd = format!("Winget Install (Manifest): {} from {}", id, url); + } else { + args.push("--id".to_string()); + args.push(id.clone()); + args.push("-e".to_string()); + + if let Some(v) = &version { + if !v.is_empty() { + args.push("--version".to_string()); + args.push(v.clone()); + } + } + + display_cmd = match &version { + Some(v) if !v.is_empty() => format!("Winget Install: {} (v{})", id, v), + _ => format!("Winget Install: {}", id), + }; + } + + // 共同的静默与协议参数 + args.extend([ "--silent".to_string(), "--accept-package-agreements".to_string(), "--accept-source-agreements".to_string(), "--disable-interactivity".to_string(), - ]; + ]); - if let Some(v) = version { - if !v.is_empty() { - args.push("--version".to_string()); - args.push(v); - } - } + emit_log(&handle, &log_id, &display_cmd, "Starting...", "info"); + + let id_for_progress = id.clone(); + let h = handle.clone(); let child = Command::new("winget") .args(&args) @@ -253,7 +276,7 @@ pub fn run() { if let Some(caps) = perc_re.captures(clean_line) { if let Ok(p_val) = caps[1].parse::() { let _ = h.emit("install-status", InstallProgress { - id: id_for_cmd.clone(), + id: id_for_progress.clone(), status: "installing".to_string(), progress: p_val / 100.0, }); @@ -265,7 +288,7 @@ pub fn run() { let total = caps[2].parse::().unwrap_or(1.0); if total > 0.0 { let _ = h.emit("install-status", InstallProgress { - id: id_for_cmd.clone(), + id: id_for_progress.clone(), status: "installing".to_string(), progress: (current / total).min(1.0), }); diff --git a/src-tauri/src/winget.rs b/src-tauri/src/winget.rs index e305897..975fb50 100644 --- a/src-tauri/src/winget.rs +++ b/src-tauri/src/winget.rs @@ -16,10 +16,14 @@ pub struct Software { pub status: String, // "idle", "pending", "installing", "success", "error" #[serde(default = "default_progress")] pub progress: f32, + #[serde(default = "default_false")] + pub use_manifest: bool, + pub manifest_url: Option, } fn default_status() -> String { "idle".to_string() } fn default_progress() -> f32 { 0.0 } +fn default_false() -> bool { false } #[derive(Debug, Deserialize)] #[serde(rename_all = "PascalCase")] @@ -276,5 +280,7 @@ fn map_package(p: WingetPackage) -> Software { icon_url: p.icon_url, status: "idle".to_string(), progress: 0.0, + use_manifest: false, + manifest_url: None, } } diff --git a/src/components/SoftwareCard.vue b/src/components/SoftwareCard.vue index fdca5bf..fe36c3a 100644 --- a/src/components/SoftwareCard.vue +++ b/src/components/SoftwareCard.vue @@ -119,10 +119,13 @@ const props = defineProps<{ name: string; description?: string; version?: string; + recommended_version?: string; available_version?: string; icon_url?: string; status: string; progress: number; + use_manifest?: boolean; + manifest_url?: string; }, actionLabel?: string, selectable?: boolean, @@ -139,7 +142,7 @@ const displayProgress = computed(() => { const isInstalled = computed(() => { return props.software.status === 'installed' || (props.software.status === 'idle' && props.actionLabel === '更新') || - (props.software.status === 'idle' && !props.actionLabel && props.software.installed_version); + (props.software.status === 'idle' && !props.actionLabel && props.software.version); }); const isVersionLower = (current: string | undefined | null, target: string | undefined | null) => { diff --git a/src/store/software.ts b/src/store/software.ts index 64fb061..942bcb5 100644 --- a/src/store/software.ts +++ b/src/store/software.ts @@ -194,7 +194,12 @@ export const useSoftwareStore = defineStore('software', { const software = this.findSoftware(id) if (software) { software.status = 'pending'; - await invoke('install_software', { id, version: software.version }) + await invoke('install_software', { + id, + version: software.version, + use_manifest: software.use_manifest, + manifest_url: software.manifest_url + }) } }, findSoftware(id: string) {