Skip to content

Commit

Permalink
Markdown image upload. #396
Browse files Browse the repository at this point in the history
  • Loading branch information
James Calfee committed Jan 19, 2017
1 parent f3f72d3 commit ad8ffb7
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 6 deletions.
89 changes: 86 additions & 3 deletions app/components/elements/ReplyEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import HtmlReady from 'shared/HtmlReady'
import g from 'app/redux/GlobalReducer'
import {Set} from 'immutable'
import Remarkable from 'remarkable'
import Dropzone from 'react-dropzone'

const remarkable = new Remarkable({ html: true, linkify: false, breaks: true })
const RichTextEditor = process.env.BROWSER ? require('react-rte-image').default : null;
Expand Down Expand Up @@ -49,7 +50,7 @@ class ReplyEditor extends React.Component {

constructor(props) {
super()
this.state = {}
this.state = {progress: {}}
this.initForm(props)
}

Expand Down Expand Up @@ -178,6 +179,7 @@ class ReplyEditor extends React.Component {
replyForm.resetForm()
this.setAutoVote()
this.setState({rte_value: stateFromHtml()})
this.setState({progress: {}})
if(onCancel) onCancel(e)
}
}
Expand Down Expand Up @@ -229,6 +231,60 @@ class ReplyEditor extends React.Component {
if(payoutType !== '0%') localStorage.setItem('defaultPayoutType', payoutType)
}

onDrop = (acceptedFiles, rejectedFiles) => {
if(!acceptedFiles.length) {
console.log('onDrop Rejected files: ', rejectedFiles);
return
}
const file = acceptedFiles[0]
this.upload(file, file.name)
}

onOpenClick = () => {
this.dropzone.open();
}

onPasteCapture = e => {
try {
if(e.clipboardData) {
for(const item of e.clipboardData.items) {
if(item.kind === 'file' && /^image\//.test(item.type)) {
const blob = item.getAsFile()
this.upload(blob)
}
}
} else {
// http://joelb.me/blog/2011/code-snippet-accessing-clipboard-images-with-javascript/
// contenteditable element that catches all pasted data
this.setState({noClipboardData: true})
}
} catch(error) {
console.error('Error analyzing clipboard event', error);
}
}

upload = (file, name = '') => {
const {uploadImage} = this.props
this.setState({progress: {message: 'Uploading...'}})
uploadImage(file, progress => {
if(progress.url) {
this.setState({ progress: {} })
const {url} = progress
const image_md = `![${name}](${url})`
const {body} = this.props.fields
const {selectionStart, selectionEnd} = this.refs.postRef
body.onChange(
body.value.substring(0, selectionStart) +
image_md +
body.value.substring(selectionEnd, body.value.length)
)
} else {
this.setState({ progress })
}
setTimeout(() => { this.setState({ progress: {} }) }, 4000) // clear message
})
}

render() {
const originalPost = {
category: this.props.category,
Expand All @@ -243,6 +299,7 @@ class ReplyEditor extends React.Component {
} = this.props
const {submitting, valid, handleSubmit} = this.state.replyForm
const {postError, titleWarn, rte, payoutType} = this.state
const {progress, noClipboardData} = this.state
const disabled = submitting || !valid
const loading = submitting || this.state.loading

Expand Down Expand Up @@ -304,8 +361,28 @@ class ReplyEditor extends React.Component {
value={this.state.rte_value}
onChange={this.onChange}
onBlur={body.onBlur} tabIndex={2} />
:
<textarea {...body.props} disabled={loading} rows={isStory ? 10 : 3} placeholder={isStory ? 'Write your story...' : 'Reply'} autoComplete="off" ref="postRef" tabIndex={2} />
: <span>
<Dropzone onDrop={this.onDrop}
className="dropzone"
disableClick multiple={false} accept="image/*"
ref={(node) => { this.dropzone = node; }}>
<textarea {...body.props}
ref="postRef"
onPasteCapture={this.onPasteCapture}
className="upload-enabled"
disabled={loading} rows={isStory ? 10 : 3}
placeholder={isStory ? 'Write your story...' : 'Reply'}
autoComplete="off"
tabIndex={2} />
</Dropzone>
<p className="drag-and-drop">
Insert images by dragging &amp; dropping,&nbsp;
{noClipboardData ? '' : 'pasting from the clipboard, '}
or by <a onClick={this.onOpenClick}>selecting them</a>.
</p>
{progress.message && <div className="info">{progress.message}</div>}
{progress.error && <div className="error">Image upload: {progress.error}</div>}
</span>
}
</div>
<div className={vframe_section_shrink_class}>
Expand Down Expand Up @@ -434,6 +511,12 @@ export default formId => connect(
setMetaData: (id, jsonMetadata) => {
dispatch(g.actions.setMetaData({id, meta: jsonMetadata ? jsonMetadata.steem : null}))
},
uploadImage: (file, progress) => {
dispatch({
type: 'user/UPLOAD_IMAGE',
payload: {file, progress},
})
},
reply: ({category, title, body, author, permlink, parent_author, parent_permlink, isHtml, isStory,
type, originalPost, autoVote = false, payoutType = '50%',
state, jsonMetadata,
Expand Down
18 changes: 18 additions & 0 deletions app/components/elements/ReplyEditor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@
}
}

.upload-enabled {
border-bottom: 2px dashed #ddd;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}

.drag-and-drop {
padding: 7px 10px;
margin: 0;
color: #767676;
background-color: #fafafa;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-bottom-right-radius: 3;
border-bottom-left-radius: 3;
}

.PostFull .ReplyEditor__body {
margin: 1rem 0 0;
}
Expand Down
2 changes: 1 addition & 1 deletion app/redux/UserSaga.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ function* uploadImage({payload: {file, dataUrl, filename = 'image.txt', progress
const username = stateUser.getIn(['current', 'username'])
const d = stateUser.getIn(['current', 'private_keys', 'posting_private'])
if(!username) {
progress({error: 'Not logged in'})
progress({error: 'Please logged first.'})
return
}
if(!d) {
Expand Down
12 changes: 11 additions & 1 deletion npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"babel-preset-stage-0": "^6.16.0",
"bigi": "^1.4.1",
"blocked": "^1.1.0",
"blueimp-file-upload": "^9.12.5",
"bs58": "^3.0.0",
"bytebuffer": "^5.0.0",
"bytes": "^2.4.0",
Expand Down Expand Up @@ -90,6 +89,7 @@
"react-addons-pure-render-mixin": "^15.4.1",
"react-dom": "^15.4.1",
"react-foundation-components": "git+https://github.com/valzav/react-foundation-components.git#d14362c7c8eee946a4acc3b18d70271d5a82813e",
"react-dropzone": "^3.7.3",
"react-highcharts": "^8.3.3",
"react-intl": "^2.1.3",
"react-medium-editor": "^1.8.0",
Expand Down

0 comments on commit ad8ffb7

Please sign in to comment.