11use std:: sync:: mpsc;
2+ use std:: time:: Duration ;
23
34use eframe:: egui;
45use fastpack_compress:: {
@@ -18,6 +19,8 @@ use fastpack_formats::{
1819 pixijs:: PixiJsExporter ,
1920 } ,
2021} ;
22+ use notify_debouncer_mini:: notify:: RecursiveMode ;
23+ use notify_debouncer_mini:: { DebounceEventResult , new_debouncer} ;
2124
2225use crate :: {
2326 menu,
@@ -42,6 +45,8 @@ pub struct FastPackApp {
4245 prefs_open : bool ,
4346 update_status : UpdateStatus ,
4447 update_rx : Option < mpsc:: Receiver < UpdateMsg > > ,
48+ file_watcher : Option < Box < dyn Send > > ,
49+ watch_rx : Option < mpsc:: Receiver < DebounceEventResult > > ,
4550}
4651
4752impl Default for FastPackApp {
@@ -60,6 +65,8 @@ impl Default for FastPackApp {
6065 prefs_open : false ,
6166 update_status : UpdateStatus :: Idle ,
6267 update_rx : None ,
68+ file_watcher : None ,
69+ watch_rx : None ,
6370 } ;
6471 if app. prefs . auto_check_updates {
6572 let ( tx, rx) = mpsc:: channel ( ) ;
@@ -75,6 +82,7 @@ impl eframe::App for FastPackApp {
7582 fn update ( & mut self , ctx : & egui:: Context , _frame : & mut eframe:: Frame ) {
7683 crate :: theme:: apply ( ctx, self . state . dark_mode ) ;
7784 self . poll_worker ( ctx) ;
85+ self . poll_watcher ( ctx) ;
7886 self . handle_pending ( ctx) ;
7987 self . handle_dropped_files ( ctx) ;
8088
@@ -260,9 +268,12 @@ impl FastPackApp {
260268 if std:: mem:: take ( & mut self . state . pending . new_project ) {
261269 self . state . new_project ( self . prefs . default_config . clone ( ) ) ;
262270 self . atlas_textures . clear ( ) ;
271+ self . file_watcher = None ;
272+ self . watch_rx = None ;
263273 }
264274 if std:: mem:: take ( & mut self . state . pending . open_project ) {
265275 self . do_open_project ( ) ;
276+ self . state . pending . rebuild_watcher = true ;
266277 }
267278 if std:: mem:: take ( & mut self . state . pending . save_project ) {
268279 self . do_save_project ( false ) ;
@@ -276,6 +287,9 @@ impl FastPackApp {
276287 if std:: mem:: take ( & mut self . state . pending . open_prefs ) {
277288 self . prefs_open = true ;
278289 }
290+ if std:: mem:: take ( & mut self . state . pending . rebuild_watcher ) {
291+ self . rebuild_watcher ( ) ;
292+ }
279293 }
280294
281295 fn spawn_pack ( & mut self , ctx : egui:: Context ) {
@@ -585,4 +599,62 @@ impl FastPackApp {
585599 }
586600 }
587601 }
602+
603+ fn rebuild_watcher ( & mut self ) {
604+ self . file_watcher = None ;
605+ self . watch_rx = None ;
606+
607+ if self . state . project . sources . is_empty ( ) {
608+ return ;
609+ }
610+
611+ let ( tx, rx) = mpsc:: channel :: < DebounceEventResult > ( ) ;
612+ match new_debouncer ( Duration :: from_millis ( 500 ) , tx) {
613+ Ok ( mut debouncer) => {
614+ let watch_paths: Vec < _ > = self
615+ . state
616+ . project
617+ . sources
618+ . iter ( )
619+ . map ( |s| {
620+ if s. path . is_file ( ) {
621+ s. path . parent ( ) . unwrap_or ( s. path . as_path ( ) ) . to_path_buf ( )
622+ } else {
623+ s. path . clone ( )
624+ }
625+ } )
626+ . collect ( ) ;
627+ let mut errors: Vec < String > = Vec :: new ( ) ;
628+ for path in & watch_paths {
629+ if let Err ( e) = debouncer. watcher ( ) . watch ( path, RecursiveMode :: Recursive ) {
630+ errors. push ( format ! ( "Could not watch {}: {e}" , path. display( ) ) ) ;
631+ }
632+ }
633+ for err in errors {
634+ self . state . log_warn ( err) ;
635+ }
636+ self . file_watcher = Some ( Box :: new ( debouncer) ) ;
637+ self . watch_rx = Some ( rx) ;
638+ }
639+ Err ( e) => self
640+ . state
641+ . log_warn ( format ! ( "Could not start file watcher: {e}" ) ) ,
642+ }
643+ }
644+
645+ fn poll_watcher ( & mut self , ctx : & egui:: Context ) {
646+ let Some ( rx) = & self . watch_rx else { return } ;
647+ let mut changed = false ;
648+ loop {
649+ match rx. try_recv ( ) {
650+ Ok ( Ok ( _) ) => changed = true ,
651+ Ok ( Err ( _) ) | Err ( mpsc:: TryRecvError :: Empty ) => break ,
652+ Err ( mpsc:: TryRecvError :: Disconnected ) => break ,
653+ }
654+ }
655+ if changed && !self . state . packing {
656+ self . state . pending . pack = true ;
657+ ctx. request_repaint ( ) ;
658+ }
659+ }
588660}
0 commit comments