Add confirmation dialog when posting media without description
Fixes #211
This commit is contained in:
parent
5ce6727669
commit
1544ac4e27
|
@ -2,6 +2,7 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import { defineMessages } from 'react-intl';
|
||||||
|
|
||||||
const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\S+)/i;
|
const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\S+)/i;
|
||||||
|
|
||||||
|
@ -49,6 +50,13 @@ import { assignHandlers } from 'flavours/glitch/util/react_helpers';
|
||||||
import { wrap } from 'flavours/glitch/util/redux_helpers';
|
import { wrap } from 'flavours/glitch/util/redux_helpers';
|
||||||
import { privacyPreference } from 'flavours/glitch/util/privacy_preference';
|
import { privacyPreference } from 'flavours/glitch/util/privacy_preference';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
missingDescriptionMessage: { id: 'confirmations.missing_media_description.message',
|
||||||
|
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
|
||||||
|
missingDescriptionConfirm: { id: 'confirmations.missing_media_description.confirm',
|
||||||
|
defaultMessage: 'Send anyway' },
|
||||||
|
});
|
||||||
|
|
||||||
// State mapping.
|
// State mapping.
|
||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']);
|
const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']);
|
||||||
|
@ -93,11 +101,12 @@ function mapStateToProps (state) {
|
||||||
text: state.getIn(['compose', 'text']),
|
text: state.getIn(['compose', 'text']),
|
||||||
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
|
||||||
spoilersAlwaysOn: spoilersAlwaysOn,
|
spoilersAlwaysOn: spoilersAlwaysOn,
|
||||||
|
mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dispatch mapping.
|
// Dispatch mapping.
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
onCancelReply() {
|
onCancelReply() {
|
||||||
dispatch(cancelReplyCompose());
|
dispatch(cancelReplyCompose());
|
||||||
},
|
},
|
||||||
|
@ -149,6 +158,13 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onSelectSuggestion(position, token, suggestion) {
|
onSelectSuggestion(position, token, suggestion) {
|
||||||
dispatch(selectComposeSuggestion(position, token, suggestion));
|
dispatch(selectComposeSuggestion(position, token, suggestion));
|
||||||
},
|
},
|
||||||
|
onMediaDescriptionConfirm() {
|
||||||
|
dispatch(openModal('CONFIRM', {
|
||||||
|
message: intl.formatMessage(messages.missingDescriptionMessage),
|
||||||
|
confirm: intl.formatMessage(messages.missingDescriptionConfirm),
|
||||||
|
onConfirm: () => dispatch(submitCompose()),
|
||||||
|
}));
|
||||||
|
},
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
dispatch(submitCompose());
|
dispatch(submitCompose());
|
||||||
},
|
},
|
||||||
|
@ -212,8 +228,11 @@ const handlers = {
|
||||||
onSubmit,
|
onSubmit,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
isUploading,
|
isUploading,
|
||||||
|
media,
|
||||||
anyMedia,
|
anyMedia,
|
||||||
text,
|
text,
|
||||||
|
mediaDescriptionConfirmation,
|
||||||
|
onMediaDescriptionConfirm,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// If something changes inside the textarea, then we update the
|
// If something changes inside the textarea, then we update the
|
||||||
|
@ -227,8 +246,15 @@ const handlers = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submits the status.
|
// Submit unless there are media with missing descriptions
|
||||||
if (onSubmit) {
|
if (mediaDescriptionConfirmation && onMediaDescriptionConfirm && media && media.some(item => !item.get('description'))) {
|
||||||
|
const firstWithoutDescription = media.findIndex(item => !item.get('description'));
|
||||||
|
const inputs = document.querySelectorAll('.composer--upload_form--item input');
|
||||||
|
if (inputs.length == media.size && firstWithoutDescription !== -1) {
|
||||||
|
inputs[firstWithoutDescription].focus();
|
||||||
|
}
|
||||||
|
onMediaDescriptionConfirm();
|
||||||
|
} else if (onSubmit) {
|
||||||
onSubmit();
|
onSubmit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -495,6 +521,9 @@ Composer.propTypes = {
|
||||||
suggestionToken: PropTypes.string,
|
suggestionToken: PropTypes.string,
|
||||||
suggestions: ImmutablePropTypes.list,
|
suggestions: ImmutablePropTypes.list,
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
|
anyMedia: PropTypes.bool,
|
||||||
|
spoilersAlwaysOn: PropTypes.bool,
|
||||||
|
mediaDescriptionConfirmation: PropTypes.bool,
|
||||||
|
|
||||||
// Dispatch props.
|
// Dispatch props.
|
||||||
onCancelReply: PropTypes.func,
|
onCancelReply: PropTypes.func,
|
||||||
|
@ -517,8 +546,7 @@ Composer.propTypes = {
|
||||||
onUndoUpload: PropTypes.func,
|
onUndoUpload: PropTypes.func,
|
||||||
onUnmount: PropTypes.func,
|
onUnmount: PropTypes.func,
|
||||||
onUpload: PropTypes.func,
|
onUpload: PropTypes.func,
|
||||||
anyMedia: PropTypes.bool,
|
onMediaDescriptionConfirm: PropTypes.func,
|
||||||
spoilersAlwaysOn: PropTypes.bool,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Connecting and export.
|
// Connecting and export.
|
||||||
|
|
|
@ -83,6 +83,14 @@ export default class LocalSettingsPage extends React.PureComponent {
|
||||||
>
|
>
|
||||||
<FormattedMessage id='settings.always_show_spoilers_field' defaultMessage='Always enable the Content Warning field' />
|
<FormattedMessage id='settings.always_show_spoilers_field' defaultMessage='Always enable the Content Warning field' />
|
||||||
</LocalSettingsPageItem>
|
</LocalSettingsPageItem>
|
||||||
|
<LocalSettingsPageItem
|
||||||
|
settings={settings}
|
||||||
|
item={['confirm_missing_media_description']}
|
||||||
|
id='mastodon-settings--confirm_missing_media_description'
|
||||||
|
onChange={onChange}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='settings.confirm_missing_media_description' defaultMessage='Show confirmation dialog before sending toots lacking media descriptions' />
|
||||||
|
</LocalSettingsPageItem>
|
||||||
<LocalSettingsPageItem
|
<LocalSettingsPageItem
|
||||||
settings={settings}
|
settings={settings}
|
||||||
item={['side_arm']}
|
item={['side_arm']}
|
||||||
|
|
|
@ -13,6 +13,7 @@ const initialState = ImmutableMap({
|
||||||
side_arm_reply_mode : 'keep',
|
side_arm_reply_mode : 'keep',
|
||||||
show_reply_count : false,
|
show_reply_count : false,
|
||||||
always_show_spoilers_field: false,
|
always_show_spoilers_field: false,
|
||||||
|
confirm_missing_media_description: false,
|
||||||
collapsed : ImmutableMap({
|
collapsed : ImmutableMap({
|
||||||
enabled : true,
|
enabled : true,
|
||||||
auto : ImmutableMap({
|
auto : ImmutableMap({
|
||||||
|
|
Loading…
Reference in New Issue