1
1
use indicatif:: { MultiProgress , ProgressBar , ProgressDrawTarget , ProgressStyle } ;
2
- use std:: time :: Duration ;
2
+ use std:: collections :: HashMap ;
3
3
4
4
use crate :: dist:: Notification as In ;
5
5
use crate :: notifications:: Notification ;
@@ -13,8 +13,8 @@ use crate::utils::Notification as Un;
13
13
pub ( crate ) struct DownloadTracker {
14
14
/// MultiProgress bar for the downloads.
15
15
multi_progress_bars : MultiProgress ,
16
- /// ProgressBar for the current download .
17
- progress_bar : ProgressBar ,
16
+ /// Mapping of files to their corresponding progress bars .
17
+ file_progress_bars : HashMap < String , ProgressBar > ,
18
18
}
19
19
20
20
impl DownloadTracker {
@@ -28,22 +28,29 @@ impl DownloadTracker {
28
28
29
29
Self {
30
30
multi_progress_bars,
31
- progress_bar : ProgressBar :: hidden ( ) ,
31
+ file_progress_bars : HashMap :: new ( ) ,
32
32
}
33
33
}
34
34
35
35
pub ( crate ) fn handle_notification ( & mut self , n : & Notification < ' _ > ) -> bool {
36
36
match * n {
37
- Notification :: Install ( In :: Utils ( Un :: DownloadContentLengthReceived ( content_len) ) ) => {
38
- self . content_length_received ( content_len) ;
37
+ Notification :: Install ( In :: Utils ( Un :: DownloadContentLengthReceived (
38
+ content_len,
39
+ file,
40
+ ) ) ) => {
41
+ self . content_length_received ( content_len, file) ;
39
42
true
40
43
}
41
- Notification :: Install ( In :: Utils ( Un :: DownloadDataReceived ( data) ) ) => {
42
- self . data_received ( data. len ( ) ) ;
44
+ Notification :: Install ( In :: Utils ( Un :: DownloadDataReceived ( data, file ) ) ) => {
45
+ self . data_received ( data. len ( ) , file ) ;
43
46
true
44
47
}
45
- Notification :: Install ( In :: Utils ( Un :: DownloadFinished ) ) => {
46
- self . download_finished ( ) ;
48
+ Notification :: Install ( In :: Utils ( Un :: DownloadFinished ( file) ) ) => {
49
+ self . download_finished ( file) ;
50
+ true
51
+ }
52
+ Notification :: Install ( In :: DownloadingComponent ( component, _, _) ) => {
53
+ self . create_progress_bar ( component) ;
47
54
true
48
55
}
49
56
Notification :: Install ( In :: Utils ( Un :: DownloadPushUnit ( _) ) ) => true ,
@@ -53,30 +60,61 @@ impl DownloadTracker {
53
60
}
54
61
}
55
62
56
- /// Sets the length for a new ProgressBar and gives it a style.
57
- pub ( crate ) fn content_length_received ( & mut self , content_len : u64 ) {
58
- self . progress_bar . set_length ( content_len) ;
59
- self . progress_bar . set_style (
63
+ /// Helper function to find the progress bar for a given file.
64
+ fn find_progress_bar ( & mut self , file : & str ) -> Option < & mut ProgressBar > {
65
+ // During the installation this function can be called with an empty file/URL.
66
+ if file. is_empty ( ) {
67
+ return None ;
68
+ }
69
+ let component = self
70
+ . file_progress_bars
71
+ . keys ( )
72
+ . find ( |comp| file. contains ( * comp) )
73
+ . cloned ( ) ?;
74
+
75
+ self . file_progress_bars . get_mut ( & component)
76
+ }
77
+
78
+ /// Creates a new ProgressBar for the given component.
79
+ pub ( crate ) fn create_progress_bar ( & mut self , component : & str ) {
80
+ let pb = ProgressBar :: hidden ( ) ;
81
+ pb. set_style (
60
82
ProgressStyle :: with_template (
61
- "[{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
83
+ "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
62
84
)
63
85
. unwrap ( )
64
86
. progress_chars ( "## " ) ,
65
87
) ;
88
+ pb. set_message ( component. to_string ( ) ) ;
89
+ self . multi_progress_bars . add ( pb. clone ( ) ) ;
90
+ self . file_progress_bars . insert ( component. to_string ( ) , pb) ;
91
+ }
92
+
93
+ /// Sets the length for a new ProgressBar and gives it a style.
94
+ pub ( crate ) fn content_length_received ( & mut self , content_len : u64 , file : & str ) {
95
+ if let Some ( pb) = self . find_progress_bar ( file) {
96
+ pb. set_length ( content_len) ;
97
+ }
66
98
}
67
99
68
100
/// Notifies self that data of size `len` has been received.
69
- pub ( crate ) fn data_received ( & mut self , len : usize ) {
70
- if self . progress_bar . is_hidden ( ) && self . progress_bar . elapsed ( ) >= Duration :: from_secs ( 1 ) {
71
- self . multi_progress_bars . add ( self . progress_bar . clone ( ) ) ;
101
+ pub ( crate ) fn data_received ( & mut self , len : usize , file : & str ) {
102
+ if let Some ( pb ) = self . find_progress_bar ( file ) {
103
+ pb . inc ( len as u64 ) ;
72
104
}
73
- self . progress_bar . inc ( len as u64 ) ;
74
105
}
75
106
76
107
/// Notifies self that the download has finished.
77
- pub ( crate ) fn download_finished ( & mut self ) {
78
- self . progress_bar . finish_and_clear ( ) ;
79
- self . multi_progress_bars . remove ( & self . progress_bar ) ;
80
- self . progress_bar = ProgressBar :: hidden ( ) ;
108
+ pub ( crate ) fn download_finished ( & mut self , file : & str ) {
109
+ if let Some ( pb) = self . find_progress_bar ( file) {
110
+ pb. set_style (
111
+ ProgressStyle :: with_template (
112
+ "{msg:>12.bold} downloaded {total_bytes} in {elapsed}." ,
113
+ )
114
+ . unwrap ( ) ,
115
+ ) ;
116
+ let msg = pb. message ( ) ;
117
+ pb. finish_with_message ( msg) ;
118
+ }
81
119
}
82
120
}
0 commit comments