diff --git a/app/soapbox/features/forms/index.tsx b/app/soapbox/features/forms/index.tsx index c458cd6b1..9504d0560 100644 --- a/app/soapbox/features/forms/index.tsx +++ b/app/soapbox/features/forms/index.tsx @@ -167,6 +167,7 @@ interface ICheckbox { hint?: React.ReactNode, name?: string, checked?: boolean, + disabled?: boolean, onChange?: React.ChangeEventHandler, required?: boolean, } diff --git a/app/soapbox/features/ui/components/edit_federation_modal.js b/app/soapbox/features/ui/components/edit_federation_modal.js deleted file mode 100644 index 53e21078f..000000000 --- a/app/soapbox/features/ui/components/edit_federation_modal.js +++ /dev/null @@ -1,151 +0,0 @@ -import { Map as ImmutableMap, is } 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, injectIntl } from 'react-intl'; -import { connect } from 'react-redux'; - -import { updateMrf } from 'soapbox/actions/mrf'; -import snackbar from 'soapbox/actions/snackbar'; -import { SimpleForm, Checkbox } from 'soapbox/features/forms'; -import { makeGetRemoteInstance } from 'soapbox/selectors'; - -const getRemoteInstance = makeGetRemoteInstance(); - -const messages = defineMessages({ - reject: { id: 'edit_federation.reject', defaultMessage: 'Reject all activities' }, - mediaRemoval: { id: 'edit_federation.media_removal', defaultMessage: 'Strip media' }, - forceNsfw: { id: 'edit_federation.force_nsfw', defaultMessage: 'Force attachments to be marked sensitive' }, - unlisted: { id: 'edit_federation.unlisted', defaultMessage: 'Force posts unlisted' }, - followersOnly: { id: 'edit_federation.followers_only', defaultMessage: 'Hide posts except to followers' }, - save: { id: 'edit_federation.save', defaultMessage: 'Save' }, - success: { id: 'edit_federation.success', defaultMessage: '{host} federation was updated' }, -}); - -const mapStateToProps = (state, { host }) => { - return { - remoteInstance: getRemoteInstance(state, host), - }; -}; - -export default @connect(mapStateToProps) -@injectIntl -class EditFederationModal extends ImmutablePureComponent { - - static propTypes = { - host: PropTypes.string.isRequired, - remoteInstance: ImmutablePropTypes.map, - }; - - state = { - data: ImmutableMap(), - } - - hydrateState = () => { - const { remoteInstance } = this.props; - this.setState({ data: remoteInstance.get('federation') }); - } - - componentDidMount() { - this.hydrateState(); - } - - componentDidUpdate(prevProps) { - const { remoteInstance } = this.props; - - if (!is(prevProps.remoteInstance, remoteInstance)) { - this.hydrateState(); - } - } - - handleDataChange = key => { - return ({ target }) => { - const { data } = this.state; - this.setState({ data: data.set(key, target.checked) }); - }; - } - - handleMediaRemoval = ({ target: { checked } }) => { - const data = this.state.data.merge({ - avatar_removal: checked, - banner_removal: checked, - media_removal: checked, - }); - - this.setState({ data }); - } - - handleSubmit = e => { - const { intl, dispatch, host, onClose } = this.props; - const { data } = this.state; - - dispatch(updateMrf(host, data)) - .then(() => dispatch(snackbar.success(intl.formatMessage(messages.success, { host })))) - .catch(() => {}); - - onClose(); - } - - render() { - const { intl, remoteInstance } = this.props; - const { data } = this.state; - - const { - avatar_removal, - banner_removal, - federated_timeline_removal, - followers_only, - media_nsfw, - media_removal, - reject, - } = data.toJS(); - - const fullMediaRemoval = avatar_removal && banner_removal && media_removal; - - return ( -
-
-
- {remoteInstance.get('host')} -
- - - - - - - - -
-
- ); - } - -} diff --git a/app/soapbox/features/ui/components/edit_federation_modal.tsx b/app/soapbox/features/ui/components/edit_federation_modal.tsx new file mode 100644 index 000000000..3d4456a75 --- /dev/null +++ b/app/soapbox/features/ui/components/edit_federation_modal.tsx @@ -0,0 +1,122 @@ +import { Map as ImmutableMap } from 'immutable'; +import React, { useState, useEffect } from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { updateMrf } from 'soapbox/actions/mrf'; +import snackbar from 'soapbox/actions/snackbar'; +import { SimpleForm, Checkbox } from 'soapbox/features/forms'; +import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; +import { makeGetRemoteInstance } from 'soapbox/selectors'; + +const getRemoteInstance = makeGetRemoteInstance(); + +const messages = defineMessages({ + reject: { id: 'edit_federation.reject', defaultMessage: 'Reject all activities' }, + mediaRemoval: { id: 'edit_federation.media_removal', defaultMessage: 'Strip media' }, + forceNsfw: { id: 'edit_federation.force_nsfw', defaultMessage: 'Force attachments to be marked sensitive' }, + unlisted: { id: 'edit_federation.unlisted', defaultMessage: 'Force posts unlisted' }, + followersOnly: { id: 'edit_federation.followers_only', defaultMessage: 'Hide posts except to followers' }, + save: { id: 'edit_federation.save', defaultMessage: 'Save' }, + success: { id: 'edit_federation.success', defaultMessage: '{host} federation was updated' }, +}); + +interface IEditFederationModal { + host: string, + onClose: () => void, +} + +/** Modal for moderators to edit federation with a remote instance. */ +const EditFederationModal: React.FC = ({ host, onClose }) => { + const intl = useIntl(); + const dispatch = useAppDispatch(); + + const remoteInstance = useAppSelector(state => getRemoteInstance(state, host)); + + const [data, setData] = useState(ImmutableMap()); + + useEffect(() => { + setData(remoteInstance.get('federation') as any); + }, [remoteInstance]); + + const handleDataChange = (key: string): React.ChangeEventHandler => { + return ({ target }) => { + setData(data.set(key, target.checked)); + }; + }; + + const handleMediaRemoval: React.ChangeEventHandler = ({ target: { checked } }) => { + const newData = data.merge({ + avatar_removal: checked, + banner_removal: checked, + media_removal: checked, + }); + + setData(newData); + }; + + const handleSubmit: React.FormEventHandler = () => { + dispatch(updateMrf(host, data)) + .then(() => dispatch(snackbar.success(intl.formatMessage(messages.success, { host })))) + .catch(() => {}); + + onClose(); + }; + + const { + avatar_removal, + banner_removal, + federated_timeline_removal, + followers_only, + media_nsfw, + media_removal, + reject, + } = data.toJS() as Record; + + const fullMediaRemoval = avatar_removal && banner_removal && media_removal; + + return ( +
+
+
+ {host} +
+ + + + + + + + +
+
+ ); +}; + +export default EditFederationModal;