diff --git a/app/soapbox/actions/accounts.js b/app/soapbox/actions/accounts.js index ec1d1cb6b..6cf4224dc 100644 --- a/app/soapbox/actions/accounts.js +++ b/app/soapbox/actions/accounts.js @@ -27,6 +27,10 @@ export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST'; export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS'; export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL'; +export const REMOVE_FOLLOWER_REQUEST = 'REMOVE_FOLLOWER_REQUEST'; +export const REMOVE_FOLLOWER_SUCCESS = 'REMOVE_FOLLOWER_SUCCESS'; +export const REMOVE_FOLLOWER_FAIL = 'REMOVE_FOLLOWER_FAIL'; + export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST'; export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS'; export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL'; @@ -315,6 +319,45 @@ export function unblockAccountFail(error) { }; }; +export function removeFollower(id) { + return (dispatch, getState) => { + if (!getState().get('me')) return; + + dispatch(removeFollowerRequest(id)); + // no endpoint exists to remove follower, so use "soft block" to do the same + api(getState).post(`/api/v1/accounts/${id}/block`).then(response => { + api(getState).post(`/api/v1/accounts/${id}/unblock`).then(response => { + dispatch(removeFollowerSuccess(response.data)); + }).catch(error => { + dispatch(removeFollowerFail(id, error)); + }); + }).catch(error => { + dispatch(removeFollowerFail(id, error)); + }); + }; +}; + +export function removeFollowerRequest(id) { + return { + type: REMOVE_FOLLOWER_REQUEST, + id, + }; +}; + +export function removeFollowerSuccess(relationship, statuses) { + return { + type: REMOVE_FOLLOWER_SUCCESS, + relationship, + statuses, + }; +}; + +export function removeFollowerFail(error) { + return { + type: REMOVE_FOLLOWER_FAIL, + error, + }; +}; export function muteAccount(id, notifications) { return (dispatch, getState) => { diff --git a/app/soapbox/components/account.js b/app/soapbox/components/account.js index bc236da85..223ff19ac 100644 --- a/app/soapbox/components/account.js +++ b/app/soapbox/components/account.js @@ -13,6 +13,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; const messages = defineMessages({ follow: { id: 'account.follow', defaultMessage: 'Follow' }, unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, + remove: { id: 'account.remove', defaultMessage: 'Remove' }, requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' }, @@ -34,6 +35,7 @@ class Account extends ImmutablePureComponent { account: ImmutablePropTypes.map.isRequired, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, + onRemoveFollower: PropTypes.func.isRequired, onMute: PropTypes.func.isRequired, onMuteNotifications: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -55,6 +57,10 @@ class Account extends ImmutablePureComponent { this.props.onMute(this.props.account); } + handleRemoveFollower = () => { + this.props.onRemoveFollower(this.props.account); + } + handleMuteNotifications = () => { this.props.onMuteNotifications(this.props.account, true); } @@ -129,6 +135,7 @@ class Account extends ImmutablePureComponent { { followed_by ? + : '' } diff --git a/app/soapbox/containers/account_container.js b/app/soapbox/containers/account_container.js index 1e890a7e2..1093fa584 100644 --- a/app/soapbox/containers/account_container.js +++ b/app/soapbox/containers/account_container.js @@ -10,6 +10,7 @@ import { unblockAccount, muteAccount, unmuteAccount, + removeFollower, } from '../actions/accounts'; import { openModal } from '../actions/modal'; import { initMuteModal } from '../actions/mutes'; @@ -17,6 +18,7 @@ import { getSettings } from '../actions/settings'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, + removeFollowerConfirm: { id: 'confirmations.remove.confirm', defaultMessage: 'Remove' }, }); const makeMapStateToProps = () => { @@ -66,6 +68,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onRemoveFollower(account) { + dispatch(removeFollower(account.get('id'))); + }, + onMuteNotifications(account, notifications) { dispatch(muteAccount(account.get('id'), notifications)); }, diff --git a/app/soapbox/features/manage_followers/index.js b/app/soapbox/features/manage_followers/index.js index 9c965f6b2..b7edf3ab4 100644 --- a/app/soapbox/features/manage_followers/index.js +++ b/app/soapbox/features/manage_followers/index.js @@ -16,6 +16,7 @@ import { const messages = defineMessages({ heading: { id: 'column.manage_followers', defaultMessage: 'Manage followers' }, + remove: { id: 'column.manage_followers.remove', defaultMessage: 'Remove' }, }); const mapStateToProps = state => { @@ -77,7 +78,9 @@ class ManageFollowers extends ImmutablePureComponent { emptyMessage={emptyMessage} > {accountIds && accountIds.map(id => - + ( + + ) )}