diff options
5 files changed, 54 insertions, 6 deletions
diff --git a/app/assets/javascripts/components/components/autosuggest_textarea.jsx b/app/assets/javascripts/components/components/autosuggest_textarea.jsx index 8d9da1601..39ccbcaf9 100644 --- a/app/assets/javascripts/components/components/autosuggest_textarea.jsx +++ b/app/assets/javascripts/components/components/autosuggest_textarea.jsx @@ -32,6 +32,7 @@ const AutosuggestTextarea = React.createClass({ value: React.PropTypes.string, suggestions: ImmutablePropTypes.list, disabled: React.PropTypes.bool, + fileDropDate: React.PropTypes.instanceOf(Date), placeholder: React.PropTypes.string, onSuggestionSelected: React.PropTypes.func.isRequired, onSuggestionsClearRequested: React.PropTypes.func.isRequired, @@ -42,6 +43,8 @@ const AutosuggestTextarea = React.createClass({ getInitialState () { return { + isFileDragging: false, + fileDraggingDate: undefined, suggestionsHidden: false, selectedSuggestion: 0, lastToken: null, @@ -120,21 +123,51 @@ const AutosuggestTextarea = React.createClass({ if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden) { this.setState({ suggestionsHidden: false }); } + + const fileDropDate = nextProps.fileDropDate; + const { isFileDragging, fileDraggingDate } = this.state; + + /* + * We can't detect drop events, because they might not be on the textarea (the app allows dropping anywhere in the + * window). Instead, on-drop, we notify this textarea to stop its hover effect by passing in a prop with the + * drop-date. + */ + if (isFileDragging && fileDraggingDate && fileDropDate // if dragging when props updated, and dates aren't undefined + && fileDropDate > fileDraggingDate) { // and if the drop date is now greater than when we started dragging + // then we should stop dragging + this.setState({ + isFileDragging: false + }); + } }, setTextarea (c) { this.textarea = c; }, + onDragEnter () { + this.setState({ + isFileDragging: true, + fileDraggingDate: new Date() + }) + }, + + onDragExit () { + this.setState({ + isFileDragging: false + }) + }, + render () { - const { value, suggestions, disabled, placeholder, onKeyUp } = this.props; - const { suggestionsHidden, selectedSuggestion } = this.state; + const { value, suggestions, fileDropDate, disabled, placeholder, onKeyUp } = this.props; + const { isFileDragging, suggestionsHidden, selectedSuggestion } = this.state; + const className = isFileDragging ? 'autosuggest-textarea__textarea file-drop' : 'autosuggest-textarea__textarea'; return ( <div className='autosuggest-textarea'> <textarea ref={this.setTextarea} - className='autosuggest-textarea__textarea' + className={className} disabled={disabled} placeholder={placeholder} value={value} @@ -142,6 +175,8 @@ const AutosuggestTextarea = React.createClass({ onKeyDown={this.onKeyDown} onKeyUp={onKeyUp} onBlur={this.onBlur} + onDragEnter={this.onDragEnter} + onDragExit={this.onDragExit} /> <div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'> 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 012e39c91..55f361b0b 100644 --- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx +++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx @@ -27,6 +27,7 @@ const ComposeForm = React.createClass({ sensitive: React.PropTypes.bool, unlisted: React.PropTypes.bool, private: React.PropTypes.bool, + fileDropDate: React.PropTypes.instanceOf(Date), is_submitting: React.PropTypes.bool, is_uploading: React.PropTypes.bool, in_reply_to: ImmutablePropTypes.map, @@ -110,6 +111,7 @@ const ComposeForm = React.createClass({ ref={this.setAutosuggestTextarea} placeholder={intl.formatMessage(messages.placeholder)} disabled={disabled} + fileDropDate={this.props.fileDropDate} value={this.props.text} onChange={this.handleChange} suggestions={this.props.suggestions} 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 1d8f20ca7..2b6ee1ae7 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 @@ -24,6 +24,7 @@ const makeMapStateToProps = () => { sensitive: state.getIn(['compose', 'sensitive']), unlisted: state.getIn(['compose', 'unlisted']), private: state.getIn(['compose', 'private']), + fileDropDate: state.getIn(['compose', 'fileDropDate']), is_submitting: state.getIn(['compose', 'is_submitting']), is_uploading: state.getIn(['compose', 'is_uploading']), in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])), diff --git a/app/assets/javascripts/components/reducers/compose.jsx b/app/assets/javascripts/components/reducers/compose.jsx index 742272e6f..16215684e 100644 --- a/app/assets/javascripts/components/reducers/compose.jsx +++ b/app/assets/javascripts/components/reducers/compose.jsx @@ -30,6 +30,7 @@ const initialState = Immutable.Map({ unlisted: false, private: false, text: '', + fileDropDate: null, in_reply_to: null, is_submitting: false, is_uploading: false, @@ -116,7 +117,10 @@ export default function compose(state = initialState, action) { case COMPOSE_SUBMIT_FAIL: return state.set('is_submitting', false); case COMPOSE_UPLOAD_REQUEST: - return state.set('is_uploading', true); + return state.withMutations(map => { + map.set('is_uploading', true); + map.set('fileDropDate', new Date()); + }); case COMPOSE_UPLOAD_SUCCESS: return appendMedia(state, Immutable.fromJS(action.media)); case COMPOSE_UPLOAD_FAIL: diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss index 290b370a9..832b9e9b1 100644 --- a/app/assets/stylesheets/components.scss +++ b/app/assets/stylesheets/components.scss @@ -549,13 +549,19 @@ width: 100%; height: 100px; resize: none; - border: none; color: #282c37; - padding: 10px; + padding: 7px; font-family: 'Roboto'; font-size: 14px; margin: 0; resize: vertical; + + border: 3px dashed transparent; + transition: border-color 0.3s ease; + + &.file-drop { + border-color: #aaa; + } } .autosuggest-textarea__suggestions { |