refactor try_decode_image

This commit is contained in:
Frederic Laing 2025-11-16 18:40:55 +01:00
parent 0353009321
commit 006b69d98b
No known key found for this signature in database
GPG key ID: C126157F0CDCD306

View file

@ -2979,101 +2979,122 @@ impl Tab {
} }
fn trigger_async_decode(&mut self) -> Vec<Command> { fn trigger_async_decode(&mut self) -> Vec<Command> {
let mut commands = Vec::new();
// Only trigger decode in gallery mode for the currently selected image // Only trigger decode in gallery mode for the currently selected image
if !self.gallery { if !self.gallery {
return commands; return Vec::new();
} }
if let Some(index) = self.select_focus { let Some(index) = self.select_focus else {
if let Some(items) = &self.items_opt { return Vec::new();
if let Some(item) = items.get(index) { };
if let Some(ItemThumbnail::Image(_, _, _full_handle_opt)) = &item.thumbnail_opt
{
if let Some(path) = item.path_opt() {
self.large_image_manager.clear_error(path);
// Only decode if not already decoded or decoding let Some(items) = &self.items_opt else {
if self.large_image_manager.get_decoded(path).is_none() return Vec::new();
&& !self.large_image_manager.is_decoding(path) };
{
if let Some((width, height)) = get_image_dimensions(path) {
let (has_memory, error_opt) =
check_memory_available(width, height);
if !has_memory { let Some(item) = items.get(index) else {
// Insufficient memory --> try clearing cache return Vec::new();
if !self.large_image_manager.cache_is_empty() { };
log::info!(
"Insufficient memory, clearing {} cached images",
self.large_image_manager.cache_size()
);
self.large_image_manager.clear_cache();
// Check again after clearing cache let Some(ItemThumbnail::Image(_, _, _)) = &item.thumbnail_opt else {
let (has_memory_after_clear, error_opt_after) = return Vec::new();
check_memory_available(width, height); };
if !has_memory_after_clear {
if let Some(error_msg) = error_opt_after {
self.large_image_manager
.store_error(path.clone(), error_msg);
log::warn!(
"Cannot load {}: insufficient memory even after cache clear",
path.display()
);
}
return commands;
}
log::info!(
"Memory available after cache clear, proceeding with decode"
);
} else {
if let Some(error_msg) = error_opt {
self.large_image_manager
.store_error(path.clone(), error_msg);
log::warn!(
"Cannot load {}: insufficient memory and cache is empty",
path.display()
);
}
return commands;
}
}
self.large_image_manager.mark_decoding(path.clone()); let Some(path) = item.path_opt() else {
return Vec::new();
};
let path_clone = path.clone(); // Clone path to avoid borrow checker issues
commands.push(Command::Iced( let path = path.to_path_buf();
cosmic::iced::Task::perform(
decode_large_image(path_clone), // Clear any previous errors for this image
|result| { self.large_image_manager.clear_error(&path);
if let Some((path, width, height, pixels)) = result
{ // Check if image is already decoded or currently decoding
Message::ImageDecoded( if self.large_image_manager.get_decoded(&path).is_some()
path, width, height, pixels, || self.large_image_manager.is_decoding(&path)
) {
} else { return Vec::new();
Message::AutoScroll(None) }
}
}, // Try to decode the image
) self.try_decode_image(&path)
.into(), }
));
} else { /// Attempt to decode a large image, handling memory constraints
self.large_image_manager.store_error( fn try_decode_image(&mut self, path: &PathBuf) -> Vec<Command> {
path.clone(), let Some((width, height)) = get_image_dimensions(path) else {
"Failed to read image dimensions".to_string(), self.large_image_manager.store_error(
); path.clone(),
} "Failed to read image dimensions".to_string(),
} );
} return Vec::new();
} };
}
if !self.ensure_memory_available(path, width, height) {
return Vec::new();
}
// Mark image as decoding and create the decode task
self.large_image_manager.mark_decoding(path.clone());
vec![self.create_decode_command(path.clone())]
}
fn ensure_memory_available(&mut self, path: &PathBuf, width: u32, height: u32) -> bool {
let (has_memory, error_opt) = check_memory_available(width, height);
if has_memory {
return true;
}
// Try clearing cache
if self.large_image_manager.cache_is_empty() {
if let Some(error_msg) = error_opt {
self.large_image_manager
.store_error(path.clone(), error_msg);
log::warn!(
"Cannot load {}: insufficient memory and cache is empty",
path.display()
);
} }
return false;
} }
commands log::info!(
"Insufficient memory, clearing {} cached images",
self.large_image_manager.cache_size()
);
self.large_image_manager.clear_cache();
let (has_memory_after_clear, error_opt_after) = check_memory_available(width, height);
if has_memory_after_clear {
log::info!("Memory available after cache clear, proceeding with decode");
return true;
}
if let Some(error_msg) = error_opt_after {
self.large_image_manager
.store_error(path.clone(), error_msg);
log::warn!(
"Cannot load {}: insufficient memory even after cache clear",
path.display()
);
}
false
}
fn create_decode_command(&self, path: PathBuf) -> Command {
Command::Iced(
cosmic::iced::Task::perform(decode_large_image(path), |result| {
result
.map(|(path, width, height, pixels)| {
Message::ImageDecoded(path, width, height, pixels)
})
.unwrap_or_else(|| Message::AutoScroll(None))
})
.into(),
)
} }
pub fn change_location(&mut self, location: &Location, history_i_opt: Option<usize>) { pub fn change_location(&mut self, location: &Location, history_i_opt: Option<usize>) {