From 8cfb6b0b199586d45edf5abefbb8cf26f98cb829 Mon Sep 17 00:00:00 2001 From: jelemux Date: Thu, 22 Oct 2020 23:09:31 +0200 Subject: added QR code generation --- Cargo.toml | 1 + src/lib.rs | 2 + src/view.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 111 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bda1251..2dc092e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ printpdf = "0.3.3" base64 = "0.13.0" vcard = "0.4.7" console_error_panic_hook = "0.1.6" +qrcodegen = "1.6.0" [dependencies.chrono] version = "0.4.19" diff --git a/src/lib.rs b/src/lib.rs index 2e54410..fd0e53c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ +#![recursion_limit="1024"] + mod view; mod pdfgen; \ No newline at end of file diff --git a/src/view.rs b/src/view.rs index 281cb63..8da1a6c 100644 --- a/src/view.rs +++ b/src/view.rs @@ -1,4 +1,6 @@ extern crate console_error_panic_hook; +use qrcodegen::QrCode; +use qrcodegen::QrCodeEcc; use crate::pdfgen; use wasm_bindgen::prelude::*; use js_sys; @@ -12,14 +14,17 @@ fn init() { pub struct Form { link: ComponentLink, - error: Option, + error: Vec, formatted_name: String, - generated_vcard: Option, + vcard: Option, + qr_code: Option, } pub enum Msg { UpdateFormattedName(String), GenerateVCard, + GeneratePdf, + GenerateQrCode, Nope, } @@ -28,21 +33,42 @@ impl Component for Form { type Properties = (); fn create(_props: Self::Properties, link: ComponentLink) -> Self { - Self { link, error: None, formatted_name: String::new(), generated_vcard: None } + Self { link, error: vec![], formatted_name: String::new(), vcard: None, qr_code: None } } fn update(&mut self, msg: Self::Message) -> ShouldRender { + self.error.clear(); match msg { Msg::UpdateFormattedName(value) => self.formatted_name = String::from(value), Msg::GenerateVCard => { match self.generate_vcard() { - Ok(vcard) => self.generated_vcard = Some(vcard.to_string()), - Err(VCardError::FormatError(err)) => self.error = Some(err.to_string()), - Err(VCardError::EmptyFormatName) => self.error = Some(String::from("A VCard should have at least one formatted name.")), + Ok(vcard) => self.vcard = Some(vcard.to_string()), + Err(VCardError::FormatError(err)) => self.error.push(err.to_string()), + Err(VCardError::EmptyFormatName) => self.error.push(String::from("A VCard should have at least one formatted name.")), }; } - Msg::Nope => (), + Msg::GeneratePdf => { + + } + Msg::GenerateQrCode => { + match self.generate_vcard() { + Ok(vcard) => self.vcard = Some(vcard.to_string()), + Err(VCardError::FormatError(err)) => self.error.push(err.to_string()), + Err(VCardError::EmptyFormatName) => self.error.push(String::from("A VCard should have at least one formatted name.")), + }; + if self.vcard.is_some() { + match QrCode::encode_text(self.vcard.as_ref().unwrap(), QrCodeEcc::Low) { + Ok(qr) => self.qr_code = Some(qr.to_svg_string(4)), + Err(_) => self.error.push(String::from("Sorry, VCard is too long!")), + }; + } + } + Msg::Nope => return false, }; + if self.error.len() > 0 { + self.vcard = None; + self.qr_code = None; + } true } @@ -52,26 +78,63 @@ impl Component for Form { fn view(&self) -> Html { - let formatted_name_input = self.link.callback(|e: ChangeData| + let formatted_name_input = self.link.batch_callback(|e: InputData| + vec![Msg::UpdateFormattedName(e.value), Msg::GenerateVCard] + ); + + let download_options = self.link.callback(|e: ChangeData| match e { - ChangeData::Value(v) => Msg::UpdateFormattedName(v), + ChangeData::Select(v) => match v.value().as_str() { + "vcard" => Msg::GenerateVCard, + "pdf" => Msg::GeneratePdf, + "qrcode" => Msg::GenerateQrCode, + _ => Msg::Nope, + }, _ => Msg::Nope, } ); html!{ -
+
+ { self.render_error() } - - - - - - - - +

{ "Name" }

+
+ + +
+ + +
+ + + + + + + + +
+ + +
+ { self.render_pdf() } { self.render_vcard() } + +
+ { self.render_qrcode() } +
} } @@ -85,14 +148,18 @@ impl Form { } } fn render_error(&self) -> Html { - if self.error.is_some() { - html!{ -
-

{ self.error.as_ref().unwrap() }

-
- } - } else { - html!{} + html!{ + <> + { + for self.error.iter().map(|err| + html!{ +
+

{ err }

+
+ } + ) + } + } } fn render_pdf(&self) -> Html { @@ -108,8 +175,8 @@ impl Form { } } fn render_vcard(&self) -> Html { - if self.generated_vcard.is_some() { - let data = base64::encode(self.generated_vcard.as_ref().unwrap()); + if self.vcard.is_some() { + let data = base64::encode(self.vcard.as_ref().unwrap()); let uri_component: String = js_sys::encode_uri_component(&data).into(); let href = format!("data:text/vcard;base64,{}", uri_component); @@ -122,6 +189,19 @@ impl Form { html!{} } } + fn render_qrcode(&self) -> Html { + if self.qr_code.is_some() { + let data = base64::encode(self.qr_code.as_ref().unwrap()); + let uri_component: String = js_sys::encode_uri_component(&data).into(); + let src = format!("data:image/svg+xml;base64,{}", uri_component); + + html!{ + QR Code + } + } else { + html!{} + } + } } -- cgit v1.2.3