✨ 添加收藏和下载队列
This commit is contained in:
153
src-tauri/src/handlers/download.rs
Normal file
153
src-tauri/src/handlers/download.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
use crate::models::download::{DownloadStatus, DownloadTask};
|
||||
use tauri::State;
|
||||
use std::sync::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use crate::handlers::server::get_json_server_url;
|
||||
use crate::utils::{format_icon_url, UA};
|
||||
|
||||
pub type DownloadQueue = Mutex<HashMap<String, DownloadTask>>;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_downloads(queue: State<'_, DownloadQueue>) -> Result<Vec<DownloadTask>, String> {
|
||||
let downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
Ok(downloads.values().cloned().collect())
|
||||
}
|
||||
|
||||
// 检查是否有正在下载的任务
|
||||
fn has_downloading_task(downloads: &HashMap<String, DownloadTask>) -> bool {
|
||||
downloads.values().any(|task| matches!(task.status, DownloadStatus::Downloading))
|
||||
}
|
||||
|
||||
// 获取下一个等待下载的任务
|
||||
fn get_next_queued_task(downloads: &mut HashMap<String, DownloadTask>) -> Option<String> {
|
||||
downloads
|
||||
.iter()
|
||||
.find(|(_, task)| matches!(task.status, DownloadStatus::Queued))
|
||||
.map(|(task_id, _)| task_id.clone())
|
||||
}
|
||||
|
||||
// 开始下载下一个任务
|
||||
fn start_next_download(downloads: &mut HashMap<String, DownloadTask>) {
|
||||
if let Some(task_id) = get_next_queued_task(downloads) {
|
||||
if let Some(task) = downloads.get_mut(&task_id) {
|
||||
task.status = DownloadStatus::Downloading;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn add_download(category: String, pkgname: String, filename:String, name:String, queue: State<'_, DownloadQueue>) -> Result<(), String> {
|
||||
let task_id = format!("{}/{}", category, pkgname);
|
||||
|
||||
// 检查任务是否已存在
|
||||
{
|
||||
let downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
if downloads.contains_key(&task_id) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取metalink文件URL
|
||||
let json_server_url = get_json_server_url();
|
||||
let metalink_url = format!("{}{}/{}/{}.metalink", json_server_url, category, pkgname, filename);
|
||||
// 发送请求获取metalink文件
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
.get(&metalink_url)
|
||||
.header("User-Agent", UA)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("获取metalink文件失败: {}", e))?;
|
||||
|
||||
// 检查响应状态
|
||||
if !response.status().is_success() {
|
||||
return Err(format!("获取metalink文件失败: HTTP {}", response.status()));
|
||||
}
|
||||
|
||||
let mut downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
let initial_status = if has_downloading_task(&downloads) {
|
||||
DownloadStatus::Queued
|
||||
} else {
|
||||
DownloadStatus::Downloading
|
||||
};
|
||||
|
||||
// 创建下载任务
|
||||
let task = DownloadTask {
|
||||
category: category.clone(),
|
||||
pkgname: pkgname.clone(),
|
||||
filename,
|
||||
name,
|
||||
icon: format_icon_url(&category, &pkgname),
|
||||
status: initial_status,
|
||||
progress: 0.0,
|
||||
speed: None,
|
||||
size: None,
|
||||
};
|
||||
|
||||
// 添加任务到队列
|
||||
downloads.insert(task_id, task);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn pause_download(category: String, pkgname: String, queue: State<'_, DownloadQueue>) -> Result<(), String> {
|
||||
let mut downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
let task_id = format!("{}/{}", category, pkgname);
|
||||
|
||||
if let Some(task) = downloads.get_mut(&task_id) {
|
||||
let old_status = task.status.clone();
|
||||
task.status = DownloadStatus::Paused;
|
||||
if matches!(old_status, DownloadStatus::Downloading) {
|
||||
start_next_download(&mut downloads);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn resume_download(category: String, pkgname: String, queue: State<'_, DownloadQueue>) -> Result<(), String> {
|
||||
let mut downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
let task_id = format!("{}/{}", category, pkgname);
|
||||
|
||||
// 先检查任务是否存在且处于暂停状态
|
||||
let should_resume = downloads
|
||||
.get(&task_id)
|
||||
.map(|task| matches!(task.status, DownloadStatus::Paused))
|
||||
.unwrap_or(false);
|
||||
|
||||
if should_resume {
|
||||
// 检查是否有其他正在下载的任务
|
||||
let has_downloading = has_downloading_task(&downloads);
|
||||
|
||||
// 更新任务状态
|
||||
if let Some(task) = downloads.get_mut(&task_id) {
|
||||
task.status = if has_downloading {
|
||||
DownloadStatus::Queued
|
||||
} else {
|
||||
DownloadStatus::Downloading
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn cancel_download(category: String, pkgname: String, queue: State<'_, DownloadQueue>) -> Result<(), String> {
|
||||
let mut downloads = queue.lock().map_err(|e| e.to_string())?;
|
||||
let task_id = format!("{}/{}", category, pkgname);
|
||||
|
||||
let was_downloading = downloads
|
||||
.get(&task_id)
|
||||
.map(|task| matches!(task.status, DownloadStatus::Downloading))
|
||||
.unwrap_or(false);
|
||||
|
||||
downloads.remove(&task_id);
|
||||
|
||||
if was_downloading {
|
||||
start_next_download(&mut downloads);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
22
src-tauri/src/handlers/file.rs
Normal file
22
src-tauri/src/handlers/file.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use std::fs;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn save_text_file(filename: String, content: String) -> Result<(), String> {
|
||||
let config_dir = dirs::config_dir().ok_or("无法获取配置目录")?;
|
||||
let dir = config_dir.join(env!("CARGO_PKG_NAME"));
|
||||
|
||||
// 确保目录存在
|
||||
fs::create_dir_all(&dir).map_err(|e| format!("创建目录失败: {}", e))?;
|
||||
|
||||
let file_path = dir.join(filename);
|
||||
fs::write(file_path, content).map_err(|e| format!("写入文件失败: {}", e))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn read_text_file(filename: String) -> Result<String, String> {
|
||||
let config_dir = dirs::config_dir().ok_or("无法获取配置目录")?;
|
||||
let dir = config_dir.join(env!("CARGO_PKG_NAME"));
|
||||
let file_path = dir.join(filename);
|
||||
|
||||
fs::read_to_string(file_path).map_err(|e| format!("读取文件失败: {}", e))
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
pub mod category;
|
||||
pub mod server;
|
||||
pub mod app;
|
||||
pub mod home;
|
||||
pub mod home;
|
||||
pub mod file;
|
||||
pub mod download;
|
||||
@@ -7,6 +7,7 @@ pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_clipboard_manager::init())
|
||||
.manage(handlers::download::DownloadQueue::default())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
handlers::category::get_all_categories,
|
||||
handlers::category::get_category_apps,
|
||||
@@ -19,6 +20,13 @@ pub fn run() {
|
||||
handlers::home::get_home_links,
|
||||
handlers::home::get_home_lists,
|
||||
handlers::home::get_home_list_apps,
|
||||
handlers::file::read_text_file,
|
||||
handlers::file::save_text_file,
|
||||
handlers::download::get_downloads,
|
||||
handlers::download::add_download,
|
||||
handlers::download::pause_download,
|
||||
handlers::download::resume_download,
|
||||
handlers::download::cancel_download,
|
||||
utils::get_user_agent,
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
|
||||
24
src-tauri/src/models/download.rs
Normal file
24
src-tauri/src/models/download.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct DownloadTask {
|
||||
pub category: String,
|
||||
pub pkgname: String,
|
||||
pub filename: String,
|
||||
pub status: DownloadStatus,
|
||||
pub progress: f32,
|
||||
pub icon: String,
|
||||
pub name: String,
|
||||
pub speed: Option<String>,
|
||||
pub size: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum DownloadStatus {
|
||||
Downloading,
|
||||
Queued,
|
||||
Paused,
|
||||
Completed,
|
||||
Error,
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod category;
|
||||
pub mod app;
|
||||
pub mod home;
|
||||
pub mod home;
|
||||
pub mod download;
|
||||
Reference in New Issue
Block a user