feat: improve sync workspace and updater stability in 0.1.27
This commit is contained in:
2
desktop-client/src-tauri/Cargo.lock
generated
2
desktop-client/src-tauri/Cargo.lock
generated
@@ -693,7 +693,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "desktop-client"
|
||||
version = "0.1.26"
|
||||
version = "0.1.27"
|
||||
dependencies = [
|
||||
"reqwest 0.12.28",
|
||||
"rusqlite",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "desktop-client"
|
||||
version = "0.1.26"
|
||||
version = "0.1.27"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -12,6 +12,8 @@ use std::io::{Read, Seek, SeekFrom};
|
||||
use std::os::windows::process::CommandExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::process::Stdio;
|
||||
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
|
||||
use tauri::Emitter;
|
||||
use tokio::time::sleep;
|
||||
@@ -25,6 +27,10 @@ use windows_sys::Win32::Foundation::LocalFree;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
#[cfg(target_os = "windows")]
|
||||
const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
|
||||
#[cfg(target_os = "windows")]
|
||||
const DETACHED_PROCESS: u32 = 0x00000008;
|
||||
const RESUMABLE_CHUNK_MAX_RETRIES: u32 = 3;
|
||||
const RESUMABLE_CHUNK_RETRY_BASE_DELAY_MS: u64 = 900;
|
||||
|
||||
@@ -440,6 +446,61 @@ fn build_download_resume_temp_path(download_dir: &Path, preferred_name: &str, ur
|
||||
download_dir.join(temp_name)
|
||||
}
|
||||
|
||||
fn is_update_installer_file_name(file_name: &str) -> bool {
|
||||
let lower = file_name.trim().to_ascii_lowercase();
|
||||
if !lower.ends_with(".exe") {
|
||||
return false;
|
||||
}
|
||||
lower.starts_with("wanwan-cloud-desktop_v") || file_name.trim().starts_with("玩玩云_v")
|
||||
}
|
||||
|
||||
fn cleanup_old_update_installers(
|
||||
download_dir: &Path,
|
||||
keep_file_name: &str,
|
||||
keep_latest: usize,
|
||||
) -> Result<(), String> {
|
||||
let mut entries: Vec<(PathBuf, SystemTime)> = Vec::new();
|
||||
let normalized_keep = keep_file_name.trim();
|
||||
for entry in fs::read_dir(download_dir).map_err(|err| format!("扫描下载目录失败: {}", err))? {
|
||||
let path = match entry {
|
||||
Ok(item) => item.path(),
|
||||
Err(_) => continue,
|
||||
};
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
let Some(file_name) = path.file_name().and_then(|name| name.to_str()) else {
|
||||
continue;
|
||||
};
|
||||
if !is_update_installer_file_name(file_name) {
|
||||
continue;
|
||||
}
|
||||
let modified = fs::metadata(&path)
|
||||
.ok()
|
||||
.and_then(|meta| meta.modified().ok())
|
||||
.unwrap_or(SystemTime::UNIX_EPOCH);
|
||||
entries.push((path, modified));
|
||||
}
|
||||
|
||||
entries.sort_by(|a, b| b.1.cmp(&a.1));
|
||||
let retain_count = keep_latest.max(1);
|
||||
let mut retained = 0usize;
|
||||
for (path, _) in entries {
|
||||
let file_name = path
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.unwrap_or_default()
|
||||
.to_string();
|
||||
let should_keep = file_name == normalized_keep || retained < retain_count;
|
||||
if should_keep {
|
||||
retained += 1;
|
||||
continue;
|
||||
}
|
||||
let _ = fs::remove_file(&path);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resolve_local_state_dir() -> PathBuf {
|
||||
if let Some(appdata) = env::var_os("APPDATA") {
|
||||
return PathBuf::from(appdata).join("wanwan-cloud-desktop");
|
||||
@@ -502,10 +563,17 @@ fn load_login_state_record() -> Result<Option<(String, String, String)>, String>
|
||||
record.get::<_, String>(2)?,
|
||||
))
|
||||
});
|
||||
drop(stmt);
|
||||
match row {
|
||||
Ok((base_url, username, password)) => {
|
||||
let decoded_password = decode_login_password(&password)?;
|
||||
Ok(Some((base_url, username, decoded_password)))
|
||||
match decode_login_password(&password) {
|
||||
Ok(decoded_password) => Ok(Some((base_url, username, decoded_password))),
|
||||
Err(err) => {
|
||||
eprintln!("decode login state failed, clearing invalid state: {}", err);
|
||||
let _ = conn.execute("DELETE FROM login_state WHERE id = 1", []);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
|
||||
Err(err) => Err(format!("读取登录状态失败: {}", err)),
|
||||
@@ -1124,6 +1192,11 @@ async fn api_native_download(
|
||||
let save_path = alloc_download_path(&download_dir, preferred_name);
|
||||
fs::rename(&resume_temp_path, &save_path)
|
||||
.map_err(|err| format!("完成断点下载失败: {}", err))?;
|
||||
if let Some(saved_name) = save_path.file_name().and_then(|name| name.to_str()) {
|
||||
if is_update_installer_file_name(saved_name) {
|
||||
let _ = cleanup_old_update_installers(&download_dir, saved_name, 3);
|
||||
}
|
||||
}
|
||||
if let Some(ref id) = task_id {
|
||||
emit_native_download_progress(
|
||||
&window,
|
||||
@@ -1232,6 +1305,11 @@ async fn api_native_download(
|
||||
let save_path = alloc_download_path(&download_dir, preferred_name);
|
||||
fs::rename(&resume_temp_path, &save_path)
|
||||
.map_err(|err| format!("保存下载文件失败: {}", err))?;
|
||||
if let Some(saved_name) = save_path.file_name().and_then(|name| name.to_str()) {
|
||||
if is_update_installer_file_name(saved_name) {
|
||||
let _ = cleanup_old_update_installers(&download_dir, saved_name, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref id) = task_id {
|
||||
emit_native_download_progress(
|
||||
@@ -1419,7 +1497,10 @@ del \"%~f0\" >nul 2>nul\r\n",
|
||||
.arg("call")
|
||||
.arg(&script_path)
|
||||
.current_dir(&temp_dir)
|
||||
.creation_flags(CREATE_NO_WINDOW)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.creation_flags(CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS)
|
||||
.spawn();
|
||||
if let Err(err) = spawn_result {
|
||||
let _ = fs::OpenOptions::new()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "玩玩云",
|
||||
"version": "0.1.26",
|
||||
"version": "0.1.27",
|
||||
"identifier": "cn.workyai.wanwancloud.desktop",
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
|
||||
Reference in New Issue
Block a user