On file-drag, show a border around textarea
This commit is contained in:
		
							parent
							
								
									3125dd8920
								
							
						
					
					
						commit
						4d300e2507
					
				@ -32,6 +32,7 @@ const AutosuggestTextarea = React.createClass({
 | 
				
			|||||||
    value: React.PropTypes.string,
 | 
					    value: React.PropTypes.string,
 | 
				
			||||||
    suggestions: ImmutablePropTypes.list,
 | 
					    suggestions: ImmutablePropTypes.list,
 | 
				
			||||||
    disabled: React.PropTypes.bool,
 | 
					    disabled: React.PropTypes.bool,
 | 
				
			||||||
 | 
					    fileDropDate: React.PropTypes.instanceOf(Date),
 | 
				
			||||||
    placeholder: React.PropTypes.string,
 | 
					    placeholder: React.PropTypes.string,
 | 
				
			||||||
    onSuggestionSelected: React.PropTypes.func.isRequired,
 | 
					    onSuggestionSelected: React.PropTypes.func.isRequired,
 | 
				
			||||||
    onSuggestionsClearRequested: React.PropTypes.func.isRequired,
 | 
					    onSuggestionsClearRequested: React.PropTypes.func.isRequired,
 | 
				
			||||||
@ -42,6 +43,8 @@ const AutosuggestTextarea = React.createClass({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  getInitialState () {
 | 
					  getInitialState () {
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
 | 
					      isFileDragging: false,
 | 
				
			||||||
 | 
					      fileDraggingDate: undefined,
 | 
				
			||||||
      suggestionsHidden: false,
 | 
					      suggestionsHidden: false,
 | 
				
			||||||
      selectedSuggestion: 0,
 | 
					      selectedSuggestion: 0,
 | 
				
			||||||
      lastToken: null,
 | 
					      lastToken: null,
 | 
				
			||||||
@ -120,21 +123,51 @@ const AutosuggestTextarea = React.createClass({
 | 
				
			|||||||
    if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden) {
 | 
					    if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden) {
 | 
				
			||||||
      this.setState({ suggestionsHidden: false });
 | 
					      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) {
 | 
					  setTextarea (c) {
 | 
				
			||||||
    this.textarea = c;
 | 
					    this.textarea = c;
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onDragEnter () {
 | 
				
			||||||
 | 
					    this.setState({
 | 
				
			||||||
 | 
					      isFileDragging: true,
 | 
				
			||||||
 | 
					      fileDraggingDate: new Date()
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onDragExit () {
 | 
				
			||||||
 | 
					    this.setState({
 | 
				
			||||||
 | 
					      isFileDragging: false
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { value, suggestions, disabled, placeholder, onKeyUp } = this.props;
 | 
					    const { value, suggestions, fileDropDate, disabled, placeholder, onKeyUp } = this.props;
 | 
				
			||||||
    const { suggestionsHidden, selectedSuggestion } = this.state;
 | 
					    const { isFileDragging, suggestionsHidden, selectedSuggestion } = this.state;
 | 
				
			||||||
 | 
					    const className = isFileDragging ? 'autosuggest-textarea__textarea file-drop' : 'autosuggest-textarea__textarea';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className='autosuggest-textarea'>
 | 
					      <div className='autosuggest-textarea'>
 | 
				
			||||||
        <textarea
 | 
					        <textarea
 | 
				
			||||||
          ref={this.setTextarea}
 | 
					          ref={this.setTextarea}
 | 
				
			||||||
          className='autosuggest-textarea__textarea'
 | 
					          className={className}
 | 
				
			||||||
          disabled={disabled}
 | 
					          disabled={disabled}
 | 
				
			||||||
          placeholder={placeholder}
 | 
					          placeholder={placeholder}
 | 
				
			||||||
          value={value}
 | 
					          value={value}
 | 
				
			||||||
@ -142,6 +175,8 @@ const AutosuggestTextarea = React.createClass({
 | 
				
			|||||||
          onKeyDown={this.onKeyDown}
 | 
					          onKeyDown={this.onKeyDown}
 | 
				
			||||||
          onKeyUp={onKeyUp}
 | 
					          onKeyUp={onKeyUp}
 | 
				
			||||||
          onBlur={this.onBlur}
 | 
					          onBlur={this.onBlur}
 | 
				
			||||||
 | 
					          onDragEnter={this.onDragEnter}
 | 
				
			||||||
 | 
					          onDragExit={this.onDragExit}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'>
 | 
					        <div style={{ display: (suggestions.size > 0 && !suggestionsHidden) ? 'block' : 'none' }} className='autosuggest-textarea__suggestions'>
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
    sensitive: React.PropTypes.bool,
 | 
					    sensitive: React.PropTypes.bool,
 | 
				
			||||||
    unlisted: React.PropTypes.bool,
 | 
					    unlisted: React.PropTypes.bool,
 | 
				
			||||||
    private: React.PropTypes.bool,
 | 
					    private: React.PropTypes.bool,
 | 
				
			||||||
 | 
					    fileDropDate: React.PropTypes.instanceOf(Date),
 | 
				
			||||||
    is_submitting: React.PropTypes.bool,
 | 
					    is_submitting: React.PropTypes.bool,
 | 
				
			||||||
    is_uploading: React.PropTypes.bool,
 | 
					    is_uploading: React.PropTypes.bool,
 | 
				
			||||||
    in_reply_to: ImmutablePropTypes.map,
 | 
					    in_reply_to: ImmutablePropTypes.map,
 | 
				
			||||||
@ -110,6 +111,7 @@ const ComposeForm = React.createClass({
 | 
				
			|||||||
          ref={this.setAutosuggestTextarea}
 | 
					          ref={this.setAutosuggestTextarea}
 | 
				
			||||||
          placeholder={intl.formatMessage(messages.placeholder)}
 | 
					          placeholder={intl.formatMessage(messages.placeholder)}
 | 
				
			||||||
          disabled={disabled}
 | 
					          disabled={disabled}
 | 
				
			||||||
 | 
					          fileDropDate={this.props.fileDropDate}
 | 
				
			||||||
          value={this.props.text}
 | 
					          value={this.props.text}
 | 
				
			||||||
          onChange={this.handleChange}
 | 
					          onChange={this.handleChange}
 | 
				
			||||||
          suggestions={this.props.suggestions}
 | 
					          suggestions={this.props.suggestions}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,6 +24,7 @@ const makeMapStateToProps = () => {
 | 
				
			|||||||
      sensitive: state.getIn(['compose', 'sensitive']),
 | 
					      sensitive: state.getIn(['compose', 'sensitive']),
 | 
				
			||||||
      unlisted: state.getIn(['compose', 'unlisted']),
 | 
					      unlisted: state.getIn(['compose', 'unlisted']),
 | 
				
			||||||
      private: state.getIn(['compose', 'private']),
 | 
					      private: state.getIn(['compose', 'private']),
 | 
				
			||||||
 | 
					      fileDropDate: state.getIn(['compose', 'fileDropDate']),
 | 
				
			||||||
      is_submitting: state.getIn(['compose', 'is_submitting']),
 | 
					      is_submitting: state.getIn(['compose', 'is_submitting']),
 | 
				
			||||||
      is_uploading: state.getIn(['compose', 'is_uploading']),
 | 
					      is_uploading: state.getIn(['compose', 'is_uploading']),
 | 
				
			||||||
      in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])),
 | 
					      in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])),
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ const initialState = Immutable.Map({
 | 
				
			|||||||
  unlisted: false,
 | 
					  unlisted: false,
 | 
				
			||||||
  private: false,
 | 
					  private: false,
 | 
				
			||||||
  text: '',
 | 
					  text: '',
 | 
				
			||||||
 | 
					  fileDropDate: null,
 | 
				
			||||||
  in_reply_to: null,
 | 
					  in_reply_to: null,
 | 
				
			||||||
  is_submitting: false,
 | 
					  is_submitting: false,
 | 
				
			||||||
  is_uploading: false,
 | 
					  is_uploading: false,
 | 
				
			||||||
@ -116,7 +117,10 @@ export default function compose(state = initialState, action) {
 | 
				
			|||||||
    case COMPOSE_SUBMIT_FAIL:
 | 
					    case COMPOSE_SUBMIT_FAIL:
 | 
				
			||||||
      return state.set('is_submitting', false);
 | 
					      return state.set('is_submitting', false);
 | 
				
			||||||
    case COMPOSE_UPLOAD_REQUEST:
 | 
					    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:
 | 
					    case COMPOSE_UPLOAD_SUCCESS:
 | 
				
			||||||
      return appendMedia(state, Immutable.fromJS(action.media));
 | 
					      return appendMedia(state, Immutable.fromJS(action.media));
 | 
				
			||||||
    case COMPOSE_UPLOAD_FAIL:
 | 
					    case COMPOSE_UPLOAD_FAIL:
 | 
				
			||||||
 | 
				
			|||||||
@ -549,13 +549,19 @@
 | 
				
			|||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 100px;
 | 
					  height: 100px;
 | 
				
			||||||
  resize: none;
 | 
					  resize: none;
 | 
				
			||||||
  border: none;
 | 
					 | 
				
			||||||
  color: #282c37;
 | 
					  color: #282c37;
 | 
				
			||||||
  padding: 10px;
 | 
					  padding: 7px;
 | 
				
			||||||
  font-family: 'Roboto';
 | 
					  font-family: 'Roboto';
 | 
				
			||||||
  font-size: 14px;
 | 
					  font-size: 14px;
 | 
				
			||||||
  margin: 0;
 | 
					  margin: 0;
 | 
				
			||||||
  resize: vertical;
 | 
					  resize: vertical;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  border: 3px dashed transparent;
 | 
				
			||||||
 | 
					  transition: border-color 0.3s ease;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.file-drop {
 | 
				
			||||||
 | 
					    border-color: #aaa;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.autosuggest-textarea__suggestions {
 | 
					.autosuggest-textarea__suggestions {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user