diff --git a/app/soapbox/features/ui/components/report_modal.js b/app/soapbox/features/ui/components/report_modal.js deleted file mode 100644 index 2dcdd03d7..000000000 --- a/app/soapbox/features/ui/components/report_modal.js +++ /dev/null @@ -1,161 +0,0 @@ -import { OrderedSet } from 'immutable'; -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; -import Toggle from 'react-toggle'; - -import { blockAccount } from 'soapbox/actions/accounts'; -import { changeReportComment, changeReportForward, changeReportBlock, submitReport } from 'soapbox/actions/reports'; -import { expandAccountTimeline } from 'soapbox/actions/timelines'; -import { Button, Modal } from 'soapbox/components/ui'; -import { makeGetAccount } from 'soapbox/selectors'; -import { isRemote, getDomain } from 'soapbox/utils/accounts'; -import { getFeatures } from 'soapbox/utils/features'; - - -import StatusCheckBox from '../../report/containers/status_check_box_container'; - -const messages = defineMessages({ - close: { id: 'lightbox.close', defaultMessage: 'Close' }, - placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, - submit: { id: 'report.submit', defaultMessage: 'Submit' }, -}); - -const makeMapStateToProps = () => { - const getAccount = makeGetAccount(); - - const mapStateToProps = state => { - const accountId = state.getIn(['reports', 'new', 'account_id']); - const account = getAccount(state, accountId); - const instance = state.get('instance'); - const features = getFeatures(instance); - - return { - isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']), - account, - comment: state.getIn(['reports', 'new', 'comment']), - forward: state.getIn(['reports', 'new', 'forward']), - block: state.getIn(['reports', 'new', 'block']), - statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])), - canForward: isRemote(account) && features.federating, - }; - }; - - return mapStateToProps; -}; - -export default @connect(makeMapStateToProps) -@injectIntl -class ReportModal extends ImmutablePureComponent { - - static propTypes = { - isSubmitting: PropTypes.bool, - account: ImmutablePropTypes.record, - statusIds: ImmutablePropTypes.orderedSet.isRequired, - comment: PropTypes.string.isRequired, - forward: PropTypes.bool, - block: PropTypes.bool, - canForward: PropTypes.bool, - dispatch: PropTypes.func.isRequired, - intl: PropTypes.object.isRequired, - }; - - handleCommentChange = e => { - this.props.dispatch(changeReportComment(e.target.value)); - } - - handleForwardChange = e => { - this.props.dispatch(changeReportForward(e.target.checked)); - } - - handleBlockChange = e => { - this.props.dispatch(changeReportBlock(e.target.checked)); - } - - handleSubmit = () => { - this.props.dispatch(submitReport()); - if (this.props.block) { - this.props.dispatch(blockAccount(this.props.account.get('id'))); - } - } - - handleKeyDown = e => { - if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { - this.handleSubmit(); - } - } - - componentDidMount() { - this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true })); - } - - componentDidUpdate(prevProps) { - const { account } = this.props; - if (prevProps.account !== account && account) { - this.props.dispatch(expandAccountTimeline(account.get('id'), { withReplies: true })); - } - } - - render() { - const { account, comment, intl, statusIds, isSubmitting, forward, block, canForward, onClose } = this.props; - - if (!account) { - return null; - } - - return ( - {account.get('acct')} }} />} - onClose={onClose} - > - - - - - - - {canForward && ( - - - - - - - - - )} - - - - - - - - - - - {intl.formatMessage(messages.submit)} - - - - - {statusIds.map(statusId => )} - - - - - ); - } - -} diff --git a/app/soapbox/features/ui/components/report_modal.tsx b/app/soapbox/features/ui/components/report_modal.tsx new file mode 100644 index 000000000..a1744f3a0 --- /dev/null +++ b/app/soapbox/features/ui/components/report_modal.tsx @@ -0,0 +1,129 @@ +import { OrderedSet } from 'immutable'; +import React, { useEffect } from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { useDispatch } from 'react-redux'; +import Toggle from 'react-toggle'; + +import { blockAccount } from 'soapbox/actions/accounts'; +import { changeReportComment, changeReportForward, changeReportBlock, submitReport } from 'soapbox/actions/reports'; +import { expandAccountTimeline } from 'soapbox/actions/timelines'; +import { Button, Modal } from 'soapbox/components/ui'; +import { useAccount, useAppSelector, useFeatures } from 'soapbox/hooks'; +import { isRemote, getDomain } from 'soapbox/utils/accounts'; + +import StatusCheckBox from '../../report/containers/status_check_box_container'; + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, + submit: { id: 'report.submit', defaultMessage: 'Submit' }, +}); + +interface IReportModal { + onClose: () => void +} + +const ReportModal = ({ onClose }: IReportModal) => { + const dispatch = useDispatch(); + const features = useFeatures(); + const intl = useIntl(); + + const accountId = useAppSelector((state) => state.reports.getIn(['new', 'account_id']) as string); + const account = useAccount(accountId); + + const isBlocked = useAppSelector((state) => state.reports.getIn(['new', 'block']) as boolean); + const isSubmitting = useAppSelector((state) => state.reports.getIn(['new', 'isSubmitting']) as boolean); + const isForward = useAppSelector((state) => state.reports.getIn(['reports', 'forward']) as boolean); + const comment = useAppSelector((state) => state.reports.getIn(['new', 'comment']) as string); + const statusIds = useAppSelector((state) => OrderedSet(state.timelines.getIn([`account:${accountId}:with_replies`, 'items'])).union(state.reports.getIn(['new', 'status_ids']) as Iterable) as OrderedSet); + const canForward = isRemote(account as any) && features.federating; + + const handleCommentChange = (event: React.ChangeEvent) => { + dispatch(changeReportComment(event.target.value)); + }; + + const handleForwardChange = (event: React.ChangeEvent) => { + dispatch(changeReportForward(event.target.checked)); + }; + + const handleBlockChange = (event: React.ChangeEvent) => { + dispatch(changeReportBlock(event.target.checked)); + }; + + const handleSubmit = () => { + dispatch(submitReport()); + + if (isBlocked && account) { + dispatch(blockAccount(account.id)); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.keyCode === 13 && (event.ctrlKey || event.metaKey)) { + handleSubmit(); + } + }; + + useEffect(() => { + if (account) { + dispatch(expandAccountTimeline(account.id, { withReplies: true, maxId: null })); + } + }, [account]); + + if (!account) { + return null; + } + + return ( + @{account.acct} }} />} + onClose={onClose} + > + + + + + + + {canForward && ( + + + + + + + + + )} + + + + + + + + + + + {intl.formatMessage(messages.submit)} + + + + + {statusIds.map((statusId) => )} + + + + + ); +}; + +export default ReportModal; diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 6ec919a94..0c6698988 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -1,3 +1,4 @@ +export { useAccount } from './useAccount'; export { useAppDispatch } from './useAppDispatch'; export { useAppSelector } from './useAppSelector'; export { useFeatures } from './useFeatures'; diff --git a/app/soapbox/hooks/useAccount.ts b/app/soapbox/hooks/useAccount.ts new file mode 100644 index 000000000..471df571a --- /dev/null +++ b/app/soapbox/hooks/useAccount.ts @@ -0,0 +1,6 @@ +import { useAppSelector } from 'soapbox/hooks'; +import { makeGetAccount } from 'soapbox/selectors'; + +const getAccount = makeGetAccount(); + +export const useAccount = (id: string) => useAppSelector((state) => getAccount(state, id));