diff --git a/crates/image_viewer/src/image_viewer.rs b/crates/image_viewer/src/image_viewer.rs index 950a6a1da9..8b2cfe6fa2 100644 --- a/crates/image_viewer/src/image_viewer.rs +++ b/crates/image_viewer/src/image_viewer.rs @@ -498,6 +498,15 @@ impl ImageView { } cx.notify(); } + ImageItemEvent::PageChanged => { + self.page_bounds.borrow_mut().clear(); + self.image_size = self + .image_item + .read(cx) + .image_metadata + .map(|m| (m.width, m.height)); + cx.notify(); + } } } @@ -5292,6 +5301,7 @@ mod tests { assert_eq!(cache.current_memory_bytes(), 0); assert!(cache.is_empty()); } + } mod persistence { diff --git a/crates/project/src/image_store.rs b/crates/project/src/image_store.rs index 93f3cc30cd..7462df1892 100644 --- a/crates/project/src/image_store.rs +++ b/crates/project/src/image_store.rs @@ -21,9 +21,9 @@ use util::{ResultExt, rel_path::RelPath}; use worktree::{LoadedBinaryFile, PathChange, Worktree, WorktreeId}; const EMPTY_1X1_PNG: &[u8] = &[ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, - 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 120, 156, 99, 96, 96, - 96, 96, 0, 0, 0, 5, 0, 1, 165, 246, 69, 64, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, + 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, + 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 120, 156, 99, 96, 96, 96, 96, 0, 0, 0, 5, + 0, 1, 165, 246, 69, 64, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, ]; #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Ord, Eq)] @@ -53,6 +53,7 @@ pub enum ImageItemEvent { Reloaded, FileHandleChanged, MetadataUpdated, + PageChanged, } impl EventEmitter for ImageItem {} @@ -180,7 +181,9 @@ impl ImageItem { if image_bytes.starts_with(b"%PDF-") { let engine = pdf_viewer::pdfium::PdfiumEngine::new(); let doc = engine.load_document_from_bytes(image_bytes, None)?; - let dim = doc.page_size(0).unwrap_or(pdf_viewer::PageDimensions::new(612.0, 792.0)); + let dim = doc + .page_size(0) + .unwrap_or(pdf_viewer::PageDimensions::new(612.0, 792.0)); let (width, height) = dim.to_pixel_size(1.0, 144.0); return Ok(ImageMetadata { width, @@ -278,7 +281,9 @@ impl ImageItem { if let Some(ref text) = info.full_text { Some(text.clone()) } else { - pdf_viewer::PdfiumEngine::new().extract_text_from_bytes(&info.pdf_bytes, None).ok() + pdf_viewer::PdfiumEngine::new() + .extract_text_from_bytes(&info.pdf_bytes, None) + .ok() } } @@ -299,8 +304,9 @@ impl ImageItem { format: image::ImageFormat::Png, colors: ImageColorInfo::from_color_type(image::ColorType::Rgba8), }); - cx.emit(ImageItemEvent::Reloaded); - cx.emit(ImageItemEvent::MetadataUpdated); + // A page turn keeps the same document bytes, so document-derived state + // (outline, caches, edits) stays valid; only the layout changes. + cx.emit(ImageItemEvent::PageChanged); cx.notify(); true } else { @@ -340,13 +346,15 @@ impl ImageItem { self.reload_task = Some(cx.spawn(async move |this, cx| { if let Ok(bytes) = content.await.context("Failed to load image content") { let is_pdf = bytes.starts_with(b"%PDF-"); - let cur_page = this.read_with(cx, |this, _| this.current_page()).unwrap_or(0); + let cur_page = this + .read_with(cx, |this, _| this.current_page()) + .unwrap_or(0); if is_pdf { let bytes_clone = bytes.clone(); - let pdf_res = background.spawn(async move { - create_gpui_images_from_pdf(&bytes_clone) - }).await; + let pdf_res = background + .spawn(async move { create_gpui_images_from_pdf(&bytes_clone) }) + .await; if let Ok((pages, full_text)) = pdf_res { let total_pages = pages.len(); let target_page = cur_page.min(total_pages.saturating_sub(1)); @@ -403,7 +411,9 @@ pub fn is_image_file(project: &Entity, path: &ProjectPath, cx: &App) -> }); match ext { - Some(ext) => (Img::extensions().contains(&ext.as_str()) || ext == "pdf") && !ext.contains("svg"), + Some(ext) => { + (Img::extensions().contains(&ext.as_str()) || ext == "pdf") && !ext.contains("svg") + } None => false, } } @@ -759,7 +769,10 @@ impl RemoteImageStore { pages, full_text, }; - let dummy_img = Arc::new(gpui::Image::from_bytes(gpui::ImageFormat::Png, EMPTY_1X1_PNG.to_vec())); + let dummy_img = Arc::new(gpui::Image::from_bytes( + gpui::ImageFormat::Png, + EMPTY_1X1_PNG.to_vec(), + )); (dummy_img, Some(pdf_info)) } else { (create_gpui_image(content.clone())?, None) @@ -829,9 +842,9 @@ impl ImageStoreImpl for Entity { let is_pdf = content.starts_with(b"%PDF-"); let (image, pdf_info) = if is_pdf { let content_clone = content.clone(); - let pdf_res = background.spawn(async move { - create_gpui_images_from_pdf(&content_clone) - }).await; + let pdf_res = background + .spawn(async move { create_gpui_images_from_pdf(&content_clone) }) + .await; if let Ok((pages, full_text)) = pdf_res { let total_pages = pages.len(); let pdf_info = PdfPageInfo { @@ -841,7 +854,10 @@ impl ImageStoreImpl for Entity { pages, full_text, }; - let dummy_img = Arc::new(gpui::Image::from_bytes(gpui::ImageFormat::Png, EMPTY_1X1_PNG.to_vec())); + let dummy_img = Arc::new(gpui::Image::from_bytes( + gpui::ImageFormat::Png, + EMPTY_1X1_PNG.to_vec(), + )); (dummy_img, Some(pdf_info)) } else { (create_gpui_image(content.clone())?, None)