Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
358 changes: 331 additions & 27 deletions src-tauri/Cargo.lock

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ tauri-build = { version = "2", features = [] }
chrono = { version = "0.4.41", features = ["serde"] }

[dependencies]
tauri = { version = "2", features = ["devtools"] }
tauri-plugin-opener = "2"
tauri = { version = "2.9", features = ["devtools"] }
tauri-plugin-opener = "2.5"
tauri-plugin-shell = "2.0"
tauri-plugin-dialog = "2.0"
tauri-plugin-dialog = "2.4"
tauri-plugin-fs = "2.4.2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand All @@ -33,3 +33,7 @@ reqwest = { version = "0.11", features = ["json", "stream"] }
futures-util = "0.3"
rfd = "0.15"
fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" }
async-trait = "0.1"
zip = "2.2.2"
flate2 = "1.0"
tar = "0.4"
49 changes: 49 additions & 0 deletions src-tauri/src/env_commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::env_manager::{EnvironmentInfo, EnvironmentManager};
use log::info;
use tauri::{AppHandle, State};
use tokio::sync::Mutex;

pub type EnvironmentManagerState = Mutex<EnvironmentManager>;

#[tauri::command]
pub async fn get_environment_info(
language: String,
env_manager: State<'_, EnvironmentManagerState>,
) -> Result<EnvironmentInfo, String> {
info!("获取 {} 环境信息", language);
let manager = env_manager.lock().await;
manager.get_environment_info(&language).await
}

#[tauri::command]
pub async fn download_and_install_version(
language: String,
version: String,
app_handle: AppHandle,
env_manager: State<'_, EnvironmentManagerState>,
) -> Result<String, String> {
info!("下载并安装 {} 版本 {}", language, version);
let manager = env_manager.lock().await;
manager
.download_and_install_version(&language, &version, app_handle)
.await
}

#[tauri::command]
pub async fn switch_environment_version(
language: String,
version: String,
env_manager: State<'_, EnvironmentManagerState>,
) -> Result<(), String> {
info!("切换 {} 到版本 {}", language, version);
let manager = env_manager.lock().await;
manager.switch_version(&language, &version).await
}

#[tauri::command]
pub async fn get_supported_environment_languages(
env_manager: State<'_, EnvironmentManagerState>,
) -> Result<Vec<String>, String> {
let manager = env_manager.lock().await;
Ok(manager.get_supported_languages())
}
177 changes: 177 additions & 0 deletions src-tauri/src/env_manager.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
use async_trait::async_trait;
use log::{error, info};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use tauri::{AppHandle, Emitter};

// 环境版本信息
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct EnvironmentVersion {
pub version: String,
pub download_url: String,
pub install_path: Option<String>,
pub is_installed: bool,
pub size: Option<u64>,
pub release_date: Option<String>,
}

// 环境管理器响应
#[derive(Debug, Serialize, Deserialize)]
pub struct EnvironmentInfo {
pub language: String,
pub current_version: Option<String>,
pub installed_versions: Vec<EnvironmentVersion>,
pub available_versions: Vec<EnvironmentVersion>,
}

// 下载进度事件
#[derive(Debug, Serialize, Clone)]
pub struct DownloadProgress {
pub language: String,
pub version: String,
pub downloaded: u64,
pub total: u64,
pub percentage: f64,
pub status: DownloadStatus,
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum DownloadStatus {
Downloading,
Extracting,
Installing,
Completed,
_Failed,
}

// 语言环境提供者特征
#[async_trait]
pub trait EnvironmentProvider: Send + Sync {
// 获取语言名称
fn get_language(&self) -> &'static str;

// 获取可用版本列表
async fn fetch_available_versions(&self) -> Result<Vec<EnvironmentVersion>, String>;

// 获取已安装版本列表
async fn get_installed_versions(&self) -> Result<Vec<EnvironmentVersion>, String>;

// 下载并安装指定版本
async fn download_and_install(
&self,
version: &str,
app_handle: AppHandle,
) -> Result<String, String>;

// 切换到指定版本
async fn switch_version(&self, version: &str) -> Result<(), String>;

// 获取当前激活的版本
async fn get_current_version(&self) -> Result<Option<String>, String>;

// 获取安装目录
#[allow(dead_code)]
fn get_install_dir(&self) -> PathBuf;
}

// 环境管理器
pub struct EnvironmentManager {
providers: HashMap<String, Box<dyn EnvironmentProvider>>,
}

impl EnvironmentManager {
pub fn new() -> Self {
Self {
providers: HashMap::new(),
}
}

pub fn register_provider(&mut self, provider: Box<dyn EnvironmentProvider>) {
let language = provider.get_language().to_string();
info!("注册环境提供者: {}", language);
self.providers.insert(language, provider);
}

pub async fn get_environment_info(&self, language: &str) -> Result<EnvironmentInfo, String> {
let provider = self
.providers
.get(language)
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;

info!("获取 {} 环境信息", language);

let current_version = provider.get_current_version().await.ok().flatten();
let installed_versions = provider.get_installed_versions().await.unwrap_or_default();
let available_versions = provider
.fetch_available_versions()
.await
.unwrap_or_default();

Ok(EnvironmentInfo {
language: language.to_string(),
current_version,
installed_versions,
available_versions,
})
}

pub async fn download_and_install_version(
&self,
language: &str,
version: &str,
app_handle: AppHandle,
) -> Result<String, String> {
let provider = self
.providers
.get(language)
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;

info!("开始下载并安装 {} 版本 {}", language, version);
provider.download_and_install(version, app_handle).await
}

pub async fn switch_version(&self, language: &str, version: &str) -> Result<(), String> {
let provider = self
.providers
.get(language)
.ok_or_else(|| format!("暂未支持 {} 语言,请前往 github 提供 issus", language))?;

info!("切换 {} 到版本 {}", language, version);
provider.switch_version(version).await
}

pub fn get_supported_languages(&self) -> Vec<String> {
self.providers.keys().cloned().collect()
}
}

// 辅助函数:发送下载进度事件
pub fn emit_download_progress(
app_handle: &AppHandle,
language: &str,
version: &str,
downloaded: u64,
total: u64,
status: DownloadStatus,
) {
let percentage = if total > 0 {
(downloaded as f64 / total as f64) * 100.0
} else {
0.0
};

let progress = DownloadProgress {
language: language.to_string(),
version: version.to_string(),
downloaded,
total,
percentage,
status,
};

if let Err(e) = app_handle.emit("env-download-progress", progress) {
error!("发送下载进度事件失败: {}", e);
}
}
3 changes: 3 additions & 0 deletions src-tauri/src/env_providers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod scala;

pub use scala::ScalaEnvironmentProvider;
Loading
Loading