@@ -2030,127 +2030,119 @@ pub fn apply_auto_adjustments_to_paths(
20302030 paths : Vec < String > ,
20312031 app_handle : AppHandle ,
20322032) -> Result < ( ) , String > {
2033- let settings = load_settings ( app_handle. clone ( ) ) . unwrap_or_default ( ) ;
2034- let highlight_compression = settings. raw_highlight_compression . unwrap_or ( 2.5 ) ;
2035- let linear_mode = settings. linear_raw_mode ;
2036- let enable_xmp_sync = settings. enable_xmp_sync . unwrap_or ( false ) ;
2037- let create_xmp_if_missing = settings. create_xmp_if_missing . unwrap_or ( false ) ;
2033+ thread:: spawn ( move || {
2034+ let settings = load_settings ( app_handle. clone ( ) ) . unwrap_or_default ( ) ;
2035+ let highlight_compression = settings. raw_highlight_compression . unwrap_or ( 2.5 ) ;
2036+ let linear_mode = settings. linear_raw_mode ;
2037+ let enable_xmp_sync = settings. enable_xmp_sync . unwrap_or ( false ) ;
2038+ let create_xmp_if_missing = settings. create_xmp_if_missing . unwrap_or ( false ) ;
20382039
2039- paths. par_iter ( ) . for_each ( |path| {
2040- let result: Result < ( ) , String > = ( || {
2041- let ( source_path, sidecar_path) = parse_virtual_path ( path) ;
2042- let source_path_str = source_path. to_string_lossy ( ) . to_string ( ) ;
2040+ let state = app_handle. state :: < AppState > ( ) ;
2041+ let gpu_context = gpu_processing:: get_or_init_gpu_context ( & state) . ok ( ) ;
2042+ let thumb_cache_dir = resolve_thumbnail_cache_dir ( & app_handle) . ok ( ) ;
20432043
2044- let file_bytes = fs:: read ( & source_path) . map_err ( |e| e. to_string ( ) ) ?;
2045- let image = image_loader:: load_base_image_from_bytes (
2046- & file_bytes,
2047- & source_path_str,
2048- false ,
2049- highlight_compression,
2050- linear_mode. clone ( ) ,
2051- None ,
2052- )
2053- . map_err ( |e| e. to_string ( ) ) ?;
2044+ let total_count = paths. len ( ) ;
2045+ let completed_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
20542046
2055- let auto_results = perform_auto_analysis ( & image) ;
2056- let auto_adjustments_json = auto_results_to_json ( & auto_results) ;
2047+ paths. par_iter ( ) . for_each ( |path| {
2048+ let result: Result < ( ) , String > = ( || {
2049+ let ( source_path, sidecar_path) = parse_virtual_path ( path) ;
2050+ let source_path_str = source_path. to_string_lossy ( ) . to_string ( ) ;
20572051
2058- let mut existing_metadata: ImageMetadata = if sidecar_path. exists ( ) {
2059- fs:: read_to_string ( & sidecar_path)
2060- . ok ( )
2061- . and_then ( |content| serde_json:: from_str ( & content) . ok ( ) )
2062- . unwrap_or_default ( )
2063- } else {
2064- ImageMetadata :: default ( )
2065- } ;
2052+ let file_bytes = fs:: read ( & source_path) . map_err ( |e| e. to_string ( ) ) ?;
2053+ let image = image_loader:: load_base_image_from_bytes (
2054+ & file_bytes,
2055+ & source_path_str,
2056+ false ,
2057+ highlight_compression,
2058+ linear_mode. clone ( ) ,
2059+ None ,
2060+ )
2061+ . map_err ( |e| e. to_string ( ) ) ?;
20662062
2067- if existing_metadata. adjustments . is_null ( ) {
2068- existing_metadata. adjustments = serde_json:: json!( { } ) ;
2069- }
2063+ let auto_results = perform_auto_analysis ( & image) ;
2064+ let auto_adjustments_json = auto_results_to_json ( & auto_results) ;
2065+
2066+ let mut existing_metadata: ImageMetadata = if sidecar_path. exists ( ) {
2067+ fs:: read_to_string ( & sidecar_path)
2068+ . ok ( )
2069+ . and_then ( |content| serde_json:: from_str ( & content) . ok ( ) )
2070+ . unwrap_or_default ( )
2071+ } else {
2072+ ImageMetadata :: default ( )
2073+ } ;
2074+
2075+ if existing_metadata. adjustments . is_null ( ) {
2076+ existing_metadata. adjustments = serde_json:: json!( { } ) ;
2077+ }
20702078
2071- if let ( Some ( existing_map) , Some ( auto_map) ) = (
2072- existing_metadata. adjustments . as_object_mut ( ) ,
2073- auto_adjustments_json. as_object ( ) ,
2074- ) {
2075- for ( k, v) in auto_map {
2076- if k == "sectionVisibility" {
2077- if let Some ( existing_vis_val) = existing_map. get_mut ( k) {
2078- if let ( Some ( existing_vis) , Some ( auto_vis) ) =
2079- ( existing_vis_val. as_object_mut ( ) , v. as_object ( ) )
2080- {
2081- for ( vis_k, vis_v) in auto_vis {
2082- existing_vis. insert ( vis_k. clone ( ) , vis_v. clone ( ) ) ;
2079+ if let ( Some ( existing_map) , Some ( auto_map) ) = (
2080+ existing_metadata. adjustments . as_object_mut ( ) ,
2081+ auto_adjustments_json. as_object ( ) ,
2082+ ) {
2083+ for ( k, v) in auto_map {
2084+ if k == "sectionVisibility" {
2085+ if let Some ( existing_vis_val) = existing_map. get_mut ( k) {
2086+ if let ( Some ( existing_vis) , Some ( auto_vis) ) =
2087+ ( existing_vis_val. as_object_mut ( ) , v. as_object ( ) )
2088+ {
2089+ for ( vis_k, vis_v) in auto_vis {
2090+ existing_vis. insert ( vis_k. clone ( ) , vis_v. clone ( ) ) ;
2091+ }
20832092 }
2093+ } else {
2094+ existing_map. insert ( k. clone ( ) , v. clone ( ) ) ;
20842095 }
20852096 } else {
20862097 existing_map. insert ( k. clone ( ) , v. clone ( ) ) ;
20872098 }
2088- } else {
2089- existing_map. insert ( k. clone ( ) , v. clone ( ) ) ;
20902099 }
20912100 }
2092- }
20932101
2094- existing_metadata. rating = existing_metadata. adjustments [ "rating" ]
2095- . as_u64 ( )
2096- . unwrap_or ( 0 ) as u8 ;
2102+ existing_metadata. rating = existing_metadata. adjustments [ "rating" ]
2103+ . as_u64 ( )
2104+ . unwrap_or ( 0 ) as u8 ;
20972105
2098- if let Ok ( json_string) = serde_json:: to_string_pretty ( & existing_metadata) {
2099- let _ = std:: fs:: write ( & sidecar_path, json_string) ;
2100- }
2101-
2102- if enable_xmp_sync {
2103- sync_metadata_to_xmp ( & source_path, & existing_metadata, create_xmp_if_missing) ;
2104- }
2105- Ok ( ( ) )
2106- } ) ( ) ;
2107- if let Err ( e) = result {
2108- eprintln ! ( "Failed to apply auto adjustments to {}: {}" , path, e) ;
2109- }
2110- } ) ;
2111-
2112- thread:: spawn ( move || {
2113- let state = app_handle. state :: < AppState > ( ) ;
2114- let thumb_cache_dir = match resolve_thumbnail_cache_dir ( & app_handle) {
2115- Ok ( dir) => dir,
2116- Err ( e) => {
2117- log:: warn!( "Unable to initialize thumbnail cache directory: {}" , e) ;
2118- for path in & paths {
2119- emit_thumbnail_cache_setup_error ( & app_handle, path, & e) ;
2106+ if let Ok ( json_string) = serde_json:: to_string_pretty ( & existing_metadata) {
2107+ let _ = std:: fs:: write ( & sidecar_path, json_string) ;
21202108 }
2121- let _ = app_handle. emit ( "thumbnail-generation-complete" , true ) ;
2122- return ;
2123- }
2124- } ;
21252109
2126- let gpu_context = gpu_processing :: get_or_init_gpu_context ( & state ) . ok ( ) ;
2127- let total_count = paths . len ( ) ;
2128- let completed_count = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
2110+ if enable_xmp_sync {
2111+ sync_metadata_to_xmp ( & source_path , & existing_metadata , create_xmp_if_missing ) ;
2112+ }
21292113
2130- paths. par_iter ( ) . for_each ( |path_str| {
2131- let result = generate_single_thumbnail_and_cache (
2132- path_str,
2133- & thumb_cache_dir,
2134- gpu_context. as_ref ( ) ,
2135- None ,
2136- true ,
2137- & app_handle,
2138- ) ;
2114+ // Regenerate thumbnail immediately using the already-decoded image,
2115+ // so the UI updates without waiting for the full batch to finish.
2116+ if let Some ( cache_dir) = & thumb_cache_dir {
2117+ if let Some ( ( thumbnail_data, rating) ) = generate_single_thumbnail_and_cache (
2118+ path,
2119+ cache_dir,
2120+ gpu_context. as_ref ( ) ,
2121+ Some ( & image) ,
2122+ true ,
2123+ & app_handle,
2124+ ) {
2125+ let _ = app_handle. emit (
2126+ "thumbnail-generated" ,
2127+ serde_json:: json!( { "path" : path, "data" : thumbnail_data, "rating" : rating } ) ,
2128+ ) ;
2129+ }
2130+ }
21392131
2140- if let Some ( ( thumbnail_data, rating) ) = result {
2141- let _ = app_handle. emit (
2142- "thumbnail-generated" ,
2143- serde_json:: json!( { "path" : path_str, "data" : thumbnail_data, "rating" : rating } ) ,
2144- ) ;
2132+ Ok ( ( ) )
2133+ } ) ( ) ;
2134+ if let Err ( e) = result {
2135+ eprintln ! ( "Failed to apply auto adjustments to {}: {}" , path, e) ;
21452136 }
21462137
21472138 let completed = completed_count. fetch_add ( 1 , Ordering :: Relaxed ) + 1 ;
21482139 let _ = app_handle. emit (
2149- "thumbnail -progress" ,
2140+ "auto-adjust -progress" ,
21502141 serde_json:: json!( { "completed" : completed, "total" : total_count } ) ,
21512142 ) ;
21522143 } ) ;
21532144
2145+ let _ = app_handle. emit ( "auto-adjust-complete" , true ) ;
21542146 let _ = app_handle. emit ( "thumbnail-generation-complete" , true ) ;
21552147 } ) ;
21562148
0 commit comments