Merge branch 'remove-from-followers' into 'develop'
Add 'Remove from followers' See merge request soapbox-pub/soapbox-fe!1408
This commit is contained in:
commit
21be58ecb4
6 changed files with 83 additions and 0 deletions
|
@ -57,6 +57,10 @@ export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
|
||||||
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
|
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
|
||||||
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
|
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_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST';
|
||||||
export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS';
|
export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS';
|
||||||
export const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL';
|
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) {
|
export function fetchFollowers(id) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
dispatch(fetchFollowersRequest(id));
|
dispatch(fetchFollowersRequest(id));
|
||||||
|
|
|
@ -48,6 +48,7 @@ const messages = defineMessages({
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||||
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
|
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
|
||||||
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t 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}' },
|
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' },
|
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}' },
|
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'])) {
|
if (account.getIn(['relationship', 'muting'])) {
|
||||||
menu.push({
|
menu.push({
|
||||||
text: intl.formatMessage(messages.unmute, { name: account.get('username') }),
|
text: intl.formatMessage(messages.unmute, { name: account.get('username') }),
|
||||||
|
|
|
@ -25,6 +25,7 @@ class Header extends ImmutablePureComponent {
|
||||||
onUnblockDomain: PropTypes.func.isRequired,
|
onUnblockDomain: PropTypes.func.isRequired,
|
||||||
onEndorseToggle: PropTypes.func.isRequired,
|
onEndorseToggle: PropTypes.func.isRequired,
|
||||||
onAddToList: PropTypes.func.isRequired,
|
onAddToList: PropTypes.func.isRequired,
|
||||||
|
onRemoveFromFollowers: PropTypes.func.isRequired,
|
||||||
username: PropTypes.string,
|
username: PropTypes.string,
|
||||||
history: PropTypes.object,
|
history: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
@ -141,6 +142,10 @@ class Header extends ImmutablePureComponent {
|
||||||
this.props.onShowNote(this.props.account);
|
this.props.onShowNote(this.props.account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleRemoveFromFollowers = () => {
|
||||||
|
this.props.onRemoveFromFollowers(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account } = this.props;
|
const { account } = this.props;
|
||||||
const moved = (account) ? account.get('moved') : false;
|
const moved = (account) ? account.get('moved') : false;
|
||||||
|
@ -177,6 +182,7 @@ class Header extends ImmutablePureComponent {
|
||||||
onSuggestUser={this.handleSuggestUser}
|
onSuggestUser={this.handleSuggestUser}
|
||||||
onUnsuggestUser={this.handleUnsuggestUser}
|
onUnsuggestUser={this.handleUnsuggestUser}
|
||||||
onShowNote={this.handleShowNote}
|
onShowNote={this.handleShowNote}
|
||||||
|
onRemoveFromFollowers={this.handleRemoveFromFollowers}
|
||||||
username={this.props.username}
|
username={this.props.username}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
unpinAccount,
|
unpinAccount,
|
||||||
subscribeAccount,
|
subscribeAccount,
|
||||||
unsubscribeAccount,
|
unsubscribeAccount,
|
||||||
|
removeFromFollowers,
|
||||||
} from 'soapbox/actions/accounts';
|
} from 'soapbox/actions/accounts';
|
||||||
import {
|
import {
|
||||||
verifyUser,
|
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' },
|
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' },
|
userSuggested: { id: 'admin.users.user_suggested_message', defaultMessage: '@{acct} was suggested' },
|
||||||
userUnsuggested: { id: 'admin.users.user_unsuggested_message', defaultMessage: '@{acct} was unsuggested' },
|
userUnsuggested: { id: 'admin.users.user_unsuggested_message', defaultMessage: '@{acct} was unsuggested' },
|
||||||
|
removeFromFollowersConfirm: { id: 'confirmations.remove_from_followers.confirm', defaultMessage: 'Remove' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
|
@ -269,6 +271,21 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
onShowNote(account) {
|
onShowNote(account) {
|
||||||
dispatch(initAccountNoteModal(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));
|
export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Header));
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
ACCOUNT_UNSUBSCRIBE_SUCCESS,
|
ACCOUNT_UNSUBSCRIBE_SUCCESS,
|
||||||
ACCOUNT_PIN_SUCCESS,
|
ACCOUNT_PIN_SUCCESS,
|
||||||
ACCOUNT_UNPIN_SUCCESS,
|
ACCOUNT_UNPIN_SUCCESS,
|
||||||
|
ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS,
|
||||||
RELATIONSHIPS_FETCH_SUCCESS,
|
RELATIONSHIPS_FETCH_SUCCESS,
|
||||||
} from '../actions/accounts';
|
} from '../actions/accounts';
|
||||||
import {
|
import {
|
||||||
|
@ -108,6 +109,7 @@ export default function relationships(state = initialState, action) {
|
||||||
case ACCOUNT_PIN_SUCCESS:
|
case ACCOUNT_PIN_SUCCESS:
|
||||||
case ACCOUNT_UNPIN_SUCCESS:
|
case ACCOUNT_UNPIN_SUCCESS:
|
||||||
case ACCOUNT_NOTE_SUBMIT_SUCCESS:
|
case ACCOUNT_NOTE_SUBMIT_SUCCESS:
|
||||||
|
case ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS:
|
||||||
return normalizeRelationship(state, action.relationship);
|
return normalizeRelationship(state, action.relationship);
|
||||||
case RELATIONSHIPS_FETCH_SUCCESS:
|
case RELATIONSHIPS_FETCH_SUCCESS:
|
||||||
return normalizeRelationships(state, action.relationships);
|
return normalizeRelationships(state, action.relationships);
|
||||||
|
|
|
@ -420,6 +420,15 @@ const getInstanceFeatures = (instance: Instance) => {
|
||||||
*/
|
*/
|
||||||
remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
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([
|
reportMultipleStatuses: any([
|
||||||
v.software === MASTODON,
|
v.software === MASTODON,
|
||||||
v.software === PLEROMA,
|
v.software === PLEROMA,
|
||||||
|
|
Loading…
Reference in a new issue