diff --git a/components/Editor.js b/components/Editor.js
index 982affc..2d4fafe 100644
--- a/components/Editor.js
+++ b/components/Editor.js
@@ -175,8 +175,15 @@ class Editor extends React.Component {
this.updateSetting('language', language.mime || language.mode)
}
- updateBackground(changes, cb) {
- this.setState(changes, cb)
+ updateBackground({ photographer, ...changes }) {
+ if (photographer) {
+ this.setState(({ code = DEFAULT_CODE }) => ({
+ ...changes,
+ code: code + `\n\n// Photo by ${photographer.name} on Unsplash`
+ }))
+ } else {
+ this.setState(changes)
+ }
}
render() {
diff --git a/components/ImagePicker.js b/components/ImagePicker.js
index 1102049..681b934 100644
--- a/components/ImagePicker.js
+++ b/components/ImagePicker.js
@@ -2,6 +2,7 @@ import React from 'react'
import ReactCrop, { makeAspectCrop } from 'react-image-crop'
import RandomImage from './RandomImage'
+import PhotoCredit from './PhotoCredit'
import { fileToDataURL } from '../lib/util'
const getCroppedImg = (imageDataURL, pixelCrop) => {
@@ -31,7 +32,7 @@ const getCroppedImg = (imageDataURL, pixelCrop) => {
})
}
-const INITIAL_STATE = { crop: null, imageAspectRatio: null, pixelCrop: null }
+const INITIAL_STATE = { crop: null, imageAspectRatio: null, pixelCrop: null, photographer: null }
export default class extends React.Component {
constructor(props) {
@@ -88,11 +89,17 @@ export default class extends React.Component {
})
}
- selectImage(e) {
+ selectImage(e, { photographer }) {
const file = e.target ? e.target.files[0] : e
return fileToDataURL(file).then(dataURL =>
- this.props.onChange({ backgroundImage: dataURL, backgroundImageSelection: null })
+ this.setState({ photographer }, () => {
+ this.props.onChange({
+ backgroundImage: dataURL,
+ backgroundImageSelection: null,
+ photographer
+ })
+ })
)
}
@@ -173,6 +180,7 @@ export default class extends React.Component {
minWidth={10}
keepSelection
/>
+ {this.state.photographer && }
+
+)
diff --git a/components/RandomImage.js b/components/RandomImage.js
index 458e1ed..1d3624f 100644
--- a/components/RandomImage.js
+++ b/components/RandomImage.js
@@ -2,25 +2,33 @@ import React from 'react'
import axios from 'axios'
import Spinner from 'react-spinner'
-import { range, fileToDataURL } from '../lib/util'
-
-const RAND_RANGE = 1000000
-const UPDATE_SIZE = 20
-const WALLPAPER_COLLECTION_ID = 136026
-const RANDOM_WALLPAPER_URL = `https://source.unsplash.com/collection/${WALLPAPER_COLLECTION_ID}/240x320`
+import PhotoCredit from './PhotoCredit'
+import { fileToDataURL } from '../lib/util'
+
+const downloadThumbnailImage = img => {
+ return axios
+ .get(img.url, { responseType: 'blob' })
+ .then(res => res.data)
+ .then(fileToDataURL)
+ .then(dataURL => Object.assign(img, { dataURL }))
+}
-const largerImage = url => url.replace(/w=\d+/, 'w=1920').replace(/&h=\d+/, '')
+const getImageDownloadUrl = img =>
+ axios.get(`/unsplash/download/${img.id}`).then(res => res.data.url)
-export default class RandomImage extends React.Component {
+class RandomImage extends React.Component {
constructor(props) {
super(props)
this.state = { cacheIndex: 0, loading: false }
this.selectImage = this.selectImage.bind(this)
this.updateCache = this.updateCache.bind(this)
- this.getImage = this.getImage.bind(this)
+ this.getImages = this.getImages.bind(this)
this.nextImage = this.nextImage.bind(this)
}
+ cache = []
+ imageUrls = {}
+
// fetch images in browser (we require window.FileReader)
componentDidMount() {
// clear cache when remounted
@@ -28,38 +36,25 @@ export default class RandomImage extends React.Component {
this.updateCache()
}
- async getImage() {
- // circumvent browser caching
- const sig = Math.floor(Math.random() * RAND_RANGE)
-
- const res = await axios.get(`${RANDOM_WALLPAPER_URL}?sig=${sig}`, { responseType: 'blob' })
-
- // image already in cache?
- if (this.imageUrls[res.request.responseURL]) return undefined
-
- this.imageUrls[res.request.responseURL] = true
- return {
- url: res.request.responseURL,
- dataURL: await fileToDataURL(res.data)
- }
+ async getImages() {
+ const imageUrls = await axios.get('/unsplash/random')
+ return Promise.all(imageUrls.data.map(downloadThumbnailImage))
}
- cache = []
- imageUrls = {}
-
selectImage() {
+ const image = this.cache[this.state.cacheIndex]
+
this.setState({ loading: true })
- axios
- .get(largerImage(this.cache[this.state.cacheIndex].url), { responseType: 'blob' })
+ getImageDownloadUrl(image)
+ .then(url => axios.get(url, { responseType: 'blob' }))
.then(res => res.data)
- .then(this.props.onChange)
+ .then(blob => this.props.onChange(blob, image))
.then(() => this.setState({ loading: false }))
}
updateCache() {
this.setState({ loading: true })
- Promise.all(range(UPDATE_SIZE).map(this.getImage))
- .then(imgs => imgs.filter(img => img)) // remove null
+ this.getImages()
.then(imgs => (this.cache = this.cache.concat(imgs)))
.then(() => this.setState({ loading: false }))
}
@@ -75,6 +70,8 @@ export default class RandomImage extends React.Component {
}
render() {
+ const photographer =
+ this.cache[this.state.cacheIndex] && this.cache[this.state.cacheIndex].photographer
const bgImage = this.cache[this.state.cacheIndex] && this.cache[this.state.cacheIndex].dataURL
return (
@@ -84,14 +81,16 @@ export default class RandomImage extends React.Component {
Try Another
{this.state.loading && }
+ {photographer && }