Merge branch 'master' into glitch-soc/merge-upstream

master
Thibaut Girka 6 years ago
commit fae53e1a39
  1. 2
      app/javascript/mastodon/components/status_action_bar.js
  2. 9
      app/javascript/mastodon/containers/status_container.js
  3. 2
      app/javascript/mastodon/features/account/components/header.js
  4. 6
      app/javascript/mastodon/features/account_timeline/containers/header_container.js
  5. 2
      app/javascript/mastodon/features/status/components/action_bar.js
  6. 9
      app/javascript/mastodon/features/status/containers/detailed_status_container.js
  7. 9
      app/javascript/mastodon/features/status/index.js
  8. 12
      app/javascript/mastodon/features/ui/components/confirmation_modal.js
  9. 1
      app/javascript/styles/mastodon/components.scss
  10. 10
      app/validators/html_validator.rb
  11. 2
      config/locales/en.yml

@ -139,7 +139,7 @@ class StatusActionBar extends ImmutablePureComponent {
} }
handleBlockClick = () => { handleBlockClick = () => {
this.props.onBlock(this.props.status.get('account')); this.props.onBlock(this.props.status);
} }
handleOpen = () => { handleOpen = () => {

@ -38,6 +38,7 @@ const messages = defineMessages({
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
@ -134,11 +135,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(openModal('VIDEO', { media, time })); dispatch(openModal('VIDEO', { media, time }));
}, },
onBlock (account) { onBlock (status) {
const account = status.get('account');
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.blockConfirm), confirm: intl.formatMessage(messages.blockConfirm),
onConfirm: () => dispatch(blockAccount(account.get('id'))), onConfirm: () => dispatch(blockAccount(account.get('id'))),
secondary: intl.formatMessage(messages.blockAndReport),
onSecondary: () => {
dispatch(blockAccount(account.get('id')));
dispatch(initReport(account, status));
},
})); }));
}, },

@ -212,7 +212,7 @@ class Header extends ImmutablePureComponent {
<div className='account__header__bar'> <div className='account__header__bar'>
<div className='account__header__tabs'> <div className='account__header__tabs'>
<a className='avatar' href={account.get('url')}> <a className='avatar' href={account.get('url')} target='_blank'>
<Avatar account={account} size={90} /> <Avatar account={account} size={90} />
</a> </a>

@ -26,6 +26,7 @@ const messages = defineMessages({
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' }, blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
@ -65,6 +66,11 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.blockConfirm), confirm: intl.formatMessage(messages.blockConfirm),
onConfirm: () => dispatch(blockAccount(account.get('id'))), onConfirm: () => dispatch(blockAccount(account.get('id'))),
secondary: intl.formatMessage(messages.blockAndReport),
onSecondary: () => {
dispatch(blockAccount(account.get('id')));
dispatch(initReport(account));
},
})); }));
} }
}, },

@ -92,7 +92,7 @@ class ActionBar extends React.PureComponent {
} }
handleBlockClick = () => { handleBlockClick = () => {
this.props.onBlock(this.props.status.get('account')); this.props.onBlock(this.props.status);
} }
handleReport = () => { handleReport = () => {

@ -38,6 +38,7 @@ const messages = defineMessages({
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' }, blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
@ -135,11 +136,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(openModal('VIDEO', { media, time })); dispatch(openModal('VIDEO', { media, time }));
}, },
onBlock (account) { onBlock (status) {
const account = status.get('account');
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.blockConfirm), confirm: intl.formatMessage(messages.blockConfirm),
onConfirm: () => dispatch(blockAccount(account.get('id'))), onConfirm: () => dispatch(blockAccount(account.get('id'))),
secondary: intl.formatMessage(messages.blockAndReport),
onSecondary: () => {
dispatch(blockAccount(account.get('id')));
dispatch(initReport(account, status));
},
})); }));
}, },

@ -57,6 +57,7 @@ const messages = defineMessages({
detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' }, detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
}); });
const makeMapStateToProps = () => { const makeMapStateToProps = () => {
@ -253,13 +254,19 @@ class Status extends ImmutablePureComponent {
} }
} }
handleBlockClick = (account) => { handleBlockClick = (status) => {
const { dispatch, intl } = this.props; const { dispatch, intl } = this.props;
const account = status.get('account');
dispatch(openModal('CONFIRM', { dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />, message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.blockConfirm), confirm: intl.formatMessage(messages.blockConfirm),
onConfirm: () => dispatch(blockAccount(account.get('id'))), onConfirm: () => dispatch(blockAccount(account.get('id'))),
secondary: intl.formatMessage(messages.blockAndReport),
onSecondary: () => {
dispatch(blockAccount(account.get('id')));
dispatch(initReport(account, status));
},
})); }));
} }

@ -11,6 +11,8 @@ class ConfirmationModal extends React.PureComponent {
confirm: PropTypes.string.isRequired, confirm: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired, onConfirm: PropTypes.func.isRequired,
secondary: PropTypes.string,
onSecondary: PropTypes.func,
intl: PropTypes.object.isRequired, intl: PropTypes.object.isRequired,
}; };
@ -23,6 +25,11 @@ class ConfirmationModal extends React.PureComponent {
this.props.onConfirm(); this.props.onConfirm();
} }
handleSecondary = () => {
this.props.onClose();
this.props.onSecondary();
}
handleCancel = () => { handleCancel = () => {
this.props.onClose(); this.props.onClose();
} }
@ -32,7 +39,7 @@ class ConfirmationModal extends React.PureComponent {
} }
render () { render () {
const { message, confirm } = this.props; const { message, confirm, secondary } = this.props;
return ( return (
<div className='modal-root__modal confirmation-modal'> <div className='modal-root__modal confirmation-modal'>
@ -44,6 +51,9 @@ class ConfirmationModal extends React.PureComponent {
<Button onClick={this.handleCancel} className='confirmation-modal__cancel-button'> <Button onClick={this.handleCancel} className='confirmation-modal__cancel-button'>
<FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' /> <FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
</Button> </Button>
{secondary !== undefined && (
<Button text={secondary} onClick={this.handleSecondary} className='confirmation-modal__secondary-button' />
)}
<Button text={confirm} onClick={this.handleClick} ref={this.setRef} /> <Button text={confirm} onClick={this.handleClick} ref={this.setRef} />
</div> </div>
</div> </div>

@ -4128,6 +4128,7 @@ a.status-card.compact:hover {
.confirmation-modal__action-bar, .confirmation-modal__action-bar,
.mute-modal__action-bar { .mute-modal__action-bar {
.confirmation-modal__secondary-button,
.confirmation-modal__cancel-button, .confirmation-modal__cancel-button,
.mute-modal__cancel-button { .mute-modal__cancel-button {
background-color: transparent; background-color: transparent;

@ -3,12 +3,16 @@
class HtmlValidator < ActiveModel::EachValidator class HtmlValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
return if value.blank? return if value.blank?
record.errors.add(attribute, I18n.t('html_validator.invalid_markup')) unless valid_html?(value) errors = html_errors(value)
unless errors.empty?
record.errors.add(attribute, I18n.t('html_validator.invalid_markup', error: errors.first.to_s))
end
end end
private private
def valid_html?(str) def html_errors(str)
Nokogiri::HTML.fragment(str).to_s == str fragment = Nokogiri::HTML.fragment(str)
fragment.errors
end end
end end

@ -642,7 +642,7 @@ en:
one: Something isn't quite right yet! Please review the error below one: Something isn't quite right yet! Please review the error below
other: Something isn't quite right yet! Please review %{count} errors below other: Something isn't quite right yet! Please review %{count} errors below
html_validator: html_validator:
invalid_markup: contains invalid HTML markup invalid_markup: 'contains invalid HTML markup: %{error}'
identity_proofs: identity_proofs:
active: Active active: Active
authorize: Yes, authorize authorize: Yes, authorize

Loading…
Cancel
Save