11use indicatif:: { MultiProgress , ProgressBar , ProgressDrawTarget , ProgressStyle } ;
2- use std:: time :: Duration ;
2+ use std:: collections :: HashMap ;
33
44use crate :: dist:: Notification as In ;
55use crate :: notifications:: Notification ;
@@ -13,8 +13,8 @@ use crate::utils::Notification as Un;
1313pub ( crate ) struct DownloadTracker {
1414 /// MultiProgress bar for the downloads.
1515 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 > ,
1818}
1919
2020impl DownloadTracker {
@@ -28,22 +28,29 @@ impl DownloadTracker {
2828
2929 Self {
3030 multi_progress_bars,
31- progress_bar : ProgressBar :: hidden ( ) ,
31+ file_progress_bars : HashMap :: new ( ) ,
3232 }
3333 }
3434
3535 pub ( crate ) fn handle_notification ( & mut self , n : & Notification < ' _ > ) -> bool {
3636 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) ;
3942 true
4043 }
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 ) ;
4346 true
4447 }
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) ;
4754 true
4855 }
4956 Notification :: Install ( In :: Utils ( Un :: DownloadPushUnit ( _) ) ) => true ,
@@ -53,30 +60,60 @@ impl DownloadTracker {
5360 }
5461 }
5562
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 progress_bar ( & mut self , file : & str ) -> Option < & 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+
74+ self . file_progress_bars . get ( component)
75+ }
76+
77+ /// Creates a new ProgressBar for the given component.
78+ pub ( crate ) fn create_progress_bar ( & mut self , component : & str ) {
79+ let pb = ProgressBar :: hidden ( ) ;
80+ pb. set_style (
6081 ProgressStyle :: with_template (
61- "[{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
82+ "{msg:>12.bold} [{bar:40}] {bytes}/{total_bytes} ({bytes_per_sec}, ETA: {eta})" ,
6283 )
6384 . unwrap ( )
6485 . progress_chars ( "## " ) ,
6586 ) ;
87+ pb. set_message ( component. to_string ( ) ) ;
88+ self . multi_progress_bars . add ( pb. clone ( ) ) ;
89+ self . file_progress_bars . insert ( component. to_string ( ) , pb) ;
90+ }
91+
92+ /// Sets the length for a new ProgressBar and gives it a style.
93+ pub ( crate ) fn content_length_received ( & mut self , content_len : u64 , file : & str ) {
94+ if let Some ( pb) = self . progress_bar ( file) {
95+ pb. set_length ( content_len) ;
96+ }
6697 }
6798
6899 /// 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 ( ) ) ;
100+ pub ( crate ) fn data_received ( & mut self , len : usize , file : & str ) {
101+ if let Some ( pb ) = self . progress_bar ( file ) {
102+ pb . inc ( len as u64 ) ;
72103 }
73- self . progress_bar . inc ( len as u64 ) ;
74104 }
75105
76106 /// 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 ( ) ;
107+ pub ( crate ) fn download_finished ( & mut self , file : & str ) {
108+ if let Some ( pb) = self . progress_bar ( file) {
109+ pb. set_style (
110+ ProgressStyle :: with_template (
111+ "{msg:>12.bold} downloaded {total_bytes} in {elapsed}" ,
112+ )
113+ . unwrap ( ) ,
114+ ) ;
115+ let msg = pb. message ( ) ;
116+ pb. finish_with_message ( msg) ;
117+ }
81118 }
82119}
0 commit comments