2026-02-24 00:51:25 +09:00
|
|
|
mod engine;
|
2026-02-25 01:40:52 +09:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::io::Write;
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
use tauri::Manager;
|
2026-02-24 00:51:25 +09:00
|
|
|
|
|
|
|
|
use engine::{
|
2026-02-25 01:40:52 +09:00
|
|
|
aria2_add_torrent, aria2_add_uri, aria2_change_global_option, aria2_get_task_detail,
|
|
|
|
|
aria2_list_tasks, aria2_pause_all, aria2_pause_task, aria2_remove_task,
|
|
|
|
|
aria2_remove_task_record, aria2_resume_all, aria2_resume_task, detect_aria2_binary,
|
|
|
|
|
engine_start, engine_status, engine_stop,
|
|
|
|
|
load_torrent_file,
|
|
|
|
|
open_path_in_file_manager, stop_engine_for_exit, EngineState,
|
2026-02-24 00:51:25 +09:00
|
|
|
};
|
|
|
|
|
|
2026-02-25 01:40:52 +09:00
|
|
|
#[tauri::command]
|
|
|
|
|
async fn focus_main_window(app: tauri::AppHandle) -> Result<(), String> {
|
|
|
|
|
let window = app
|
|
|
|
|
.get_webview_window("main")
|
|
|
|
|
.ok_or_else(|| "메인 창을 찾을 수 없습니다.".to_string())?;
|
|
|
|
|
|
|
|
|
|
window
|
|
|
|
|
.show()
|
|
|
|
|
.map_err(|error| format!("창 표시 실패: {error}"))?;
|
|
|
|
|
window
|
|
|
|
|
.unminimize()
|
|
|
|
|
.map_err(|error| format!("창 복원 실패: {error}"))?;
|
|
|
|
|
window
|
|
|
|
|
.set_focus()
|
|
|
|
|
.map_err(|error| format!("창 포커스 실패: {error}"))?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
|
struct ExternalAddRequest {
|
|
|
|
|
url: String,
|
|
|
|
|
out: Option<String>,
|
|
|
|
|
dir: Option<String>,
|
|
|
|
|
referer: Option<String>,
|
|
|
|
|
user_agent: Option<String>,
|
|
|
|
|
authorization: Option<String>,
|
|
|
|
|
cookie: Option<String>,
|
|
|
|
|
proxy: Option<String>,
|
|
|
|
|
split: Option<u32>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn external_add_queue_path() -> Result<PathBuf, String> {
|
|
|
|
|
let home = std::env::var("HOME").map_err(|err| format!("HOME 경로 확인 실패: {err}"))?;
|
|
|
|
|
Ok(PathBuf::from(home).join(".gdown").join("external_add_queue.jsonl"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tauri::command]
|
|
|
|
|
fn take_external_add_requests() -> Result<Vec<ExternalAddRequest>, String> {
|
|
|
|
|
let path = external_add_queue_path()?;
|
|
|
|
|
let parent = path
|
|
|
|
|
.parent()
|
|
|
|
|
.ok_or_else(|| "큐 디렉터리 경로를 계산할 수 없습니다.".to_string())?;
|
|
|
|
|
fs::create_dir_all(parent).map_err(|err| format!("큐 디렉터리 생성 실패: {err}"))?;
|
|
|
|
|
|
|
|
|
|
if !path.exists() {
|
|
|
|
|
return Ok(Vec::new());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let content = fs::read_to_string(&path).map_err(|err| format!("큐 읽기 실패: {err}"))?;
|
|
|
|
|
let mut requests: Vec<ExternalAddRequest> = Vec::new();
|
|
|
|
|
for line in content.lines() {
|
|
|
|
|
let trimmed = line.trim();
|
|
|
|
|
if trimmed.is_empty() {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if let Ok(item) = serde_json::from_str::<ExternalAddRequest>(trimmed) {
|
|
|
|
|
requests.push(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut file = fs::OpenOptions::new()
|
|
|
|
|
.write(true)
|
|
|
|
|
.truncate(true)
|
|
|
|
|
.open(&path)
|
|
|
|
|
.map_err(|err| format!("큐 초기화 실패: {err}"))?;
|
|
|
|
|
file
|
|
|
|
|
.write_all(b"")
|
|
|
|
|
.map_err(|err| format!("큐 파일 쓰기 실패: {err}"))?;
|
|
|
|
|
|
|
|
|
|
Ok(requests)
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 00:51:25 +09:00
|
|
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
|
|
|
pub fn run() {
|
|
|
|
|
tauri::Builder::default()
|
|
|
|
|
.manage(EngineState::default())
|
2026-02-24 12:00:30 +09:00
|
|
|
.plugin(tauri_plugin_dialog::init())
|
2026-02-25 01:40:52 +09:00
|
|
|
.plugin(tauri_plugin_deep_link::init())
|
|
|
|
|
.on_window_event(|window, event| {
|
|
|
|
|
if let tauri::WindowEvent::CloseRequested { .. } = event {
|
|
|
|
|
if window.label() == "main" {
|
|
|
|
|
let state = window.state::<EngineState>();
|
|
|
|
|
stop_engine_for_exit(&state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
2026-02-24 00:51:25 +09:00
|
|
|
.setup(|app| {
|
|
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
|
app.handle().plugin(
|
|
|
|
|
tauri_plugin_log::Builder::default()
|
|
|
|
|
.level(log::LevelFilter::Info)
|
|
|
|
|
.build(),
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
})
|
|
|
|
|
.invoke_handler(tauri::generate_handler![
|
|
|
|
|
engine_start,
|
|
|
|
|
engine_stop,
|
|
|
|
|
engine_status,
|
2026-02-24 12:00:30 +09:00
|
|
|
detect_aria2_binary,
|
2026-02-24 00:51:25 +09:00
|
|
|
aria2_add_torrent,
|
|
|
|
|
aria2_add_uri,
|
2026-02-25 01:40:52 +09:00
|
|
|
aria2_change_global_option,
|
|
|
|
|
aria2_get_task_detail,
|
2026-02-24 00:51:25 +09:00
|
|
|
aria2_list_tasks,
|
2026-02-24 12:00:30 +09:00
|
|
|
aria2_pause_task,
|
|
|
|
|
aria2_resume_task,
|
|
|
|
|
aria2_remove_task,
|
|
|
|
|
aria2_remove_task_record,
|
|
|
|
|
aria2_pause_all,
|
|
|
|
|
aria2_resume_all,
|
|
|
|
|
load_torrent_file,
|
2026-02-25 01:40:52 +09:00
|
|
|
open_path_in_file_manager,
|
|
|
|
|
focus_main_window,
|
|
|
|
|
take_external_add_requests
|
2026-02-24 00:51:25 +09:00
|
|
|
])
|
|
|
|
|
.run(tauri::generate_context!())
|
|
|
|
|
.expect("error while running tauri application");
|
|
|
|
|
}
|