From ed19bef94a247d3eb501ae9f3bcd9496be229d80 Mon Sep 17 00:00:00 2001 From: jelemux Date: Fri, 5 Mar 2021 20:09:25 +0100 Subject: get pdf generation to work and refactor code a little --- src/view/main.rs | 485 ++++++++++--------------------------------------------- 1 file changed, 81 insertions(+), 404 deletions(-) (limited to 'src/view') diff --git a/src/view/main.rs b/src/view/main.rs index 40aaa34..3eb9677 100644 --- a/src/view/main.rs +++ b/src/view/main.rs @@ -7,18 +7,10 @@ use crate::model::property_groups::telephone::*; use crate::model::utility::*; use crate::model::vcard::VCardData; use crate::model::Error; -use crate::model::VCardPropertyInputGroupObject; use crate::view::property_group::PropertyGroupInputComponent; use crate::view::weak_links::WeakComponentLink; -use boolinator::Boolinator; -use chrono::prelude::*; -use genpdf::Element as _; -use genpdf::{elements, fonts, style}; use qrcodegen::QrCode; use qrcodegen::QrCodeEcc; -use uuid::Uuid; -use vobject::parameters; -use vobject::vcard::VcardBuilder; use yew::prelude::*; use yew::services::ConsoleService; use yewtil::ptr::Mrc; @@ -156,64 +148,36 @@ impl Component for MainView { false } Msg::Generate => { - if self.selected_option == DownloadOption::VCard - || self.selected_option == DownloadOption::QrCode - { - for name_link in self.name_links.iter() { - let name_link = name_link.borrow().clone().unwrap(); - name_link.send_message(NameMsg::Generate); - } - - for address_link in self.address_links.iter() { - let address_link = address_link.borrow().clone().unwrap(); - address_link.send_message(AddressMsg::Generate); - } + + for name_link in self.name_links.iter() { + let name_link = name_link.borrow().clone().unwrap(); + name_link.send_message(NameMsg::Generate); + } - for telephone_link in self.telephone_links.iter() { - let telephone_link = telephone_link.borrow().clone().unwrap(); - telephone_link.send_message(TelephoneMsg::Generate); - } + for address_link in self.address_links.iter() { + let address_link = address_link.borrow().clone().unwrap(); + address_link.send_message(AddressMsg::Generate); + } - for other_identifications_link in self.other_identifications_links.iter() { - let other_identifications_link = - other_identifications_link.borrow().clone().unwrap(); - other_identifications_link.send_message(OtherIdentificationMsg::Generate) - } + for telephone_link in self.telephone_links.iter() { + let telephone_link = telephone_link.borrow().clone().unwrap(); + telephone_link.send_message(TelephoneMsg::Generate); + } - for organizational_link in self.organizational_links.iter() { - let organizational_link = organizational_link.borrow().clone().unwrap(); - organizational_link.send_message(OrganizationalMsg::Generate) - } + for other_identifications_link in self.other_identifications_links.iter() { + let other_identifications_link = + other_identifications_link.borrow().clone().unwrap(); + other_identifications_link.send_message(OtherIdentificationMsg::Generate) + } - for communcation_link in self.communcation_links.iter() { - let communcation_link = communcation_link.borrow().clone().unwrap(); - communcation_link.send_message(CommunicationMsg::Generate) - } + for organizational_link in self.organizational_links.iter() { + let organizational_link = organizational_link.borrow().clone().unwrap(); + organizational_link.send_message(OrganizationalMsg::Generate) } - if self.selected_option == DownloadOption::PDF { - match self.generate_pdf() { - Ok(pdf) => { - let mut vcard_name = String::new(); - if let Some(vcard_data) = self.vcard_data.get_mut() { - if let Some(name) = vcard_data.names.get(0) { - vcard_name = name.generate_fn(); - } - } - self.download = Some( - Download { - file_name: format!("Visitenkarten {}.pdf", vcard_name), - content: pdf, - mime_type: MimeType::PDF, - } - ); - }, - Err(_) => self.error = Some( - Error { - msg: String::from("Unexpected error while generating the PDF. Please contact me about it.") - } - ), - } + for communcation_link in self.communcation_links.iter() { + let communcation_link = communcation_link.borrow().clone().unwrap(); + communcation_link.send_message(CommunicationMsg::Generate) } true @@ -291,229 +255,71 @@ impl Component for MainView { Msg::GenerationComplete => { self.answer_count = 0; - let vcard_data = self.vcard_data.clone_inner(); - - let mut builder = VcardBuilder::new(); - - for name in vcard_data.names { - if !name.is_empty() { - builder = builder.with_fullname(name.generate_fn()).with_name( - parameters!(), - (!name.last_name.is_empty()).as_some(name.last_name.clone()), - (!name.first_name.is_empty()).as_some(name.first_name.clone()), - (!name.middle_name.is_empty()).as_some(name.middle_name.clone()), - (!name.prefix.is_empty()).as_some(name.prefix.clone()), - (!name.suffix.is_empty()).as_some(name.suffix.clone()), - ); - } - } - - for address in vcard_data.addresses { - if !address.is_empty() { - let mut types = String::new(); - if address.work { - types.push_str("WORK"); - } - if address.home { - if !types.is_empty() { - types.push(','); + if let DownloadOption::PDF = self.selected_option { + match self.vcard_data.generate_pdf() { + Ok(pdf) => { + let mut vcard_name = String::new(); + if let Some(vcard_data) = self.vcard_data.get_mut() { + if let Some(name) = vcard_data.names.get(0) { + vcard_name = name.generate_fn(); + } } - types.push_str("HOME") - } - let params = if types.is_empty() { - parameters!() - } else { - parameters!("TYPE" => types) - }; - - builder = builder.with_adr( - params, - (!address.post_office_box.is_empty()) - .as_some(address.post_office_box.clone()), - (!address.extension.is_empty()).as_some(address.extension.clone()), - (!address.street.is_empty()).as_some(address.street.clone()), - (!address.locality.is_empty()).as_some(address.locality.clone()), - (!address.region.is_empty()).as_some(address.region.clone()), - (!address.code.is_empty()).as_some(address.code.clone()), - (!address.country.is_empty()).as_some(address.country.clone()), - ); - } - } - - for telephone in vcard_data.telephones { - if !telephone.is_empty() { - let mut types = String::new(); - if telephone.work { - types.push_str("WORK"); - } - if telephone.home { - if !types.is_empty() { - types.push(','); - } - types.push_str("HOME") - } - if telephone.text { - if !types.is_empty() { - types.push(','); - } - types.push_str("TEXT") - } - if telephone.voice { - if !types.is_empty() { - types.push(','); - } - types.push_str("VOICE") - } - if telephone.fax { - if !types.is_empty() { - types.push(','); - } - types.push_str("FAX") - } - if telephone.cell { - if !types.is_empty() { - types.push(','); - } - types.push_str("CELL") - } - if telephone.video { - if !types.is_empty() { - types.push(','); - } - types.push_str("VIDEO") - } - if telephone.pager { - if !types.is_empty() { - types.push(','); + self.download = Some( + Download { + file_name: format!("Visitenkarten {}.pdf", vcard_name), + content: pdf, + mime_type: MimeType::PDF, + } + ); + }, + Err(_) => self.error = Some( + Error { + msg: String::from("Unexpected error while generating the PDF. Please contact me about it.") } - types.push_str("PAGER") + ), + }; + } else { + match self.vcard_data.build_vcard() { + Ok(vcard) => { + match self.selected_option { + DownloadOption::VCard => { + self.download = Some(Download { + file_name: String::from("VCard.vcs"), + content: vobject::write_component(&vcard), + mime_type: MimeType::VCard, + }); + } + DownloadOption::QrCode => { + match QrCode::encode_text( + &vobject::write_component(&vcard), + QrCodeEcc::Low, + ) { + Ok(qr) => { + self.download = Some(Download { + file_name: String::from("QR-Code VCard.svg"), + content: qr.to_svg_string(4), + mime_type: MimeType::SVG, + }) + } + Err(_) => { + self.error = Some(Error { + msg: String::from("Sorry, VCard is too long!"), + }) + } + }; + } + _ => (), + }; } - if telephone.text_phone { - if !types.is_empty() { - types.push(','); - } - types.push_str("TEXTPHONE") + Err(err) => { + self.error = Some(Error { + msg: err.to_string(), + }) } - - let params = if types.is_empty() { - parameters!() - } else { - parameters!("TYPE" => types) - }; - - builder = builder.with_tel(params, telephone.number.clone()); - } - } - - for communication in vcard_data.communications { - if !communication.email_address.is_empty() { - builder = builder.with_email(communication.email_address.clone()); - } - if !communication.impp.is_empty() { - builder = builder.with_impp(communication.impp.clone()); - } - } - - for other_identification in vcard_data.other_identifications { - if !other_identification.nickname.is_empty() { - builder = - builder.with_nickname(parameters!(), other_identification.nickname); - } - - match other_identification.photo { - Some(file) => builder = builder.with_photo(parameters!(), file.content), - None => (), }; - - if !other_identification.anniversary.is_empty() { - builder = builder.with_anniversary(other_identification.anniversary); - } - - if !other_identification.birthday.is_empty() { - builder = builder.with_bday(parameters!(), other_identification.birthday); - } - - if !other_identification.gender.is_empty() { - builder = builder.with_gender(parameters!(), other_identification.gender); - } - } - - for organizational in vcard_data.organizationals { - if !organizational.org.is_empty() { - builder = builder.with_org(vec![organizational.org]); - } - - match organizational.logo { - Some(file) => builder = builder.with_logo(file.content), - None => (), - }; - - if !organizational.title.is_empty() { - builder = builder.with_title(organizational.title); - } - - if !organizational.role.is_empty() { - builder = builder.with_role(organizational.role); - } - - if !organizational.member.is_empty() { - builder = builder.with_member(organizational.member); - } - - if !organizational.related.is_empty() { - builder = builder.with_related(organizational.related); - } } - let uid = format!("urn:uuid:{}", Uuid::new_v4()); - - let rev = Local::now().to_string(); - - match builder - .with_version("4.0".to_string()) - .with_rev(rev) - .with_uid(uid) - .build() - { - Ok(vcard) => { - match self.selected_option { - DownloadOption::VCard => { - self.download = Some(Download { - file_name: String::from("VCard.vcs"), - content: vobject::write_component(&vcard), - mime_type: MimeType::VCard, - }); - } - DownloadOption::QrCode => { - match QrCode::encode_text( - &vobject::write_component(&vcard), - QrCodeEcc::Low, - ) { - Ok(qr) => { - self.download = Some(Download { - file_name: String::from("QR-Code VCard.svg"), - content: qr.to_svg_string(4), - mime_type: MimeType::SVG, - }) - } - Err(_) => { - self.error = Some(Error { - msg: String::from("Sorry, VCard is too long!"), - }) - } - }; - } - _ => (), - }; - } - Err(err) => { - self.error = Some(Error { - msg: err.to_string(), - }) - } - }; - match self.vcard_data.get_mut() { Some(vcard_data) => *vcard_data = VCardData::new(), None => ConsoleService::info("Couldn't reset VCardData"), @@ -810,135 +616,6 @@ impl MainView { } } - fn generate_pdf(&self) -> Result { - let regular_bytes = - include_bytes!("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"); - let regular_font_data = fonts::FontData::new( - regular_bytes.to_vec(), - Some(printpdf::BuiltinFont::Helvetica), - ) - .expect("font data should be correct"); - - let bold_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-Bold.ttf"); - let bold_font_data = fonts::FontData::new( - bold_bytes.to_vec(), - Some(printpdf::BuiltinFont::HelveticaBold), - ) - .expect("font data should be correct"); - - let italic_bytes = include_bytes!("/usr/share/fonts/liberation/LiberationSans-Italic.ttf"); - let italic_font_data = fonts::FontData::new( - italic_bytes.to_vec(), - Some(printpdf::BuiltinFont::HelveticaOblique), - ) - .expect("font data should be correct"); - - let bold_italic_bytes = - include_bytes!("/usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf"); - let bold_italic_font_data = fonts::FontData::new( - bold_italic_bytes.to_vec(), - Some(printpdf::BuiltinFont::HelveticaBoldOblique), - ) - .expect("font data should be correct"); - - let font_family = fonts::FontFamily { - regular: regular_font_data, - bold: bold_font_data, - italic: italic_font_data, - bold_italic: bold_italic_font_data, - }; - - let mut doc = genpdf::Document::new(font_family); - - doc.set_title("wasm-card test"); - doc.set_minimal_conformance(); - - let mut decorator = genpdf::SimplePageDecorator::new(); - decorator.set_margins(10); - doc.set_page_decorator(decorator); - - doc.set_line_spacing(1.25); - - doc.push( - elements::Paragraph::new("genpdf Demo Document") - .aligned(elements::Alignment::Center) - .styled(style::Style::new().bold().with_font_size(20)), - ); - - let mut card_data = elements::Paragraph::new(""); - - if let Ok(vcard_data) = self.vcard_data.irc().try_unwrap() { - if let Some(name) = vcard_data.names.get(0) { - card_data.push_styled( - name.generate_fn(), - style::Effect::Bold - ); - } - card_data.push( - "" - ); - if let Some(communication) = vcard_data.communications.get(0) { - card_data.push( - communication.email_address.clone() - ); - } - card_data.push( - "" - ); - if let Some(address) = vcard_data.addresses.get(0) { - card_data.push( - address.street.clone() - ); - card_data.push( - format!("{} {} {}", address.code, address.locality, address.extension) - ); - card_data.push( - format!("{} {}", address.region, address.country) - ); - } - card_data.push( - "" - ); - for telephone in vcard_data.telephones { - card_data.push( - telephone.number - ); - } - } else { - ConsoleService::log("Could not unwrap vcard_data."); - } - - let framed_card_data = elements::FramedElement::new( - card_data - ); - - let mut table = elements::TableLayout::new(vec![1,1]); - table.set_cell_decorator( - elements::FrameCellDecorator::new(false, false, false) - ); - for _i in 0..4 { - table - .row() - .element(framed_card_data.clone()) - .element(framed_card_data.clone()) - .push() - .expect("invalid table row"); - } - - doc.push(table); - - // TODO fill doc with real data - - let mut buf: Vec = Vec::new(); - match doc.render(&mut buf) { - Ok(_) => Ok(match String::from_utf8(buf) { - Ok(s) => s, - Err(_) => return Err(()), - }), - Err(_) => Err(()), - } - } - fn get_subcomponent_count(&self) -> usize { self.name_links.len() + self.address_links.len() -- cgit v1.2.3