@@ -13,7 +13,7 @@ use std::{
1313 path:: PathBuf ,
1414 sync:: { Arc , LazyLock , Mutex } ,
1515} ;
16- use tracing:: info;
16+ use tracing:: { debug , error , info} ;
1717
1818mod data;
1919mod data_display_options;
@@ -39,6 +39,8 @@ pub struct LogViewerApp {
3939 should_scroll : bool ,
4040 #[ serde( skip) ]
4141 loading_status : LoadingStatus ,
42+ #[ serde( skip) ]
43+ last_save_hash : Option < u64 > ,
4244}
4345
4446impl Default for LogViewerApp {
@@ -56,6 +58,7 @@ impl Default for LogViewerApp {
5658 should_focus_search : Default :: default ( ) ,
5759 should_scroll : Default :: default ( ) ,
5860 show_last_filename : true ,
61+ last_save_hash : Default :: default ( ) ,
5962 }
6063 }
6164}
@@ -702,6 +705,26 @@ impl LogViewerApp {
702705 }
703706 }
704707 }
708+
709+ fn is_changed_since_last_save ( & mut self ) -> bool {
710+ let as_ron = match ron:: to_string ( & self ) {
711+ Ok ( s) => s,
712+ Err ( err_msg) => {
713+ error ! ( ?err_msg, "failed to serialize app data" ) ;
714+ return true ;
715+ }
716+ } ;
717+ let mut hasher = DefaultHasher :: new ( ) ;
718+ as_ron. hash ( & mut hasher) ;
719+ let new_hash = hasher. finish ( ) ;
720+ if let Some ( & old_hash) = self . last_save_hash . as_ref ( ) {
721+ if old_hash == new_hash {
722+ return false ;
723+ }
724+ }
725+ self . last_save_hash = Some ( new_hash) ;
726+ true
727+ }
705728}
706729
707730#[ cfg( not( target_arch = "wasm32" ) ) ]
@@ -749,8 +772,12 @@ fn execute<F: std::future::Future<Output = Box<LoadingStatus>> + 'static>(
749772impl eframe:: App for LogViewerApp {
750773 /// Called by the frame work to save state before shutdown.
751774 fn save ( & mut self , storage : & mut dyn eframe:: Storage ) {
752- info ! ( "Saving data" ) ;
753- eframe:: set_value ( storage, eframe:: APP_KEY , self ) ;
775+ if self . is_changed_since_last_save ( ) {
776+ info ! ( "Saving data" ) ;
777+ eframe:: set_value ( storage, eframe:: APP_KEY , self ) ;
778+ } else {
779+ debug ! ( "Save skipped, no change detected" ) ;
780+ }
754781 }
755782
756783 /// Called each time the UI needs repainting, which may be many times per second.
0 commit comments