From 17614b52da2fe28d9e591064d1bce74c67f7190f Mon Sep 17 00:00:00 2001 From: Craun718 <3653544699@qq.com> Date: Thu, 11 Jun 2026 00:59:47 +0800 Subject: [PATCH 1/2] chore(config): tighten download thread limits --- packages/ui/src/components/config-editor.tsx | 2 +- src-tauri/src/core/config.rs | 14 +++++++++++--- src-tauri/src/main.rs | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/ui/src/components/config-editor.tsx b/packages/ui/src/components/config-editor.tsx index 129b8f72..b14ab942 100644 --- a/packages/ui/src/components/config-editor.tsx +++ b/packages/ui/src/components/config-editor.tsx @@ -22,7 +22,7 @@ const launcherConfigSchema: ZodType = z.object({ javaPath: z.string(), width: z.number(), height: z.number(), - downloadThreads: z.number(), + downloadThreads: z.number().min(1).max(64), customBackgroundPath: z.string().nullable(), enableGpuAcceleration: z.boolean(), enableVisualEffects: z.boolean(), diff --git a/src-tauri/src/core/config.rs b/src-tauri/src/core/config.rs index d1f306a4..a376def7 100644 --- a/src-tauri/src/core/config.rs +++ b/src-tauri/src/core/config.rs @@ -85,7 +85,7 @@ pub struct LauncherConfig { pub java_path: String, pub width: u32, pub height: u32, - pub download_threads: u32, // concurrent download threads (1-128) + pub download_threads: u32, // concurrent download threads (1-64) pub custom_background_path: Option, pub enable_gpu_acceleration: bool, pub enable_visual_effects: bool, @@ -109,7 +109,7 @@ impl Default for LauncherConfig { java_path: "java".to_string(), width: 854, height: 480, - download_threads: 32, + download_threads: 8, custom_background_path: None, enable_gpu_acceleration: false, enable_visual_effects: true, @@ -125,6 +125,12 @@ impl Default for LauncherConfig { } } +impl LauncherConfig { + pub fn sanitize(&mut self) { + self.download_threads = self.download_threads.clamp(1, 64); + } +} + pub struct ConfigState { pub config: Mutex, pub file_path: PathBuf, @@ -137,7 +143,9 @@ impl ConfigState { let config = if config_path.exists() { let content = fs::read_to_string(&config_path).unwrap_or_default(); - serde_json::from_str(&content).unwrap_or_default() + let mut config: LauncherConfig = serde_json::from_str(&content).unwrap_or_default(); + config.sanitize(); + config } else { LauncherConfig::default() }; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 952d2501..72556f34 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1646,11 +1646,15 @@ async fn save_raw_config( content: String, ) -> Result<(), String> { // Validate JSON - let new_config: core::config::LauncherConfig = + let mut new_config: core::config::LauncherConfig = serde_json::from_str(&content).map_err(|e| format!("Invalid JSON: {}", e))?; + new_config.sanitize(); + + let normalized_content = + serde_json::to_string_pretty(&new_config).map_err(|e| format!("Invalid JSON: {}", e))?; // Save to file - tokio::fs::write(&state.file_path, &content) + tokio::fs::write(&state.file_path, &normalized_content) .await .map_err(|e| e.to_string())?; From 44c2c2b121ad7ea8cd2d258f30c19db50c5eb17e Mon Sep 17 00:00:00 2001 From: Craun718 <3653544699@qq.com> Date: Sat, 13 Jun 2026 17:50:47 +0800 Subject: [PATCH 2/2] refactor(config): extract download thread limits into shared constants --- packages/ui/src/components/config-editor.tsx | 6 +++++- packages/ui/src/lib/config.ts | 2 ++ packages/ui/src/pages/settings.tsx | 5 +++-- src-tauri/src/core/config.rs | 13 ++++++++++--- src-tauri/src/main.rs | 4 ++-- 5 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 packages/ui/src/lib/config.ts diff --git a/packages/ui/src/components/config-editor.tsx b/packages/ui/src/components/config-editor.tsx index b14ab942..18650673 100644 --- a/packages/ui/src/components/config-editor.tsx +++ b/packages/ui/src/components/config-editor.tsx @@ -1,6 +1,7 @@ import type React from "react"; import { useEffect, useState } from "react"; import { type ZodType, z } from "zod"; +import { MAX_DOWNLOAD_THREADS, MIN_DOWNLOAD_THREADS } from "@/lib/config"; import { useSettingsStore } from "@/models/settings"; import type { LauncherConfig } from "@/types"; import { Button } from "./ui/button"; @@ -22,7 +23,10 @@ const launcherConfigSchema: ZodType = z.object({ javaPath: z.string(), width: z.number(), height: z.number(), - downloadThreads: z.number().min(1).max(64), + downloadThreads: z + .number() + .min(MIN_DOWNLOAD_THREADS) + .max(MAX_DOWNLOAD_THREADS), customBackgroundPath: z.string().nullable(), enableGpuAcceleration: z.boolean(), enableVisualEffects: z.boolean(), diff --git a/packages/ui/src/lib/config.ts b/packages/ui/src/lib/config.ts new file mode 100644 index 00000000..ef24327c --- /dev/null +++ b/packages/ui/src/lib/config.ts @@ -0,0 +1,2 @@ +export const MIN_DOWNLOAD_THREADS = 1; +export const MAX_DOWNLOAD_THREADS = 64; diff --git a/packages/ui/src/pages/settings.tsx b/packages/ui/src/pages/settings.tsx index 9387e236..208c1025 100644 --- a/packages/ui/src/pages/settings.tsx +++ b/packages/ui/src/pages/settings.tsx @@ -31,6 +31,7 @@ import { import { Spinner } from "@/components/ui/spinner"; import { Switch } from "@/components/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { MAX_DOWNLOAD_THREADS, MIN_DOWNLOAD_THREADS } from "@/lib/config"; import { useJavaStore } from "@/models/java"; import { useSettingsStore } from "@/models/settings"; @@ -168,8 +169,8 @@ export function SettingsPage() { onBlur={() => { settings.save(); }} - min={1} - max={64} + min={MIN_DOWNLOAD_THREADS} + max={MAX_DOWNLOAD_THREADS} /> diff --git a/src-tauri/src/core/config.rs b/src-tauri/src/core/config.rs index a376def7..417b7744 100644 --- a/src-tauri/src/core/config.rs +++ b/src-tauri/src/core/config.rs @@ -5,6 +5,9 @@ use std::sync::Mutex; use tauri::{AppHandle, Manager}; use ts_rs::TS; +pub const MIN_DOWNLOAD_THREADS: u32 = 1; +pub const MAX_DOWNLOAD_THREADS: u32 = 64; + #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, export_to = "config.ts")] @@ -85,7 +88,8 @@ pub struct LauncherConfig { pub java_path: String, pub width: u32, pub height: u32, - pub download_threads: u32, // concurrent download threads (1-64) + /// Concurrent download threads. Clamped via MIN_DOWNLOAD_THREADS/MAX_DOWNLOAD_THREADS. + pub download_threads: u32, pub custom_background_path: Option, pub enable_gpu_acceleration: bool, pub enable_visual_effects: bool, @@ -127,7 +131,9 @@ impl Default for LauncherConfig { impl LauncherConfig { pub fn sanitize(&mut self) { - self.download_threads = self.download_threads.clamp(1, 64); + self.download_threads = + self.download_threads + .clamp(MIN_DOWNLOAD_THREADS, MAX_DOWNLOAD_THREADS); } } @@ -158,7 +164,8 @@ impl ConfigState { pub fn save(&self) -> Result<(), String> { let config = self.config.lock().unwrap(); - let content = serde_json::to_string_pretty(&*config).map_err(|e| e.to_string())?; + let content = serde_json::to_string_pretty(&*config) + .map_err(|e| format!("Failed to serialize config: {}", e))?; fs::create_dir_all(self.file_path.parent().unwrap()).map_err(|e| e.to_string())?; fs::write(&self.file_path, content).map_err(|e| e.to_string())?; Ok(()) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 72556f34..fec8f11d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1650,8 +1650,8 @@ async fn save_raw_config( serde_json::from_str(&content).map_err(|e| format!("Invalid JSON: {}", e))?; new_config.sanitize(); - let normalized_content = - serde_json::to_string_pretty(&new_config).map_err(|e| format!("Invalid JSON: {}", e))?; + let normalized_content = serde_json::to_string_pretty(&new_config) + .map_err(|e| format!("Failed to serialize config: {}", e))?; // Save to file tokio::fs::write(&state.file_path, &normalized_content)