extern crate console_error_panic_hook; use qrcodegen::QrCode; use qrcodegen::QrCodeEcc; use crate::pdfgen; use wasm_bindgen::prelude::*; use js_sys; use yew::prelude::*; use vcard::{VCard, VCardError}; use std::panic; fn init() { panic::set_hook(Box::new(console_error_panic_hook::hook)); } pub struct Form { link: ComponentLink, error: Vec, formatted_name: String, vcard: Option, qr_code: Option, } pub enum Msg { UpdateFormattedName(String), GenerateVCard, GeneratePdf, GenerateQrCode, Nope, } impl Component for Form { type Message = Msg; type Properties = (); fn create(_props: Self::Properties, link: ComponentLink) -> Self { 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.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::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 } fn change(&mut self, _props: Self::Properties) -> ShouldRender { false } fn view(&self) -> Html { 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::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() }
} } } impl Form { fn generate_vcard(&self) -> Result { match VCard::from_formatted_name_str(&self.formatted_name) { Ok(vcard) => Ok(vcard), Err(err) => Err(err), } } fn render_error(&self) -> Html { html!{ <> { for self.error.iter().map(|err| html!{

{ err }

} ) } } } fn render_pdf(&self) -> Html { let raw = pdfgen::genpdf(); let data = base64::encode(&raw); let uri_component: String = js_sys::encode_uri_component(&data).into(); let href = format!{"data:application/pdf;base64,{}", uri_component }; html!{ { "Download PDF" } } } fn render_vcard(&self) -> Html { 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); html!{ { "Download vCard" } } } else { 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!{} } } } #[wasm_bindgen(start)] pub fn run_app() { init(); App::
::new().mount_to_body(); }