Allow drag&drop of link to quote in compose form (#36859)

This commit is contained in:
Jeong Arm
2025-11-14 23:14:37 +09:00
committed by GitHub
parent c5eca8ffb2
commit 4ab1d5d724
3 changed files with 34 additions and 14 deletions

View File

@@ -50,6 +50,7 @@ const AutosuggestTextarea = forwardRef(({
onKeyUp,
onKeyDown,
onPaste,
onDrop,
onFocus,
autoFocus = true,
lang,
@@ -153,6 +154,12 @@ const AutosuggestTextarea = forwardRef(({
onPaste(e);
}, [onPaste]);
const handleDrop = useCallback((e) => {
if (onDrop) {
onDrop(e);
}
}, [onDrop]);
// Show the suggestions again whenever they change and the textarea is focused
useEffect(() => {
if (suggestions.size > 0 && textareaRef.current === document.activeElement) {
@@ -204,6 +211,7 @@ const AutosuggestTextarea = forwardRef(({
onFocus={handleFocus}
onBlur={handleBlur}
onPaste={handlePaste}
onDrop={handleDrop}
dir='auto'
aria-autocomplete='list'
aria-label={placeholder}
@@ -235,6 +243,7 @@ AutosuggestTextarea.propTypes = {
onKeyUp: PropTypes.func,
onKeyDown: PropTypes.func,
onPaste: PropTypes.func.isRequired,
onDrop: PropTypes.func,
onFocus:PropTypes.func,
autoFocus: PropTypes.bool,
lang: PropTypes.string,

View File

@@ -64,6 +64,7 @@ class ComposeForm extends ImmutablePureComponent {
onSuggestionSelected: PropTypes.func.isRequired,
onChangeSpoilerText: PropTypes.func.isRequired,
onPaste: PropTypes.func.isRequired,
onDrop: PropTypes.func.isRequired,
onPickEmoji: PropTypes.func.isRequired,
autoFocus: PropTypes.bool,
withoutNavigation: PropTypes.bool,
@@ -249,7 +250,7 @@ class ComposeForm extends ImmutablePureComponent {
};
render () {
const { intl, onPaste, autoFocus, withoutNavigation, maxChars, isSubmitting } = this.props;
const { intl, onPaste, onDrop, autoFocus, withoutNavigation, maxChars, isSubmitting } = this.props;
const { highlighted } = this.state;
return (
@@ -305,6 +306,7 @@ class ComposeForm extends ImmutablePureComponent {
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
onSuggestionSelected={this.onSuggestionSelected}
onPaste={onPaste}
onDrop={onDrop}
autoFocus={autoFocus}
lang={this.props.lang}
className='compose-form__input'

View File

@@ -18,6 +18,24 @@ import ComposeForm from '../components/compose_form';
const urlLikeRegex = /^https?:\/\/[^\s]+\/[^\s]+$/i;
const processPasteOrDrop = (transfer, e, dispatch) => {
if (transfer && transfer.files.length === 1) {
dispatch(uploadCompose(transfer.files));
e.preventDefault();
} else if (transfer && transfer.files.length === 0) {
const data = transfer.getData('text/plain');
if (!data.match(urlLikeRegex)) return;
try {
const url = new URL(data);
dispatch(pasteLinkCompose({ url }));
e.preventDefault();
} catch {
return;
}
}
};
const mapStateToProps = state => ({
text: state.getIn(['compose', 'text']),
suggestions: state.getIn(['compose', 'suggestions']),
@@ -85,20 +103,11 @@ const mapDispatchToProps = (dispatch, props) => ({
},
onPaste (e) {
if (e.clipboardData && e.clipboardData.files.length === 1) {
dispatch(uploadCompose(e.clipboardData.files));
e.preventDefault();
} else if (e.clipboardData && e.clipboardData.files.length === 0) {
const data = e.clipboardData.getData('text/plain');
if (!data.match(urlLikeRegex)) return;
processPasteOrDrop(e.clipboardData, e, dispatch);
},
try {
const url = new URL(data);
dispatch(pasteLinkCompose({ url }));
} catch {
return;
}
}
onDrop (e) {
processPasteOrDrop(e.dataTransfer, e, dispatch);
},
onPickEmoji (position, data, needsSpace) {