@@ -11,6 +11,7 @@ use oauth2::{
1111 AuthUrl , ClientId , ClientSecret , ResourceOwnerPassword , ResourceOwnerUsername , TokenUrl ,
1212} ;
1313use reqwest:: { blocking:: Client , Url } ;
14+ use serde:: Serialize ;
1415use std:: collections:: HashMap ;
1516use std:: io:: Write ;
1617use std:: path:: Path ;
@@ -21,6 +22,12 @@ use tmc_langs_util::task_executor;
2122pub type Token =
2223 oauth2:: StandardTokenResponse < oauth2:: EmptyExtraTokenFields , oauth2:: basic:: BasicTokenType > ;
2324
25+ #[ derive( Debug , Serialize ) ]
26+ pub enum StatusUpdate {
27+ Processing ( & ' static str , f64 ) ,
28+ Finished ,
29+ }
30+
2431/// A struct for interacting with the TestMyCode service, including authentication
2532pub struct TmcCore {
2633 client : Client ,
@@ -29,6 +36,7 @@ pub struct TmcCore {
2936 api_url : Url ,
3037 auth_url : String ,
3138 token : Option < Token > ,
39+ progress_report : Option < Box < dyn Fn ( StatusUpdate ) > > ,
3240}
3341
3442// TODO: cache API results?
@@ -64,6 +72,7 @@ impl TmcCore {
6472 api_url,
6573 auth_url,
6674 token : None ,
75+ progress_report : None ,
6776 } )
6877 }
6978
@@ -83,6 +92,25 @@ impl TmcCore {
8392 Self :: new ( config_dir, root_url)
8493 }
8594
95+ pub fn set_progress_report < F > ( & mut self , progress_report : F )
96+ where
97+ F : Fn ( StatusUpdate ) + ' static ,
98+ {
99+ self . progress_report = Some ( Box :: new ( progress_report) ) ;
100+ }
101+
102+ pub fn report_progress ( & self , msg : & ' static str , progress : f64 ) {
103+ self . progress_report
104+ . as_ref ( )
105+ . map ( |f| f ( StatusUpdate :: Processing ( msg, progress) ) ) ;
106+ }
107+
108+ pub fn report_complete ( & self ) {
109+ self . progress_report
110+ . as_ref ( )
111+ . map ( |f| f ( StatusUpdate :: Finished ) ) ;
112+ }
113+
86114 /// Attempts to log in with the given credentials, returns an error if an authentication token is already present.
87115 /// Username can be the user's username or email.
88116 ///
@@ -329,12 +357,18 @@ impl TmcCore {
329357 locale : Language ,
330358 ) -> Result < NewSubmission > {
331359 // compress
360+ self . report_progress ( "Submitting exercise. Compressing submission..." , 0.0 ) ;
332361 let compressed = task_executor:: compress_project ( submission_path) ?;
362+ self . report_progress ( "Compressed submission. Creating temporary file..." , 0.25 ) ;
333363 let mut file = NamedTempFile :: new ( ) . map_err ( CoreError :: TempFile ) ?;
364+ self . report_progress ( "Created temporary file. Writing compressed data..." , 0.5 ) ;
334365 file. write_all ( & compressed)
335366 . map_err ( |e| CoreError :: FileWrite ( file. path ( ) . to_path_buf ( ) , e) ) ?;
367+ self . report_progress ( "Wrote compressed data. Posting submission..." , 0.75 ) ;
336368
337- self . post_submission ( submission_url, file. path ( ) , locale)
369+ let result = self . post_submission ( submission_url, file. path ( ) , locale) ;
370+ self . report_complete ( ) ;
371+ result
338372 }
339373
340374 /// Fetches the course's exercises from the server,
0 commit comments