mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-29 03:57:11 +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())
|
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 {
|
if bytes_per_second >= 1024.0 * 1024.0 {
|
||||||
format!("{:.1} MB/s", 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 {
|
} 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 {
|
if bytes >= 1024.0 * 1024.0 * 1024.0 {
|
||||||
format!("{:.2} GB", bytes / (1024.0 * 1024.0 * 1024.0))
|
format!("{:.2} GB", bytes / (1024.0 * 1024.0 * 1024.0))
|
||||||
} else if bytes >= 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 {
|
if seconds >= 3600.0 {
|
||||||
format!("{:.0}h {:.0}m", seconds / 3600.0, (seconds % 3600.0) / 60.0)
|
format!("{:.0}h {:.0}m", seconds / 3600.0, (seconds % 3600.0) / 60.0)
|
||||||
} else if seconds >= 60.0 {
|
} else if seconds >= 60.0 {
|
||||||
|
|||||||
+80
-2
@@ -686,11 +686,20 @@ async fn start_download(
|
|||||||
options
|
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
|
.await
|
||||||
.map(|_| ())
|
|
||||||
.map_err(|e| AppError::Internal(e))?;
|
.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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
@@ -1573,3 +1582,72 @@ async fn db_delete_queue(state: tauri::State<'_, crate::db::DbState>, id: String
|
|||||||
let conn = state.conn.lock().await;
|
let conn = state.conn.lock().await;
|
||||||
crate::db::delete_queue(&conn, &id).map_err(|e| e.to_string())
|
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