From 104f70b0968d7138d6cf944da98d95a405b1a049 Mon Sep 17 00:00:00 2001 From: jelemux Date: Wed, 11 Nov 2020 23:28:29 +0100 Subject: add addresses, generate name, improve responsiveness --- src/lib.rs | 221 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 129 insertions(+), 92 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 67c2eed..30d6d59 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ #![recursion_limit="1024"] extern crate wee_alloc; extern crate console_error_panic_hook; +use std::collections::HashSet; use name::{NameView,Name}; +use address::{AddressView,Address,AddressType}; use genpdf::Element as _; use genpdf::{elements, style, fonts}; use qrcodegen::QrCode; @@ -12,6 +14,7 @@ use vcard::{VCard, VCardError}; use std::panic; mod name; +mod address; // Use `wee_alloc` as the global allocator. #[global_allocator] @@ -21,6 +24,7 @@ fn init() { panic::set_hook(Box::new(console_error_panic_hook::hook)); } +#[derive(Clone)] pub struct Download { pub file_name: String, pub content: String, @@ -36,16 +40,7 @@ impl Download { } } -impl Clone for Download { - fn clone(&self) -> Self { - Self { - file_name: self.file_name.clone(), - content: self.content.clone(), - mime_type: self.mime_type.clone(), - } - } -} - +#[derive(Clone, Copy)] pub enum MimeType { PDF, VCard, @@ -62,28 +57,28 @@ impl MimeType { } } -impl Clone for MimeType { - fn clone(&self) -> Self { - match self { - MimeType::PDF => MimeType::PDF, - MimeType::VCard => MimeType::VCard, - MimeType::SVG => MimeType::SVG, - } - } +#[derive(Clone, Copy)] +pub enum DownloadOption { + PDF, + VCard, + QrCode, } pub struct MainView { link: ComponentLink, error: Vec, name: Name, + work_address: Address, + home_address: Address, download: Option, + selected_option: DownloadOption, } pub enum Msg { UpdateName(Name), - GenerateVCard, - GeneratePdf, - GenerateQrCode, + UpdateHomeAddress(Address), + UpdateWorkAddress(Address), + Generate(DownloadOption), Nope, } @@ -92,56 +87,85 @@ impl Component for MainView { type Properties = (); fn create(_props: Self::Properties, link: ComponentLink) -> Self { - MainView { link, error: vec![], name: Name::new(), download: None, } + MainView { + link, + error: vec![], + name: Name::new(), + work_address: Address::new_with_type(AddressType::Work), + home_address: Address::new_with_type(AddressType::Home), + download: None, + selected_option: DownloadOption::VCard + } } fn update(&mut self, msg: Self::Message) -> ShouldRender { self.error.clear(); match msg { - Msg::UpdateName(value) => self.name = value, - Msg::GenerateVCard => { - match self.generate_vcard() { - Ok(vcard) => self.download = Some( - Download { - file_name: format!("{}.vcs", self.name.formatted_name()), - content: vcard.to_string(), - mime_type: MimeType::VCard, - } - ), - 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::UpdateName(value) => { + self.name = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::UpdateHomeAddress(value) => { + self.home_address = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::UpdateWorkAddress(value) => { + self.work_address = value; + self.link.send_message(Msg::Generate(self.selected_option)); + }, + Msg::Generate(option) => { + self.selected_option = option; + + let vcard_content = match self.generate_vcard() { + Ok(vcard) => Some(vcard.to_string()), + Err(VCardError::FormatError(err)) => { + self.error.push(err.to_string()); + None + } + Err(VCardError::EmptyFormatName) => { + self.error.push(String::from("At least one of the name fields should be filled out.")); + None + } }; - } - Msg::GeneratePdf => { - match self.generate_pdf() { - Ok(pdf) => self.download = Some( - Download { - file_name: format!("Visitenkarten {}.pdf", self.name.formatted_name()), - content: pdf, - mime_type: MimeType::PDF, + + match option { + DownloadOption::VCard => { + if vcard_content.is_some() { + self.download = Some( + Download { + file_name: format!("{}.vcs", self.name.formatted_name()), + content: vcard_content.unwrap().to_string(), + mime_type: MimeType::VCard, + } + ) } - ), - Err(_) => self.error.push(String::from("Unexpected error while generating the PDF. Please contact me about it.")), - } - } - Msg::GenerateQrCode => { - let mut vcard_content = None; - match self.generate_vcard() { - Ok(vcard) => vcard_content = 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 vcard_content.is_some() { - match QrCode::encode_text(vcard_content.as_ref().unwrap(), QrCodeEcc::Low) { - Ok(qr) => self.download = Some( - Download { - file_name: format!("QR-Code VCard {}.svg", self.name.formatted_name()), - content: qr.to_svg_string(4), - mime_type: MimeType::SVG, - } - ), - Err(_) => self.error.push(String::from("Sorry, VCard is too long!")), - }; + } + DownloadOption::QrCode => { + if vcard_content.is_some() { + match QrCode::encode_text(vcard_content.as_ref().unwrap(), QrCodeEcc::Low) { + Ok(qr) => self.download = Some( + Download { + file_name: format!("QR-Code VCard {}.svg", self.name.formatted_name()), + content: qr.to_svg_string(4), + mime_type: MimeType::SVG, + } + ), + Err(_) => self.error.push(String::from("Sorry, VCard is too long!")), + }; + } + } + DownloadOption::PDF => { + match self.generate_pdf() { + Ok(pdf) => self.download = Some( + Download { + file_name: format!("Visitenkarten {}.pdf", self.name.formatted_name()), + content: pdf, + mime_type: MimeType::PDF, + } + ), + Err(_) => self.error.push(String::from("Unexpected error while generating the PDF. Please contact me about it.")), + } + } } } Msg::Nope => return false, @@ -158,29 +182,12 @@ impl Component for MainView { fn view(&self) -> Html { - let download = self.download.clone(); - - let on_name_input = self.link.batch_callback(move |n: Name| - if download.is_some() { - vec![ - Msg::UpdateName(n), - match download.as_ref().unwrap().mime_type { - MimeType::PDF => Msg::GeneratePdf, - MimeType::SVG => Msg::GenerateQrCode, - MimeType::VCard => Msg::GenerateVCard, - } - ] - } else { - vec![Msg::UpdateName(n), 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, + "vcard" => Msg::Generate(DownloadOption::VCard), + "pdf" => Msg::Generate(DownloadOption::PDF), + "qrcode" => Msg::Generate(DownloadOption::QrCode), _ => Msg::Nope, }, _ => Msg::Nope, @@ -204,10 +211,14 @@ impl Component for MainView { { self.render_errors() } - + -
-
+ + + + +
+