fast_down_gui/core/
start.rs1use crate::{
2 core::{App, download},
3 persist::{self, DatabaseEntry},
4 ui::{DownloadConfig, EntryData, Status},
5 utils::{ForceSendExt, LogErr},
6};
7use fast_down_ffi::FileId;
8use slint::{SharedString, ToSharedString, VecModel};
9use std::{path::PathBuf, time::Duration};
10use tokio_util::sync::CancellationToken;
11use tracing::{error, info};
12use url::Url;
13
14pub fn start_entry(app: &App, entry: &EntryData, list: &VecModel<EntryData>) -> bool {
16 if matches!(entry.status, Status::Running | Status::Waiting) {
17 return false;
18 }
19 let gid = entry.gid;
20 let Some(db_entry) = app.db.inner.data.get(&gid).map(|e| e.clone()) else {
21 return false;
22 };
23 let url = db_entry.url.clone();
24 let config = db_entry.config.to_ui_download_config();
25 if db_entry.status == persist::Status::Completed {
26 start_new_entry(app, url, &config, list);
27 return false;
28 }
29 let app_c = app.clone();
30 let cancel_token = CancellationToken::new();
31 let token = cancel_token.clone();
32 let fut = async move {
33 app_c.update_ui_row(gid, move |_, data| data.error = SharedString::new());
34 let handler = app_c.create_download_handler(gid);
35 match download(url, &config, token, Some(db_entry), handler).await {
36 Ok(()) => info!(gid = gid, "任务下载完成"),
37 Err(e) => {
38 error!(gid = gid, err = ?e, "下载任务出错");
39 app_c.db.update_status(gid, persist::Status::Error);
40 app_c.update_ui_row(gid, move |_, data| {
41 data.status = Status::Error;
42 data.error = e.to_shared_string();
43 });
44 }
45 }
46 }
47 .force_send();
48 app.task_set.add_task(gid, cancel_token, fut);
49 true
50}
51
52pub fn start_new_entry(
53 app: &App,
54 url: Url,
55 config: &DownloadConfig,
56 list_model: &VecModel<EntryData>,
57) {
58 let gid = app.db.next_gid();
59 let entry = DatabaseEntry {
60 file_name: url.to_string(),
61 file_path: PathBuf::new(),
62 file_size: 0,
63 file_id: FileId::default(),
64 progress: Vec::new(),
65 elapsed: Duration::ZERO,
66 url: url.clone(),
67 config: config.into(),
68 status: persist::Status::Paused,
69 };
70 let mut ui_entry = entry.to_entry_data(gid);
71 ui_entry.status = Status::Waiting;
72 list_model.push(ui_entry);
73 let _ = app.db.init_entry(gid, entry).log_err("数据库插入条目失败");
74
75 let app_c = app.clone();
76 let cancel_token = CancellationToken::new();
77 let token = cancel_token.clone();
78 let config = config.clone();
79
80 let fut = async move {
81 let handler = app_c.create_download_handler(gid);
82 match download(url, &config, token, None, handler).await {
83 Ok(()) => info!(gid = gid, "任务下载完成"),
84 Err(e) => {
85 error!(gid = gid, err = ?e, "下载任务出错");
86 app_c.db.update_status(gid, persist::Status::Error);
87 app_c.update_ui_row(gid, move |_, data| {
88 data.status = Status::Error;
89 data.error = e.to_shared_string();
90 });
91 }
92 }
93 }
94 .force_send();
95 app.task_set.add_task(gid, cancel_token, fut);
96}