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