mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-12-22 17:23:22 +01:00
vcard tweaks, generate base64 photo
This commit is contained in:
parent
5b25e2090a
commit
03b39e3d1d
File diff suppressed because one or more lines are too long
91
src/components/atoms/Vcard.js
Normal file
91
src/components/atoms/Vcard.js
Normal file
@ -0,0 +1,91 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FileSaver from 'file-saver'
|
||||
import vCard from '../../lib/vcf/vcard'
|
||||
|
||||
class Vcard extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
toDataURL(src, callback, outputFormat) {
|
||||
const img = new Image()
|
||||
img.crossOrigin = 'Anonymous'
|
||||
|
||||
img.onload = function() {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
let dataURL
|
||||
|
||||
canvas.height = this.naturalHeight
|
||||
canvas.width = this.naturalWidth
|
||||
ctx.drawImage(this, 0, 0)
|
||||
dataURL = canvas.toDataURL(outputFormat)
|
||||
callback(dataURL)
|
||||
}
|
||||
|
||||
img.src = src
|
||||
if (img.complete || img.complete === undefined) {
|
||||
img.src =
|
||||
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=='
|
||||
img.src = src
|
||||
}
|
||||
}
|
||||
|
||||
constructVcard() {
|
||||
const meta = this.props.meta
|
||||
const contact = new vCard()
|
||||
const photoSrc = meta.avatar.childImageSharp.original.src
|
||||
|
||||
this.toDataURL(
|
||||
photoSrc,
|
||||
dataUrl => {
|
||||
// stripping this data out of base64 string
|
||||
// is required for vcard 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')
|
||||
|
||||
this.downloadVcard(vcard)
|
||||
},
|
||||
'image/jpeg'
|
||||
)
|
||||
}
|
||||
|
||||
downloadVcard(vcard) {
|
||||
const name = this.props.meta.addressbook.split('/').join('')
|
||||
const blob = new Blob([vcard], { type: 'text/x-vcard' })
|
||||
FileSaver.saveAs(blob, name)
|
||||
}
|
||||
|
||||
handleAddressbookClick = e => {
|
||||
e.preventDefault()
|
||||
this.constructVcard()
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a
|
||||
href={this.props.meta.addressbook}
|
||||
onClick={this.handleAddressbookClick}
|
||||
>
|
||||
Add to addressbook
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Vcard.propTypes = {
|
||||
meta: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Vcard
|
@ -1,7 +1,6 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import FileSaver from 'file-saver'
|
||||
import vCard from '../../lib/vcf/vcard'
|
||||
import Vcard from '../atoms/Vcard'
|
||||
import Networks from '../molecules/Networks'
|
||||
import './Footer.scss'
|
||||
|
||||
@ -12,43 +11,6 @@ class Footer extends PureComponent {
|
||||
this.state = { year: new Date().getFullYear() }
|
||||
}
|
||||
|
||||
generateFileName() {
|
||||
// results in 'matthias-kretschmann.vcf'
|
||||
return `${this.props.meta.title
|
||||
.toLowerCase()
|
||||
.split(' ')
|
||||
.join('-')}.vcf`
|
||||
}
|
||||
|
||||
constructVcard() {
|
||||
const meta = this.props.meta
|
||||
const contact = new vCard()
|
||||
const photo = meta.avatarBase64
|
||||
|
||||
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' })
|
||||
contact.set('photo', photo, { encoding: 'b', type: 'JPEG' })
|
||||
|
||||
const vcard = contact.toString('3.0')
|
||||
this.downloadVcard(vcard)
|
||||
}
|
||||
|
||||
downloadVcard(vcard) {
|
||||
const blob = new Blob([vcard], { type: 'text/x-vcard' })
|
||||
FileSaver.saveAs(blob, this.generateFileName())
|
||||
}
|
||||
|
||||
handleAddressbookClick = e => {
|
||||
e.preventDefault()
|
||||
this.constructVcard()
|
||||
}
|
||||
|
||||
render() {
|
||||
const meta = this.props.meta
|
||||
|
||||
@ -56,12 +18,7 @@ class Footer extends PureComponent {
|
||||
<footer className="footer">
|
||||
<Networks meta={meta} minimal />
|
||||
<p className="footer__actions">
|
||||
<a
|
||||
href={`${meta.url}/${this.generateFileName()}`}
|
||||
onClick={this.handleAddressbookClick}
|
||||
>
|
||||
Add to addressbook
|
||||
</a>
|
||||
<Vcard meta={meta} />
|
||||
<a href={meta.gpg}>PGP/GPG key</a>
|
||||
</p>
|
||||
<p>
|
||||
|
@ -104,7 +104,6 @@ export const query = graphql`
|
||||
addressbook
|
||||
typekit
|
||||
googleanalytics
|
||||
avatarBase64
|
||||
}
|
||||
}
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user