195 lines
6.0 KiB
Rust
195 lines
6.0 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use tauri::{AppHandle, Manager, State};
|
|
use tauri_plugin_opener::OpenerExt;
|
|
|
|
use super::engine::{CheckUrlResult, DownloadEngine};
|
|
use super::task::{DownloadTask, DownloaderSettings};
|
|
use super::torrent::TorrentInfo;
|
|
|
|
/// 获取所有任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_get_tasks(engine: State<'_, DownloadEngine>) -> Vec<DownloadTask> {
|
|
engine.get_tasks()
|
|
}
|
|
|
|
/// 解析磁力链 / .torrent 文件,返回种子信息(名称 / infohash / 文件列表),供前端做文件勾选
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn downloader_inspect(engine: State<'_, DownloadEngine>, input: String) -> Result<TorrentInfo, String> {
|
|
engine.inspect(&input).await
|
|
}
|
|
|
|
/// 磁力任务:元数据解析成功后,用户勾选文件并确认开始下载
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn downloader_select_bt_files(engine: State<'_, DownloadEngine>, id: String, only_files: Vec<u32>) -> Result<(), String> {
|
|
engine.select_bt_files(&id, only_files).await
|
|
}
|
|
|
|
/// 检查 URL 重复性并探测文件信息(添加下载前调用)
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn downloader_check_url(
|
|
engine: State<'_, DownloadEngine>,
|
|
url: String,
|
|
dir: Option<String>,
|
|
headers: Option<HashMap<String, String>>,
|
|
) -> Result<CheckUrlResult, String> {
|
|
let headers = headers.unwrap_or_default();
|
|
let (probe, duplicate, existing) = engine.check_url(&url, dir.as_deref(), &headers).await;
|
|
let result = match probe {
|
|
Ok(p) => CheckUrlResult {
|
|
ok: true,
|
|
error: None,
|
|
filename: p.filename.clone(),
|
|
total_size: p.total_size,
|
|
supports_resume: p.supports_resume,
|
|
duplicate,
|
|
existing,
|
|
},
|
|
Err(e) => CheckUrlResult {
|
|
ok: false,
|
|
error: Some(e),
|
|
filename: None,
|
|
total_size: None,
|
|
supports_resume: false,
|
|
duplicate,
|
|
existing,
|
|
},
|
|
};
|
|
Ok(result)
|
|
}
|
|
|
|
/// 添加下载任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn downloader_add_task(
|
|
engine: State<'_, DownloadEngine>,
|
|
url: String,
|
|
filename: Option<String>,
|
|
dir: Option<String>,
|
|
headers: Option<HashMap<String, String>>,
|
|
auto_rename: Option<bool>,
|
|
only_files: Option<Vec<u32>>,
|
|
) -> Result<String, String> {
|
|
engine.add_task(url, filename, dir, headers.unwrap_or_default(), auto_rename.unwrap_or(false), only_files).await
|
|
}
|
|
|
|
/// 暂停任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_pause_task(engine: State<'_, DownloadEngine>, id: String) -> Result<(), String> {
|
|
engine.pause_task(&id)
|
|
}
|
|
|
|
/// 恢复任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_resume_task(engine: State<'_, DownloadEngine>, id: String) -> Result<(), String> {
|
|
engine.resume_task(&id)
|
|
}
|
|
|
|
/// 取消任务(置为已取消,清空进度并删除下载文件,但保留记录)
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_cancel_task(engine: State<'_, DownloadEngine>, id: String) -> Result<(), String> {
|
|
engine.cancel_task(&id)
|
|
}
|
|
|
|
/// 重新下载已取消/出错的任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn downloader_redownload(engine: State<'_, DownloadEngine>, id: String) -> Result<(), String> {
|
|
engine.redownload(&id).await
|
|
}
|
|
|
|
/// 移除任务
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_remove_task(
|
|
engine: State<'_, DownloadEngine>,
|
|
id: String,
|
|
delete_files: Option<bool>,
|
|
) -> Result<(), String> {
|
|
engine.remove_task(&id, delete_files.unwrap_or(false))
|
|
}
|
|
|
|
/// 获取设置
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_get_settings(engine: State<'_, DownloadEngine>) -> DownloaderSettings {
|
|
engine.get_settings()
|
|
}
|
|
|
|
/// 保存设置
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_save_settings(
|
|
engine: State<'_, DownloadEngine>,
|
|
settings: DownloaderSettings,
|
|
) -> Result<(), String> {
|
|
engine.save_settings(settings);
|
|
Ok(())
|
|
}
|
|
|
|
/// 引擎状态(始终运行中)
|
|
#[tauri::command]
|
|
pub fn downloader_status(engine: State<'_, DownloadEngine>) -> serde_json::Value {
|
|
serde_json::json!({
|
|
"running": engine.is_started(),
|
|
})
|
|
}
|
|
|
|
/// 获取扩展服务信息
|
|
#[tauri::command]
|
|
pub fn downloader_get_extension_info(engine: State<'_, DownloadEngine>) -> serde_json::Value {
|
|
let settings = engine.get_settings();
|
|
serde_json::json!({
|
|
"url": format!("http://127.0.0.1:{}/", settings.extension_port),
|
|
"port": settings.extension_port,
|
|
"secret": settings.extension_secret,
|
|
"hasSecret": !settings.extension_secret.is_empty(),
|
|
})
|
|
}
|
|
|
|
/// 用系统资源管理器打开目录
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_open_dir(app: AppHandle, path: String) -> Result<(), String> {
|
|
app.opener()
|
|
.open_path(path, None::<&str>)
|
|
.map_err(|e| format!("打开目录失败: {}", e))
|
|
}
|
|
|
|
/// 用系统默认浏览器打开 URL
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_open_url(app: AppHandle, url: String) -> Result<(), String> {
|
|
app.opener()
|
|
.open_url(url, None::<&str>)
|
|
.map_err(|e| format!("打开链接失败: {}", e))
|
|
}
|
|
|
|
/// 将指定 label 的下载窗口显示并强制置为前台。
|
|
/// Tauri 的 set_focus 在 Windows 上受前台锁定限制(尤其下载窗口由后台进程创建、
|
|
/// 或创建到非主显示器时更明显),改用原生 SetForegroundWindow + BringWindowToTop
|
|
/// (模拟 Alt 键重置前台锁定),保证开始/完成下载时窗口能正确定位到前台。
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn downloader_focus_window(app: AppHandle, label: String) -> Result<(), String> {
|
|
let Some(window) = app.get_webview_window(&label) else {
|
|
return Ok(()); // 窗口已关闭则忽略
|
|
};
|
|
window.show().map_err(|e| e.to_string())?;
|
|
window.unminimize().map_err(|e| e.to_string())?;
|
|
match window.hwnd() {
|
|
Ok(hwnd) => crate::win32_util::force_foreground(hwnd.0 as isize),
|
|
Err(_) => {
|
|
window.set_focus().ok();
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|