From 11b967690b9130bb46f82beac8a5f2a323d688d4 Mon Sep 17 00:00:00 2001 From: Kibigo Date: Tue, 28 Feb 2017 18:52:46 -0800 Subject: [PATCH 1/3] Support for pasting images from clipboard --- .../components/components/autosuggest_textarea.jsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/components/components/autosuggest_textarea.jsx b/app/assets/javascripts/components/components/autosuggest_textarea.jsx index 590658671b..51be393799 100644 --- a/app/assets/javascripts/components/components/autosuggest_textarea.jsx +++ b/app/assets/javascripts/components/components/autosuggest_textarea.jsx @@ -1,6 +1,8 @@ import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { isRtl } from '../rtl'; +import { connect } from 'react-redux'; +import { uploadCompose } from '../actions/compose'; const textAtCursorMatchesToken = (str, caretPosition) => { let word; @@ -33,6 +35,7 @@ const AutosuggestTextarea = React.createClass({ value: React.PropTypes.string, suggestions: ImmutablePropTypes.list, disabled: React.PropTypes.bool, + dispatch: React.PropTypes.func.isRequired, fileDropDate: React.PropTypes.instanceOf(Date), placeholder: React.PropTypes.string, onSuggestionSelected: React.PropTypes.func.isRequired, @@ -173,6 +176,13 @@ const AutosuggestTextarea = React.createClass({ }) }, + onPaste (e) { + if (e.clipboardData && e.clipboardData.files.length === 1) { + this.props.dispatch(uploadCompose(e.clipboardData.files)); + e.preventDefault(); + } + }, + render () { const { value, suggestions, fileDropDate, disabled, placeholder, onKeyUp } = this.props; const { isFileDragging, suggestionsHidden, selectedSuggestion } = this.state; @@ -198,6 +208,7 @@ const AutosuggestTextarea = React.createClass({ onBlur={this.onBlur} onDragEnter={this.onDragEnter} onDragExit={this.onDragExit} + onPaste={this.onPaste} style={style} /> @@ -214,4 +225,4 @@ const AutosuggestTextarea = React.createClass({ }); -export default AutosuggestTextarea; +export default connect()(AutosuggestTextarea); From b9222fd7d477c9a475aef2bfc1c9fea8188ab65b Mon Sep 17 00:00:00 2001 From: Kibigo Date: Wed, 1 Mar 2017 02:56:15 -0800 Subject: [PATCH 2/3] Better smart/dumb component separation --- .../components/components/autosuggest_textarea.jsx | 10 ++++------ .../features/compose/components/compose_form.jsx | 6 ++++++ .../compose/containers/compose_form_container.jsx | 5 +++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/components/components/autosuggest_textarea.jsx b/app/assets/javascripts/components/components/autosuggest_textarea.jsx index 51be393799..38deeae0e3 100644 --- a/app/assets/javascripts/components/components/autosuggest_textarea.jsx +++ b/app/assets/javascripts/components/components/autosuggest_textarea.jsx @@ -1,8 +1,6 @@ import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { isRtl } from '../rtl'; -import { connect } from 'react-redux'; -import { uploadCompose } from '../actions/compose'; const textAtCursorMatchesToken = (str, caretPosition) => { let word; @@ -35,7 +33,6 @@ const AutosuggestTextarea = React.createClass({ value: React.PropTypes.string, suggestions: ImmutablePropTypes.list, disabled: React.PropTypes.bool, - dispatch: React.PropTypes.func.isRequired, fileDropDate: React.PropTypes.instanceOf(Date), placeholder: React.PropTypes.string, onSuggestionSelected: React.PropTypes.func.isRequired, @@ -43,7 +40,8 @@ const AutosuggestTextarea = React.createClass({ onSuggestionsFetchRequested: React.PropTypes.func.isRequired, onChange: React.PropTypes.func.isRequired, onKeyUp: React.PropTypes.func, - onKeyDown: React.PropTypes.func + onKeyDown: React.PropTypes.func, + onPaste: React.PropTypes.func.isRequired, }, getInitialState () { @@ -178,7 +176,7 @@ const AutosuggestTextarea = React.createClass({ onPaste (e) { if (e.clipboardData && e.clipboardData.files.length === 1) { - this.props.dispatch(uploadCompose(e.clipboardData.files)); + this.props.onPaste(e.clipboardData.files) e.preventDefault(); } }, @@ -225,4 +223,4 @@ const AutosuggestTextarea = React.createClass({ }); -export default connect()(AutosuggestTextarea); +export default AutosuggestTextarea; diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index 31ae8e0347..a71f5b0fdd 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -47,6 +47,7 @@ const ComposeForm = React.createClass({ onFetchSuggestions: React.PropTypes.func.isRequired, onSuggestionSelected: React.PropTypes.func.isRequired, onChangeSpoilerText: React.PropTypes.func.isRequired, + onPaste: React.PropTypes.func.isRequired, }, mixins: [PureRenderMixin], @@ -82,6 +83,10 @@ const ComposeForm = React.createClass({ this.props.onChangeSpoilerText(e.target.value); }, + onPaste (files) { + this.props.onPaste(files); + }, + componentDidUpdate (prevProps) { if (this.props.focusDate !== prevProps.focusDate) { // If replying to zero or one users, places the cursor at the end of the textbox. @@ -149,6 +154,7 @@ const ComposeForm = React.createClass({ onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} onSuggestionSelected={this.onSuggestionSelected} + onPaste={this.onPaste} />
diff --git a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx index 53129af6e3..a34201747f 100644 --- a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx +++ b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx @@ -1,5 +1,6 @@ import { connect } from 'react-redux'; import ComposeForm from '../components/compose_form'; +import { uploadCompose } from '../../../actions/compose'; import { createSelector } from 'reselect'; import { changeCompose, @@ -65,6 +66,10 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(changeComposeSpoilerText(checked)); }, + onPaste (files) { + dispatch(uploadCompose(files)); + }, + }); export default connect(mapStateToProps, mapDispatchToProps)(ComposeForm); From e7b5cecda71353300c3e95c51ab3ce7d0c59768a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 1 Mar 2017 13:57:30 +0100 Subject: [PATCH 3/3] Simplify passing of prop --- .../features/compose/components/compose_form.jsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx index a71f5b0fdd..bcc4fe1e73 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -83,10 +83,6 @@ const ComposeForm = React.createClass({ this.props.onChangeSpoilerText(e.target.value); }, - onPaste (files) { - this.props.onPaste(files); - }, - componentDidUpdate (prevProps) { if (this.props.focusDate !== prevProps.focusDate) { // If replying to zero or one users, places the cursor at the end of the textbox. @@ -105,7 +101,7 @@ const ComposeForm = React.createClass({ }, render () { - const { intl, needsPrivacyWarning, mentionedDomains } = this.props; + const { intl, needsPrivacyWarning, mentionedDomains, onPaste } = this.props; const disabled = this.props.is_submitting || this.props.is_uploading; let publishText = ''; @@ -154,7 +150,7 @@ const ComposeForm = React.createClass({ onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} onSuggestionSelected={this.onSuggestionSelected} - onPaste={this.onPaste} + onPaste={onPaste} />