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 =>
-
+ (
+
+ )
)}