|
|
@@ -938,6 +938,44 @@ where
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 安装 Claude Code VS Code 扩展
|
|
|
+async fn install_claude_code_ext<F, C>(
|
|
|
+ _app: &tauri::AppHandle,
|
|
|
+ _state: &State<'_, AppState>,
|
|
|
+ emit_status: F,
|
|
|
+ is_cancelled: C,
|
|
|
+) -> Result<InstallResult, String>
|
|
|
+where
|
|
|
+ F: Fn(&str, f64, Option<&str>, bool, Option<serde_json::Value>),
|
|
|
+ C: Fn() -> bool,
|
|
|
+{
|
|
|
+ emit_status("正在安装 Claude Code for VS Code 扩展...", 10.0, Some("install.installing"), false, Some(serde_json::json!({
|
|
|
+ "software": "Claude Code for VS Code"
|
|
|
+ })));
|
|
|
+
|
|
|
+ if is_cancelled() {
|
|
|
+ return Ok(InstallResult {
|
|
|
+ success: false,
|
|
|
+ message: "Installation cancelled".to_string(),
|
|
|
+ i18n_key: Some("install.cancelled".to_string()),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复用 vscode 模块的扩展安装功能
|
|
|
+ let result = super::vscode::install_vscode_extension_internal("anthropic.claude-code");
|
|
|
+
|
|
|
+ if result.success {
|
|
|
+ emit_status("安装成功", 100.0, Some("install.success"), false, None);
|
|
|
+ Ok(InstallResult {
|
|
|
+ success: true,
|
|
|
+ message: "Claude Code for VS Code extension installed successfully".to_string(),
|
|
|
+ i18n_key: Some("install.claudeCodeExt.success".to_string()),
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ Err(result.error.unwrap_or_else(|| "Unknown error".to_string()))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 安装所有软件
|
|
|
async fn install_all<F, C>(
|
|
|
app: &tauri::AppHandle,
|
|
|
@@ -978,34 +1016,111 @@ where
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // 计算要安装的软件数量,用于整体进度计算
|
|
|
+ let mut total_steps = 0;
|
|
|
+ if options.install_nodejs.unwrap_or(false) { total_steps += 1; }
|
|
|
+ if options.install_pnpm.unwrap_or(false) { total_steps += 1; }
|
|
|
+ if options.install_git.unwrap_or(false) { total_steps += 1; }
|
|
|
+ if options.install_claude_code.unwrap_or(false) { total_steps += 1; }
|
|
|
+ if options.install_vscode.unwrap_or(false) { total_steps += 1; }
|
|
|
+ if options.install_claude_code_ext.unwrap_or(false) { total_steps += 1; }
|
|
|
+
|
|
|
+ if total_steps == 0 {
|
|
|
+ return Ok(InstallResult {
|
|
|
+ success: true,
|
|
|
+ message: "No software selected for installation".to_string(),
|
|
|
+ i18n_key: Some("install.noSelection".to_string()),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ let mut current_step = 0;
|
|
|
+
|
|
|
+ // 创建一个包装的 emit_status,用于计算整体进度
|
|
|
+ let emit_overall_status = |message: &str, sub_progress: f64, i18n_key: Option<&str>, skip_log: bool, i18n_params: Option<serde_json::Value>, step: usize, total: usize| {
|
|
|
+ // 计算整体进度:每个软件占 100/total_steps 的进度
|
|
|
+ // sub_progress 是当前软件的进度 (0-100)
|
|
|
+ let step_size = 100.0 / total as f64;
|
|
|
+ let overall_progress = (step as f64 * step_size) + (sub_progress / 100.0 * step_size);
|
|
|
+ emit_status(message, overall_progress, i18n_key, skip_log, i18n_params);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 按界面顺序安装:Node.js -> pnpm -> Git -> Claude Code -> VS Code -> Claude Code Ext
|
|
|
+
|
|
|
+ // 1. Node.js
|
|
|
if options.install_nodejs.unwrap_or(false) {
|
|
|
- let result = install_nodejs(app, state, options, emit_status, is_cancelled).await;
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_nodejs(app, state, options, sub_emit, is_cancelled).await;
|
|
|
emit_sub_result("nodejs", &result);
|
|
|
results.push(("nodejs", result));
|
|
|
+ current_step += 1;
|
|
|
}
|
|
|
|
|
|
+ // 2. pnpm
|
|
|
if options.install_pnpm.unwrap_or(false) {
|
|
|
- let result = install_pnpm(app, state, emit_status, is_cancelled).await;
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_pnpm(app, state, sub_emit, is_cancelled).await;
|
|
|
emit_sub_result("pnpm", &result);
|
|
|
results.push(("pnpm", result));
|
|
|
+ current_step += 1;
|
|
|
}
|
|
|
|
|
|
- if options.install_vscode.unwrap_or(false) {
|
|
|
- let result = install_vscode(app, state, options, emit_status, is_cancelled).await;
|
|
|
- emit_sub_result("vscode", &result);
|
|
|
- results.push(("vscode", result));
|
|
|
- }
|
|
|
-
|
|
|
+ // 3. Git
|
|
|
if options.install_git.unwrap_or(false) {
|
|
|
- let result = install_git(app, state, options, emit_status, is_cancelled).await;
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_git(app, state, options, sub_emit, is_cancelled).await;
|
|
|
emit_sub_result("git", &result);
|
|
|
results.push(("git", result));
|
|
|
+ current_step += 1;
|
|
|
}
|
|
|
|
|
|
+ // 4. Claude Code
|
|
|
if options.install_claude_code.unwrap_or(false) {
|
|
|
- let result = install_claude_code_software(app, state, emit_status, is_cancelled).await;
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_claude_code_software(app, state, sub_emit, is_cancelled).await;
|
|
|
emit_sub_result("claudeCode", &result);
|
|
|
results.push(("claudeCode", result));
|
|
|
+ current_step += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 5. VS Code
|
|
|
+ if options.install_vscode.unwrap_or(false) {
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_vscode(app, state, options, sub_emit, is_cancelled).await;
|
|
|
+ emit_sub_result("vscode", &result);
|
|
|
+ results.push(("vscode", result));
|
|
|
+ current_step += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. Claude Code for VS Code 扩展
|
|
|
+ if options.install_claude_code_ext.unwrap_or(false) {
|
|
|
+ let step = current_step;
|
|
|
+ let total = total_steps;
|
|
|
+ let sub_emit = |msg: &str, prog: f64, key: Option<&str>, skip: bool, params: Option<serde_json::Value>| {
|
|
|
+ emit_overall_status(msg, prog, key, skip, params, step, total);
|
|
|
+ };
|
|
|
+ let result = install_claude_code_ext(app, state, sub_emit, is_cancelled).await;
|
|
|
+ emit_sub_result("claudeCodeExt", &result);
|
|
|
+ results.push(("claudeCodeExt", result));
|
|
|
}
|
|
|
|
|
|
let all_success = results.iter().all(|(_, r)| r.as_ref().map(|r| r.success).unwrap_or(false));
|