fast_down_gui/core/
app.rs1use crate::{
2 core::{DownloadEvent, TaskSet, apply_progress_diff},
3 fmt::format_size,
4 persist::{self, Database},
5 ui::{self, EntryData, MainWindow},
6 utils::LogErr,
7};
8use slint::{Model, Weak};
9
10#[derive(Clone)]
11pub struct App {
12 pub db: Database,
13 pub task_set: TaskSet<i32>,
14 pub ui: Weak<MainWindow>,
15}
16
17impl App {
18 pub fn update_ui_row<F>(&self, gid: i32, mutator: F)
19 where
20 F: FnOnce(usize, &mut EntryData) + Send + 'static,
21 {
22 let _ = self.ui.upgrade_in_event_loop(move |ui| {
23 let list_model = ui.get_all_list();
24 for (row, mut data) in list_model.iter().enumerate() {
25 if data.gid == gid {
26 mutator(row, &mut data);
27 list_model.set_row_data(row, data);
28 break;
29 }
30 }
31 });
32 }
33
34 pub fn create_download_handler(
36 &self,
37 gid: i32,
38 ) -> impl FnMut(DownloadEvent) + Send + Sync + 'static {
39 let app = self.clone();
40 let mut file_size = 0;
41 move |event| match event {
42 DownloadEvent::Info(info) => {
43 file_size = info.file_size;
44 let _ = app
45 .db
46 .init_entry(gid, *info.clone())
47 .log_err("数据库插入条目失败");
48 app.update_ui_row(gid, move |_, data| {
49 data.status = ui::Status::Running;
50 data.filename = info.file_name.into();
51 data.path = info.file_path.to_string_lossy().as_ref().into();
52 data.total = format_size(info.file_size as f64).into();
53 });
54 }
55 DownloadEvent::Progress(p) => {
56 app.db.update_entry(gid, p.progress.clone(), p.elapsed);
57 app.update_ui_row(gid, move |_, data| {
58 data.downloaded = p.downloaded;
59 data.speed = p.speed;
60 data.avg_speed = p.avg_speed;
61 data.percentage = p.percentage;
62 data.remaining_time = p.remaining_time;
63 data.remaining_size = p.remaining_size;
64 data.time = p.time;
65 if file_size > 0 {
66 data.progress = apply_progress_diff(&data.progress, &p.progress, file_size);
67 }
68 });
69 }
70 DownloadEvent::End { is_cancelled } => {
71 let db_status = if is_cancelled {
72 persist::Status::Paused
73 } else {
74 persist::Status::Completed
75 };
76 let ui_status = if is_cancelled {
77 ui::Status::Paused
78 } else {
79 ui::Status::Completed
80 };
81 app.db.update_status(gid, db_status);
82 app.update_ui_row(gid, move |_, data| data.status = ui_status);
83 }
84 }
85 }
86}