aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src-tauri
diff options
context:
space:
mode:
Diffstat (limited to 'src-tauri')
-rw-r--r--src-tauri/src/core/java/detection.rs12
-rw-r--r--src-tauri/src/core/java/mod.rs46
-rw-r--r--src-tauri/src/core/java/priority.rs17
-rw-r--r--src-tauri/src/core/java/providers/adoptium.rs12
-rw-r--r--src-tauri/src/core/java/validation.rs77
-rw-r--r--src-tauri/src/main.rs151
6 files changed, 133 insertions, 182 deletions
diff --git a/src-tauri/src/core/java/detection.rs b/src-tauri/src/core/java/detection.rs
index ee2111e..512769b 100644
--- a/src-tauri/src/core/java/detection.rs
+++ b/src-tauri/src/core/java/detection.rs
@@ -1,8 +1,7 @@
use std::io::Read;
use std::path::PathBuf;
use std::process::{Command, Stdio};
-use std::thread::sleep;
-use std::time::{Duration, Instant};
+use std::time::Duration;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
@@ -24,11 +23,11 @@ pub fn find_sdkman_java() -> Option<PathBuf> {
fn run_which_command_with_timeout() -> Option<String> {
let mut cmd = Command::new(if cfg!(windows) { "where" } else { "which" });
cmd.arg("java");
+ // Hide console window
#[cfg(target_os = "windows")]
cmd.creation_flags(0x08000000);
cmd.stdout(Stdio::piped());
- let start = Instant::now();
let mut child = cmd.spawn().ok()?;
loop {
@@ -46,12 +45,7 @@ fn run_which_command_with_timeout() -> Option<String> {
}
}
Ok(None) => {
- if start.elapsed() >= WHICH_TIMEOUT {
- let _ = child.kill();
- let _ = child.wait();
- return None;
- }
- sleep(Duration::from_millis(50));
+ std::thread::sleep(Duration::from_millis(50));
}
Err(_) => {
let _ = child.kill();
diff --git a/src-tauri/src/core/java/mod.rs b/src-tauri/src/core/java/mod.rs
index 05bf734..c88cd1c 100644
--- a/src-tauri/src/core/java/mod.rs
+++ b/src-tauri/src/core/java/mod.rs
@@ -362,24 +362,10 @@ pub async fn get_compatible_java(
) -> Option<JavaInstallation> {
let installations = detect_all_java_installations(app_handle).await;
- if let Some(max_version) = max_major_version {
- installations.into_iter().find(|java| {
- let major = validation::parse_java_version(&java.version);
- let meets_min = if let Some(required) = required_major_version {
- major >= required as u32
- } else {
- true
- };
- meets_min && major <= max_version
- })
- } else if let Some(required) = required_major_version {
- installations.into_iter().find(|java| {
- let major = validation::parse_java_version(&java.version);
- major >= required as u32
- })
- } else {
- installations.into_iter().next()
- }
+ installations.into_iter().find(|java| {
+ let major = validation::parse_java_version(&java.version);
+ validation::is_version_compatible(major, required_major_version, max_major_version)
+ })
}
pub async fn is_java_compatible(
@@ -387,23 +373,13 @@ pub async fn is_java_compatible(
required_major_version: Option<u64>,
max_major_version: Option<u32>,
) -> bool {
- let java_path_buf = PathBuf::from(java_path);
- if let Some(java) = validation::check_java_installation(&java_path_buf).await {
- let major = validation::parse_java_version(&java.version);
- let meets_min = if let Some(required) = required_major_version {
- major >= required as u32
- } else {
- true
- };
- let meets_max = if let Some(max_version) = max_major_version {
- major <= max_version
- } else {
- true
- };
- meets_min && meets_max
- } else {
- false
- }
+ let java_path_buf = PathBuf::from(java_path);
+ if let Some(java) = validation::check_java_installation(&java_path_buf).await {
+ let major = validation::parse_java_version(&java.version);
+ validation::is_version_compatible(major, required_major_version, max_major_version)
+ } else {
+ false
+ }
}
pub async fn detect_all_java_installations(app_handle: &AppHandle) -> Vec<JavaInstallation> {
diff --git a/src-tauri/src/core/java/priority.rs b/src-tauri/src/core/java/priority.rs
index 98f8b0e..09a61b3 100644
--- a/src-tauri/src/core/java/priority.rs
+++ b/src-tauri/src/core/java/priority.rs
@@ -4,7 +4,6 @@ use super::JavaInstallation;
use crate::core::java::persistence;
use crate::core::java::validation;
-#[allow(dead_code)]
pub async fn resolve_java_for_launch(
app_handle: &AppHandle,
instance_java_override: Option<&str>,
@@ -50,25 +49,11 @@ pub async fn resolve_java_for_launch(
.find(|java| is_version_compatible(java, required_major_version, max_major_version))
}
-#[allow(dead_code)]
fn is_version_compatible(
java: &JavaInstallation,
required_major_version: Option<u64>,
max_major_version: Option<u32>,
) -> bool {
let major = validation::parse_java_version(&java.version);
-
- let meets_min = if let Some(required) = required_major_version {
- major >= required as u32
- } else {
- true
- };
-
- let meets_max = if let Some(max_version) = max_major_version {
- major <= max_version
- } else {
- true
- };
-
- meets_min && meets_max
+ validation::is_version_compatible(major, required_major_version, max_major_version)
}
diff --git a/src-tauri/src/core/java/providers/adoptium.rs b/src-tauri/src/core/java/providers/adoptium.rs
index 53d1519..aac2bf2 100644
--- a/src-tauri/src/core/java/providers/adoptium.rs
+++ b/src-tauri/src/core/java/providers/adoptium.rs
@@ -171,8 +171,16 @@ impl JavaProvider for AdoptiumProvider {
// Collect all results concurrently
let mut releases = Vec::new();
for task in fetch_tasks {
- if let Ok(Some(release)) = task.await {
- releases.push(release);
+ match task.await {
+ Ok(Some(release)) => {
+ releases.push(release);
+ }
+ Ok(None) => {
+ // Task completed but returned None, should not happen in current implementation
+ }
+ Err(e) => {
+ eprintln!("AdoptiumProvider::fetch_catalog task join error: {:?}", e);
+ }
}
}
diff --git a/src-tauri/src/core/java/validation.rs b/src-tauri/src/core/java/validation.rs
index cfe6f14..e086e74 100644
--- a/src-tauri/src/core/java/validation.rs
+++ b/src-tauri/src/core/java/validation.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
@@ -86,24 +87,62 @@ pub fn extract_architecture(version_output: &str) -> String {
pub fn extract_vendor(version_output: &str) -> String {
let lower = version_output.to_lowercase();
- // TODO: Expand with more vendors as needed
- if lower.contains("temurin") || lower.contains("adoptium") {
- "Eclipse Adoptium".to_string()
- } else if lower.contains("openjdk") {
- "OpenJDK".to_string()
- } else if lower.contains("oracle") {
- "Oracle".to_string()
- } else if lower.contains("microsoft") {
- "Microsoft".to_string()
- } else if lower.contains("zulu") {
- "Azul Zulu".to_string()
- } else if lower.contains("corretto") {
- "Amazon Corretto".to_string()
- } else if lower.contains("liberica") {
- "BellSoft Liberica".to_string()
- } else if lower.contains("graalvm") {
- "GraalVM".to_string()
- } else {
- "Unknown".to_string()
+ let vendor_name: HashMap<&str, &str> = [
+ // Eclipse/Adoptium
+ ("temurin", "Temurin (Eclipse)"),
+ ("adoptium", "Eclipse Adoptium"),
+ // Amazon
+ ("corretto", "Corretto (Amazon)"),
+ ("amzn", "Corretto (Amazon)"),
+ // Alibaba
+ ("dragonwell", "Dragonwell (Alibaba)"),
+ ("albba", "Dragonwell (Alibaba)"),
+ // GraalVM
+ ("graalvm", "GraalVM"),
+ // Oracle
+ ("oracle", "Java SE Development Kit (Oracle)"),
+ // Tencent
+ ("kona", "Kona (Tencent)"),
+ // BellSoft
+ ("liberica", "Liberica (Bellsoft)"),
+ ("mandrel", "Mandrel (Red Hat)"),
+ // Microsoft
+ ("microsoft", "OpenJDK (Microsoft)"),
+ // SAP
+ ("sapmachine", "SapMachine (SAP)"),
+ // IBM
+ ("semeru", "Semeru (IBM)"),
+ ("sem", "Semeru (IBM)"),
+ // Azul
+ ("zulu", "Zulu (Azul Systems)"),
+ // Trava
+ ("trava", "Trava (Trava)"),
+ // Huawei
+ ("bisheng", "BiSheng (Huawei)"),
+ // Generic OpenJDK
+ ("openjdk", "OpenJDK"),
+ ]
+ .iter()
+ .cloned()
+ .collect();
+
+ for (key, name) in vendor_name {
+ if lower.contains(key) {
+ return name.to_string();
+ }
}
+
+ "Unknown".to_string()
+}
+
+pub fn is_version_compatible(
+ major: u32,
+ required_major_version: Option<u64>,
+ max_major_version: Option<u32>,
+) -> bool {
+ let meets_min = required_major_version
+ .map(|r| major >= r as u32)
+ .unwrap_or(true);
+ let meets_max = max_major_version.map(|m| major <= m).unwrap_or(true);
+ meets_min && meets_max
}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
index 5fa46b8..e0a71b5 100644
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -4,10 +4,9 @@
use serde::{Deserialize, Serialize};
use std::process::Stdio;
use std::sync::Mutex;
-use tauri::{Emitter, Manager, State, Window};
+use tauri::{Emitter, Manager, State, Window}; // Added Emitter
use tokio::io::{AsyncBufReadExt, BufReader};
-use tokio::process::Command;
-use ts_rs::TS;
+use tokio::process::Command; // Added Serialize
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
@@ -199,92 +198,54 @@ async fn start_game(
None
};
- // Check if configured Java is compatible
+ // Resolve Java using priority-based resolution
+ // Priority: instance override > global config > user preference > auto-detect
+ // TODO: refactor into a separate function
let app_handle = window.app_handle();
- let mut java_path_to_use = config.java_path.clone();
- if !java_path_to_use.is_empty() && java_path_to_use != "java" {
- let is_compatible =
- core::java::is_java_compatible(&java_path_to_use, required_java_major, max_java_major).await;
-
- if !is_compatible {
- emit_log!(
- window,
- format!(
- "Configured Java version may not be compatible. Looking for compatible Java..."
- )
- );
-
- // Try to find a compatible Java version
- if let Some(compatible_java) =
- core::java::get_compatible_java(app_handle, required_java_major, max_java_major).await
- {
- emit_log!(
- window,
- format!(
- "Found compatible Java {} at: {}",
- compatible_java.version, compatible_java.path
- )
- );
- java_path_to_use = compatible_java.path;
- } else {
- let version_constraint = if let Some(max) = max_java_major {
- if let Some(min) = required_java_major {
- if min == max as u64 {
- format!("Java {}", min)
- } else {
- format!("Java {} to {}", min, max)
- }
- } else {
- format!("Java {} (or lower)", max)
- }
- } else if let Some(min) = required_java_major {
- format!("Java {} or higher", min)
- } else {
- "any Java version".to_string()
- };
+ let instance = instance_state
+ .get_instance(&instance_id)
+ .ok_or_else(|| format!("Instance {} not found", instance_id))?;
- return Err(format!(
- "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
- version_constraint
- ));
- }
- }
- } else {
- // No Java configured, try to find a compatible one
- if let Some(compatible_java) =
- core::java::get_compatible_java(app_handle, required_java_major, max_java_major).await
- {
- emit_log!(
- window,
- format!(
- "Using Java {} at: {}",
- compatible_java.version, compatible_java.path
- )
- );
- java_path_to_use = compatible_java.path;
- } else {
- let version_constraint = if let Some(max) = max_java_major {
- if let Some(min) = required_java_major {
- if min == max as u64 {
- format!("Java {}", min)
- } else {
- format!("Java {} to {}", min, max)
- }
+ let java_installation = core::java::priority::resolve_java_for_launch(
+ app_handle,
+ instance.java_path_override.as_deref(),
+ Some(&config.java_path),
+ required_java_major,
+ max_java_major,
+ )
+ .await
+ .ok_or_else(|| {
+ let version_constraint = if let Some(max) = max_java_major {
+ if let Some(min) = required_java_major {
+ if min == max as u64 {
+ format!("Java {}", min)
} else {
- format!("Java {} (or lower)", max)
+ format!("Java {} to {}", min, max)
}
- } else if let Some(min) = required_java_major {
- format!("Java {} or higher", min)
} else {
- "any Java version".to_string()
- };
+ format!("Java {} (or lower)", max)
+ }
+ } else if let Some(min) = required_java_major {
+ format!("Java {} or higher", min)
+ } else {
+ "any Java version".to_string()
+ };
- return Err(format!(
- "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
- version_constraint
- ));
- }
- }
+ format!(
+ "No compatible Java installation found. This version requires {}. Please install a compatible Java version in settings.",
+ version_constraint
+ )
+ })?;
+
+ emit_log!(
+ window,
+ format!(
+ "Using Java {} at: {}",
+ java_installation.version, java_installation.path
+ )
+ );
+
+ let java_path_to_use = java_installation.path;
// 2. Prepare download tasks
emit_log!(window, "Preparing download tasks...".to_string());
@@ -1758,9 +1719,7 @@ async fn get_version_java_version(
}
/// Version metadata for display in the UI
-#[derive(serde::Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(serde::Serialize)]
struct VersionMetadata {
id: String,
#[serde(rename = "javaVersion")]
@@ -1910,9 +1869,7 @@ async fn get_version_metadata(
}
/// Installed version info
-#[derive(serde::Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(serde::Serialize)]
struct InstalledVersion {
id: String,
#[serde(rename = "type")]
@@ -2141,9 +2098,7 @@ async fn install_forge(
Ok(result)
}
-#[derive(serde::Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(serde::Serialize)]
struct GithubRelease {
tag_name: String,
name: String,
@@ -2189,9 +2144,7 @@ async fn get_github_releases() -> Result<Vec<GithubRelease>, String> {
Ok(result)
}
-#[derive(Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(Serialize)]
struct PastebinResponse {
url: String,
}
@@ -2399,9 +2352,7 @@ async fn assistant_chat_stream(
}
/// Migrate instance caches to shared global caches
-#[derive(Serialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(Serialize)]
struct MigrationResult {
moved_files: usize,
hardlinks: usize,
@@ -2450,9 +2401,7 @@ async fn migrate_shared_caches(
}
/// File information for instance file browser
-#[derive(Debug, Clone, Serialize, Deserialize, TS)]
-#[serde(rename_all = "camelCase")]
-#[ts(export, export_to = "../../packages/ui-new/src/types/bindings/core.ts")]
+#[derive(Debug, Clone, Serialize, Deserialize)]
struct FileInfo {
name: String,
path: String,