diff --git a/components/ExportSizeSelect.js b/components/ExportSizeSelect.js index e881fd3..db862ff 100644 --- a/components/ExportSizeSelect.js +++ b/components/ExportSizeSelect.js @@ -59,7 +59,7 @@ export default class extends React.Component { onClick={this.toggle} className={`display ${this.state.isVisible ? 'is-visible' : ''}`} > - Export Size + Export size {selectedExportSize.name}
{this.renderExportSizes()}
diff --git a/components/ImagePicker.js b/components/ImagePicker.js index 0f14899..d3216da 100644 --- a/components/ImagePicker.js +++ b/components/ImagePicker.js @@ -1,7 +1,10 @@ import React from 'react' import ReactCrop, { makeAspectCrop } from 'react-image-crop' + import Slider from './Slider' +import RandomImage from './RandomImage' import { COLORS } from '../lib/constants' +import { fileToDataURL } from '../lib/util' const getCroppedImg = (imageDataURL, pixelCrop) => { const canvas = document.createElement('canvas') @@ -59,18 +62,16 @@ export default class extends React.Component { } selectImage(e) { - const file = e.target.files[0] + const file = e.target ? e.target.files[0] : e - const reader = new FileReader() - reader.onload = e => - this.props.onChange({ backgroundImage: e.target.result, backgroundImageSelection: null }) - reader.readAsDataURL(file) + return fileToDataURL(file).then(dataURL => + this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null }) + ) } removeImage() { this.setState(INITIAL_STATE, () => { this.props.onChange({ - backgroundMode: 'color', backgroundImage: null, backgroundImageSelection: null }) @@ -108,18 +109,40 @@ export default class extends React.Component { render() { let content = ( -
- Click the button below to upload a background image - +
+
+ Click the button below to upload a background image: + +
+
+
+ Or use a random unsplash image: + +
) diff --git a/components/RandomImage.js b/components/RandomImage.js new file mode 100644 index 0000000..1fc980a --- /dev/null +++ b/components/RandomImage.js @@ -0,0 +1,93 @@ +import React from 'react' +import axios from 'axios' + +import { range, fileToDataURL } from '../lib/util' + +const RAND_RANGE = 1000000 +const UPDATE_SIZE = 10 +const WALLPAPER_COLLECTION_ID = 1065396 +const RANDOM_WALLPAPER_URL = `https://source.unsplash.com/collection/${WALLPAPER_COLLECTION_ID}/240x320` + +const largerImage = url => url.replace(/w=\d+/, 'w=1920').replace(/&h=\d+/, '') +const smallerImage = url => url.replace(/w=\d+/, 'w=240') + +async function getImage() { + // circumvent browser caching + const sig = Math.floor(Math.random() * RAND_RANGE) + + const res = await axios.get(`${RANDOM_WALLPAPER_URL}?sig=${sig}`, { responseType: 'blob' }) + return { + url: res.request.responseURL, + dataURL: await fileToDataURL(res.data) + } +} + +export default class extends React.Component { + constructor() { + super() + this.state = { cache: [] } + this.selectImage = this.selectImage.bind(this) + this.updateCache = this.updateCache.bind(this) + this.nextImage = this.nextImage.bind(this) + } + + // update in browser (we require window.FileReader) + componentDidMount() { + this.updateCache() + } + + selectImage() { + axios + .get(largerImage(this.state.cache[0].url), { responseType: 'blob' }) + .then(res => res.data) + .then(this.props.onChange) + } + + updateCache() { + Promise.all(range(UPDATE_SIZE).map(getImage)).then(imgs => + this.setState({ cache: this.state.cache.concat(imgs) }) + ) + } + + nextImage() { + this.setState({ cache: this.state.cache.slice(1) }) + + if (this.state.cache.length < 3) { + this.updateCache() + } + } + + render() { + const bgImage = this.state.cache[0] && this.state.cache[0].dataURL + + return ( +
+
+ Use Image + Try Another +
+
+ +
+ ) + } +} diff --git a/lib/util.js b/lib/util.js index 27f4060..42a9b18 100644 --- a/lib/util.js +++ b/lib/util.js @@ -24,3 +24,13 @@ export const getState = morph.compose(parse, escapeHtml, morph.get(KEY)) export const saveState = (window, v) => assign(window, JSON.stringify(v)) export const capitalizeFirstLetter = s => s.charAt(0).toUpperCase() + s.slice(1) + +export const range = n => [...Array(n).keys()] + +export const fileToDataURL = blob => { + return new Promise(res => { + const reader = new FileReader() + reader.onload = e => res(e.target.result) + reader.readAsDataURL(blob) + }) +}