diff --git a/app/soapbox/actions/aliases.js b/app/soapbox/actions/aliases.js index cdeb7208c..ec9093965 100644 --- a/app/soapbox/actions/aliases.js +++ b/app/soapbox/actions/aliases.js @@ -1,14 +1,19 @@ import { defineMessages } from 'react-intl'; import { isLoggedIn } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; import api from '../api'; import { showAlertForError } from './alerts'; -import { importFetchedAccount, importFetchedAccounts } from './importer'; -import { ME_PATCH_SUCCESS } from './me'; +import { importFetchedAccounts } from './importer'; +import { patchMeSuccess } from './me'; import snackbar from './snackbar'; +export const ALIASES_FETCH_REQUEST = 'ALIASES_FETCH_REQUEST'; +export const ALIASES_FETCH_SUCCESS = 'ALIASES_FETCH_SUCCESS'; +export const ALIASES_FETCH_FAIL = 'ALIASES_FETCH_FAIL'; + export const ALIASES_SUGGESTIONS_CHANGE = 'ALIASES_SUGGESTIONS_CHANGE'; export const ALIASES_SUGGESTIONS_READY = 'ALIASES_SUGGESTIONS_READY'; export const ALIASES_SUGGESTIONS_CLEAR = 'ALIASES_SUGGESTIONS_CLEAR'; @@ -26,6 +31,38 @@ const messages = defineMessages({ removeSuccess: { id: 'aliases.success.remove', defaultMessage: 'Account alias removed successfully' }, }); +export const fetchAliases = (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + const state = getState(); + + const instance = state.get('instance'); + const features = getFeatures(instance); + + if (!features.accountMoving) return; + + dispatch(fetchAliasesRequest()); + + api(getState).get('/api/pleroma/aliases') + .then(response => { + dispatch(fetchAliasesSuccess(response.data.aliases)); + }) + .catch(err => dispatch(fetchAliasesFail(err))); +}; + +export const fetchAliasesRequest = () => ({ + type: ALIASES_FETCH_REQUEST, +}); + +export const fetchAliasesSuccess = aliases => ({ + type: ALIASES_FETCH_SUCCESS, + value: aliases, +}); + +export const fetchAliasesFail = error => ({ + type: ALIASES_FETCH_FAIL, + error, +}); + export const fetchAliasesSuggestions = q => (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -56,80 +93,103 @@ export const changeAliasesSuggestions = value => ({ value, }); -export const addToAliases = (intl, apId) => (dispatch, getState) => { +export const addToAliases = (intl, account) => (dispatch, getState) => { if (!isLoggedIn(getState)) return; const state = getState(); - const me = state.get('me'); - const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); + const instance = state.get('instance'); + const features = getFeatures(instance); - dispatch(addToAliasesRequest(apId)); + if (!features.accountMoving) { + const me = state.get('me'); + const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); - api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, apId] }) - .then((response => { + dispatch(addToAliasesRequest()); + + api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, account.getIn(['pleroma', 'ap_id'])] }) + .then((response => { + dispatch(snackbar.success(intl.formatMessage(messages.createSuccess))); + dispatch(addToAliasesSuccess()); + dispatch(patchMeSuccess(response.data)); + })) + .catch(err => dispatch(addToAliasesFail(err))); + + return; + } + + dispatch(addToAliasesRequest()); + + api(getState).put('/api/pleroma/aliases', { + alias: account.get('acct'), + }) + .then(response => { dispatch(snackbar.success(intl.formatMessage(messages.createSuccess))); - dispatch(addToAliasesSuccess(response.data)); - })) - .catch(err => dispatch(addToAliasesFail(err))); + dispatch(addToAliasesSuccess); + dispatch(fetchAliases); + }) + .catch(err => dispatch(fetchAliasesFail(err))); }; -export const addToAliasesRequest = (apId) => ({ +export const addToAliasesRequest = () => ({ type: ALIASES_ADD_REQUEST, - apId, }); -export const addToAliasesSuccess = me => dispatch => { - dispatch(importFetchedAccount(me)); - dispatch({ - type: ME_PATCH_SUCCESS, - me, - }); - dispatch({ - type: ALIASES_ADD_SUCCESS, - }); -}; +export const addToAliasesSuccess = () => ({ + type: ALIASES_ADD_SUCCESS, +}); -export const addToAliasesFail = (apId, error) => ({ +export const addToAliasesFail = error => ({ type: ALIASES_ADD_FAIL, - apId, error, }); -export const removeFromAliases = (intl, apId) => (dispatch, getState) => { +export const removeFromAliases = (intl, account) => (dispatch, getState) => { if (!isLoggedIn(getState)) return; const state = getState(); - const me = state.get('me'); - const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); + const instance = state.get('instance'); + const features = getFeatures(instance); - dispatch(removeFromAliasesRequest(apId)); + if (!features.accountMoving) { + const me = state.get('me'); + const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']); - api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== apId) }) + dispatch(removeFromAliasesRequest()); + + api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== account) }) + .then(response => { + dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess))); + dispatch(removeFromAliasesSuccess); + }) + .catch(err => dispatch(removeFromAliasesFail(err))); + + return; + } + + dispatch(addToAliasesRequest()); + + api(getState).delete('/api/pleroma/aliases', { + data: { + alias: account, + }, + }) .then(response => { dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess))); - dispatch(removeFromAliasesSuccess(response.data)); + dispatch(removeFromAliasesSuccess); + dispatch(fetchAliases); }) - .catch(err => dispatch(removeFromAliasesFail(apId, err))); + .catch(err => dispatch(fetchAliasesFail(err))); }; -export const removeFromAliasesRequest = (apId) => ({ +export const removeFromAliasesRequest = () => ({ type: ALIASES_REMOVE_REQUEST, - apId, }); -export const removeFromAliasesSuccess = me => dispatch => { - dispatch(importFetchedAccount(me)); - dispatch({ - type: ME_PATCH_SUCCESS, - me, - }); - dispatch({ - type: ALIASES_REMOVE_SUCCESS, - }); -}; +export const removeFromAliasesSuccess = () => ({ + type: ALIASES_REMOVE_SUCCESS, +}); -export const removeFromAliasesFail = (apId, error) => ({ +export const removeFromAliasesFail = error => ({ type: ALIASES_REMOVE_FAIL, - apId, error, }); diff --git a/app/soapbox/features/aliases/components/account.js b/app/soapbox/features/aliases/components/account.js index 3e4c7f936..fd0abd21b 100644 --- a/app/soapbox/features/aliases/components/account.js +++ b/app/soapbox/features/aliases/components/account.js @@ -5,11 +5,12 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { connect } from 'react-redux'; -import { addToAliases } from '../../../actions/aliases'; -import Avatar from '../../../components/avatar'; -import DisplayName from '../../../components/display_name'; -import IconButton from '../../../components/icon_button'; -import { makeGetAccount } from '../../../selectors'; +import { addToAliases } from 'soapbox/actions/aliases'; +import Avatar from 'soapbox/components/avatar'; +import DisplayName from 'soapbox/components/display_name'; +import IconButton from 'soapbox/components/icon_button'; +import { makeGetAccount } from 'soapbox/selectors'; +import { getFeatures } from 'soapbox/utils/features'; const messages = defineMessages({ add: { id: 'aliases.account.add', defaultMessage: 'Create alias' }, @@ -18,17 +19,20 @@ const messages = defineMessages({ const makeMapStateToProps = () => { const getAccount = makeGetAccount(); - const mapStateToProps = (state, { accountId, added }) => { + const mapStateToProps = (state, { accountId, added, aliases }) => { const me = state.get('me'); - const ownAccount = getAccount(state, me); + + const instance = state.get('instance'); + const features = getFeatures(instance); const account = getAccount(state, accountId); const apId = account.getIn(['pleroma', 'ap_id']); + const name = features.accountMoving ? account.get('acct') : apId; return { account, apId, - added: typeof added === 'undefined' ? ownAccount.getIn(['pleroma', 'also_known_as']).includes(apId) : added, + added: typeof added === 'undefined' ? aliases.includes(name) : added, me, }; }; @@ -56,7 +60,7 @@ class Account extends ImmutablePureComponent { added: false, }; - handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.apId); + handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.account); render() { const { account, accountId, intl, added, me } = this.props; diff --git a/app/soapbox/features/aliases/index.js b/app/soapbox/features/aliases/index.js index a2f844d98..c9bd35749 100644 --- a/app/soapbox/features/aliases/index.js +++ b/app/soapbox/features/aliases/index.js @@ -1,13 +1,15 @@ +import { List as ImmutableList } from 'immutable'; import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; +import { fetchAliases, removeFromAliases } from 'soapbox/actions/aliases'; import Icon from 'soapbox/components/icon'; +import ScrollableList from 'soapbox/components/scrollable_list'; import { makeGetAccount } from 'soapbox/selectors'; +import { getFeatures } from 'soapbox/utils/features'; -import { removeFromAliases } from '../../actions/aliases'; -import ScrollableList from '../../components/scrollable_list'; import Column from '../ui/components/column'; import ColumnSubheading from '../ui/components/column_subheading'; @@ -30,8 +32,16 @@ const makeMapStateToProps = () => { const me = state.get('me'); const account = getAccount(state, me); + const instance = state.get('instance'); + const features = getFeatures(instance); + + let aliases; + + if (features.accountMoving) aliases = state.getIn(['aliases', 'aliases', 'items'], ImmutableList()); + else aliases = account.getIn(['pleroma', 'also_known_as']); + return { - aliases: account.getIn(['pleroma', 'also_known_as']), + aliases, searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']), loaded: state.getIn(['aliases', 'suggestions', 'loaded']), }; @@ -44,6 +54,11 @@ export default @connect(makeMapStateToProps) @injectIntl class Aliases extends ImmutablePureComponent { + componentDidMount = e => { + const { dispatch } = this.props; + dispatch(fetchAliases); + } + handleFilterDelete = e => { const { dispatch, intl } = this.props; dispatch(removeFromAliases(intl, e.currentTarget.dataset.value)); @@ -65,7 +80,7 @@ class Aliases extends ImmutablePureComponent { ) : (
- {searchAccountIds.map(accountId => )} + {searchAccountIds.map(accountId => )}
) } diff --git a/app/soapbox/reducers/aliases.js b/app/soapbox/reducers/aliases.js index 7c6394ee9..158e91158 100644 --- a/app/soapbox/reducers/aliases.js +++ b/app/soapbox/reducers/aliases.js @@ -4,9 +4,14 @@ import { ALIASES_SUGGESTIONS_READY, ALIASES_SUGGESTIONS_CLEAR, ALIASES_SUGGESTIONS_CHANGE, + ALIASES_FETCH_SUCCESS, } from '../actions/aliases'; const initialState = ImmutableMap({ + aliases: ImmutableMap({ + loaded: false, + items: ImmutableList(), + }), suggestions: ImmutableMap({ value: '', loaded: false, @@ -16,6 +21,9 @@ const initialState = ImmutableMap({ export default function aliasesReducer(state = initialState, action) { switch(action.type) { + case ALIASES_FETCH_SUCCESS: + return state + .setIn(['aliases', 'items'], action.value); case ALIASES_SUGGESTIONS_CHANGE: return state .setIn(['suggestions', 'value'], action.value) diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index bba076d3b..54355e005 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -88,6 +88,7 @@ export const getFeatures = createSelector([instance => instance], instance => { ]), birthdays: v.software === PLEROMA && gte(v.version, '2.4.50'), ethereumLogin: v.software === MITRA, + accountMoving: v.software === PLEROMA && gte(v.version, '2.4.50'), }; });