web: zip for batch processing, resolves #39

master
Sameer Puri 2 years ago
parent 5ff664831f
commit 29722b6fb2

30
Cargo.lock generated

@ -286,6 +286,24 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.13.4" version = "0.13.4"
@ -1297,6 +1315,7 @@ dependencies = [
"web-sys", "web-sys",
"yew", "yew",
"yewdux", "yewdux",
"zip",
] ]
[[package]] [[package]]
@ -1849,3 +1868,14 @@ dependencies = [
"quote", "quote",
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "zip"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
dependencies = [
"byteorder",
"crc32fast",
"crossbeam-utils",
]

@ -21,6 +21,7 @@ log = "0.4"
svgtypes = "0.11" svgtypes = "0.11"
serde_json = "1" serde_json = "1"
thiserror = "1.0" thiserror = "1.0"
zip = { version = "0.6", default-features = false }
yew = { version ="0.20", features = ["csr"] } yew = { version ="0.20", features = ["csr"] }
yewdux = "0.9.2" yewdux = "0.9.2"

@ -1,10 +1,14 @@
use std::path::Path; use std::{
io::Cursor,
path::{Path, PathBuf},
};
use base64::Engine; use base64::Engine;
use g_code::{ use g_code::{
emit::{format_gcode_fmt, FormatOptions}, emit::{format_gcode_fmt, format_gcode_io, FormatOptions},
parse::snippet_parser, parse::snippet_parser,
}; };
use js_sys::Date;
use log::Level; use log::Level;
use roxmltree::Document; use roxmltree::Document;
use svg2gcode::{svg2program, ConversionOptions, Machine}; use svg2gcode::{svg2program, ConversionOptions, Machine};
@ -20,6 +24,7 @@ use state::*;
use ui::*; use ui::*;
use util::*; use util::*;
use yewdux::prelude::{use_store, Dispatch}; use yewdux::prelude::{use_store, Dispatch};
use zip::{write::FileOptions, CompressionMethod, ZipWriter};
#[function_component] #[function_component]
fn App(_props: &()) -> Html { fn App(_props: &()) -> Html {
@ -45,6 +50,13 @@ fn App(_props: &()) -> Html {
let app_store = app_store.clone(); let app_store = app_store.clone();
Callback::from(move |_| { Callback::from(move |_| {
generating_setter.set(true); generating_setter.set(true);
let mut zip = ZipWriter::new(Cursor::new(vec![]));
let opts = FileOptions::default().compression_method(CompressionMethod::Stored);
if app_store.svgs.len() > 1 {
zip.add_directory("svg2gcode_output", opts.clone()).unwrap();
}
for svg in app_store.svgs.iter() { for svg in app_store.svgs.iter() {
let options = ConversionOptions { let options = ConversionOptions {
dimensions: svg.dimensions, dimensions: svg.dimensions,
@ -90,24 +102,59 @@ fn App(_props: &()) -> Html {
let program = let program =
svg2program(&document, &app_store.settings.conversion, options, machine); svg2program(&document, &app_store.settings.conversion, options, machine);
let gcode = { let filepath = if app_store.svgs.len() > 1 {
let mut acc: String = String::new(); PathBuf::from("svg2gcode_output")
format_gcode_fmt( .join(Path::new(svg.filename.as_str()).with_extension("gcode"))
} else {
Path::new(svg.filename.as_str()).with_extension("gcode")
};
if app_store.svgs.len() > 1 {
zip.start_file(filepath.to_string_lossy(), opts.clone())
.unwrap();
format_gcode_io(
&program, &program,
FormatOptions { FormatOptions {
checksums: app_store.settings.postprocess.checksums, checksums: app_store.settings.postprocess.checksums,
line_numbers: app_store.settings.postprocess.line_numbers, line_numbers: app_store.settings.postprocess.line_numbers,
..Default::default() ..Default::default()
}, },
&mut acc, &mut zip,
) )
.unwrap(); .unwrap();
acc } else if app_store.svgs.len() == 1 {
}; let gcode = {
let mut acc = String::new();
format_gcode_fmt(
&program,
FormatOptions {
checksums: app_store.settings.postprocess.checksums,
line_numbers: app_store.settings.postprocess.line_numbers,
..Default::default()
},
&mut acc,
)
.unwrap();
acc
};
prompt_download(filepath, gcode.as_bytes());
}
}
let filepath = Path::new(svg.filename.as_str()).with_extension("gcode"); if app_store.svgs.len() > 1 {
prompt_download(filepath, gcode.as_bytes()); zip.set_comment(format!(
"Created with svg2gcode: https://sameer.github.io/svg2gcode/\n{}",
env!("CARGO_PKG_DESCRIPTION")
));
let output = zip.finish().unwrap();
let date = Date::new_0().to_iso_string();
prompt_download(
format!("svg2gcode_bulk_download_{date}.zip"),
output.get_ref(),
);
} }
generating_setter.set(false); generating_setter.set(false);
}) })
}; };
@ -122,6 +169,26 @@ fn App(_props: &()) -> Html {
{ env!("CARGO_PKG_DESCRIPTION") } { env!("CARGO_PKG_DESCRIPTION") }
</p> </p>
<SvgForm/> <SvgForm/>
<ButtonGroup>
<Button
title="Generate G-Code"
style={ButtonStyle::Primary}
loading={*generating}
icon={
html_nested! (
<Icon name={IconName::Download} />
)
}
disabled={generate_disabled}
onclick={generate_onclick}
/>
<HyperlinkButton
title="Settings"
style={ButtonStyle::Default}
icon={IconName::Edit}
href="#settings"
/>
</ButtonGroup>
<div class={classes!("card-container", "columns")}> <div class={classes!("card-container", "columns")}>
{ {
for app_store.svgs.iter().enumerate().map(|(i, svg)| { for app_store.svgs.iter().enumerate().map(|(i, svg)| {
@ -155,26 +222,6 @@ fn App(_props: &()) -> Html {
}) })
} }
</div> </div>
<ButtonGroup>
<Button
title="Generate G-Code"
style={ButtonStyle::Primary}
loading={*generating}
icon={
html_nested! (
<Icon name={IconName::Download} />
)
}
disabled={generate_disabled}
onclick={generate_onclick}
/>
<HyperlinkButton
title="Settings"
style={ButtonStyle::Default}
icon={IconName::Edit}
href="#settings"
/>
</ButtonGroup>
<SettingsForm/> <SettingsForm/>
<ImportExportModal/> <ImportExportModal/>
</div> </div>

Loading…
Cancel
Save