Skip to content

Commit 3d5654d

Browse files
committed
fix: move auto adjust selected images in new thread to unblock UI
1 parent 3c077b2 commit 3d5654d

1 file changed

Lines changed: 86 additions & 94 deletions

File tree

src-tauri/src/file_management.rs

Lines changed: 86 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)