1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-09-28 03:58:47 +02:00
portfolio/src/components/atoms/Vcard.jsx

127 lines
3.3 KiB
React
Raw Normal View History

2018-12-08 20:27:45 +01:00
import React, { PureComponent } from 'react'
2018-08-26 21:28:06 +02:00
import { StaticQuery, graphql } from 'gatsby'
2018-09-27 20:20:27 +02:00
import saveAs from 'file-saver'
2018-06-20 22:50:49 +02:00
import vCard from 'vcf'
2018-05-13 00:42:59 +02:00
const query = graphql`
query {
2019-03-30 00:24:57 +01:00
contentYaml {
title
tagline
description
url
email
avatar {
childImageSharp {
original: resize {
src
2018-08-26 21:28:06 +02:00
}
}
}
social {
Email
Blog
Twitter
GitHub
Dribbble
}
gpg
addressbook
}
}
`
2018-12-08 20:27:45 +01:00
export default class Vcard extends PureComponent {
render() {
return (
<StaticQuery
query={query}
render={data => {
2019-03-30 00:24:57 +01:00
const meta = data.contentYaml
2018-05-13 00:42:59 +02:00
2018-12-08 20:27:45 +01:00
const handleAddressbookClick = e => {
e.preventDefault()
constructVcard(meta)
}
2018-05-13 00:42:59 +02:00
2018-12-08 20:27:45 +01:00
return (
<a
// href is kinda fake, only there for usability
// so user knows what to expect when hovering the link before clicking
href={meta.addressbook}
onClick={handleAddressbookClick}
>
Add to addressbook
</a>
)
}}
/>
)
}
}
2018-05-13 00:42:59 +02:00
2018-09-06 14:28:01 +02:00
// Construct the download from a blob of the just constructed vCard,
// and save it to user's file system
const downloadVcard = (vcard, meta) => {
const name = meta.addressbook.split('/').join('')
const blob = new Blob([vcard], { type: 'text/x-vcard' })
2018-09-27 20:20:27 +02:00
saveAs(blob, name)
2018-09-06 14:28:01 +02:00
}
const constructVcard = meta => {
const contact = new vCard()
const photoSrc = meta.avatar.childImageSharp.original.src
// first, convert the avatar to base64, then construct all vCard elements
toDataURL(
photoSrc,
dataUrl => {
// stripping this data out of base64 string is required
// for vcard to actually display the image for whatever reason
const dataUrlCleaned = dataUrl.split('data:image/jpeg;base64,').join('')
contact.set('photo', dataUrlCleaned, { encoding: 'b', type: 'JPEG' })
contact.set('fn', meta.title)
contact.set('title', meta.tagline)
contact.set('email', meta.email)
contact.set('url', meta.url, { type: 'Portfolio' })
contact.add('url', meta.social.Blog, { type: 'Blog' })
contact.set('nickname', 'kremalicious')
contact.add('x-socialprofile', meta.social.Twitter, { type: 'twitter' })
contact.add('x-socialprofile', meta.social.GitHub, { type: 'GitHub' })
const vcard = contact.toString('3.0')
downloadVcard(vcard, meta)
},
'image/jpeg'
)
}
2018-08-26 21:28:06 +02:00
// Helper function to create base64 string from avatar image
// without the need to read image file from file system
const toDataURL = (src, callback, outputFormat) => {
const img = new Image()
img.crossOrigin = 'Anonymous'
2018-05-13 00:42:59 +02:00
2018-08-26 21:28:06 +02:00
img.onload = function() {
// yeah, we're gonna create a fake canvas to render the image
// and then create a base64 string from the rendered result
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
let dataURL
2018-05-13 00:42:59 +02:00
2018-08-26 21:28:06 +02:00
canvas.height = this.naturalHeight
canvas.width = this.naturalWidth
ctx.drawImage(this, 0, 0)
dataURL = canvas.toDataURL(outputFormat)
callback(dataURL)
2018-05-13 00:42:59 +02:00
}
2018-08-26 21:28:06 +02:00
img.src = src
if (img.complete || img.complete === undefined) {
img.src =
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='
img.src = src
2018-05-13 00:42:59 +02:00
}
}