mirror of
https://github.com/nimbold/Firelink.git
synced 2026-07-26 12:08:27 +00:00
fix: implement aria2 polling to prevent UI from sticking on queued
This commit is contained in:
@@ -577,7 +577,7 @@ fn build_client(payload: &DownloadPayload) -> Result<Client, String> {
|
||||
builder.build().map_err(|error| error.to_string())
|
||||
}
|
||||
|
||||
fn format_speed(bytes_per_second: f64) -> String {
|
||||
pub(crate) fn format_speed(bytes_per_second: f64) -> String {
|
||||
if bytes_per_second >= 1024.0 * 1024.0 {
|
||||
format!("{:.1} MB/s", bytes_per_second / (1024.0 * 1024.0))
|
||||
} else if bytes_per_second >= 1024.0 {
|
||||
@@ -587,7 +587,7 @@ fn format_speed(bytes_per_second: f64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn format_size(bytes: f64) -> String {
|
||||
pub(crate) fn format_size(bytes: f64) -> String {
|
||||
if bytes >= 1024.0 * 1024.0 * 1024.0 {
|
||||
format!("{:.2} GB", bytes / (1024.0 * 1024.0 * 1024.0))
|
||||
} else if bytes >= 1024.0 * 1024.0 {
|
||||
@@ -599,7 +599,7 @@ fn format_size(bytes: f64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn format_duration(seconds: f64) -> String {
|
||||
pub(crate) fn format_duration(seconds: f64) -> String {
|
||||
if seconds >= 3600.0 {
|
||||
format!("{:.0}h {:.0}m", seconds / 3600.0, (seconds % 3600.0) / 60.0)
|
||||
} else if seconds >= 60.0 {
|
||||
|
||||
+80
-2
@@ -686,11 +686,20 @@ async fn start_download(
|
||||
options
|
||||
]);
|
||||
|
||||
rpc_call(state.aria2_port, &state.aria2_secret, "aria2.addUri", params)
|
||||
let result = rpc_call(state.aria2_port, &state.aria2_secret, "aria2.addUri", params)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|e| AppError::Internal(e))?;
|
||||
|
||||
let gid = result.as_str().unwrap_or("").to_string();
|
||||
|
||||
let port = state.aria2_port;
|
||||
let secret = state.aria2_secret.clone();
|
||||
let app_handle_clone = app_handle.clone();
|
||||
let id_clone = id.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
poll_aria2(app_handle_clone, port, secret, id_clone, gid).await;
|
||||
});
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
state
|
||||
@@ -1573,3 +1582,72 @@ async fn db_delete_queue(state: tauri::State<'_, crate::db::DbState>, id: String
|
||||
let conn = state.conn.lock().await;
|
||||
crate::db::delete_queue(&conn, &id).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
async fn poll_aria2(app_handle: tauri::AppHandle, port: u16, secret: String, id: String, gid: String) {
|
||||
use tauri::Emitter;
|
||||
let mut interval = tokio::time::interval(std::time::Duration::from_millis(1000));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
let params = serde_json::json!([gid, ["status", "totalLength", "completedLength", "downloadSpeed", "errorMessage"]]);
|
||||
match rpc_call(port, &secret, "aria2.tellStatus", params).await {
|
||||
Ok(status_info) => {
|
||||
let status = status_info.get("status").and_then(|s| s.as_str()).unwrap_or("");
|
||||
if status == "active" || status == "waiting" || status == "paused" {
|
||||
let total_str = status_info.get("totalLength").and_then(|s| s.as_str()).unwrap_or("0");
|
||||
let completed_str = status_info.get("completedLength").and_then(|s| s.as_str()).unwrap_or("0");
|
||||
let speed_str = status_info.get("downloadSpeed").and_then(|s| s.as_str()).unwrap_or("0");
|
||||
|
||||
let total = total_str.parse::<u64>().unwrap_or(0);
|
||||
let completed = completed_str.parse::<u64>().unwrap_or(0);
|
||||
let speed_bytes = speed_str.parse::<f64>().unwrap_or(0.0);
|
||||
|
||||
let fraction = if total > 0 { completed as f64 / total as f64 } else { 0.0 };
|
||||
|
||||
let speed = crate::download::format_speed(speed_bytes);
|
||||
let eta = if speed_bytes > 0.0 && total > completed {
|
||||
crate::download::format_duration((total - completed) as f64 / speed_bytes)
|
||||
} else {
|
||||
"-".to_string()
|
||||
};
|
||||
|
||||
let size = if total > 0 {
|
||||
Some(crate::download::format_size(total as f64))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let _ = app_handle.emit("download-progress", serde_json::json!({
|
||||
"id": id,
|
||||
"fraction": fraction,
|
||||
"speed": speed,
|
||||
"eta": eta,
|
||||
"size": size
|
||||
}));
|
||||
} else if status == "complete" {
|
||||
let _ = app_handle.emit("download-complete", id);
|
||||
break;
|
||||
} else if status == "error" {
|
||||
let err = status_info.get("errorMessage").and_then(|s| s.as_str()).unwrap_or("aria2 error").to_string();
|
||||
let _ = app_handle.emit("download-failed", serde_json::json!({
|
||||
"id": id,
|
||||
"error": err
|
||||
}));
|
||||
break;
|
||||
} else if status == "removed" {
|
||||
let _ = app_handle.emit("download-failed", serde_json::json!({
|
||||
"id": id,
|
||||
"error": "Removed from aria2"
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = app_handle.emit("download-failed", serde_json::json!({
|
||||
"id": id,
|
||||
"error": format!("RPC error: {}", e)
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user