Add feature to automatically attach quote on eligible link past in Web UI composer (#36364)
This commit is contained in:
@@ -4,6 +4,7 @@ import { createAction } from '@reduxjs/toolkit';
|
|||||||
import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
import type { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import { apiUpdateMedia } from 'mastodon/api/compose';
|
import { apiUpdateMedia } from 'mastodon/api/compose';
|
||||||
|
import { apiGetSearch } from 'mastodon/api/search';
|
||||||
import type { ApiMediaAttachmentJSON } from 'mastodon/api_types/media_attachments';
|
import type { ApiMediaAttachmentJSON } from 'mastodon/api_types/media_attachments';
|
||||||
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
import type { MediaAttachment } from 'mastodon/models/media_attachment';
|
||||||
import {
|
import {
|
||||||
@@ -16,6 +17,7 @@ import type { Status } from '../models/status';
|
|||||||
|
|
||||||
import { showAlert } from './alerts';
|
import { showAlert } from './alerts';
|
||||||
import { focusCompose } from './compose';
|
import { focusCompose } from './compose';
|
||||||
|
import { importFetchedStatuses } from './importer';
|
||||||
import { openModal } from './modal';
|
import { openModal } from './modal';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@@ -165,6 +167,41 @@ export const quoteComposeById = createAppThunk(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const pasteLinkCompose = createDataLoadingThunk(
|
||||||
|
'compose/pasteLink',
|
||||||
|
async ({ url }: { url: string }) => {
|
||||||
|
return await apiGetSearch({
|
||||||
|
q: url,
|
||||||
|
type: 'statuses',
|
||||||
|
resolve: true,
|
||||||
|
limit: 2,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(data, { dispatch, getState }) => {
|
||||||
|
const composeState = getState().compose;
|
||||||
|
|
||||||
|
if (
|
||||||
|
composeState.get('quoted_status_id') ||
|
||||||
|
composeState.get('is_submitting') ||
|
||||||
|
composeState.get('poll') ||
|
||||||
|
composeState.get('is_uploading')
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dispatch(importFetchedStatuses(data.statuses));
|
||||||
|
|
||||||
|
if (
|
||||||
|
data.statuses.length === 1 &&
|
||||||
|
data.statuses[0] &&
|
||||||
|
['automatic', 'manual'].includes(
|
||||||
|
data.statuses[0].quote_approval?.current_user ?? 'denied',
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
dispatch(quoteComposeById(data.statuses[0].id));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
|
export const quoteComposeCancel = createAction('compose/quoteComposeCancel');
|
||||||
|
|
||||||
export const setComposeQuotePolicy = createAction<ApiQuotePolicy>(
|
export const setComposeQuotePolicy = createAction<ApiQuotePolicy>(
|
||||||
|
|||||||
@@ -150,10 +150,7 @@ const AutosuggestTextarea = forwardRef(({
|
|||||||
}, [suggestions, onSuggestionSelected, textareaRef]);
|
}, [suggestions, onSuggestionSelected, textareaRef]);
|
||||||
|
|
||||||
const handlePaste = useCallback((e) => {
|
const handlePaste = useCallback((e) => {
|
||||||
if (e.clipboardData && e.clipboardData.files.length === 1) {
|
onPaste(e);
|
||||||
onPaste(e.clipboardData.files);
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}, [onPaste]);
|
}, [onPaste]);
|
||||||
|
|
||||||
// Show the suggestions again whenever they change and the textarea is focused
|
// Show the suggestions again whenever they change and the textarea is focused
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import {
|
|||||||
insertEmojiCompose,
|
insertEmojiCompose,
|
||||||
uploadCompose,
|
uploadCompose,
|
||||||
} from 'mastodon/actions/compose';
|
} from 'mastodon/actions/compose';
|
||||||
|
import { pasteLinkCompose } from 'mastodon/actions/compose_typed';
|
||||||
import { openModal } from 'mastodon/actions/modal';
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
|
|
||||||
import ComposeForm from '../components/compose_form';
|
import ComposeForm from '../components/compose_form';
|
||||||
|
|
||||||
|
const urlLikeRegex = /^https?:\/\/[^\s]+\/[^\s]+$/i;
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
text: state.getIn(['compose', 'text']),
|
text: state.getIn(['compose', 'text']),
|
||||||
suggestions: state.getIn(['compose', 'suggestions']),
|
suggestions: state.getIn(['compose', 'suggestions']),
|
||||||
@@ -71,8 +74,21 @@ const mapDispatchToProps = (dispatch, props) => ({
|
|||||||
dispatch(changeComposeSpoilerText(checked));
|
dispatch(changeComposeSpoilerText(checked));
|
||||||
},
|
},
|
||||||
|
|
||||||
onPaste (files) {
|
onPaste (e) {
|
||||||
dispatch(uploadCompose(files));
|
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;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(data);
|
||||||
|
dispatch(pasteLinkCompose({ url }));
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onPickEmoji (position, data, needsSpace) {
|
onPickEmoji (position, data, needsSpace) {
|
||||||
|
|||||||
Reference in New Issue
Block a user