Skip to content

Commit c2de157

Browse files
committed
feat: 支持 Scala 语言环境安装
1 parent 6217dbf commit c2de157

File tree

15 files changed

+1664
-36
lines changed

15 files changed

+1664
-36
lines changed

src-tauri/Cargo.lock

Lines changed: 307 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ reqwest = { version = "0.11", features = ["json", "stream"] }
3333
futures-util = "0.3"
3434
rfd = "0.15"
3535
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" }
36+
async-trait = "0.1"
37+
zip = "2.2.2"
38+
flate2 = "1.0"
39+
tar = "0.4"

src-tauri/src/env_commands.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::env_manager::{EnvironmentInfo, EnvironmentManager};
2+
use log::info;
3+
use tauri::{AppHandle, State};
4+
use tokio::sync::Mutex;
5+
6+
pub type EnvironmentManagerState = Mutex<EnvironmentManager>;
7+
8+
#[tauri::command]
9+
pub async fn get_environment_info(
10+
language: String,
11+
env_manager: State<'_, EnvironmentManagerState>,
12+
) -> Result<EnvironmentInfo, String> {
13+
info!("获取 {} 环境信息", language);
14+
let manager = env_manager.lock().await;
15+
manager.get_environment_info(&language).await
16+
}
17+
18+
#[tauri::command]
19+
pub async fn download_and_install_version(
20+
language: String,
21+
version: String,
22+
app_handle: AppHandle,
23+
env_manager: State<'_, EnvironmentManagerState>,
24+
) -> Result<String, String> {
25+
info!("下载并安装 {} 版本 {}", language, version);
26+
let manager = env_manager.lock().await;
27+
manager.download_and_install_version(&language, &version, app_handle).await
28+
}
29+
30+
#[tauri::command]
31+
pub async fn switch_environment_version(
32+
language: String,
33+
version: String,
34+
env_manager: State<'_, EnvironmentManagerState>,
35+
) -> Result<(), String> {
36+
info!("切换 {} 到版本 {}", language, version);
37+
let manager = env_manager.lock().await;
38+
manager.switch_version(&language, &version).await
39+
}
40+
41+
#[tauri::command]
42+
pub async fn get_supported_environment_languages(
43+
env_manager: State<'_, EnvironmentManagerState>,
44+
) -> Result<Vec<String>, String> {
45+
let manager = env_manager.lock().await;
46+
Ok(manager.get_supported_languages())
47+
}

src-tauri/src/env_manager.rs

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use async_trait::async_trait;
2+
use log::{debug, error, info};
3+
use serde::{Deserialize, Serialize};
4+
use std::collections::HashMap;
5+
use std::path::PathBuf;
6+
use tauri::{AppHandle, Emitter};
7+
8+
// 环境版本信息
9+
#[derive(Debug, Serialize, Deserialize, Clone)]
10+
pub struct EnvironmentVersion {
11+
pub version: String,
12+
pub download_url: String,
13+
pub install_path: Option<String>,
14+
pub is_installed: bool,
15+
pub size: Option<u64>,
16+
pub release_date: Option<String>,
17+
}
18+
19+
// 环境管理器响应
20+
#[derive(Debug, Serialize, Deserialize)]
21+
pub struct EnvironmentInfo {
22+
pub language: String,
23+
pub current_version: Option<String>,
24+
pub installed_versions: Vec<EnvironmentVersion>,
25+
pub available_versions: Vec<EnvironmentVersion>,
26+
}
27+
28+
// 下载进度事件
29+
#[derive(Debug, Serialize, Clone)]
30+
pub struct DownloadProgress {
31+
pub language: String,
32+
pub version: String,
33+
pub downloaded: u64,
34+
pub total: u64,
35+
pub percentage: f64,
36+
pub status: DownloadStatus,
37+
}
38+
39+
#[derive(Debug, Serialize, Clone)]
40+
#[serde(rename_all = "lowercase")]
41+
pub enum DownloadStatus {
42+
Downloading,
43+
Extracting,
44+
Installing,
45+
Completed,
46+
Failed,
47+
}
48+
49+
// 语言环境提供者特征
50+
#[async_trait]
51+
pub trait EnvironmentProvider: Send + Sync {
52+
// 获取语言名称
53+
fn get_language(&self) -> &'static str;
54+
55+
// 获取可用版本列表
56+
async fn fetch_available_versions(&self) -> Result<Vec<EnvironmentVersion>, String>;
57+
58+
// 获取已安装版本列表
59+
async fn get_installed_versions(&self) -> Result<Vec<EnvironmentVersion>, String>;
60+
61+
// 下载并安装指定版本
62+
async fn download_and_install(
63+
&self,
64+
version: &str,
65+
app_handle: AppHandle,
66+
) -> Result<String, String>;
67+
68+
// 切换到指定版本
69+
async fn switch_version(&self, version: &str) -> Result<(), String>;
70+
71+
// 获取当前激活的版本
72+
async fn get_current_version(&self) -> Result<Option<String>, String>;
73+
74+
// 获取安装目录
75+
fn get_install_dir(&self) -> PathBuf;
76+
}
77+
78+
// 环境管理器
79+
pub struct EnvironmentManager {
80+
providers: HashMap<String, Box<dyn EnvironmentProvider>>,
81+
}
82+
83+
impl EnvironmentManager {
84+
pub fn new() -> Self {
85+
Self {
86+
providers: HashMap::new(),
87+
}
88+
}
89+
90+
pub fn register_provider(&mut self, provider: Box<dyn EnvironmentProvider>) {
91+
let language = provider.get_language().to_string();
92+
info!("注册环境提供者: {}", language);
93+
self.providers.insert(language, provider);
94+
}
95+
96+
pub async fn get_environment_info(
97+
&self,
98+
language: &str,
99+
) -> Result<EnvironmentInfo, String> {
100+
let provider = self
101+
.providers
102+
.get(language)
103+
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;
104+
105+
info!("获取 {} 环境信息", language);
106+
107+
let current_version = provider.get_current_version().await.ok().flatten();
108+
let installed_versions = provider.get_installed_versions().await.unwrap_or_default();
109+
let available_versions = provider.fetch_available_versions().await.unwrap_or_default();
110+
111+
Ok(EnvironmentInfo {
112+
language: language.to_string(),
113+
current_version,
114+
installed_versions,
115+
available_versions,
116+
})
117+
}
118+
119+
pub async fn download_and_install_version(
120+
&self,
121+
language: &str,
122+
version: &str,
123+
app_handle: AppHandle,
124+
) -> Result<String, String> {
125+
let provider = self
126+
.providers
127+
.get(language)
128+
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;
129+
130+
info!("开始下载并安装 {} 版本 {}", language, version);
131+
provider.download_and_install(version, app_handle).await
132+
}
133+
134+
pub async fn switch_version(&self, language: &str, version: &str) -> Result<(), String> {
135+
let provider = self
136+
.providers
137+
.get(language)
138+
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;
139+
140+
info!("切换 {} 到版本 {}", language, version);
141+
provider.switch_version(version).await
142+
}
143+
144+
pub fn get_supported_languages(&self) -> Vec<String> {
145+
self.providers.keys().cloned().collect()
146+
}
147+
}
148+
149+
// 辅助函数:发送下载进度事件
150+
pub fn emit_download_progress(
151+
app_handle: &AppHandle,
152+
language: &str,
153+
version: &str,
154+
downloaded: u64,
155+
total: u64,
156+
status: DownloadStatus,
157+
) {
158+
let percentage = if total > 0 {
159+
(downloaded as f64 / total as f64) * 100.0
160+
} else {
161+
0.0
162+
};
163+
164+
let progress = DownloadProgress {
165+
language: language.to_string(),
166+
version: version.to_string(),
167+
downloaded,
168+
total,
169+
percentage,
170+
status,
171+
};
172+
173+
if let Err(e) = app_handle.emit("env-download-progress", progress) {
174+
error!("发送下载进度事件失败: {}", e);
175+
}
176+
}

src-tauri/src/env_providers/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod scala;
2+
3+
pub use scala::ScalaEnvironmentProvider;

0 commit comments

Comments
 (0)