summaryrefslogtreecommitdiff
path: root/src/view.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/view.rs')
-rw-r--r--src/view.rs151
1 files changed, 113 insertions, 38 deletions
diff --git a/src/view.rs b/src/view.rs
index 8da1a6c..9557dc5 100644
--- a/src/view.rs
+++ b/src/view.rs
@@ -1,7 +1,8 @@
extern crate console_error_panic_hook;
+use genpdf::Element as _;
+use genpdf::{elements, style, fonts};
use qrcodegen::QrCode;
use qrcodegen::QrCodeEcc;
-use crate::pdfgen;
use wasm_bindgen::prelude::*;
use js_sys;
use yew::prelude::*;
@@ -12,12 +13,42 @@ fn init() {
panic::set_hook(Box::new(console_error_panic_hook::hook));
}
+struct Download {
+ file_name: String,
+ content: Box<dyn AsRef<[u8]>>,
+ mime_type: MimeType,
+}
+
+impl Download {
+ fn as_data_link(&self) -> String {
+ let data = base64::encode(&*self.content);
+ let uri_component: String = js_sys::encode_uri_component(&data).into();
+
+ format!("data:{};base64,{}", self.mime_type.as_text(), uri_component)
+ }
+}
+
+enum MimeType {
+ PDF,
+ VCard,
+ SVG,
+}
+
+impl MimeType {
+ fn as_text(&self) -> &str {
+ match self {
+ MimeType::PDF => "application/pdf",
+ MimeType::VCard => "text/vcard",
+ MimeType::SVG => "image/svg+xml",
+ }
+ }
+}
+
pub struct Form {
link: ComponentLink<Self>,
error: Vec<String>,
formatted_name: String,
- vcard: Option<String>,
- qr_code: Option<String>,
+ download: Option<Download>,
}
pub enum Msg {
@@ -33,7 +64,7 @@ impl Component for Form {
type Properties = ();
fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
- Self { link, error: vec![], formatted_name: String::new(), vcard: None, qr_code: None }
+ Self { link, error: vec![], formatted_name: String::new(), download: None, }
}
fn update(&mut self, msg: Self::Message) -> ShouldRender {
@@ -42,23 +73,45 @@ impl Component for Form {
Msg::UpdateFormattedName(value) => self.formatted_name = String::from(value),
Msg::GenerateVCard => {
match self.generate_vcard() {
- Ok(vcard) => self.vcard = Some(vcard.to_string()),
+ Ok(vcard) => self.download = Some(
+ Download {
+ file_name: format!("{}.vcs",self.formatted_name),
+ content: Box::new(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::GeneratePdf => {
-
+ match self.generate_pdf() {
+ Ok(pdf) => self.download = Some(
+ Download {
+ file_name: format!("Visitenkarten {}.pdf", self.formatted_name),
+ content: Box::new(pdf),
+ mime_type: MimeType::PDF,
+ }
+ ),
+ 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) => self.vcard = Some(vcard.to_string()),
+ 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 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)),
+ 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.formatted_name),
+ content: Box::new(qr.to_svg_string(4)),
+ mime_type: MimeType::SVG,
+ }
+ ),
Err(_) => self.error.push(String::from("Sorry, VCard is too long!")),
};
}
@@ -66,8 +119,7 @@ impl Component for Form {
Msg::Nope => return false,
};
if self.error.len() > 0 {
- self.vcard = None;
- self.qr_code = None;
+ self.download = None;
}
true
}
@@ -124,17 +176,13 @@ impl Component for Form {
<input id="suffix" type="text"/>
</form>
<select id="download_options" onchange=download_options>
- <option value="">{ "" }</option>
<option value="vcard">{ "VCard (.vcf)" }</option>
<option value="pdf">{ "Print-ready PDF" }</option>
<option value="qrcode">{ "QR Code" }</option>
</select>
- { self.render_pdf() } { self.render_vcard() }
+ { self.render_download() }
- <div class="row">
- { self.render_qrcode() }
- </div>
</div>
}
}
@@ -147,6 +195,47 @@ impl Form {
Err(err) => Err(err),
}
}
+ fn generate_pdf(&self) -> Result<Vec<u8>, ()>{
+ 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("BCard test");
+ doc.set_minimal_conformance();
+ doc.set_margins(10);
+ 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)),
+ );
+
+ // TODO fill doc with real data
+
+ let mut buf: Vec<u8> = Vec::new();
+ match doc.render(&mut buf) {
+ Ok(_) => Ok(buf),
+ Err(_) => Err(()),
+ }
+ }
fn render_error(&self) -> Html {
html!{
<>
@@ -162,33 +251,19 @@ impl Form {
</>
}
}
- 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!{
- <a href=href download="demo.pdf" class="button success small" >
- { "Download PDF" }
- </a>
- }
- }
- 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);
+ fn render_download(&self) -> Html {
+ if self.download.is_some() {
+ let download = self.download.as_ref().unwrap();
html!{
- <a href=href download=format!("{}.vcs",self.formatted_name) class="button success small">
- { "Download vCard" }
+ <a href=download.as_data_link() download=download.file_name class="button success small" >
+ { "Download" }
</a>
}
} else {
html!{}
}
- }
+ }/*
fn render_qrcode(&self) -> Html {
if self.qr_code.is_some() {
let data = base64::encode(self.qr_code.as_ref().unwrap());
@@ -201,7 +276,7 @@ impl Form {
} else {
html!{}
}
- }
+ }*/
}