* Change report modal to include category selection in web UI * Various fixes and improvements - Change thank you text to be different based on category - Change starting headline to be different for account and status reports - Change toggle components to have a checkmark when checked - Fix report dialog being cut off on small screens - Fix thank you screen offering mute or block if already muted or blocked - Refactor toggle components in report dialog into one component * Change wording on final screen * Change checkboxes to be square when multiple options are possibleclosed-social-glitch-2
@ -1,89 +1,38 @@ | |||||
import api from '../api'; | import api from '../api'; | ||||
import { openModal, closeModal } from './modal'; | |||||
export const REPORT_INIT = 'REPORT_INIT'; | |||||
export const REPORT_CANCEL = 'REPORT_CANCEL'; | |||||
import { openModal } from './modal'; | |||||
export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST'; | export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST'; | ||||
export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'; | export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'; | ||||
export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; | export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; | ||||
export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE'; | |||||
export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE'; | |||||
export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE'; | |||||
export function initReport(account, status) { | |||||
return dispatch => { | |||||
dispatch({ | |||||
type: REPORT_INIT, | |||||
account, | |||||
status, | |||||
}); | |||||
dispatch(openModal('REPORT')); | |||||
}; | |||||
}; | |||||
export function cancelReport() { | |||||
return { | |||||
type: REPORT_CANCEL, | |||||
}; | |||||
}; | |||||
export function toggleStatusReport(statusId, checked) { | |||||
return { | |||||
type: REPORT_STATUS_TOGGLE, | |||||
statusId, | |||||
checked, | |||||
}; | |||||
}; | |||||
export function submitReport() { | |||||
return (dispatch, getState) => { | |||||
dispatch(submitReportRequest()); | |||||
api(getState).post('/api/v1/reports', { | |||||
account_id: getState().getIn(['reports', 'new', 'account_id']), | |||||
status_ids: getState().getIn(['reports', 'new', 'status_ids']), | |||||
comment: getState().getIn(['reports', 'new', 'comment']), | |||||
forward: getState().getIn(['reports', 'new', 'forward']), | |||||
}).then(response => { | |||||
dispatch(closeModal()); | |||||
dispatch(submitReportSuccess(response.data)); | |||||
}).catch(error => dispatch(submitReportFail(error))); | |||||
}; | |||||
}; | |||||
export function submitReportRequest() { | |||||
return { | |||||
type: REPORT_SUBMIT_REQUEST, | |||||
}; | |||||
}; | |||||
export function submitReportSuccess(report) { | |||||
return { | |||||
type: REPORT_SUBMIT_SUCCESS, | |||||
report, | |||||
}; | |||||
}; | |||||
export function submitReportFail(error) { | |||||
return { | |||||
type: REPORT_SUBMIT_FAIL, | |||||
error, | |||||
}; | |||||
}; | |||||
export function changeReportComment(comment) { | |||||
return { | |||||
type: REPORT_COMMENT_CHANGE, | |||||
comment, | |||||
}; | |||||
}; | |||||
export function changeReportForward(forward) { | |||||
return { | |||||
type: REPORT_FORWARD_CHANGE, | |||||
forward, | |||||
}; | |||||
}; | |||||
export const initReport = (account, status) => dispatch => | |||||
dispatch(openModal('REPORT', { | |||||
accountId: account.get('id'), | |||||
statusId: status.get('id'), | |||||
})); | |||||
export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => { | |||||
dispatch(submitReportRequest()); | |||||
api(getState).post('/api/v1/reports', params).then(response => { | |||||
dispatch(submitReportSuccess(response.data)); | |||||
if (onSuccess) onSuccess(); | |||||
}).catch(error => { | |||||
dispatch(submitReportFail(error)); | |||||
if (onFail) onFail(); | |||||
}); | |||||
}; | |||||
export const submitReportRequest = () => ({ | |||||
type: REPORT_SUBMIT_REQUEST, | |||||
}); | |||||
export const submitReportSuccess = report => ({ | |||||
type: REPORT_SUBMIT_SUCCESS, | |||||
report, | |||||
}); | |||||
export const submitReportFail = error => ({ | |||||
type: REPORT_SUBMIT_FAIL, | |||||
error, | |||||
}); |
@ -0,0 +1,27 @@ | |||||
import api from '../api'; | |||||
export const RULES_FETCH_REQUEST = 'RULES_FETCH_REQUEST'; | |||||
export const RULES_FETCH_SUCCESS = 'RULES_FETCH_SUCCESS'; | |||||
export const RULES_FETCH_FAIL = 'RULES_FETCH_FAIL'; | |||||
export const fetchRules = () => (dispatch, getState) => { | |||||
dispatch(fetchRulesRequest()); | |||||
api(getState) | |||||
.get('/api/v1/instance').then(({ data }) => dispatch(fetchRulesSuccess(data.rules))) | |||||
.catch(err => dispatch(fetchRulesFail(err))); | |||||
}; | |||||
const fetchRulesRequest = () => ({ | |||||
type: RULES_FETCH_REQUEST, | |||||
}); | |||||
const fetchRulesSuccess = rules => ({ | |||||
type: RULES_FETCH_SUCCESS, | |||||
rules, | |||||
}); | |||||
const fetchRulesFail = error => ({ | |||||
type: RULES_FETCH_FAIL, | |||||
error, | |||||
}); |
@ -0,0 +1,9 @@ | |||||
import React from 'react'; | |||||
const Check = () => ( | |||||
<svg width='14' height='11' viewBox='0 0 14 11'> | |||||
<path d='M11.264 0L5.26 6.004 2.103 2.847 0 4.95l5.26 5.26 8.108-8.107L11.264 0' fill='currentColor' fillRule='evenodd' /> | |||||
</svg> | |||||
); | |||||
export default Check; |
@ -0,0 +1,93 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | |||||
import Button from 'mastodon/components/button'; | |||||
import Option from './components/option'; | |||||
const messages = defineMessages({ | |||||
dislike: { id: 'report.reasons.dislike', defaultMessage: 'I don\'t like it' }, | |||||
dislike_description: { id: 'report.reasons.dislike_description', defaultMessage: 'It is not something you want to see' }, | |||||
spam: { id: 'report.reasons.spam', defaultMessage: 'It\'s spam' }, | |||||
spam_description: { id: 'report.reasons.spam_description', defaultMessage: 'Malicious links, fake engagement, or repetetive replies' }, | |||||
violation: { id: 'report.reasons.violation', defaultMessage: 'It violates server rules' }, | |||||
violation_description: { id: 'report.reasons.violation_description', defaultMessage: 'You are aware that it breaks specific rules' }, | |||||
other: { id: 'report.reasons.other', defaultMessage: 'It\'s something else' }, | |||||
other_description: { id: 'report.reasons.other_description', defaultMessage: 'The issue does not fit into other categories' }, | |||||
status: { id: 'report.category.title_status', defaultMessage: 'post' }, | |||||
account: { id: 'report.category.title_account', defaultMessage: 'profile' }, | |||||
}); | |||||
export default @injectIntl | |||||
class Category extends React.PureComponent { | |||||
static propTypes = { | |||||
onNextStep: PropTypes.func.isRequired, | |||||
category: PropTypes.string, | |||||
onChangeCategory: PropTypes.func.isRequired, | |||||
startedFrom: PropTypes.oneOf(['status', 'account']), | |||||
intl: PropTypes.object.isRequired, | |||||
}; | |||||
handleNextClick = () => { | |||||
const { onNextStep, category } = this.props; | |||||
switch(category) { | |||||
case 'dislike': | |||||
onNextStep('thanks'); | |||||
break; | |||||
case 'violation': | |||||
onNextStep('rules'); | |||||
break; | |||||
default: | |||||
onNextStep('statuses'); | |||||
break; | |||||
} | |||||
}; | |||||
handleCategoryToggle = (value, checked) => { | |||||
const { onChangeCategory } = this.props; | |||||
if (checked) { | |||||
onChangeCategory(value); | |||||
} | |||||
}; | |||||
render () { | |||||
const { category, startedFrom, intl } = this.props; | |||||
const options = [ | |||||
'dislike', | |||||
'spam', | |||||
'violation', | |||||
'other', | |||||
]; | |||||
return ( | |||||
<React.Fragment> | |||||
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.category.title' defaultMessage="Tell us what's going on with this {type}" values={{ type: intl.formatMessage(messages[startedFrom]) }} /></h3> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.category.subtitle' defaultMessage='Choose the best match' /></p> | |||||
<div> | |||||
{options.map(item => ( | |||||
<Option | |||||
key={item} | |||||
name='category' | |||||
value={item} | |||||
checked={category === item} | |||||
onToggle={this.handleCategoryToggle} | |||||
label={intl.formatMessage(messages[item])} | |||||
description={intl.formatMessage(messages[`${item}_description`])} | |||||
/> | |||||
))} | |||||
</div> | |||||
<div className='flex-spacer' /> | |||||
<div className='report-dialog-modal__actions'> | |||||
<Button onClick={this.handleNextClick} disabled={category === null}><FormattedMessage id='report.next' defaultMessage='Next' /></Button> | |||||
</div> | |||||
</React.Fragment> | |||||
); | |||||
} | |||||
} |
@ -0,0 +1,83 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import { injectIntl, defineMessages, FormattedMessage } from 'react-intl'; | |||||
import Button from 'mastodon/components/button'; | |||||
import Toggle from 'react-toggle'; | |||||
const messages = defineMessages({ | |||||
placeholder: { id: 'report.placeholder', defaultMessage: 'Type or paste additional comments' }, | |||||
}); | |||||
export default @injectIntl | |||||
class Comment extends React.PureComponent { | |||||
static propTypes = { | |||||
onSubmit: PropTypes.func.isRequired, | |||||
comment: PropTypes.string.isRequired, | |||||
onChangeComment: PropTypes.func.isRequired, | |||||
intl: PropTypes.object.isRequired, | |||||
isSubmitting: PropTypes.bool, | |||||
forward: PropTypes.bool, | |||||
isRemote: PropTypes.bool, | |||||
domain: PropTypes.string, | |||||
onChangeForward: PropTypes.func.isRequired, | |||||
}; | |||||
handleClick = () => { | |||||
const { onSubmit } = this.props; | |||||
onSubmit(); | |||||
}; | |||||
handleChange = e => { | |||||
const { onChangeComment } = this.props; | |||||
onChangeComment(e.target.value); | |||||
}; | |||||
handleKeyDown = e => { | |||||
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { | |||||
this.handleClick(); | |||||
} | |||||
}; | |||||
handleForwardChange = e => { | |||||
const { onChangeForward } = this.props; | |||||
onChangeForward(e.target.checked); | |||||
}; | |||||
render () { | |||||
const { comment, isRemote, forward, domain, isSubmitting, intl } = this.props; | |||||
return ( | |||||
<React.Fragment> | |||||
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.comment.title' defaultMessage='Is there anything else you think we should know?' /></h3> | |||||
<textarea | |||||
className='report-dialog-modal__textarea' | |||||
placeholder={intl.formatMessage(messages.placeholder)} | |||||
value={comment} | |||||
onChange={this.handleChange} | |||||
onKeyDown={this.handleKeyDown} | |||||
disabled={isSubmitting} | |||||
/> | |||||
{isRemote && ( | |||||
<React.Fragment> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.forward_hint' defaultMessage='The account is from another server. Send an anonymized copy of the report there as well?' /></p> | |||||
<label className='report-dialog-modal__toggle'> | |||||
<Toggle checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} /> | |||||
<FormattedMessage id='report.forward' defaultMessage='Forward to {target}' values={{ target: domain }} /> | |||||
</label> | |||||
</React.Fragment> | |||||
)} | |||||
<div className='flex-spacer' /> | |||||
<div className='report-dialog-modal__actions'> | |||||
<Button onClick={this.handleClick}><FormattedMessage id='report.submit' defaultMessage='Submit report' /></Button> | |||||
</div> | |||||
</React.Fragment> | |||||
); | |||||
} | |||||
} |
@ -0,0 +1,60 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import classNames from 'classnames'; | |||||
import Check from 'mastodon/components/check'; | |||||
export default class Option extends React.PureComponent { | |||||
static propTypes = { | |||||
name: PropTypes.string.isRequired, | |||||
value: PropTypes.string.isRequired, | |||||
checked: PropTypes.bool, | |||||
label: PropTypes.node, | |||||
description: PropTypes.node, | |||||
onToggle: PropTypes.func, | |||||
multiple: PropTypes.bool, | |||||
labelComponent: PropTypes.node, | |||||
}; | |||||
handleKeyPress = e => { | |||||
const { value, checked, onToggle } = this.props; | |||||
if (e.key === 'Enter' || e.key === ' ') { | |||||
e.stopPropagation(); | |||||
e.preventDefault(); | |||||
onToggle(value, !checked); | |||||
} | |||||
} | |||||
handleChange = e => { | |||||
const { value, onToggle } = this.props; | |||||
onToggle(value, e.target.checked); | |||||
} | |||||
render () { | |||||
const { name, value, checked, label, labelComponent, description, multiple } = this.props; | |||||
return ( | |||||
<label className='dialog-option poll__option selectable'> | |||||
<input type={multiple ? 'checkbox' : 'radio'} name={name} value={value} checked={checked} onChange={this.handleChange} /> | |||||
<span | |||||
className={classNames('poll__input', { active: checked, checkbox: multiple })} | |||||
tabIndex='0' | |||||
role='radio' | |||||
onKeyPress={this.handleKeyPress} | |||||
aria-checked={checked} | |||||
aria-label={label} | |||||
>{checked && <Check />}</span> | |||||
{labelComponent ? labelComponent : ( | |||||
<span className='poll__option__text'> | |||||
<strong>{label}</strong> | |||||
{description} | |||||
</span> | |||||
)} | |||||
</label> | |||||
); | |||||
} | |||||
} |
@ -1,19 +1,15 @@ | |||||
import { connect } from 'react-redux'; | import { connect } from 'react-redux'; | ||||
import StatusCheckBox from '../components/status_check_box'; | import StatusCheckBox from '../components/status_check_box'; | ||||
import { toggleStatusReport } from '../../../actions/reports'; | |||||
import { Set as ImmutableSet } from 'immutable'; | |||||
import { makeGetStatus } from 'mastodon/selectors'; | |||||
const mapStateToProps = (state, { id }) => ({ | |||||
status: state.getIn(['statuses', id]), | |||||
checked: state.getIn(['reports', 'new', 'status_ids'], ImmutableSet()).includes(id), | |||||
}); | |||||
const makeMapStateToProps = () => { | |||||
const getStatus = makeGetStatus(); | |||||
const mapDispatchToProps = (dispatch, { id }) => ({ | |||||
const mapStateToProps = (state, { id }) => ({ | |||||
status: getStatus(state, { id }), | |||||
}); | |||||
onToggle (e) { | |||||
dispatch(toggleStatusReport(id, e.target.checked)); | |||||
}, | |||||
return mapStateToProps; | |||||
}; | |||||
}); | |||||
export default connect(mapStateToProps, mapDispatchToProps)(StatusCheckBox); | |||||
export default connect(makeMapStateToProps)(StatusCheckBox); |
@ -0,0 +1,64 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||||
import { connect } from 'react-redux'; | |||||
import { FormattedMessage } from 'react-intl'; | |||||
import Button from 'mastodon/components/button'; | |||||
import Option from './components/option'; | |||||
const mapStateToProps = state => ({ | |||||
rules: state.get('rules'), | |||||
}); | |||||
export default @connect(mapStateToProps) | |||||
class Rules extends React.PureComponent { | |||||
static propTypes = { | |||||
onNextStep: PropTypes.func.isRequired, | |||||
rules: ImmutablePropTypes.list, | |||||
selectedRuleIds: ImmutablePropTypes.set.isRequired, | |||||
onToggle: PropTypes.func.isRequired, | |||||
}; | |||||
handleNextClick = () => { | |||||
const { onNextStep } = this.props; | |||||
onNextStep('statuses'); | |||||
}; | |||||
handleRulesToggle = (value, checked) => { | |||||
const { onToggle } = this.props; | |||||
onToggle(value, checked); | |||||
}; | |||||
render () { | |||||
const { rules, selectedRuleIds } = this.props; | |||||
return ( | |||||
<React.Fragment> | |||||
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.rules.title' defaultMessage='Which rules are being violated?' /></h3> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.rules.subtitle' defaultMessage='Select all that apply' /></p> | |||||
<div> | |||||
{rules.map(item => ( | |||||
<Option | |||||
key={item.get('id')} | |||||
name='rule_ids' | |||||
value={item.get('id')} | |||||
checked={selectedRuleIds.includes(item.get('id'))} | |||||
onToggle={this.handleRulesToggle} | |||||
label={item.get('text')} | |||||
multiple | |||||
/> | |||||
))} | |||||
</div> | |||||
<div className='flex-spacer' /> | |||||
<div className='report-dialog-modal__actions'> | |||||
<Button onClick={this.handleNextClick} disabled={selectedRuleIds.size < 1}><FormattedMessage id='report.next' defaultMessage='Next' /></Button> | |||||
</div> | |||||
</React.Fragment> | |||||
); | |||||
} | |||||
} |
@ -0,0 +1,58 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||||
import { connect } from 'react-redux'; | |||||
import StatusCheckBox from 'mastodon/features/report/containers/status_check_box_container'; | |||||
import { OrderedSet } from 'immutable'; | |||||
import { FormattedMessage } from 'react-intl'; | |||||
import Button from 'mastodon/components/button'; | |||||
const mapStateToProps = (state, { accountId }) => ({ | |||||
availableStatusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])), | |||||
}); | |||||
export default @connect(mapStateToProps) | |||||
class Statuses extends React.PureComponent { | |||||
static propTypes = { | |||||
onNextStep: PropTypes.func.isRequired, | |||||
accountId: PropTypes.string.isRequired, | |||||
availableStatusIds: ImmutablePropTypes.set.isRequired, | |||||
selectedStatusIds: ImmutablePropTypes.set.isRequired, | |||||
onToggle: PropTypes.func.isRequired, | |||||
}; | |||||
handleNextClick = () => { | |||||
const { onNextStep } = this.props; | |||||
onNextStep('comment'); | |||||
}; | |||||
render () { | |||||
const { availableStatusIds, selectedStatusIds, onToggle } = this.props; | |||||
return ( | |||||
<React.Fragment> | |||||
<h3 className='report-dialog-modal__title'><FormattedMessage id='report.statuses.title' defaultMessage='Are there any posts that back up this report?' /></h3> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.statuses.subtitle' defaultMessage='Select all that apply' /></p> | |||||
<div className='report-dialog-modal__statuses'> | |||||
{availableStatusIds.union(selectedStatusIds).map(statusId => ( | |||||
<StatusCheckBox | |||||
id={statusId} | |||||
key={statusId} | |||||
checked={selectedStatusIds.includes(statusId)} | |||||
onToggle={onToggle} | |||||
/> | |||||
))} | |||||
</div> | |||||
<div className='flex-spacer' /> | |||||
<div className='report-dialog-modal__actions'> | |||||
<Button onClick={this.handleNextClick}><FormattedMessage id='report.next' defaultMessage='Next' /></Button> | |||||
</div> | |||||
</React.Fragment> | |||||
); | |||||
} | |||||
} |
@ -0,0 +1,84 @@ | |||||
import React from 'react'; | |||||
import PropTypes from 'prop-types'; | |||||
import ImmutablePropTypes from 'react-immutable-proptypes'; | |||||
import { FormattedMessage } from 'react-intl'; | |||||
import Button from 'mastodon/components/button'; | |||||
import { connect } from 'react-redux'; | |||||
import { | |||||
unfollowAccount, | |||||
muteAccount, | |||||
blockAccount, | |||||
} from 'mastodon/actions/accounts'; | |||||
const mapStateToProps = () => ({}); | |||||
export default @connect(mapStateToProps) | |||||
class Thanks extends React.PureComponent { | |||||
static propTypes = { | |||||
submitted: PropTypes.bool, | |||||
onClose: PropTypes.func.isRequired, | |||||
account: ImmutablePropTypes.map.isRequired, | |||||
dispatch: PropTypes.func.isRequired, | |||||
}; | |||||
handleCloseClick = () => { | |||||
const { onClose } = this.props; | |||||
onClose(); | |||||
}; | |||||
handleUnfollowClick = () => { | |||||
const { dispatch, account, onClose } = this.props; | |||||
dispatch(unfollowAccount(account.get('id'))); | |||||
onClose(); | |||||
}; | |||||
handleMuteClick = () => { | |||||
const { dispatch, account, onClose } = this.props; | |||||
dispatch(muteAccount(account.get('id'))); | |||||
onClose(); | |||||
}; | |||||
handleBlockClick = () => { | |||||
const { dispatch, account, onClose } = this.props; | |||||
dispatch(blockAccount(account.get('id'))); | |||||
onClose(); | |||||
}; | |||||
render () { | |||||
const { account, submitted } = this.props; | |||||
return ( | |||||
<React.Fragment> | |||||
<h3 className='report-dialog-modal__title'>{submitted ? <FormattedMessage id='report.thanks.title_actionable' defaultMessage="Thanks for reporting, we'll look into this." /> : <FormattedMessage id='report.thanks.title' defaultMessage="Don't want to see this?" />}</h3> | |||||
<p className='report-dialog-modal__lead'>{submitted ? <FormattedMessage id='report.thanks.take_action_actionable' defaultMessage='While we review this, you can take action against @{name}:' values={{ name: account.get('username') }} /> : <FormattedMessage id='report.thanks.take_action' defaultMessage='Here are your options for controlling what you see on Mastodon:' />}</p> | |||||
{account.getIn(['relationship', 'following']) && ( | |||||
<React.Fragment> | |||||
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='report.unfollow' defaultMessage='Unfollow @{name}' values={{ name: account.get('username') }} /></h4> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.unfollow_explanation' defaultMessage='You are following this account. To not see their posts in your home feed anymore, unfollow them.' /></p> | |||||
<Button secondary onClick={this.handleUnfollowClick}><FormattedMessage id='account.unfollow' defaultMessage='Unfollow' /></Button> | |||||
<hr /> | |||||
</React.Fragment> | |||||
)} | |||||
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='account.mute' defaultMessage='Mute @{name}' values={{ name: account.get('username') }} /></h4> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.mute_explanation' defaultMessage='You will not see their posts. They can still follow you and see your posts and will not know that they are muted.' /></p> | |||||
<Button secondary onClick={this.handleMuteClick}>{!account.getIn(['relationship', 'muting']) ? <FormattedMessage id='report.mute' defaultMessage='Mute' /> : <FormattedMessage id='account.muted' defaultMessage='Muted' />}</Button> | |||||
<hr /> | |||||
<h4 className='report-dialog-modal__subtitle'><FormattedMessage id='account.block' defaultMessage='Block @{name}' values={{ name: account.get('username') }} /></h4> | |||||
<p className='report-dialog-modal__lead'><FormattedMessage id='report.block_explanation' defaultMessage='You will not see their posts. They will not be able to see your posts or follow you. They will be able to tell that they are blocked.' /></p> | |||||
<Button secondary onClick={this.handleBlockClick}>{!account.getIn(['relationship', 'blocking']) ? <FormattedMessage id='report.block' defaultMessage='Block' /> : <FormattedMessage id='account.blocked' defaultMessage='Blocked' />}</Button> | |||||
<div className='flex-spacer' /> | |||||
<div className='report-dialog-modal__actions'> | |||||
<Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button> | |||||
</div> | |||||
</React.Fragment> | |||||
); | |||||
} | |||||
} |
@ -0,0 +1,13 @@ | |||||
import { RULES_FETCH_SUCCESS } from 'mastodon/actions/rules'; | |||||
import { List as ImmutableList, fromJS } from 'immutable'; | |||||
const initialState = ImmutableList(); | |||||
export default function rules(state = initialState, action) { | |||||
switch (action.type) { | |||||
case RULES_FETCH_SUCCESS: | |||||
return fromJS(action.rules); | |||||
default: | |||||
return state; | |||||
} | |||||
} |