diff --git a/app/soapbox/features/ui/components/modals/report-modal/report-modal.tsx b/app/soapbox/features/ui/components/modals/report-modal/report-modal.tsx index 2f46b6b3b..f2891c07d 100644 --- a/app/soapbox/features/ui/components/modals/report-modal/report-modal.tsx +++ b/app/soapbox/features/ui/components/modals/report-modal/report-modal.tsx @@ -6,7 +6,10 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { blockAccount } from 'soapbox/actions/accounts'; import { submitReport, cancelReport, submitReportSuccess, submitReportFail } from 'soapbox/actions/reports'; import { expandAccountTimeline } from 'soapbox/actions/timelines'; -import { Modal, ProgressBar, Stack } from 'soapbox/components/ui'; +import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; +import StatusContent from 'soapbox/components/status_content'; +import { Modal, ProgressBar, Stack, Text } from 'soapbox/components/ui'; +import AccountContainer from 'soapbox/containers/account_container'; import { useAccount, useAppDispatch, useAppSelector } from 'soapbox/hooks'; import ConfirmationStep from './steps/confirmation-step'; @@ -14,6 +17,9 @@ import OtherActionsStep from './steps/other-actions-step'; import ReasonStep from './steps/reason-step'; const messages = defineMessages({ + blankslate: { id: 'report.reason.blankslate', defaultMessage: 'You have removed all statuses from being selected.' }, + done: { id: 'report.done', defaultMessage: 'Done' }, + next: { id: 'report.next', defaultMessage: 'Next' }, close: { id: 'lightbox.close', defaultMessage: 'Close' }, placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, submit: { id: 'report.submit', defaultMessage: 'Submit' }, @@ -31,6 +37,39 @@ const reportSteps = { THREE: ConfirmationStep, }; +const SelectedStatus = ({ statusId }: { statusId: string }) => { + const status = useAppSelector((state) => state.statuses.get(statusId)); + + if (!status) { + return null; + } + + return ( + + + + + + {status.get('media_attachments').size > 0 && ( + + )} + + ); +}; + interface IReportModal { onClose: () => void } @@ -84,14 +123,27 @@ const ReportModal = ({ onClose }: IReportModal) => { } }; + const renderSelectedStatuses = useCallback(() => { + switch (selectedStatusIds.size) { + case 0: + return ( +
+ {intl.formatMessage(messages.blankslate)} +
+ ); + default: + return ; + } + }, [selectedStatusIds.size]); + const confirmationText = useMemo(() => { switch (currentStep) { case Steps.TWO: return intl.formatMessage(messages.submit); case Steps.THREE: - return 'Done'; + return intl.formatMessage(messages.done); default: - return 'Next'; + return intl.formatMessage(messages.next); } }, [currentStep]); @@ -141,6 +193,8 @@ const ReportModal = ({ onClose }: IReportModal) => { + {currentStep !== Steps.THREE && renderSelectedStatuses()} + diff --git a/app/soapbox/features/ui/components/modals/report-modal/steps/confirmation-step.tsx b/app/soapbox/features/ui/components/modals/report-modal/steps/confirmation-step.tsx index c97ff9ba4..2756ff88f 100644 --- a/app/soapbox/features/ui/components/modals/report-modal/steps/confirmation-step.tsx +++ b/app/soapbox/features/ui/components/modals/report-modal/steps/confirmation-step.tsx @@ -1,23 +1,52 @@ import React from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { Stack, Text } from 'soapbox/components/ui'; +import { useAppSelector } from 'soapbox/hooks'; import type { ReducerAccount } from 'soapbox/reducers/accounts'; +const messages = defineMessages({ + title: { id: 'report.confirmation.title', defaultMessage: 'Thanks for submitting your report.' }, + content: { id: 'report.confirmation.content', defaultMessage: 'If we find that this account is violating the {link} we will take further action on the matter.' }, +}); + interface IOtherActionsStep { account: ReducerAccount } +const termsOfServiceText = (); + +const renderTermsOfServiceLink = (href: string) => ( + + {termsOfServiceText} + +); + const ConfirmationStep = ({ account }: IOtherActionsStep) => { + const intl = useIntl(); + const links = useAppSelector((state) => getSoapboxConfig(state).get('links') as any); + return ( - Thanks for submitting your report. + {intl.formatMessage(messages.title)} - If we find that this account is violating the TRUTH Terms of Service we - will take further action on the matter. + {intl.formatMessage(messages.content, { + link: links.get('termsOfService') ? + renderTermsOfServiceLink(links.get('termsOfService')) : + termsOfServiceText, + })} ); diff --git a/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx b/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx index 6efd904ee..b1439807c 100644 --- a/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx +++ b/app/soapbox/features/ui/components/modals/report-modal/steps/other-actions-step.tsx @@ -1,53 +1,25 @@ -import { OrderedSet, Set as ImmutableSet } from 'immutable'; -import React, { useCallback, useEffect, useState } from 'react'; -import { FormattedMessage } from 'react-intl'; +import { OrderedSet } from 'immutable'; +import React, { useEffect, useState } from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import Toggle from 'react-toggle'; import { changeReportBlock, changeReportForward } from 'soapbox/actions/reports'; import { fetchRules } from 'soapbox/actions/rules'; -import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; -import StatusContent from 'soapbox/components/status_content'; import { Button, FormGroup, HStack, Stack, Text } from 'soapbox/components/ui'; -import AccountContainer from 'soapbox/containers/account_container'; import StatusCheckBox from 'soapbox/features/report/containers/status_check_box_container'; import { useAppSelector, useFeatures } from 'soapbox/hooks'; import { isRemote, getDomain } from 'soapbox/utils/accounts'; import type { ReducerAccount } from 'soapbox/reducers/accounts'; -const SelectedStatus = ({ statusId }: { statusId: string }) => { - const status = useAppSelector((state) => state.statuses.get(statusId)); - - if (!status) { - return null; - } - - return ( - - - - - - {status.get('media_attachments').size > 0 && ( - - )} - - ); -}; +const messages = defineMessages({ + addAdditionalStatuses: { id: 'report.otherActions.addAdditionl', defaultMessage: 'Would you like to add additional statuses to this report?' }, + addMore: { id: 'report.otherActions.addMore', defaultMessage: 'Add more' }, + furtherActions: { id: 'report.otherActions.furtherActions', defaultMessage: 'Further actions:' }, + hideAdditonalStatuses: { id: 'report.otherActions.hideAdditional', defaultMessage: 'Hide additional statuses' }, + otherStatuses: { id: 'report.otherActions.otherStatuses', defaultMessage: 'Include other statuses?' }, +}); interface IOtherActionsStep { account: ReducerAccount @@ -56,8 +28,8 @@ interface IOtherActionsStep { const OtherActionsStep = ({ account }: IOtherActionsStep) => { const dispatch = useDispatch(); const features = useFeatures(); + const intl = useIntl(); - const selectedStatusIds = useAppSelector((state) => state.reports.getIn(['new', 'status_ids']) as ImmutableSet); const statusIds = useAppSelector((state) => OrderedSet(state.timelines.getIn([`account:${account.id}:with_replies`, 'items'])).union(state.reports.getIn(['new', 'status_ids']) as Iterable) as OrderedSet); const isBlocked = useAppSelector((state) => state.reports.getIn(['new', 'block']) as boolean); const isForward = useAppSelector((state) => state.reports.getIn(['reports', 'forward']) as boolean); @@ -66,19 +38,6 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { const [showAdditionalStatuses, setShowAdditionalStatuses] = useState(false); - const renderSelectedStatuses = useCallback(() => { - switch (selectedStatusIds.size) { - case 0: - return ( -
- You have removed all statuses from being selected. -
- ); - default: - return ; - } - }, [selectedStatusIds.size]); - const handleBlockChange = (event: React.ChangeEvent) => { dispatch(changeReportBlock(event.target.checked)); }; @@ -93,15 +52,13 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { return ( - {renderSelectedStatuses()} - {features.reportMultipleStatuses && ( - Include other statuses? + + {intl.formatMessage(messages.otherStatuses)} + - + {showAdditionalStatuses ? (
@@ -115,7 +72,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { size='sm' onClick={() => setShowAdditionalStatuses(false)} > - Hide additional statuses + {intl.formatMessage(messages.hideAdditonalStatuses)}
@@ -126,7 +83,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { size='sm' onClick={() => setShowAdditionalStatuses(true)} > - Add more + {intl.formatMessage(messages.addMore)} )}
@@ -134,7 +91,9 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => { )} - Further actions: + + {intl.formatMessage(messages.furtherActions)} + } diff --git a/app/soapbox/features/ui/components/modals/report-modal/steps/reason-step.tsx b/app/soapbox/features/ui/components/modals/report-modal/steps/reason-step.tsx index ea051fb85..c9ed280e5 100644 --- a/app/soapbox/features/ui/components/modals/report-modal/steps/reason-step.tsx +++ b/app/soapbox/features/ui/components/modals/report-modal/steps/reason-step.tsx @@ -1,56 +1,20 @@ import classNames from 'classnames'; -import { Set as ImmutableSet } from 'immutable'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { useDispatch } from 'react-redux'; import { changeReportComment, changeReportRule } from 'soapbox/actions/reports'; import { fetchRules } from 'soapbox/actions/rules'; -import AttachmentThumbs from 'soapbox/components/attachment_thumbs'; -import StatusContent from 'soapbox/components/status_content'; -import { FormGroup, HStack, Stack, Text, Textarea } from 'soapbox/components/ui'; -import AccountContainer from 'soapbox/containers/account_container'; +import { FormGroup, Stack, Text, Textarea } from 'soapbox/components/ui'; import { useAppSelector } from 'soapbox/hooks'; import type { ReducerAccount } from 'soapbox/reducers/accounts'; const messages = defineMessages({ placeholder: { id: 'report.placeholder', defaultMessage: 'Additional comments' }, + reasonForReporting: { id: 'report.reason.title', defaultMessage: 'Reason for reporting' }, }); -const SelectedStatus = ({ statusId }: { statusId: string }) => { - const status = useAppSelector((state) => state.statuses.get(statusId)); - - if (!status) { - return null; - } - - return ( - - - - - - {status.get('media_attachments').size > 0 && ( - - )} - - ); -}; - interface IReasonStep { account: ReducerAccount } @@ -64,25 +28,11 @@ const ReasonStep = (_props: IReasonStep) => { const [isNearBottom, setNearBottom] = useState(false); const [isNearTop, setNearTop] = useState(true); - const selectedStatusIds = useAppSelector((state) => state.reports.getIn(['new', 'status_ids']) as ImmutableSet); const comment = useAppSelector((state) => state.reports.getIn(['new', 'comment']) as string); const rules = useAppSelector((state) => state.rules.items); const ruleId = useAppSelector((state) => state.reports.getIn(['new', 'rule_id']) as boolean); const shouldRequireRule = rules.length > 0; - const renderSelectedStatuses = useCallback(() => { - switch (selectedStatusIds.size) { - case 0: - return ( -
- You have removed all statuses from being selected. -
- ); - default: - return ; - } - }, [selectedStatusIds.size]); - const handleCommentChange = (event: React.ChangeEvent) => { dispatch(changeReportComment(event.target.value)); }; @@ -111,11 +61,11 @@ const ReasonStep = (_props: IReasonStep) => { return ( - {renderSelectedStatuses()} - {shouldRequireRule && ( - Reason for reporting + + {intl.formatMessage(messages.reasonForReporting)} +
{ 'bg-gray-50 dark:bg-slate-900': isSelected, })} > -
+ {rule.text} - {rule.subtext} -
+ {rule.subtext} +