Merge branch 'remove-from-followers' into 'develop'

Add 'Remove from followers'

See merge request soapbox-pub/soapbox-fe!1408
This commit is contained in:
marcin mikołajczak 2022-05-20 18:58:36 +00:00
commit 21be58ecb4
6 changed files with 83 additions and 0 deletions

View file

@ -57,6 +57,10 @@ export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
export const ACCOUNT_REMOVE_FROM_FOLLOWERS_REQUEST = 'ACCOUNT_REMOVE_FROM_FOLLOWERS_REQUEST';
export const ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS = 'ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS';
export const ACCOUNT_REMOVE_FROM_FOLLOWERS_FAIL = 'ACCOUNT_REMOVE_FROM_FOLLOWERS_FAIL';
export const PINNED_ACCOUNTS_FETCH_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST';
export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS';
export const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL';
@ -520,6 +524,42 @@ export function unsubscribeAccountFail(error) {
};
}
export function removeFromFollowers(id) {
return (dispatch, getState) => {
if (!isLoggedIn(getState)) return;
dispatch(muteAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/remove_from_followers`).then(response => {
dispatch(removeFromFollowersSuccess(response.data));
}).catch(error => {
dispatch(removeFromFollowersFail(id, error));
});
};
}
export function removeFromFollowersRequest(id) {
return {
type: ACCOUNT_REMOVE_FROM_FOLLOWERS_REQUEST,
id,
};
}
export function removeFromFollowersSuccess(relationship) {
return {
type: ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS,
relationship,
};
}
export function removeFromFollowersFail(error) {
return {
type: ACCOUNT_REMOVE_FROM_FOLLOWERS_FAIL,
error,
};
}
export function fetchFollowers(id) {
return (dispatch, getState) => {
dispatch(fetchFollowersRequest(id));

View file

@ -48,6 +48,7 @@ const messages = defineMessages({
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
removeFromFollowers: { id: 'account.remove_from_followers', defaultMessage: 'Remove this follower' },
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
deactivateUser: { id: 'admin.users.actions.deactivate_user', defaultMessage: 'Deactivate @{name}' },
@ -283,6 +284,14 @@ class Header extends ImmutablePureComponent {
});
}
if (features.removeFromFollowers && account.getIn(['relationship', 'followed_by'])) {
menu.push({
text: intl.formatMessage(messages.removeFromFollowers),
action: this.props.onRemoveFromFollowers,
icon: require('@tabler/icons/icons/user-x.svg'),
});
}
if (account.getIn(['relationship', 'muting'])) {
menu.push({
text: intl.formatMessage(messages.unmute, { name: account.get('username') }),

View file

@ -25,6 +25,7 @@ class Header extends ImmutablePureComponent {
onUnblockDomain: PropTypes.func.isRequired,
onEndorseToggle: PropTypes.func.isRequired,
onAddToList: PropTypes.func.isRequired,
onRemoveFromFollowers: PropTypes.func.isRequired,
username: PropTypes.string,
history: PropTypes.object,
};
@ -141,6 +142,10 @@ class Header extends ImmutablePureComponent {
this.props.onShowNote(this.props.account);
}
handleRemoveFromFollowers = () => {
this.props.onRemoveFromFollowers(this.props.account);
}
render() {
const { account } = this.props;
const moved = (account) ? account.get('moved') : false;
@ -177,6 +182,7 @@ class Header extends ImmutablePureComponent {
onSuggestUser={this.handleSuggestUser}
onUnsuggestUser={this.handleUnsuggestUser}
onShowNote={this.handleShowNote}
onRemoveFromFollowers={this.handleRemoveFromFollowers}
username={this.props.username}
/>
</>

View file

@ -13,6 +13,7 @@ import {
unpinAccount,
subscribeAccount,
unsubscribeAccount,
removeFromFollowers,
} from 'soapbox/actions/accounts';
import {
verifyUser,
@ -56,6 +57,7 @@ const messages = defineMessages({
demotedToUser: { id: 'admin.users.actions.demote_to_user_message', defaultMessage: '@{acct} was demoted to a regular user' },
userSuggested: { id: 'admin.users.user_suggested_message', defaultMessage: '@{acct} was suggested' },
userUnsuggested: { id: 'admin.users.user_unsuggested_message', defaultMessage: '@{acct} was unsuggested' },
removeFromFollowersConfirm: { id: 'confirmations.remove_from_followers.confirm', defaultMessage: 'Remove' },
});
const makeMapStateToProps = () => {
@ -269,6 +271,21 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
onShowNote(account) {
dispatch(initAccountNoteModal(account));
},
onRemoveFromFollowers(account) {
dispatch((_, getState) => {
const unfollowModal = getSettings(getState()).get('unfollowModal');
if (unfollowModal) {
dispatch(openModal('CONFIRM', {
message: <FormattedMessage id='confirmations.remove_from_followers.message' defaultMessage='Are you sure you want to remove {name} from your followers?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.removeFromFollowersConfirm),
onConfirm: () => dispatch(removeFromFollowers(account.get('id'))),
}));
} else {
dispatch(removeFromFollowers(account.get('id')));
}
});
},
});
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header));

View file

@ -19,6 +19,7 @@ import {
ACCOUNT_UNSUBSCRIBE_SUCCESS,
ACCOUNT_PIN_SUCCESS,
ACCOUNT_UNPIN_SUCCESS,
ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS,
RELATIONSHIPS_FETCH_SUCCESS,
} from '../actions/accounts';
import {
@ -108,6 +109,7 @@ export default function relationships(state = initialState, action) {
case ACCOUNT_PIN_SUCCESS:
case ACCOUNT_UNPIN_SUCCESS:
case ACCOUNT_NOTE_SUBMIT_SUCCESS:
case ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS:
return normalizeRelationship(state, action.relationship);
case RELATIONSHIPS_FETCH_SUCCESS:
return normalizeRelationships(state, action.relationships);

View file

@ -420,6 +420,15 @@ const getInstanceFeatures = (instance: Instance) => {
*/
remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'),
/**
* Ability to remove an account from your followers.
* @see POST /api/v1/accounts/:id/remove_from_followers
*/
removeFromFollowers: any([
v.software === MASTODON && gte(v.compatVersion, '3.5.0'),
v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
]),
reportMultipleStatuses: any([
v.software === MASTODON,
v.software === PLEROMA,