diff --git a/src/components/callbacks/main_window_callbacks.rs b/src/components/callbacks/main_window_callbacks.rs index c7fe771..b0cb57e 100644 --- a/src/components/callbacks/main_window_callbacks.rs +++ b/src/components/callbacks/main_window_callbacks.rs @@ -1,6 +1,6 @@ use js_sys::Array; -use wasm_bindgen::{JsCast, JsValue}; -use web_sys::{Blob, HtmlAnchorElement, Url}; +use wasm_bindgen::{prelude::*, JsCast, JsValue}; +use web_sys::{Blob, HtmlAnchorElement, HtmlDialogElement, HtmlFormElement, HtmlInputElement, Url}; use yew::prelude::*; use yewdux::prelude::*; @@ -104,3 +104,86 @@ pub fn export_json_button_callback(main_state: std::rc::Rc) -> Callba } }) } + +pub fn input_json_input_callback( + main_dispatch: Dispatch, + modal: HtmlDialogElement, +) -> Closure { + Closure::::new(move |e: Event| { + if let Some(input) = e.current_target() { + let input = input + .dyn_into::() + .expect("We know this is an input."); + if let Some(files) = input.files() { + if let Some(file) = files.get(0) { + let fr = web_sys::FileReader::new().unwrap(); + fr.read_as_text(&file).unwrap(); + let fr1 = fr.clone(); // Clone to avoid outliving closure + let main_dispatch = main_dispatch.clone(); // Clone to satisfy FnMut + // trait + let modal = modal.clone(); + let onload = Closure::::new(move |_: Event| { + if let Some(value) = &fr1.result().ok().and_then(|v| v.as_string()) { + let ms = serde_json::from_str::(value); + match ms { + Ok(ms) => main_dispatch.set(ms), + Err(e) => log::debug!("{:?}", e), + }; + modal.close(); + } + }); + fr.set_onload(Some(onload.as_ref().unchecked_ref())); + onload.forget(); // Magic (don't touch) + } + } + } + }) +} + +pub fn import_json_button_callback(main_dispatch: Dispatch) -> Callback { + Callback::from(move |_| { + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + let body = document.body().unwrap(); + let modal = document + .create_element("dialog") + .unwrap() + .dyn_into::() + .unwrap(); + modal.set_text_content(Some("Import File:")); + let onclose_callback = { + let modal = modal.clone(); + Closure::::new(move |_: Event| { + modal.remove(); + }) + }; + modal.set_onclose(Some(onclose_callback.as_ref().unchecked_ref())); + onclose_callback.forget(); + + let form = document + .create_element("form") + .unwrap() + .dyn_into::() + .unwrap(); + let input = document + .create_element("input") + .unwrap() + .dyn_into::() + .unwrap(); + input.set_type("file"); + input.set_accept(".json"); + form.append_child(&input).unwrap(); + + let input_callback = { + let main_dispatch = main_dispatch.clone(); + let modal = modal.clone(); + input_json_input_callback(main_dispatch, modal) + }; + input.set_onchange(Some(input_callback.as_ref().unchecked_ref())); + input_callback.forget(); // Magic straight from the docs, don't touch :( + + modal.append_child(&form).unwrap(); + body.append_child(&modal).unwrap(); + modal.show_modal().unwrap(); + }) +} diff --git a/src/components/main_window.rs b/src/components/main_window.rs index b3cd8fe..f042f51 100644 --- a/src/components/main_window.rs +++ b/src/components/main_window.rs @@ -72,87 +72,12 @@ pub fn MainWindow() -> Html { main_window_callbacks::export_csv_button_callback(main_state) }; - let export_json_button_callback = { - main_window_callbacks::export_json_button_callback(main_state) - }; + let export_json_button_callback = + { main_window_callbacks::export_json_button_callback(main_state) }; let import_json_button_callback = { let main_dispatch = main_dispatch.clone(); - Callback::from(move |_| { - let window = web_sys::window().unwrap(); - let document = window.document().unwrap(); - let body = document.body().unwrap(); - let modal = document - .create_element("dialog") - .unwrap() - .dyn_into::() - .unwrap(); - modal.set_text_content(Some("Import File:")); - let onclose_callback = { - let modal = modal.clone(); - Closure::::new(move |_: Event| { - modal.remove(); - }) - }; - modal.set_onclose(Some(onclose_callback.as_ref().unchecked_ref())); - onclose_callback.forget(); - - let form = document - .create_element("form") - .unwrap() - .dyn_into::() - .unwrap(); - let input = document - .create_element("input") - .unwrap() - .dyn_into::() - .unwrap(); - input.set_type("file"); - input.set_accept(".json"); - form.append_child(&input).unwrap(); - - let input_callback = { - let main_dispatch = main_dispatch.clone(); - let modal = modal.clone(); - Closure::::new(move |e: Event| { - if let Some(input) = e.current_target() { - let input = input - .dyn_into::() - .expect("We know this is an input."); - if let Some(files) = input.files() { - if let Some(file) = files.get(0) { - let fr = web_sys::FileReader::new().unwrap(); - fr.read_as_text(&file).unwrap(); - let fr1 = fr.clone(); // Clone to avoid outliving closure - let main_dispatch = main_dispatch.clone(); // Clone to satisfy FnMut - // trait - let modal = modal.clone(); - let onload = Closure::::new(move |_: Event| { - if let Some(value) = - &fr1.result().ok().and_then(|v| v.as_string()) - { - let ms = serde_json::from_str::(value); - match ms { - Ok(ms) => main_dispatch.set(ms), - Err(e) => log::debug!("{:?}", e), - }; - modal.close(); - } - }); - fr.set_onload(Some(onload.as_ref().unchecked_ref())); - onload.forget(); // Magic (don't touch) - } - } - } - }) - }; - input.set_onchange(Some(input_callback.as_ref().unchecked_ref())); - input_callback.forget(); // Magic straight from the docs, don't touch :( - - modal.append_child(&form).unwrap(); - body.append_child(&modal).unwrap(); - modal.show_modal().unwrap(); - }) + main_window_callbacks::import_json_button_callback(main_dispatch) }; let import_transfer_csv_callback = {