Skip to content
Snippets Groups Projects
Commit 44ff332b authored by James Calfee's avatar James Calfee Committed by Tim
Browse files

Implements image upload retry from draft. #185

parent 5ad9af41
No related branches found
No related tags found
No related merge requests found
......@@ -350,32 +350,19 @@ function* lookupPreviousOwnerAuthority({payload: {}}) {
}
import {Signature, hash} from 'shared/ecc'
// import request from 'request'
function* uploadImageWatch() {
yield* takeLatest('user/UPLOAD_IMAGE', uploadImage);
}
function* uploadImage({payload: {file, progress}}) {
function* uploadImage({payload: {file, dataUrl, filename = 'image.txt', progress}}) {
const _progress = progress
progress = msg => {
console.log('Upload image progress', msg)
progress(msg)
_progress(msg)
}
if(!file) {
console.error('uploadImage required: file')
return
}
const reader = new FileReader()
const data = yield new Promise(resolve => {
reader.addEventListener('load', () => {
const result = new Buffer(reader.result, 'binary')
resolve(result)
})
reader.readAsBinaryString(file)
})
const bufSha = hash.sha256(data)
const stateUser = yield select(state => state.user)
const username = stateUser.getIn(['current', 'username'])
const d = stateUser.getIn(['current', 'private_keys', 'posting_private'])
......@@ -388,8 +375,40 @@ function* uploadImage({payload: {file, progress}}) {
return
}
if(!file && !dataUrl) {
console.error('uploadImage required: file or dataUrl')
return
}
let data, dataBs64
if(file) {
// drag and drop
const reader = new FileReader()
data = yield new Promise(resolve => {
reader.addEventListener('load', () => {
const result = new Buffer(reader.result, 'binary')
resolve(result)
})
reader.readAsBinaryString(file)
})
} else {
// recover from preview
const commaIdx = dataUrl.indexOf(',')
dataBs64 = dataUrl.substring(commaIdx + 1)
data = new Buffer(dataBs64, 'base64')
}
const bufSha = hash.sha256(data)
const formData = new FormData()
if(file) {
formData.append('file', file)
} else {
// formData.append('file', file, filename) <- Failed to add filename=xxx to Content-Disposition
// Can't easily make this look like a file so this relies on the server supporting: filename and filebinary
formData.append('filename', filename)
formData.append('filebase64', dataBs64)
}
const sig = Signature.signBufferSha256(bufSha, d)
const postUrl = `http://localhost:3234/${username}/${sig.toHex()}`
......@@ -405,8 +424,8 @@ function* uploadImage({payload: {file, progress}}) {
progress({error: 'Error: ' + error})
return
}
const {files: [url]} = res
progress({url: `${url}/${file.name}`})
const {url} = res
progress({url})
})
}
......
......@@ -86,7 +86,7 @@ export default ({large = true, highQualityPost = true, noImage = false, sanitize
let {src, alt} = attribs
if(!/^(https?:)?\/\//i.test(src)) {
console.log('Blocked, image tag src does not appear to be a url', tagName, attribs)
sanitizeErrors.push('Image URL does not appear to be valid: ' + src)
sanitizeErrors.push('An image in this post did not save properly.')
return {tagName: 'img', attribs: {src: 'brokenimg.jpg'}}
}
......
......@@ -23,11 +23,11 @@ export default {
},
{
"text": "much",
"marks": [
{
"type": "italic"
}
]
// "marks": [
// {
// "type": "italic"
// }
// ]
},
{
"text": " better than a "
......
......@@ -4,74 +4,116 @@ import {connect} from 'react-redux'
export default connect(
(state, ownProps) => ownProps,
dispatch => ({
uploadImage: (file, progress) => {
uploadImage: (file, dataUrl, filename, progress) => {
dispatch({
type: 'user/UPLOAD_IMAGE',
payload: {file, progress},
payload: {file, dataUrl, filename, progress},
})
},
})
)(
class Image extends React.Component {
state = {};
state = {
progress: {},
};
componentWillMount() {
const file = this.props.node.data.get('file')
// Save `file` for "Retry"
// Try to load incase data url was loaded from a draft
this.setState({ file })
}
componentDidMount() {
console.log("** image mounted..", this.state, this.props)
const { node } = this.props
const { data } = node
const file = data.get('file')
if(file) this.load(file)
this.load()
}
load(file) {
console.log("** image being loaded.. ----->", file)
const reader = new FileReader()
reader.addEventListener('load', () => {
// this.setState({ src: reader.result })
setImageSrc(src, filename) {
const {editor, node} = this.props
const state = editor.getState();
const next = state
.transform()
.setNodeByKey(node.key, {
data: {
src: reader.result
}
})
.setNodeByKey(node.key, { data: { src, alt: filename } })
.apply()
editor.onChange(next)
}
load = () => {
let dataUrl, filename
const {file} = this.state
if(file) {
// image dropped -- show a quick preview
console.log("** image being loaded.. ----->", file)
const reader = new FileReader()
reader.addEventListener('load', () => {
dataUrl = reader.result
this.setImageSrc(dataUrl, file.name)
})
reader.readAsDataURL(file)
filename = file.name
} else {
// draft, recover data using the preview data url
const {data} = this.props.node
dataUrl = data.get('src')
filename = data.get('alt')
}
if(!file && !dataUrl) return
this.setState({ progress: {}, uploading: true}, () => {
const {uploadImage} = this.props
uploadImage(file, progress => {
this.setState({ progress })
uploadImage(file, dataUrl, filename, progress => {
this.setState({ progress, uploading: false })
if(progress.url) {
this.setImageSrc(progress.url, filename)
}
})
})
reader.readAsDataURL(file)
}
render() {
const { node, state, attributes } = this.props
let { src, progress } = this.state
const isFocused = state.selection.hasEdgeIn(node)
const className = isFocused ? 'active' : null
const src = node.data.get('src')
if(src) {
console.log("** uploaded image being rendered..", (src ? src.substring(0, 30) : '') + '...', state)
} else {
const src2 = node.data.get('src')
console.log("** image source was not in state. data.src = ", (src2 ? src2.substring(0, 30) : '') + '...')
src = src2;
}
if(!src) {
// if(!src) {
// src = 'https://img1.steemit.com/0x0/http://ariasprado.name/wp-content/uploads/2012/09/missing-tile-256x256.png'
// src = $STM_Config.img_proxy_prefix + '0x0/' + src
}
return src ? <span>
<img {...attributes} src={src} className={className} />
{progress}
</span>
: <span>Loading... ({src})</span>
// }
if(!src) return <small className="info">Loading Image&hellip;</small>
const alt = node.data.get('alt')
const img = <img {...attributes} src={src} alt={alt} className={className} />
if(/^https?:\/\//.test(src)) return img
const {uploading} = this.state
if(uploading)
return <div>
{img}
<br />
<small className="info">Uploading Image&hellip;</small>
</div>
const { error } = this.state.progress
return <div>
{img}
<div className="error">
<small>
Image was not Saved (<a onClick={this.load}>retry</a>)
<br />
{error}
</small>
</div>
</div>
}
})
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment