Fixed problem with drag/drop in compose form. Need to try to uncondense compose form when dropping file onto it

drag_drop
crockwave 2020-09-24 20:44:06 -05:00
rodzic 6ab8461551
commit 65e45e136a
4 zmienionych plików z 154 dodań i 138 usunięć

Wyświetl plik

@ -1,5 +1,4 @@
import React from 'react';
import { connect } from 'react-redux';
import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container';
import AutosuggestEmoji from './autosuggest_emoji';
import ImmutablePropTypes from 'react-immutable-proptypes';
@ -8,8 +7,6 @@ import { isRtl } from '../rtl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Textarea from 'react-textarea-autosize';
import classNames from 'classnames';
import UploadArea from 'soapbox/features/ui/components/upload_area';
import { uploadCompose } from 'soapbox/actions/compose';
const textAtCursorMatchesToken = (str, caretPosition) => {
let word;
@ -36,11 +33,9 @@ const textAtCursorMatchesToken = (str, caretPosition) => {
}
};
export default @connect()
class AutosuggestTextarea extends ImmutablePureComponent {
export default class AutosuggestTextarea extends ImmutablePureComponent {
static propTypes = {
dispatch: PropTypes.func.isRequired,
value: PropTypes.string,
suggestions: ImmutablePropTypes.list,
disabled: PropTypes.bool,
@ -55,7 +50,6 @@ class AutosuggestTextarea extends ImmutablePureComponent {
autoFocus: PropTypes.bool,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onAttachment: PropTypes.func,
};
static defaultProps = {
@ -68,25 +62,8 @@ class AutosuggestTextarea extends ImmutablePureComponent {
selectedSuggestion: 0,
lastToken: null,
tokenStart: 0,
draggingOver: false,
};
componentDidMount() {
this.node.addEventListener('dragenter', this.handleDragEnter, false);
this.node.addEventListener('dragover', this.handleDragOver, false);
this.node.addEventListener('drop', this.handleDrop, false);
this.node.addEventListener('dragleave', this.handleDragLeave, false);
this.node.addEventListener('dragend', this.handleDragEnd, false);
}
componentWillUnmount() {
this.node.removeEventListener('dragenter', this.handleDragEnter);
this.node.removeEventListener('dragover', this.handleDragOver);
this.node.removeEventListener('drop', this.handleDrop);
this.node.removeEventListener('dragleave', this.handleDragLeave);
this.node.removeEventListener('dragend', this.handleDragEnd);
}
onChange = (e) => {
const [ tokenStart, token ] = textAtCursorMatchesToken(e.target.value, e.target.selectionStart);
@ -193,96 +170,6 @@ class AutosuggestTextarea extends ImmutablePureComponent {
this.textarea = c;
}
setRef = c => {
this.node = c;
}
dataTransferIsText = (dataTransfer) => {
return (dataTransfer && Array.from(dataTransfer.types).includes('text/plain') && dataTransfer.items.length === 1);
}
handleDragEnter = (e) => {
e.preventDefault();
if (!this.dragTargets) {
this.dragTargets = [];
}
if (this.dragTargets.indexOf(e.target) === -1) {
this.dragTargets.push(e.target);
}
if (e.dataTransfer && Array.from(e.dataTransfer.types).includes('Files')) {
this.setState({ draggingOver: true });
}
}
handleDragOver = (e) => {
if (this.dataTransferIsText(e.dataTransfer)) return false;
e.preventDefault();
e.stopPropagation();
try {
e.dataTransfer.dropEffect = 'copy';
} catch (err) {
}
return false;
}
handleAttachment = () => {
const { onAttachment } = this.props;
onAttachment(true);
}
handleFiles = (files) => {
const { dispatch } = this.props;
this.setState({ isUploading: true });
// const data = new FormData();
// data.append('file', files[0]);
dispatch(uploadCompose(files));
dispatch(this.handleAttachment());
// dispatch(uploadMedia(data, this.onUploadProgress)).then(response => {
// this.setState({ attachment: response.data, isUploading: false });
// this.handleAttachment();
// }).catch(() => {
// this.setState({ isUploading: false });
// });
}
handleDrop = (e) => {
if (this.dataTransferIsText(e.dataTransfer)) return;
e.preventDefault();
this.setState({ draggingOver: false });
this.dragTargets = [];
if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
this.handleFiles(e.dataTransfer.files);
// this.props.dispatch(uploadCompose(e.dataTransfer.files));
}
}
handleDragLeave = (e) => {
e.preventDefault();
e.stopPropagation();
this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.node.contains(el));
if (this.dragTargets.length > 0) {
return;
}
this.setState({ draggingOver: false });
}
closeUploadModal = () => {
this.setState({ draggingOver: false });
}
onPaste = (e) => {
if (e.clipboardData && e.clipboardData.files.length === 1) {
this.props.onPaste(e.clipboardData.files);
@ -314,7 +201,7 @@ class AutosuggestTextarea extends ImmutablePureComponent {
render() {
const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, children } = this.props;
const { draggingOver, suggestionsHidden } = this.state;
const { suggestionsHidden } = this.state;
const style = { direction: 'ltr' };
if (isRtl(value)) {
@ -322,9 +209,8 @@ class AutosuggestTextarea extends ImmutablePureComponent {
}
return [
<div className='compose-form__autosuggest-wrapper' key='compose-form__autosuggest-wrapper' ref={this.setRef}>
<div className='compose-form__autosuggest-wrapper' key='compose-form__autosuggest-wrapper'>
<div className='autosuggest-textarea'>
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
<label>
<span style={{ display: 'none' }}>{placeholder}</span>

Wyświetl plik

@ -281,9 +281,8 @@ class ChatBox extends ImmutablePureComponent {
}
render() {
const { chatMessageIds, chatId, intl, windowState } = this.props;
const { chatMessageIds, chatId, intl } = this.props;
const { content, isUploading, uploadProgress } = this.state;
console.log('window state: ' + windowState + ', chatID: ' + chatId);
if (!chatMessageIds) return null;
return (

Wyświetl plik

@ -10,6 +10,7 @@ import AutosuggestInput from '../../../components/autosuggest_input';
import PollButtonContainer from '../containers/poll_button_container';
import UploadButtonContainer from '../containers/upload_button_container';
import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import SpoilerButtonContainer from '../containers/spoiler_button_container';
import MarkdownButtonContainer from '../containers/markdown_button_container';
import PrivacyDropdownContainer from '../containers/privacy_dropdown_container';
@ -23,6 +24,8 @@ import { length } from 'stringz';
import { countableText } from '../util/counter';
import Icon from 'soapbox/components/icon';
import { get } from 'lodash';
import UploadArea from 'soapbox/features/ui/components/upload_area';
import { uploadCompose } from 'soapbox/actions/compose';
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
@ -33,7 +36,8 @@ const messages = defineMessages({
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
});
export default @injectIntl
export default @connect()
@injectIntl
class ComposeForm extends ImmutablePureComponent {
state = {
@ -46,6 +50,7 @@ class ComposeForm extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
text: PropTypes.string.isRequired,
suggestions: ImmutablePropTypes.list,
spoiler: PropTypes.bool,
@ -87,12 +92,6 @@ class ComposeForm extends ImmutablePureComponent {
});
}
handleAttachment = () => {
this.setState({
shouldCondense: false,
});
}
handleKeyDown = (e) => {
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
this.handleSubmit();
@ -179,13 +178,83 @@ class ComposeForm extends ImmutablePureComponent {
componentDidMount() {
document.addEventListener('click', this.handleClick, true);
this.setCursor(this.props.text.length); // Set cursor at end
this.setState({
shouldCondense: this.props.shouldCondense,
});
const composeForm = document.getElementById('compose-form');
composeForm.addEventListener('dragenter', this.handleDragEnter, false);
composeForm.addEventListener('dragover', this.handleDragOver, false);
composeForm.addEventListener('drop', this.handleDrop, false);
composeForm.addEventListener('dragleave', this.handleDragLeave, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClick, true);
const composeForm = document.getElementById('compose-form');
composeForm.removeEventListener('dragenter', this.handleDragEnter);
composeForm.removeEventListener('dragover', this.handleDragOver);
composeForm.removeEventListener('drop', this.handleDrop);
composeForm.removeEventListener('dragleave', this.handleDragLeave);
}
handleDragEnter = (e) => {
e.preventDefault();
if (!this.dragTargets) {
this.dragTargets = [];
}
if (this.dragTargets.indexOf(e.target) === -1) {
this.dragTargets.push(e.target);
}
if (e.dataTransfer && Array.from(e.dataTransfer.types).includes('Files')) {
this.setState({ draggingOver: true });
}
}
handleDragOver = (e) => {
if (this.dataTransferIsText(e.dataTransfer)) return false;
e.preventDefault();
e.stopPropagation();
try {
e.dataTransfer.dropEffect = 'copy';
} catch (err) {
}
return false;
}
handleDrop = (e) => {
if (this.dataTransferIsText(e.dataTransfer)) return;
e.preventDefault();
this.setState({ draggingOver: false });
this.dragTargets = [];
if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
this.props.dispatch(uploadCompose(e.dataTransfer.files));
}
}
handleDragLeave = (e) => {
e.preventDefault();
e.stopPropagation();
this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.form.contains(el));
if (this.dragTargets.length > 0) {
return;
}
this.setState({ draggingOver: false });
}
dataTransferIsText = (dataTransfer) => {
return (dataTransfer && Array.from(dataTransfer.types).includes('text/plain') && dataTransfer.items.length === 1);
}
closeUploadModal = () => {
this.setState({ draggingOver: false });
}
setAutosuggestTextarea = (c) => {
@ -233,8 +302,8 @@ class ComposeForm extends ImmutablePureComponent {
}
render() {
const { intl, onPaste, showSearch, anyMedia, autoFocus, isModalOpen, maxTootChars } = this.props;
const { shouldCondense } = this.state;
const { intl, onPaste, showSearch, anyMedia, shouldCondense, autoFocus, isModalOpen, maxTootChars } = this.props;
const { draggingOver } = this.state;
const condensed = shouldCondense && !this.props.text && !this.state.composeFocused;
const disabled = this.props.isSubmitting;
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
@ -255,7 +324,7 @@ class ComposeForm extends ImmutablePureComponent {
});
return (
<div className={composeClassNames} ref={this.setForm} onClick={this.handleClick}>
<div className={composeClassNames} ref={this.setForm} onClick={this.handleClick} id='compose-form'>
<WarningContainer />
{ !shouldCondense && <ReplyIndicatorContainer /> }
@ -281,6 +350,7 @@ class ComposeForm extends ImmutablePureComponent {
<div className='emoji-picker-wrapper'>
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} />
</div>
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
<AutosuggestTextarea
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
@ -295,7 +365,6 @@ class ComposeForm extends ImmutablePureComponent {
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onSuggestionSelected={this.onSuggestionSelected}
onPaste={onPaste}
onAttachment={this.handleAttachment}
autoFocus={shouldAutoFocus}
>
{

Wyświetl plik

@ -295,6 +295,7 @@ class UI extends React.PureComponent {
};
state = {
draggingOver: false,
mobile: isMobile(window.innerWidth),
};
@ -314,6 +315,72 @@ class UI extends React.PureComponent {
this.props.dispatch(clearHeight());
}
// handleDragEnter = (e) => {
// e.preventDefault();
//
// if (!this.dragTargets) {
// this.dragTargets = [];
// }
//
// if (this.dragTargets.indexOf(e.target) === -1) {
// this.dragTargets.push(e.target);
// }
//
// if (e.dataTransfer && Array.from(e.dataTransfer.types).includes('Files')) {
// this.setState({ draggingOver: true });
// }
// }
//
// handleDragOver = (e) => {
// if (this.dataTransferIsText(e.dataTransfer)) return false;
// e.preventDefault();
// e.stopPropagation();
//
// try {
// e.dataTransfer.dropEffect = 'copy';
// } catch (err) {
//
// }
//
// return false;
// }
//
// handleDrop = (e) => {
// const { me } = this.props;
// if (!me) return;
//
// if (this.dataTransferIsText(e.dataTransfer)) return;
// e.preventDefault();
//
// this.setState({ draggingOver: false });
// this.dragTargets = [];
//
// if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
// this.props.dispatch(uploadCompose(e.dataTransfer.files));
// }
// }
//
// handleDragLeave = (e) => {
// e.preventDefault();
// e.stopPropagation();
//
// this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.node.contains(el));
//
// if (this.dragTargets.length > 0) {
// return;
// }
//
// this.setState({ draggingOver: false });
// }
//
// dataTransferIsText = (dataTransfer) => {
// return (dataTransfer && Array.from(dataTransfer.types).includes('text/plain') && dataTransfer.items.length === 1);
// }
//
// closeUploadModal = () => {
// this.setState({ draggingOver: false });
// }
handleServiceWorkerPostMessage = ({ data }) => {
if (data.type === 'navigate') {
this.context.router.history.push(data.path);
@ -378,11 +445,6 @@ class UI extends React.PureComponent {
componentWillUnmount() {
window.removeEventListener('beforeunload', this.handleBeforeUnload);
window.removeEventListener('resize', this.handleResize);
document.removeEventListener('dragenter', this.handleDragEnter);
document.removeEventListener('dragover', this.handleDragOver);
document.removeEventListener('drop', this.handleDrop);
document.removeEventListener('dragleave', this.handleDragLeave);
document.removeEventListener('dragend', this.handleDragEnd);
this.disconnectStreaming();
}