refactor try_decode_image
This commit is contained in:
parent
0353009321
commit
006b69d98b
1 changed files with 104 additions and 83 deletions
187
src/tab.rs
187
src/tab.rs
|
|
@ -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>) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue