diff --git a/Cargo.lock b/Cargo.lock index e9dc99b16..671ff7c53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2324,7 +2324,7 @@ dependencies = [ [[package]] name = "iced" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "iced_core", "iced_debug", @@ -2351,7 +2351,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "bitflags 2.13.1", "bytes", @@ -2369,7 +2369,7 @@ dependencies = [ [[package]] name = "iced_debug" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "iced_core", "iced_futures", @@ -2391,7 +2391,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "futures", "iced_core", @@ -2405,7 +2405,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "bitflags 2.13.1", "bytemuck", @@ -2426,7 +2426,7 @@ dependencies = [ [[package]] name = "iced_program" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "iced_graphics", "iced_runtime", @@ -2435,7 +2435,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2447,7 +2447,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "bytes", "iced_core", @@ -2458,7 +2458,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "bytemuck", "cosmic-text 0.19.0", @@ -2475,7 +2475,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "bitflags 2.13.1", "bytemuck", @@ -2495,7 +2495,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "iced_renderer", "iced_runtime", @@ -2510,7 +2510,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.15.0-dev" -source = "git+https://github.com/HakanSeven12/iced.git?rev=1d1a17f146a3dc01597883ca524633c14646934a#1d1a17f146a3dc01597883ca524633c14646934a" +source = "git+https://github.com/iced-rs/iced.git?rev=23604ff22ab0aad9e00b9327cb7b8546ed84db39#23604ff22ab0aad9e00b9327cb7b8546ed84db39" dependencies = [ "arboard", "iced_debug", diff --git a/Cargo.toml b/Cargo.toml index 0f63de303..1e2ce7451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,8 +19,8 @@ winresource = "0.1" serde_json = "1" serde = { version = "1", features = ["derive"] } semver = "1" -iced = { git = "https://github.com/HakanSeven12/iced.git", rev = "1d1a17f146a3dc01597883ca524633c14646934a", features = ["image", "svg", "advanced", "canvas", "smol", "markdown"] } -iced_core = { git = "https://github.com/HakanSeven12/iced.git", rev = "1d1a17f146a3dc01597883ca524633c14646934a" } +iced = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39", features = ["image", "svg", "advanced", "canvas", "smol", "markdown"] } +iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" } iced_aw = { git = "https://github.com/HakanSeven12/iced_aw.git", branch = "agent/fix-iced-fonts", features = ["menu", "context_menu", "color_picker", "drop_down"] } bytemuck = { version = "1.25", features = ["derive"] } glam = { version = "0.33", features = ["bytemuck"] } @@ -57,8 +57,8 @@ windows-sys = { version = "0.61", features = ["Win32_UI_Shell", "Win32_UI_Window ashpd = { version = "0.13.13", default-features = false, features = ["async-io", "wayland"] } [patch.crates-io] -iced_core = { git = "https://github.com/HakanSeven12/iced.git", rev = "1d1a17f146a3dc01597883ca524633c14646934a" } -iced_widget = { git = "https://github.com/HakanSeven12/iced.git", rev = "1d1a17f146a3dc01597883ca524633c14646934a" } +iced_core = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" } +iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39" } [patch."https://github.com/HakanSeven12/cadcodec.git"] acadrust = { git = "https://git@github.com/HakanSeven12/cadcodec.git", rev = "393d6c0857447f9ca678bed97a612707f0a842c6" } @@ -117,7 +117,7 @@ web-sys = { version = "=0.3.85", features = [ "Node", "HtmlElement", ] } -iced = { git = "https://github.com/HakanSeven12/iced.git", rev = "1d1a17f146a3dc01597883ca524633c14646934a", features = ["webgl", "fira-sans"] } +iced = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0aad9e00b9327cb7b8546ed84db39", features = ["webgl", "fira-sans"] } [profile.release] strip = true diff --git a/src/app/mod.rs b/src/app/mod.rs index a8c407776..dd84633c2 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -671,8 +671,6 @@ pub(super) struct OpenCADStudio { main_window: Option, /// Hides drawing UI overlays for one thumbnail capture frame. thumbnail_capture_clean: bool, - #[cfg(not(target_arch = "wasm32"))] - pending_native_thumbnail_save: Option, #[cfg(target_arch = "wasm32")] pending_web_thumbnail_save: Option, // ── Floating panel windows ──────────────────────────────────────────── @@ -1229,18 +1227,6 @@ pub(super) enum SaveContinuation { Quit, } -#[derive(Debug, Clone)] -#[cfg(not(target_arch = "wasm32"))] -pub(super) struct PendingNativeThumbnailSave { - tab_id: u64, - path: PathBuf, - version: acadrust::DxfVersion, - purpose: SavePurpose, - continuation: SaveContinuation, - set_current_path: bool, - check_external_change: bool, -} - #[derive(Debug, Clone)] #[cfg(target_arch = "wasm32")] pub(super) struct PendingWebThumbnailSave { @@ -2063,8 +2049,6 @@ pub enum Message { AutoSave, /// A clean viewport frame is ready for thumbnail capture. ThumbnailCaptureFrame, - /// Restore drawing UI after the compositor screenshot is captured. - ThumbnailCaptureFinished, /// Native background save/autosave completed. #[cfg(not(target_arch = "wasm32"))] SaveFinished(SaveOutcome), @@ -3389,8 +3373,6 @@ impl OpenCADStudio { last_point: None, main_window: None, thumbnail_capture_clean: false, - #[cfg(not(target_arch = "wasm32"))] - pending_native_thumbnail_save: None, #[cfg(target_arch = "wasm32")] pending_web_thumbnail_save: None, color_pick_target: None, diff --git a/src/app/update/file.rs b/src/app/update/file.rs index 3defb1f27..4978c24ab 100644 --- a/src/app/update/file.rs +++ b/src/app/update/file.rs @@ -1709,22 +1709,7 @@ pub(super) fn on_open_file(&mut self) -> Task { #[cfg(not(target_arch = "wasm32"))] pub(super) fn on_thumbnail_capture_frame(&mut self) -> Task { - let Some(pending) = self.pending_native_thumbnail_save.take() else { - return Task::none(); - }; - let Some(i) = self.tabs.iter().position(|tab| tab.id == pending.tab_id) else { - self.thumbnail_capture_clean = false; - return Task::none(); - }; - self.queue_native_save( - i, - pending.path, - pending.version, - pending.purpose, - pending.continuation, - pending.set_current_path, - pending.check_external_change, - ) + Task::none() } #[cfg(target_arch = "wasm32")] @@ -1816,27 +1801,11 @@ pub(super) fn on_open_file(&mut self) -> Task { check_external_change: bool, ) -> Task { let tab_id = self.tabs[i].id; - if self - .pending_native_thumbnail_save - .as_ref() - .is_some_and(|pending| pending.tab_id == tab_id) - { - if purpose != crate::app::SavePurpose::Autosave { - self.command_line - .push_info(crate::t!("Save already running for this drawing.").as_ref()); - } - return Task::none(); - } - let capture_ready = - self.thumbnail_capture_clean && self.pending_native_thumbnail_save.is_none(); if self.active_save_jobs.contains_key(&tab_id) { if purpose != crate::app::SavePurpose::Autosave { self.command_line .push_info(crate::t!("Save already running for this drawing.").as_ref()); } - if capture_ready { - self.thumbnail_capture_clean = false; - } return Task::none(); } let destination_is_current = self.tabs[i] @@ -1854,9 +1823,6 @@ pub(super) fn on_open_file(&mut self) -> Task { self.active_tab = i; self.save_dialog_for_unsaved = continuation != crate::app::SaveContinuation::None; - if capture_ready { - self.thumbnail_capture_clean = false; - } return self.open_save_dialog_window(i); } if purpose != crate::app::SavePurpose::Autosave @@ -1881,33 +1847,6 @@ pub(super) fn on_open_file(&mut self) -> Task { }); self.restore_failed_save_continuation(continuation, i); self.active_modal = Some(crate::app::ModalKind::FileInUse); - if capture_ready { - self.thumbnail_capture_clean = false; - } - return Task::none(); - } - - if purpose != crate::app::SavePurpose::Autosave - && i == self.active_tab - && !self.thumbnail_capture_clean - && self.main_window.is_some() - && crate::ui::wrap_bar::dropdown_bounds( - crate::app::view::VIEWPORT_CAPTURE_BOUNDS_ID, - ) - .is_some() - { - self.pending_native_thumbnail_save = Some( - crate::app::PendingNativeThumbnailSave { - tab_id, - path, - version, - purpose, - continuation, - set_current_path, - check_external_change, - }, - ); - self.thumbnail_capture_clean = true; return Task::none(); } @@ -1934,9 +1873,6 @@ pub(super) fn on_open_file(&mut self) -> Task { }); self.restore_failed_save_continuation(continuation, i); self.active_modal = Some(crate::app::ModalKind::FileInUse); - if capture_ready { - self.thumbnail_capture_clean = false; - } return Task::none(); } Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => { @@ -1950,13 +1886,6 @@ pub(super) fn on_open_file(&mut self) -> Task { let epoch = self.tabs[i].scene.geometry_epoch; let revision = self.tabs[i].edit_revision; let camera_generation = self.tabs[i].scene.camera_generation; - let thumbnail = (purpose != crate::app::SavePurpose::Autosave && i == self.active_tab) - .then_some(version >= acadrust::DxfVersion::AC1027); - let capture_bounds = thumbnail.and_then(|_| { - crate::ui::wrap_bar::dropdown_bounds( - crate::app::view::VIEWPORT_CAPTURE_BOUNDS_ID, - ) - }); let clone_started = iced::time::Instant::now(); let snapshot = self.tabs[i].scene.document.clone(); let clone_ms = clone_started.elapsed().as_secs_f64() * 1000.0; @@ -2004,9 +1933,6 @@ pub(super) fn on_open_file(&mut self) -> Task { let (expected_fingerprint, verify_reader) = match verification { Ok(verification) => verification, Err(error) => { - if capture_ready { - self.thumbnail_capture_clean = false; - } return Task::perform( async move { crate::app::SaveOutcome { @@ -2030,97 +1956,40 @@ pub(super) fn on_open_file(&mut self) -> Task { } }; let worker_path = path.clone(); - let capture_window = thumbnail.and(capture_bounds).and(self.main_window); - let mut work = Some(( - snapshot, - thumbnail, - capture_bounds, - worker_path, - expected_fingerprint, - verify_reader, - path, - previous_autosave, - )); - let mut run_save = move |screenshot: Option| { - let ( - mut snapshot, - thumbnail, - capture_bounds, - worker_path, - expected_fingerprint, - verify_reader, - path, - previous_autosave, - ) = work.take().expect("save capture produced more than one result"); - Task::perform( - async move { - let (result, refreshed_preview) = std::thread::spawn(move || { - let mut refreshed_preview = None; - if let Some(png) = thumbnail { - let started = iced::time::Instant::now(); - if let Some(preview) = screenshot.as_ref().and_then(|screenshot| { - capture_bounds.and_then(|bounds| { - crate::io::thumbnail::from_screenshot(screenshot, bounds, png) - }) - }) { - snapshot.preview = Some(preview); - refreshed_preview = Some(snapshot.preview.clone()); - } - if crate::perf::enabled() { - crate::perf_record!( - "[perf] save-thumbnail {:.1}ms", - started.elapsed().as_secs_f64() * 1000.0, - ); - } - } - let result = crate::io::save_owned_as_version_atomic( - snapshot, - &worker_path, - version, - backup, - expected_fingerprint, - verify_reader, - ); - (result, refreshed_preview) - }) - .join() - .unwrap_or_else(|_| { - ( - Err(crate::io::SaveFailure::other("save worker panicked")), - None, - ) - }); - crate::app::SaveOutcome { - job_id, - tab_id, - epoch, - revision, - camera_generation, - path, + Task::perform( + async move { + let result = std::thread::spawn(move || { + crate::io::save_owned_as_version_atomic( + snapshot, + &worker_path, version, - previous_autosave, - set_current_path, - purpose, - continuation, - refreshed_preview, - result, - } - }, - Message::SaveFinished, - ) - }; - match capture_window { - Some(window) => iced::window::screenshot(window).map(Some).then(move |screenshot| { - Task::batch([ - Task::done(Message::ThumbnailCaptureFinished), - run_save(screenshot), - ]) - }), - None => { - self.thumbnail_capture_clean = false; - run_save(None) - } - } + backup, + expected_fingerprint, + verify_reader, + ) + }) + .join() + .unwrap_or_else(|_| { + Err(crate::io::SaveFailure::other("save worker panicked")) + }); + crate::app::SaveOutcome { + job_id, + tab_id, + epoch, + revision, + camera_generation, + path, + version, + previous_autosave, + set_current_path, + purpose, + continuation, + refreshed_preview: None, + result, + } + }, + Message::SaveFinished, + ) } #[cfg(not(target_arch = "wasm32"))] diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 62ab2c13c..374ad10ea 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -6994,11 +6994,6 @@ impl OpenCADStudio { Message::ThumbnailCaptureFrame => self.on_thumbnail_capture_frame(), - Message::ThumbnailCaptureFinished => { - self.thumbnail_capture_clean = false; - Task::none() - } - #[cfg(not(target_arch = "wasm32"))] Message::SaveFinished(outcome) => self.on_save_finished(outcome), diff --git a/src/io/thumbnail.rs b/src/io/thumbnail.rs index 28272b409..21d3b45ab 100644 --- a/src/io/thumbnail.rs +++ b/src/io/thumbnail.rs @@ -7,12 +7,18 @@ //! the shared [`dwg_thumbnailer`] core crate (also used by the Windows/macOS //! thumbnail handlers). +#[cfg(any(target_arch = "wasm32", test))] use acadrust::{Preview, PreviewFormat}; +#[cfg(target_arch = "wasm32")] use iced::Rectangle; -use image::{ImageFormat, RgbImage}; +use image::ImageFormat; +#[cfg(any(target_arch = "wasm32", test))] +use image::RgbImage; +#[cfg(any(target_arch = "wasm32", test))] use std::io::Cursor; /// Build a preview from the visible drawing area of an Iced window screenshot. +#[cfg(target_arch = "wasm32")] pub fn from_screenshot( screenshot: &iced::window::Screenshot, bounds: Rectangle, @@ -59,6 +65,7 @@ pub fn from_screenshot( const MAX_DIM: u32 = 256; /// Canvas dimensions for an aspect ratio, longest edge = [`MAX_DIM`]. +#[cfg(any(target_arch = "wasm32", test))] fn canvas_dims(aspect: f64) -> (u32, u32) { if aspect >= 1.0 { (MAX_DIM, ((MAX_DIM as f64 / aspect).round() as u32).clamp(16, MAX_DIM)) @@ -68,6 +75,7 @@ fn canvas_dims(aspect: f64) -> (u32, u32) { } /// Encode PNG for R2013+; older targets receive a BMP/DIB. +#[cfg(any(target_arch = "wasm32", test))] fn encode(img: RgbImage, png: bool) -> Option { if png { let mut buf = Cursor::new(Vec::new()); @@ -81,6 +89,7 @@ fn encode(img: RgbImage, png: bool) -> Option { /// Build an 8-bit palettised, `BI_RLE8`-compressed DIB. `None` when the image /// holds more than 256 distinct colours (the caller then uses 24-bit). +#[cfg(any(target_arch = "wasm32", test))] fn rle8_dib(img: &RgbImage) -> Option> { let (w, h) = (img.width(), img.height()); // Exact palette + per-pixel index (top-to-bottom, left-to-right). @@ -149,6 +158,7 @@ fn rle8_dib(img: &RgbImage) -> Option> { } /// 24-bit uncompressed DIB (fallback): the `image` BMP minus its file header. +#[cfg(any(target_arch = "wasm32", test))] fn bmp24_dib(img: &RgbImage) -> Option> { let mut buf = Cursor::new(Vec::new()); img.write_to(&mut buf, ImageFormat::Bmp).ok()?;