From 80584becc1a86e9fe2832a3201172194546f8cb8 Mon Sep 17 00:00:00 2001 From: kirjavascript Date: Wed, 15 Mar 2023 20:05:20 +0000 Subject: [PATCH] add saving to file abstraction --- Cargo.lock | 8 ++++---- frontend/Cargo.toml | 4 ++-- frontend/src/app.rs | 5 ++++- frontend/src/widgets/file.rs | 40 ++++++++++++++++++++++++++++-------- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39afd6b..c0dc76b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1364,9 +1364,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -2664,9 +2664,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index c2c97bd..94a4a71 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -19,18 +19,18 @@ emu = { path = "../emu" } egui = "0.21.0" eframe = { version = "0.21.0", features = ["persistence"] } -rfd = "0.11" # serde = { version = "1", features = ["derive"] } # You only need this if you want app persistence # native: [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tracing-subscriber = "0.3" +rfd = "0.11" # web: [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" tracing-wasm = "0.2" wasm-bindgen-futures = "0.4" -web-sys = { version = "0.3.58" } +web-sys = { version = "0.3.61", features = ["Window", "Url", "File", "Blob", "HtmlAnchorElement", "BlobPropertyBag", "FilePropertyBag"] } wasm-bindgen = "=0.2.84" js-sys = "0.3" diff --git a/frontend/src/app.rs b/frontend/src/app.rs index 3fe59fe..e091d7a 100644 --- a/frontend/src/app.rs +++ b/frontend/src/app.rs @@ -111,10 +111,13 @@ impl eframe::App for App { self.test_vec.pop_front(); } - if ui.button("Open fileā€¦").clicked() { + if ui.button("Open file").clicked() { self.file.open(); } + if ui.button("Save file").clicked() { + self.file.save("test.txt", vec![0, 1, 2, 3, 33]); + } if let Some(file) = self.file.get() { println!("{:#?}", file); diff --git a/frontend/src/widgets/file.rs b/frontend/src/widgets/file.rs index 62f9bb7..cd095cb 100644 --- a/frontend/src/widgets/file.rs +++ b/frontend/src/widgets/file.rs @@ -1,4 +1,4 @@ -type File = Vec; +type FileData = Vec; // wasm @@ -7,15 +7,15 @@ use wasm_bindgen::prelude::*; #[cfg(target_arch = "wasm32")] use wasm_bindgen::JsCast; #[cfg(target_arch = "wasm32")] -use web_sys::{window, console, Element, HtmlInputElement, FileReader}; +use web_sys::{window, Url, File, HtmlInputElement, FileReader}; #[cfg(target_arch = "wasm32")] -use js_sys::{Uint8Array, ArrayBuffer, Object}; +use js_sys::{Uint8Array, ArrayBuffer}; #[cfg(target_arch = "wasm32")] pub struct FileDialog { - tx: std::sync::mpsc::Sender, - rx: std::sync::mpsc::Receiver, + tx: std::sync::mpsc::Sender, + rx: std::sync::mpsc::Receiver, input: HtmlInputElement, closure: Option>, } @@ -69,7 +69,7 @@ impl FileDialog { let onload_closure = Closure::once(Box::new(move || { let array_buffer = reader_clone.result().unwrap().dyn_into::().unwrap(); let buffer = Uint8Array::new(&array_buffer).to_vec(); - tx.send(buffer); + tx.send(buffer).ok(); })); reader.set_onload(Some(onload_closure.as_ref().unchecked_ref())); @@ -91,6 +91,21 @@ impl FileDialog { } } + pub fn save(&self, filename: &str, filedata: FileData) { + let array = js_sys::Uint8Array::from(filedata.as_slice()); + let blob_parts = js_sys::Array::new(); + blob_parts.push(&array.buffer()); + + let file = File::new_with_blob_sequence_and_options( + &blob_parts.into(), + filename, + web_sys::FilePropertyBag::new().type_("application/octet-stream") + ).unwrap(); + let url = Url::create_object_url_with_blob(&file); + if let Some(window) = web_sys::window() { + window.location().set_href(&url.unwrap()).ok(); + } + } } // native @@ -100,7 +115,7 @@ use rfd; #[cfg(not(target_arch = "wasm32"))] pub struct FileDialog { - file: Option, + file: Option, } #[cfg(not(target_arch = "wasm32"))] @@ -121,8 +136,17 @@ impl FileDialog { } } - pub fn get(&mut self) -> Option { + pub fn get(&mut self) -> Option { std::mem::replace(&mut self.file, None) } + pub fn save(&self, filename: &str, file: FileData) { + let path = rfd::FileDialog::new() + .set_file_name(filename) + .save_file(); + + if let Some(path) = path { + std::fs::write(path, file).ok(); + } + } }