kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Actions: TypeScript
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>merge-requests/1534/head
rodzic
0115f064a0
commit
6214084890
|
@ -1,196 +0,0 @@
|
|||
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 { 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';
|
||||
|
||||
export const ALIASES_ADD_REQUEST = 'ALIASES_ADD_REQUEST';
|
||||
export const ALIASES_ADD_SUCCESS = 'ALIASES_ADD_SUCCESS';
|
||||
export const ALIASES_ADD_FAIL = 'ALIASES_ADD_FAIL';
|
||||
|
||||
export const ALIASES_REMOVE_REQUEST = 'ALIASES_REMOVE_REQUEST';
|
||||
export const ALIASES_REMOVE_SUCCESS = 'ALIASES_REMOVE_SUCCESS';
|
||||
export const ALIASES_REMOVE_FAIL = 'ALIASES_REMOVE_FAIL';
|
||||
|
||||
const messages = defineMessages({
|
||||
createSuccess: { id: 'aliases.success.add', defaultMessage: 'Account alias created successfully' },
|
||||
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;
|
||||
|
||||
const params = {
|
||||
q,
|
||||
resolve: true,
|
||||
limit: 4,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchAliasesSuggestionsReady(q, data));
|
||||
}).catch(error => dispatch(showAlertForError(error)));
|
||||
};
|
||||
|
||||
export const fetchAliasesSuggestionsReady = (query, accounts) => ({
|
||||
type: ALIASES_SUGGESTIONS_READY,
|
||||
query,
|
||||
accounts,
|
||||
});
|
||||
|
||||
export const clearAliasesSuggestions = () => ({
|
||||
type: ALIASES_SUGGESTIONS_CLEAR,
|
||||
});
|
||||
|
||||
export const changeAliasesSuggestions = value => ({
|
||||
type: ALIASES_SUGGESTIONS_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
||||
export const addToAliases = (account) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
if (!features.accountMoving) {
|
||||
const me = state.get('me');
|
||||
const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(addToAliasesRequest());
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, account.getIn(['pleroma', 'ap_id'])] })
|
||||
.then((response => {
|
||||
dispatch(snackbar.success(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(messages.createSuccess));
|
||||
dispatch(addToAliasesSuccess);
|
||||
dispatch(fetchAliases);
|
||||
})
|
||||
.catch(err => dispatch(fetchAliasesFail(err)));
|
||||
};
|
||||
|
||||
export const addToAliasesRequest = () => ({
|
||||
type: ALIASES_ADD_REQUEST,
|
||||
});
|
||||
|
||||
export const addToAliasesSuccess = () => ({
|
||||
type: ALIASES_ADD_SUCCESS,
|
||||
});
|
||||
|
||||
export const addToAliasesFail = error => ({
|
||||
type: ALIASES_ADD_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
export const removeFromAliases = (account) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
|
||||
if (!features.accountMoving) {
|
||||
const me = state.get('me');
|
||||
const alsoKnownAs = state.getIn(['accounts_meta', me, 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(removeFromAliasesRequest());
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== account) })
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(messages.removeSuccess));
|
||||
dispatch(removeFromAliasesSuccess);
|
||||
dispatch(patchMeSuccess(response.data));
|
||||
})
|
||||
.catch(err => dispatch(removeFromAliasesFail(err)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(addToAliasesRequest());
|
||||
|
||||
api(getState).delete('/api/pleroma/aliases', {
|
||||
data: {
|
||||
alias: account,
|
||||
},
|
||||
})
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(messages.removeSuccess));
|
||||
dispatch(removeFromAliasesSuccess);
|
||||
dispatch(fetchAliases);
|
||||
})
|
||||
.catch(err => dispatch(fetchAliasesFail(err)));
|
||||
};
|
||||
|
||||
export const removeFromAliasesRequest = () => ({
|
||||
type: ALIASES_REMOVE_REQUEST,
|
||||
});
|
||||
|
||||
export const removeFromAliasesSuccess = () => ({
|
||||
type: ALIASES_REMOVE_SUCCESS,
|
||||
});
|
||||
|
||||
export const removeFromAliasesFail = error => ({
|
||||
type: ALIASES_REMOVE_FAIL,
|
||||
error,
|
||||
});
|
|
@ -0,0 +1,234 @@
|
|||
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 { importFetchedAccounts } from './importer';
|
||||
import { patchMeSuccess } from './me';
|
||||
import snackbar from './snackbar';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity, Account } from 'soapbox/types/entities';
|
||||
|
||||
const ALIASES_FETCH_REQUEST = 'ALIASES_FETCH_REQUEST';
|
||||
const ALIASES_FETCH_SUCCESS = 'ALIASES_FETCH_SUCCESS';
|
||||
const ALIASES_FETCH_FAIL = 'ALIASES_FETCH_FAIL';
|
||||
|
||||
const ALIASES_SUGGESTIONS_CHANGE = 'ALIASES_SUGGESTIONS_CHANGE';
|
||||
const ALIASES_SUGGESTIONS_READY = 'ALIASES_SUGGESTIONS_READY';
|
||||
const ALIASES_SUGGESTIONS_CLEAR = 'ALIASES_SUGGESTIONS_CLEAR';
|
||||
|
||||
const ALIASES_ADD_REQUEST = 'ALIASES_ADD_REQUEST';
|
||||
const ALIASES_ADD_SUCCESS = 'ALIASES_ADD_SUCCESS';
|
||||
const ALIASES_ADD_FAIL = 'ALIASES_ADD_FAIL';
|
||||
|
||||
const ALIASES_REMOVE_REQUEST = 'ALIASES_REMOVE_REQUEST';
|
||||
const ALIASES_REMOVE_SUCCESS = 'ALIASES_REMOVE_SUCCESS';
|
||||
const ALIASES_REMOVE_FAIL = 'ALIASES_REMOVE_FAIL';
|
||||
|
||||
const messages = defineMessages({
|
||||
createSuccess: { id: 'aliases.success.add', defaultMessage: 'Account alias created successfully' },
|
||||
removeSuccess: { id: 'aliases.success.remove', defaultMessage: 'Account alias removed successfully' },
|
||||
});
|
||||
|
||||
const fetchAliases = (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const instance = state.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)));
|
||||
};
|
||||
|
||||
const fetchAliasesRequest = () => ({
|
||||
type: ALIASES_FETCH_REQUEST,
|
||||
});
|
||||
|
||||
const fetchAliasesSuccess = (aliases: APIEntity[]) => ({
|
||||
type: ALIASES_FETCH_SUCCESS,
|
||||
value: aliases,
|
||||
});
|
||||
|
||||
const fetchAliasesFail = (error: AxiosError) => ({
|
||||
type: ALIASES_FETCH_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
const fetchAliasesSuggestions = (q: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const params = {
|
||||
q,
|
||||
resolve: true,
|
||||
limit: 4,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchAliasesSuggestionsReady(q, data));
|
||||
}).catch(error => dispatch(showAlertForError(error)));
|
||||
};
|
||||
|
||||
const fetchAliasesSuggestionsReady = (query: string, accounts: APIEntity[]) => ({
|
||||
type: ALIASES_SUGGESTIONS_READY,
|
||||
query,
|
||||
accounts,
|
||||
});
|
||||
|
||||
const clearAliasesSuggestions = () => ({
|
||||
type: ALIASES_SUGGESTIONS_CLEAR,
|
||||
});
|
||||
|
||||
const changeAliasesSuggestions = (value: string) => ({
|
||||
type: ALIASES_SUGGESTIONS_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
||||
const addToAliases = (account: Account) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const instance = state.instance;
|
||||
const features = getFeatures(instance);
|
||||
|
||||
if (!features.accountMoving) {
|
||||
const me = state.me;
|
||||
const alsoKnownAs = state.accounts_meta.get(me as string)!.pleroma.get('also_known_as');
|
||||
|
||||
dispatch(addToAliasesRequest());
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, account.pleroma.get('ap_id')] })
|
||||
.then((response => {
|
||||
dispatch(snackbar.success(messages.createSuccess));
|
||||
dispatch(addToAliasesSuccess);
|
||||
dispatch(patchMeSuccess(response.data));
|
||||
}))
|
||||
.catch(err => dispatch(addToAliasesFail(err)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(addToAliasesRequest());
|
||||
|
||||
api(getState).put('/api/pleroma/aliases', {
|
||||
alias: account.acct,
|
||||
})
|
||||
.then(() => {
|
||||
dispatch(snackbar.success(messages.createSuccess));
|
||||
dispatch(addToAliasesSuccess);
|
||||
dispatch(fetchAliases);
|
||||
})
|
||||
.catch(err => dispatch(fetchAliasesFail(err)));
|
||||
};
|
||||
|
||||
const addToAliasesRequest = () => ({
|
||||
type: ALIASES_ADD_REQUEST,
|
||||
});
|
||||
|
||||
const addToAliasesSuccess = () => ({
|
||||
type: ALIASES_ADD_SUCCESS,
|
||||
});
|
||||
|
||||
const addToAliasesFail = (error: AxiosError) => ({
|
||||
type: ALIASES_ADD_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
const removeFromAliases = (account: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const state = getState();
|
||||
|
||||
const instance = state.instance;
|
||||
const features = getFeatures(instance);
|
||||
|
||||
if (!features.accountMoving) {
|
||||
const me = state.me;
|
||||
const alsoKnownAs = state.accounts_meta.get(me as string)!.pleroma.get('also_known_as');
|
||||
|
||||
dispatch(removeFromAliasesRequest());
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter((id: string) => id !== account) })
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(messages.removeSuccess));
|
||||
dispatch(removeFromAliasesSuccess);
|
||||
dispatch(patchMeSuccess(response.data));
|
||||
})
|
||||
.catch(err => dispatch(removeFromAliasesFail(err)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(addToAliasesRequest());
|
||||
|
||||
api(getState).delete('/api/pleroma/aliases', {
|
||||
data: {
|
||||
alias: account,
|
||||
},
|
||||
})
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(messages.removeSuccess));
|
||||
dispatch(removeFromAliasesSuccess);
|
||||
dispatch(fetchAliases);
|
||||
})
|
||||
.catch(err => dispatch(fetchAliasesFail(err)));
|
||||
};
|
||||
|
||||
const removeFromAliasesRequest = () => ({
|
||||
type: ALIASES_REMOVE_REQUEST,
|
||||
});
|
||||
|
||||
const removeFromAliasesSuccess = () => ({
|
||||
type: ALIASES_REMOVE_SUCCESS,
|
||||
});
|
||||
|
||||
const removeFromAliasesFail = (error: AxiosError) => ({
|
||||
type: ALIASES_REMOVE_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
export {
|
||||
ALIASES_FETCH_REQUEST,
|
||||
ALIASES_FETCH_SUCCESS,
|
||||
ALIASES_FETCH_FAIL,
|
||||
ALIASES_SUGGESTIONS_CHANGE,
|
||||
ALIASES_SUGGESTIONS_READY,
|
||||
ALIASES_SUGGESTIONS_CLEAR,
|
||||
ALIASES_ADD_REQUEST,
|
||||
ALIASES_ADD_SUCCESS,
|
||||
ALIASES_ADD_FAIL,
|
||||
ALIASES_REMOVE_REQUEST,
|
||||
ALIASES_REMOVE_SUCCESS,
|
||||
ALIASES_REMOVE_FAIL,
|
||||
fetchAliases,
|
||||
fetchAliasesRequest,
|
||||
fetchAliasesSuccess,
|
||||
fetchAliasesFail,
|
||||
fetchAliasesSuggestions,
|
||||
fetchAliasesSuggestionsReady,
|
||||
clearAliasesSuggestions,
|
||||
changeAliasesSuggestions,
|
||||
addToAliases,
|
||||
addToAliasesRequest,
|
||||
addToAliasesSuccess,
|
||||
addToAliasesFail,
|
||||
removeFromAliases,
|
||||
removeFromAliasesRequest,
|
||||
removeFromAliasesSuccess,
|
||||
removeFromAliasesFail,
|
||||
};
|
|
@ -1,182 +0,0 @@
|
|||
import { List as ImmutableList } from 'immutable';
|
||||
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
import { favourite, unfavourite } from './interactions';
|
||||
|
||||
export const EMOJI_REACT_REQUEST = 'EMOJI_REACT_REQUEST';
|
||||
export const EMOJI_REACT_SUCCESS = 'EMOJI_REACT_SUCCESS';
|
||||
export const EMOJI_REACT_FAIL = 'EMOJI_REACT_FAIL';
|
||||
|
||||
export const UNEMOJI_REACT_REQUEST = 'UNEMOJI_REACT_REQUEST';
|
||||
export const UNEMOJI_REACT_SUCCESS = 'UNEMOJI_REACT_SUCCESS';
|
||||
export const UNEMOJI_REACT_FAIL = 'UNEMOJI_REACT_FAIL';
|
||||
|
||||
export const EMOJI_REACTS_FETCH_REQUEST = 'EMOJI_REACTS_FETCH_REQUEST';
|
||||
export const EMOJI_REACTS_FETCH_SUCCESS = 'EMOJI_REACTS_FETCH_SUCCESS';
|
||||
export const EMOJI_REACTS_FETCH_FAIL = 'EMOJI_REACTS_FETCH_FAIL';
|
||||
|
||||
const noOp = () => () => new Promise(f => f());
|
||||
|
||||
export const simpleEmojiReact = (status, emoji) => {
|
||||
return (dispatch, getState) => {
|
||||
const emojiReacts = status.getIn(['pleroma', 'emoji_reactions'], ImmutableList());
|
||||
|
||||
if (emoji === '👍' && status.get('favourited')) return dispatch(unfavourite(status));
|
||||
|
||||
const undo = emojiReacts.filter(e => e.get('me') === true && e.get('name') === emoji).count() > 0;
|
||||
if (undo) return dispatch(unEmojiReact(status, emoji));
|
||||
|
||||
return Promise.all(
|
||||
emojiReacts
|
||||
.filter(emojiReact => emojiReact.get('me') === true)
|
||||
.map(emojiReact => dispatch(unEmojiReact(status, emojiReact.get('name')))),
|
||||
status.get('favourited') && dispatch(unfavourite(status)),
|
||||
).then(() => {
|
||||
if (emoji === '👍') {
|
||||
dispatch(favourite(status));
|
||||
} else {
|
||||
dispatch(emojiReact(status, emoji));
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export function fetchEmojiReacts(id, emoji) {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(fetchEmojiReactsRequest(id, emoji));
|
||||
|
||||
const url = emoji
|
||||
? `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||
: `/api/v1/pleroma/statuses/${id}/reactions`;
|
||||
|
||||
return api(getState).get(url).then(response => {
|
||||
response.data.forEach(emojiReact => {
|
||||
dispatch(importFetchedAccounts(emojiReact.accounts));
|
||||
});
|
||||
dispatch(fetchEmojiReactsSuccess(id, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchEmojiReactsFail(id, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReact(status, emoji) {
|
||||
return function(dispatch, getState) {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(emojiReactRequest(status, emoji));
|
||||
|
||||
return api(getState)
|
||||
.put(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
|
||||
.then(function(response) {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(emojiReactSuccess(status, emoji));
|
||||
}).catch(function(error) {
|
||||
dispatch(emojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReact(status, emoji) {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(unEmojiReactRequest(status, emoji));
|
||||
|
||||
return api(getState)
|
||||
.delete(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
|
||||
.then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unEmojiReactSuccess(status, emoji));
|
||||
}).catch(error => {
|
||||
dispatch(unEmojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactsRequest(id, emoji) {
|
||||
return {
|
||||
type: EMOJI_REACTS_FETCH_REQUEST,
|
||||
id,
|
||||
emoji,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactsSuccess(id, emojiReacts) {
|
||||
return {
|
||||
type: EMOJI_REACTS_FETCH_SUCCESS,
|
||||
id,
|
||||
emojiReacts,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchEmojiReactsFail(id, error) {
|
||||
return {
|
||||
type: EMOJI_REACTS_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactRequest(status, emoji) {
|
||||
return {
|
||||
type: EMOJI_REACT_REQUEST,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactSuccess(status, emoji) {
|
||||
return {
|
||||
type: EMOJI_REACT_SUCCESS,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function emojiReactFail(status, emoji, error) {
|
||||
return {
|
||||
type: EMOJI_REACT_FAIL,
|
||||
status,
|
||||
emoji,
|
||||
error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactRequest(status, emoji) {
|
||||
return {
|
||||
type: UNEMOJI_REACT_REQUEST,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactSuccess(status, emoji) {
|
||||
return {
|
||||
type: UNEMOJI_REACT_SUCCESS,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function unEmojiReactFail(status, emoji, error) {
|
||||
return {
|
||||
type: UNEMOJI_REACT_FAIL,
|
||||
status,
|
||||
emoji,
|
||||
error,
|
||||
skipLoading: true,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { importFetchedAccounts, importFetchedStatus } from './importer';
|
||||
import { favourite, unfavourite } from './interactions';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity, Status } from 'soapbox/types/entities';
|
||||
|
||||
const EMOJI_REACT_REQUEST = 'EMOJI_REACT_REQUEST';
|
||||
const EMOJI_REACT_SUCCESS = 'EMOJI_REACT_SUCCESS';
|
||||
const EMOJI_REACT_FAIL = 'EMOJI_REACT_FAIL';
|
||||
|
||||
const UNEMOJI_REACT_REQUEST = 'UNEMOJI_REACT_REQUEST';
|
||||
const UNEMOJI_REACT_SUCCESS = 'UNEMOJI_REACT_SUCCESS';
|
||||
const UNEMOJI_REACT_FAIL = 'UNEMOJI_REACT_FAIL';
|
||||
|
||||
const EMOJI_REACTS_FETCH_REQUEST = 'EMOJI_REACTS_FETCH_REQUEST';
|
||||
const EMOJI_REACTS_FETCH_SUCCESS = 'EMOJI_REACTS_FETCH_SUCCESS';
|
||||
const EMOJI_REACTS_FETCH_FAIL = 'EMOJI_REACTS_FETCH_FAIL';
|
||||
|
||||
const noOp = () => () => new Promise(f => f(undefined));
|
||||
|
||||
const simpleEmojiReact = (status: Status, emoji: string) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const emojiReacts: ImmutableList<ImmutableMap<string, any>> = status.pleroma.get('emoji_reactions') || ImmutableList();
|
||||
|
||||
if (emoji === '👍' && status.favourited) return dispatch(unfavourite(status));
|
||||
|
||||
const undo = emojiReacts.filter(e => e.get('me') === true && e.get('name') === emoji).count() > 0;
|
||||
if (undo) return dispatch(unEmojiReact(status, emoji));
|
||||
|
||||
return Promise.all([
|
||||
...emojiReacts
|
||||
.filter((emojiReact) => emojiReact.get('me') === true)
|
||||
.map(emojiReact => dispatch(unEmojiReact(status, emojiReact.get('name')))).toArray(),
|
||||
status.favourited && dispatch(unfavourite(status)),
|
||||
]).then(() => {
|
||||
if (emoji === '👍') {
|
||||
dispatch(favourite(status));
|
||||
} else {
|
||||
dispatch(emojiReact(status, emoji));
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
const fetchEmojiReacts = (id: string, emoji: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(fetchEmojiReactsRequest(id, emoji));
|
||||
|
||||
const url = emoji
|
||||
? `/api/v1/pleroma/statuses/${id}/reactions/${emoji}`
|
||||
: `/api/v1/pleroma/statuses/${id}/reactions`;
|
||||
|
||||
return api(getState).get(url).then(response => {
|
||||
response.data.forEach((emojiReact: APIEntity) => {
|
||||
dispatch(importFetchedAccounts(emojiReact.accounts));
|
||||
});
|
||||
dispatch(fetchEmojiReactsSuccess(id, response.data));
|
||||
}).catch(error => {
|
||||
dispatch(fetchEmojiReactsFail(id, error));
|
||||
});
|
||||
};
|
||||
|
||||
const emojiReact = (status: Status, emoji: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(emojiReactRequest(status, emoji));
|
||||
|
||||
return api(getState)
|
||||
.put(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
|
||||
.then(function(response) {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(emojiReactSuccess(status, emoji));
|
||||
}).catch(function(error) {
|
||||
dispatch(emojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
|
||||
const unEmojiReact = (status: Status, emoji: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp());
|
||||
|
||||
dispatch(unEmojiReactRequest(status, emoji));
|
||||
|
||||
return api(getState)
|
||||
.delete(`/api/v1/pleroma/statuses/${status.get('id')}/reactions/${emoji}`)
|
||||
.then(response => {
|
||||
dispatch(importFetchedStatus(response.data));
|
||||
dispatch(unEmojiReactSuccess(status, emoji));
|
||||
}).catch(error => {
|
||||
dispatch(unEmojiReactFail(status, emoji, error));
|
||||
});
|
||||
};
|
||||
|
||||
const fetchEmojiReactsRequest = (id: string, emoji: string) => ({
|
||||
type: EMOJI_REACTS_FETCH_REQUEST,
|
||||
id,
|
||||
emoji,
|
||||
});
|
||||
|
||||
const fetchEmojiReactsSuccess = (id: string, emojiReacts: APIEntity[]) => ({
|
||||
type: EMOJI_REACTS_FETCH_SUCCESS,
|
||||
id,
|
||||
emojiReacts,
|
||||
});
|
||||
|
||||
const fetchEmojiReactsFail = (id: string, error: AxiosError) => ({
|
||||
type: EMOJI_REACTS_FETCH_FAIL,
|
||||
id,
|
||||
error,
|
||||
});
|
||||
|
||||
const emojiReactRequest = (status: Status, emoji: string) => ({
|
||||
type: EMOJI_REACT_REQUEST,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
const emojiReactSuccess = (status: Status, emoji: string) => ({
|
||||
type: EMOJI_REACT_SUCCESS,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
const emojiReactFail = (status: Status, emoji: string, error: AxiosError) => ({
|
||||
type: EMOJI_REACT_FAIL,
|
||||
status,
|
||||
emoji,
|
||||
error,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
const unEmojiReactRequest = (status: Status, emoji: string) => ({
|
||||
type: UNEMOJI_REACT_REQUEST,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
const unEmojiReactSuccess = (status: Status, emoji: string) => ({
|
||||
type: UNEMOJI_REACT_SUCCESS,
|
||||
status,
|
||||
emoji,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
const unEmojiReactFail = (status: Status, emoji: string, error: AxiosError) => ({
|
||||
type: UNEMOJI_REACT_FAIL,
|
||||
status,
|
||||
emoji,
|
||||
error,
|
||||
skipLoading: true,
|
||||
});
|
||||
|
||||
export {
|
||||
EMOJI_REACT_REQUEST,
|
||||
EMOJI_REACT_SUCCESS,
|
||||
EMOJI_REACT_FAIL,
|
||||
UNEMOJI_REACT_REQUEST,
|
||||
UNEMOJI_REACT_SUCCESS,
|
||||
UNEMOJI_REACT_FAIL,
|
||||
EMOJI_REACTS_FETCH_REQUEST,
|
||||
EMOJI_REACTS_FETCH_SUCCESS,
|
||||
EMOJI_REACTS_FETCH_FAIL,
|
||||
simpleEmojiReact,
|
||||
fetchEmojiReacts,
|
||||
emojiReact,
|
||||
unEmojiReact,
|
||||
fetchEmojiReactsRequest,
|
||||
fetchEmojiReactsSuccess,
|
||||
fetchEmojiReactsFail,
|
||||
emojiReactRequest,
|
||||
emojiReactSuccess,
|
||||
emojiReactFail,
|
||||
unEmojiReactRequest,
|
||||
unEmojiReactSuccess,
|
||||
unEmojiReactFail,
|
||||
};
|
|
@ -1,123 +0,0 @@
|
|||
import KVStore from 'soapbox/storage/kv_store';
|
||||
import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { loadCredentials } from './auth';
|
||||
import { importFetchedAccount } from './importer';
|
||||
|
||||
export const ME_FETCH_REQUEST = 'ME_FETCH_REQUEST';
|
||||
export const ME_FETCH_SUCCESS = 'ME_FETCH_SUCCESS';
|
||||
export const ME_FETCH_FAIL = 'ME_FETCH_FAIL';
|
||||
export const ME_FETCH_SKIP = 'ME_FETCH_SKIP';
|
||||
|
||||
export const ME_PATCH_REQUEST = 'ME_PATCH_REQUEST';
|
||||
export const ME_PATCH_SUCCESS = 'ME_PATCH_SUCCESS';
|
||||
export const ME_PATCH_FAIL = 'ME_PATCH_FAIL';
|
||||
|
||||
const noOp = () => new Promise(f => f());
|
||||
|
||||
const getMeId = state => state.get('me') || getAuthUserId(state);
|
||||
|
||||
const getMeUrl = state => {
|
||||
const accountId = getMeId(state);
|
||||
return state.getIn(['accounts', accountId, 'url']) || getAuthUserUrl(state);
|
||||
};
|
||||
|
||||
const getMeToken = state => {
|
||||
// Fallback for upgrading IDs to URLs
|
||||
const accountUrl = getMeUrl(state) || state.getIn(['auth', 'me']);
|
||||
return state.getIn(['auth', 'users', accountUrl, 'access_token']);
|
||||
};
|
||||
|
||||
export function fetchMe() {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const token = getMeToken(state);
|
||||
const accountUrl = getMeUrl(state);
|
||||
|
||||
if (!token) {
|
||||
dispatch({ type: ME_FETCH_SKIP }); return noOp();
|
||||
}
|
||||
|
||||
dispatch(fetchMeRequest());
|
||||
return dispatch(loadCredentials(token, accountUrl)).catch(error => {
|
||||
dispatch(fetchMeFail(error));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/** Update the auth account in IndexedDB for Mastodon, etc. */
|
||||
const persistAuthAccount = (account, params) => {
|
||||
if (account && account.url) {
|
||||
if (!account.pleroma) account.pleroma = {};
|
||||
|
||||
if (!account.pleroma.settings_store) {
|
||||
account.pleroma.settings_store = params.pleroma_settings_store || {};
|
||||
}
|
||||
KVStore.setItem(`authAccount:${account.url}`, account).catch(console.error);
|
||||
}
|
||||
};
|
||||
|
||||
export function patchMe(params) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(patchMeRequest());
|
||||
|
||||
return api(getState)
|
||||
.patch('/api/v1/accounts/update_credentials', params)
|
||||
.then(response => {
|
||||
persistAuthAccount(response.data, params);
|
||||
dispatch(patchMeSuccess(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(patchMeFail(error));
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMeRequest() {
|
||||
return {
|
||||
type: ME_FETCH_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMeSuccess(me) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: ME_FETCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMeFail(error) {
|
||||
return {
|
||||
type: ME_FETCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function patchMeRequest() {
|
||||
return {
|
||||
type: ME_PATCH_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function patchMeSuccess(me) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function patchMeFail(error) {
|
||||
return {
|
||||
type: ME_PATCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
import KVStore from 'soapbox/storage/kv_store';
|
||||
import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth';
|
||||
|
||||
import api from '../api';
|
||||
|
||||
import { loadCredentials } from './auth';
|
||||
import { importFetchedAccount } from './importer';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity } from 'soapbox/types/entities';
|
||||
|
||||
const ME_FETCH_REQUEST = 'ME_FETCH_REQUEST';
|
||||
const ME_FETCH_SUCCESS = 'ME_FETCH_SUCCESS';
|
||||
const ME_FETCH_FAIL = 'ME_FETCH_FAIL';
|
||||
const ME_FETCH_SKIP = 'ME_FETCH_SKIP';
|
||||
|
||||
const ME_PATCH_REQUEST = 'ME_PATCH_REQUEST';
|
||||
const ME_PATCH_SUCCESS = 'ME_PATCH_SUCCESS';
|
||||
const ME_PATCH_FAIL = 'ME_PATCH_FAIL';
|
||||
|
||||
const noOp = () => new Promise(f => f(undefined));
|
||||
|
||||
const getMeId = (state: RootState) => state.me || getAuthUserId(state);
|
||||
|
||||
const getMeUrl = (state: RootState) => {
|
||||
const accountId = getMeId(state);
|
||||
return state.accounts.get(accountId)!.url || getAuthUserUrl(state);
|
||||
};
|
||||
|
||||
const getMeToken = (state: RootState) => {
|
||||
// Fallback for upgrading IDs to URLs
|
||||
const accountUrl = getMeUrl(state) || state.auth.get('me');
|
||||
return state.auth.getIn(['users', accountUrl, 'access_token']);
|
||||
};
|
||||
|
||||
const fetchMe = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const token = getMeToken(state);
|
||||
const accountUrl = getMeUrl(state);
|
||||
|
||||
if (!token) {
|
||||
dispatch({ type: ME_FETCH_SKIP }); return noOp();
|
||||
}
|
||||
|
||||
dispatch(fetchMeRequest());
|
||||
return dispatch(loadCredentials(token, accountUrl)).catch(error => {
|
||||
dispatch(fetchMeFail(error));
|
||||
});
|
||||
};
|
||||
|
||||
/** Update the auth account in IndexedDB for Mastodon, etc. */
|
||||
const persistAuthAccount = (account: APIEntity, params: Record<string, any>) => {
|
||||
if (account && account.url) {
|
||||
if (!account.pleroma) account.pleroma = {};
|
||||
|
||||
if (!account.pleroma.settings_store) {
|
||||
account.pleroma.settings_store = params.pleroma_settings_store || {};
|
||||
}
|
||||
KVStore.setItem(`authAccount:${account.url}`, account).catch(console.error);
|
||||
}
|
||||
};
|
||||
|
||||
const patchMe = (params: Record<string, any>) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch(patchMeRequest());
|
||||
|
||||
return api(getState)
|
||||
.patch('/api/v1/accounts/update_credentials', params)
|
||||
.then(response => {
|
||||
persistAuthAccount(response.data, params);
|
||||
dispatch(patchMeSuccess(response.data));
|
||||
}).catch(error => {
|
||||
dispatch(patchMeFail(error));
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
const fetchMeRequest = () => ({
|
||||
type: ME_FETCH_REQUEST,
|
||||
});
|
||||
|
||||
const fetchMeSuccess = (me: APIEntity) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({
|
||||
type: ME_FETCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
};
|
||||
|
||||
const fetchMeFail = (error: APIEntity) => ({
|
||||
type: ME_FETCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
});
|
||||
|
||||
const patchMeRequest = () => ({
|
||||
type: ME_PATCH_REQUEST,
|
||||
});
|
||||
|
||||
const patchMeSuccess = (me: APIEntity) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
};
|
||||
|
||||
const patchMeFail = (error: AxiosError) => ({
|
||||
type: ME_PATCH_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
});
|
||||
|
||||
export {
|
||||
ME_FETCH_REQUEST,
|
||||
ME_FETCH_SUCCESS,
|
||||
ME_FETCH_FAIL,
|
||||
ME_FETCH_SKIP,
|
||||
ME_PATCH_REQUEST,
|
||||
ME_PATCH_SUCCESS,
|
||||
ME_PATCH_FAIL,
|
||||
fetchMe,
|
||||
patchMe,
|
||||
fetchMeRequest,
|
||||
fetchMeSuccess,
|
||||
fetchMeFail,
|
||||
patchMeRequest,
|
||||
patchMeSuccess,
|
||||
patchMeFail,
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
import api from '../api';
|
||||
|
||||
export const MFA_FETCH_REQUEST = 'MFA_FETCH_REQUEST';
|
||||
export const MFA_FETCH_SUCCESS = 'MFA_FETCH_SUCCESS';
|
||||
export const MFA_FETCH_FAIL = 'MFA_FETCH_FAIL';
|
||||
|
||||
export const MFA_BACKUP_CODES_FETCH_REQUEST = 'MFA_BACKUP_CODES_FETCH_REQUEST';
|
||||
export const MFA_BACKUP_CODES_FETCH_SUCCESS = 'MFA_BACKUP_CODES_FETCH_SUCCESS';
|
||||
export const MFA_BACKUP_CODES_FETCH_FAIL = 'MFA_BACKUP_CODES_FETCH_FAIL';
|
||||
|
||||
export const MFA_SETUP_REQUEST = 'MFA_SETUP_REQUEST';
|
||||
export const MFA_SETUP_SUCCESS = 'MFA_SETUP_SUCCESS';
|
||||
export const MFA_SETUP_FAIL = 'MFA_SETUP_FAIL';
|
||||
|
||||
export const MFA_CONFIRM_REQUEST = 'MFA_CONFIRM_REQUEST';
|
||||
export const MFA_CONFIRM_SUCCESS = 'MFA_CONFIRM_SUCCESS';
|
||||
export const MFA_CONFIRM_FAIL = 'MFA_CONFIRM_FAIL';
|
||||
|
||||
export const MFA_DISABLE_REQUEST = 'MFA_DISABLE_REQUEST';
|
||||
export const MFA_DISABLE_SUCCESS = 'MFA_DISABLE_SUCCESS';
|
||||
export const MFA_DISABLE_FAIL = 'MFA_DISABLE_FAIL';
|
||||
|
||||
export function fetchMfa() {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: MFA_FETCH_REQUEST });
|
||||
return api(getState).get('/api/pleroma/accounts/mfa').then(({ data }) => {
|
||||
dispatch({ type: MFA_FETCH_SUCCESS, data });
|
||||
}).catch(error => {
|
||||
dispatch({ type: MFA_FETCH_FAIL });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBackupCodes() {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_REQUEST });
|
||||
return api(getState).get('/api/pleroma/accounts/mfa/backup_codes').then(({ data }) => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_SUCCESS, data });
|
||||
return data;
|
||||
}).catch(error => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_FAIL });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function setupMfa(method) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: MFA_SETUP_REQUEST, method });
|
||||
return api(getState).get(`/api/pleroma/accounts/mfa/setup/${method}`).then(({ data }) => {
|
||||
dispatch({ type: MFA_SETUP_SUCCESS, data });
|
||||
return data;
|
||||
}).catch(error => {
|
||||
dispatch({ type: MFA_SETUP_FAIL });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function confirmMfa(method, code, password) {
|
||||
return (dispatch, getState) => {
|
||||
const params = { code, password };
|
||||
dispatch({ type: MFA_CONFIRM_REQUEST, method, code });
|
||||
return api(getState).post(`/api/pleroma/accounts/mfa/confirm/${method}`, params).then(({ data }) => {
|
||||
dispatch({ type: MFA_CONFIRM_SUCCESS, method, code });
|
||||
return data;
|
||||
}).catch(error => {
|
||||
dispatch({ type: MFA_CONFIRM_FAIL, method, code, error, skipAlert: true });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function disableMfa(method, password) {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: MFA_DISABLE_REQUEST, method });
|
||||
return api(getState).delete(`/api/pleroma/accounts/mfa/${method}`, { data: { password } }).then(({ data }) => {
|
||||
dispatch({ type: MFA_DISABLE_SUCCESS, method });
|
||||
return data;
|
||||
}).catch(error => {
|
||||
dispatch({ type: MFA_DISABLE_FAIL, method, skipAlert: true });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
import api from '../api';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
|
||||
const MFA_FETCH_REQUEST = 'MFA_FETCH_REQUEST';
|
||||
const MFA_FETCH_SUCCESS = 'MFA_FETCH_SUCCESS';
|
||||
const MFA_FETCH_FAIL = 'MFA_FETCH_FAIL';
|
||||
|
||||
const MFA_BACKUP_CODES_FETCH_REQUEST = 'MFA_BACKUP_CODES_FETCH_REQUEST';
|
||||
const MFA_BACKUP_CODES_FETCH_SUCCESS = 'MFA_BACKUP_CODES_FETCH_SUCCESS';
|
||||
const MFA_BACKUP_CODES_FETCH_FAIL = 'MFA_BACKUP_CODES_FETCH_FAIL';
|
||||
|
||||
const MFA_SETUP_REQUEST = 'MFA_SETUP_REQUEST';
|
||||
const MFA_SETUP_SUCCESS = 'MFA_SETUP_SUCCESS';
|
||||
const MFA_SETUP_FAIL = 'MFA_SETUP_FAIL';
|
||||
|
||||
const MFA_CONFIRM_REQUEST = 'MFA_CONFIRM_REQUEST';
|
||||
const MFA_CONFIRM_SUCCESS = 'MFA_CONFIRM_SUCCESS';
|
||||
const MFA_CONFIRM_FAIL = 'MFA_CONFIRM_FAIL';
|
||||
|
||||
const MFA_DISABLE_REQUEST = 'MFA_DISABLE_REQUEST';
|
||||
const MFA_DISABLE_SUCCESS = 'MFA_DISABLE_SUCCESS';
|
||||
const MFA_DISABLE_FAIL = 'MFA_DISABLE_FAIL';
|
||||
|
||||
const fetchMfa = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: MFA_FETCH_REQUEST });
|
||||
return api(getState).get('/api/pleroma/accounts/mfa').then(({ data }) => {
|
||||
dispatch({ type: MFA_FETCH_SUCCESS, data });
|
||||
}).catch(() => {
|
||||
dispatch({ type: MFA_FETCH_FAIL });
|
||||
});
|
||||
};
|
||||
|
||||
const fetchBackupCodes = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_REQUEST });
|
||||
return api(getState).get('/api/pleroma/accounts/mfa/backup_codes').then(({ data }) => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_SUCCESS, data });
|
||||
return data;
|
||||
}).catch(() => {
|
||||
dispatch({ type: MFA_BACKUP_CODES_FETCH_FAIL });
|
||||
});
|
||||
};
|
||||
|
||||
const setupMfa = (method: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: MFA_SETUP_REQUEST, method });
|
||||
return api(getState).get(`/api/pleroma/accounts/mfa/setup/${method}`).then(({ data }) => {
|
||||
dispatch({ type: MFA_SETUP_SUCCESS, data });
|
||||
return data;
|
||||
}).catch((error: AxiosError) => {
|
||||
dispatch({ type: MFA_SETUP_FAIL });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
const confirmMfa = (method: string, code: string, password: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const params = { code, password };
|
||||
dispatch({ type: MFA_CONFIRM_REQUEST, method, code });
|
||||
return api(getState).post(`/api/pleroma/accounts/mfa/confirm/${method}`, params).then(({ data }) => {
|
||||
dispatch({ type: MFA_CONFIRM_SUCCESS, method, code });
|
||||
return data;
|
||||
}).catch((error: AxiosError) => {
|
||||
dispatch({ type: MFA_CONFIRM_FAIL, method, code, error, skipAlert: true });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
const disableMfa = (method: string, password: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: MFA_DISABLE_REQUEST, method });
|
||||
return api(getState).delete(`/api/pleroma/accounts/mfa/${method}`, { data: { password } }).then(({ data }) => {
|
||||
dispatch({ type: MFA_DISABLE_SUCCESS, method });
|
||||
return data;
|
||||
}).catch((error: AxiosError) => {
|
||||
dispatch({ type: MFA_DISABLE_FAIL, method, skipAlert: true });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
MFA_FETCH_REQUEST,
|
||||
MFA_FETCH_SUCCESS,
|
||||
MFA_FETCH_FAIL,
|
||||
MFA_BACKUP_CODES_FETCH_REQUEST,
|
||||
MFA_BACKUP_CODES_FETCH_SUCCESS,
|
||||
MFA_BACKUP_CODES_FETCH_FAIL,
|
||||
MFA_SETUP_REQUEST,
|
||||
MFA_SETUP_SUCCESS,
|
||||
MFA_SETUP_FAIL,
|
||||
MFA_CONFIRM_REQUEST,
|
||||
MFA_CONFIRM_SUCCESS,
|
||||
MFA_CONFIRM_FAIL,
|
||||
MFA_DISABLE_REQUEST,
|
||||
MFA_DISABLE_SUCCESS,
|
||||
MFA_DISABLE_FAIL,
|
||||
fetchMfa,
|
||||
fetchBackupCodes,
|
||||
setupMfa,
|
||||
confirmMfa,
|
||||
disableMfa,
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { defineMessages } from 'react-intl';
|
||||
import { defineMessages, IntlShape } from 'react-intl';
|
||||
|
||||
import { fetchAccountByUsername } from 'soapbox/actions/accounts';
|
||||
import { deactivateUsers, deleteUsers, deleteStatus, toggleStatusSensitivity } from 'soapbox/actions/admin';
|
||||
|
@ -8,6 +8,8 @@ import snackbar from 'soapbox/actions/snackbar';
|
|||
import AccountContainer from 'soapbox/containers/account_container';
|
||||
import { isLocal } from 'soapbox/utils/accounts';
|
||||
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
|
||||
const messages = defineMessages({
|
||||
deactivateUserHeading: { id: 'confirmations.admin.deactivate_user.heading', defaultMessage: 'Deactivate @{acct}' },
|
||||
deactivateUserPrompt: { id: 'confirmations.admin.deactivate_user.message', defaultMessage: 'You are about to deactivate @{acct}. Deactivating a user is a reversible action.' },
|
||||
|
@ -35,11 +37,11 @@ const messages = defineMessages({
|
|||
statusMarkedNotSensitive: { id: 'admin.statuses.status_marked_message_not_sensitive', defaultMessage: 'Post by @{acct} was marked not sensitive' },
|
||||
});
|
||||
|
||||
export function deactivateUserModal(intl, accountId, afterConfirm = () => {}) {
|
||||
return function(dispatch, getState) {
|
||||
const deactivateUserModal = (intl: IntlShape, accountId: string, afterConfirm = () => {}) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const acct = state.getIn(['accounts', accountId, 'acct']);
|
||||
const name = state.getIn(['accounts', accountId, 'username']);
|
||||
const acct = state.accounts.get(accountId)!.acct;
|
||||
const name = state.accounts.get(accountId)!.username;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
icon: require('@tabler/icons/icons/user-off.svg'),
|
||||
|
@ -55,15 +57,15 @@ export function deactivateUserModal(intl, accountId, afterConfirm = () => {}) {
|
|||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteUserModal(intl, accountId, afterConfirm = () => {}) {
|
||||
return function(dispatch, getState) {
|
||||
const deleteUserModal = (intl: IntlShape, accountId: string, afterConfirm = () => {}) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const acct = state.getIn(['accounts', accountId, 'acct']);
|
||||
const name = state.getIn(['accounts', accountId, 'username']);
|
||||
const favicon = state.getIn(['accounts', accountId, 'pleroma', 'favicon']);
|
||||
const local = isLocal(state.getIn(['accounts', accountId]));
|
||||
const account = state.accounts.get(accountId)!;
|
||||
const acct = account.acct;
|
||||
const name = account.username;
|
||||
const favicon = account.pleroma.get('favicon');
|
||||
const local = isLocal(account);
|
||||
|
||||
const message = (<>
|
||||
<AccountContainer id={accountId} />
|
||||
|
@ -96,13 +98,12 @@ export function deleteUserModal(intl, accountId, afterConfirm = () => {}) {
|
|||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function rejectUserModal(intl, accountId, afterConfirm = () => {}) {
|
||||
return function(dispatch, getState) {
|
||||
const rejectUserModal = (intl: IntlShape, accountId: string, afterConfirm = () => {}) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const acct = state.getIn(['accounts', accountId, 'acct']);
|
||||
const name = state.getIn(['accounts', accountId, 'username']);
|
||||
const acct = state.accounts.get(accountId)!.acct;
|
||||
const name = state.accounts.get(accountId)!.username;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
icon: require('@tabler/icons/icons/user-off.svg'),
|
||||
|
@ -118,13 +119,12 @@ export function rejectUserModal(intl, accountId, afterConfirm = () => {}) {
|
|||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleStatusSensitivityModal(intl, statusId, sensitive, afterConfirm = () => {}) {
|
||||
return function(dispatch, getState) {
|
||||
const toggleStatusSensitivityModal = (intl: IntlShape, statusId: string, sensitive: boolean, afterConfirm = () => {}) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const accountId = state.getIn(['statuses', statusId, 'account']);
|
||||
const acct = state.getIn(['accounts', accountId, 'acct']);
|
||||
const accountId = state.statuses.get(statusId)!.account;
|
||||
const acct = state.accounts.get(accountId)!.acct;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
icon: require('@tabler/icons/icons/alert-triangle.svg'),
|
||||
|
@ -140,13 +140,12 @@ export function toggleStatusSensitivityModal(intl, statusId, sensitive, afterCon
|
|||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteStatusModal(intl, statusId, afterConfirm = () => {}) {
|
||||
return function(dispatch, getState) {
|
||||
const deleteStatusModal = (intl: IntlShape, statusId: string, afterConfirm = () => {}) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const accountId = state.getIn(['statuses', statusId, 'account']);
|
||||
const acct = state.getIn(['accounts', accountId, 'acct']);
|
||||
const accountId = state.statuses.get(statusId)!.account;
|
||||
const acct = state.accounts.get(accountId)!.acct;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
icon: require('@tabler/icons/icons/trash.svg'),
|
||||
|
@ -162,4 +161,12 @@ export function deleteStatusModal(intl, statusId, afterConfirm = () => {}) {
|
|||
},
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export {
|
||||
deactivateUserModal,
|
||||
deleteUserModal,
|
||||
rejectUserModal,
|
||||
toggleStatusSensitivityModal,
|
||||
deleteStatusModal,
|
||||
};
|
|
@ -1,116 +0,0 @@
|
|||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getNextLinkName } from 'soapbox/utils/quirks';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
import { openModal } from './modals';
|
||||
|
||||
export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
|
||||
export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
|
||||
export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL';
|
||||
|
||||
export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST';
|
||||
export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
|
||||
export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
|
||||
|
||||
export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
|
||||
export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS';
|
||||
|
||||
export function fetchMutes() {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
dispatch(fetchMutesRequest());
|
||||
|
||||
api(getState).get('/api/v1/mutes').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)));
|
||||
}).catch(error => dispatch(fetchMutesFail(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMutesRequest() {
|
||||
return {
|
||||
type: MUTES_FETCH_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMutesSuccess(accounts, next) {
|
||||
return {
|
||||
type: MUTES_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMutesFail(error) {
|
||||
return {
|
||||
type: MUTES_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandMutes() {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
const url = getState().getIn(['user_lists', 'mutes', 'next']);
|
||||
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(expandMutesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)));
|
||||
}).catch(error => dispatch(expandMutesFail(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function expandMutesRequest() {
|
||||
return {
|
||||
type: MUTES_EXPAND_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandMutesSuccess(accounts, next) {
|
||||
return {
|
||||
type: MUTES_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandMutesFail(error) {
|
||||
return {
|
||||
type: MUTES_EXPAND_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function initMuteModal(account) {
|
||||
return dispatch => {
|
||||
dispatch({
|
||||
type: MUTES_INIT_MODAL,
|
||||
account,
|
||||
});
|
||||
|
||||
dispatch(openModal('MUTE'));
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleHideNotifications() {
|
||||
return dispatch => {
|
||||
dispatch({ type: MUTES_TOGGLE_HIDE_NOTIFICATIONS });
|
||||
};
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getNextLinkName } from 'soapbox/utils/quirks';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
import { openModal } from './modals';
|
||||
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity, Account as AccountEntity } from 'soapbox/types/entities';
|
||||
|
||||
const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
|
||||
const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
|
||||
const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL';
|
||||
|
||||
const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST';
|
||||
const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
|
||||
const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
|
||||
|
||||
const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
|
||||
const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS';
|
||||
|
||||
const fetchMutes = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
dispatch(fetchMutesRequest());
|
||||
|
||||
api(getState).get('/api/v1/mutes').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
}).catch(error => dispatch(fetchMutesFail(error)));
|
||||
};
|
||||
|
||||
const fetchMutesRequest = () => ({
|
||||
type: MUTES_FETCH_REQUEST,
|
||||
});
|
||||
|
||||
const fetchMutesSuccess = (accounts: APIEntity[], next: string | null) => ({
|
||||
type: MUTES_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const fetchMutesFail = (error: AxiosError) => ({
|
||||
type: MUTES_FETCH_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
const expandMutes = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
const url = getState().user_lists.getIn(['mutes', 'next']);
|
||||
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(expandMutesRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id)));
|
||||
}).catch(error => dispatch(expandMutesFail(error)));
|
||||
};
|
||||
|
||||
const expandMutesRequest = () => ({
|
||||
type: MUTES_EXPAND_REQUEST,
|
||||
});
|
||||
|
||||
const expandMutesSuccess = (accounts: APIEntity[], next: string | null) => ({
|
||||
type: MUTES_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
});
|
||||
|
||||
const expandMutesFail = (error: AxiosError) => ({
|
||||
type: MUTES_EXPAND_FAIL,
|
||||
error,
|
||||
});
|
||||
|
||||
const initMuteModal = (account: AccountEntity) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({
|
||||
type: MUTES_INIT_MODAL,
|
||||
account,
|
||||
});
|
||||
|
||||
dispatch(openModal('MUTE'));
|
||||
};
|
||||
|
||||
const toggleHideNotifications = () =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({ type: MUTES_TOGGLE_HIDE_NOTIFICATIONS });
|
||||
};
|
||||
|
||||
export {
|
||||
MUTES_FETCH_REQUEST,
|
||||
MUTES_FETCH_SUCCESS,
|
||||
MUTES_FETCH_FAIL,
|
||||
MUTES_EXPAND_REQUEST,
|
||||
MUTES_EXPAND_SUCCESS,
|
||||
MUTES_EXPAND_FAIL,
|
||||
MUTES_INIT_MODAL,
|
||||
MUTES_TOGGLE_HIDE_NOTIFICATIONS,
|
||||
fetchMutes,
|
||||
fetchMutesRequest,
|
||||
fetchMutesSuccess,
|
||||
fetchMutesFail,
|
||||
expandMutes,
|
||||
expandMutesRequest,
|
||||
expandMutesSuccess,
|
||||
expandMutesFail,
|
||||
initMuteModal,
|
||||
toggleHideNotifications,
|
||||
};
|
|
@ -1,20 +1,18 @@
|
|||
import {
|
||||
List as ImmutableList,
|
||||
Map as ImmutableMap,
|
||||
OrderedMap as ImmutableOrderedMap,
|
||||
} from 'immutable';
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
import 'intl-pluralrules';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import api, { getLinks } from 'soapbox/api';
|
||||
import { getFilters, regexFromFilters } from 'soapbox/selectors';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { parseVersion, PLEROMA } from 'soapbox/utils/features';
|
||||
import { unescapeHTML } from 'soapbox/utils/html';
|
||||
import { joinPublicPath } from 'soapbox/utils/static';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
import { getFilters, regexFromFilters } from '../selectors';
|
||||
import { unescapeHTML } from '../utils/html';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import {
|
||||
importFetchedAccount,
|
||||
|
@ -25,32 +23,36 @@ import {
|
|||
import { saveMarker } from './markers';
|
||||
import { getSettings, saveSettings } from './settings';
|
||||
|
||||
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
||||
export const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
|
||||
export const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity } from 'soapbox/types/entities';
|
||||
|
||||
export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
|
||||
export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
|
||||
export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
||||
const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
|
||||
const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
|
||||
const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE';
|
||||
const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE';
|
||||
|
||||
export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
|
||||
const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
|
||||
const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
|
||||
const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
|
||||
|
||||
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||
export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||
const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
|
||||
|
||||
export const NOTIFICATIONS_MARK_READ_REQUEST = 'NOTIFICATIONS_MARK_READ_REQUEST';
|
||||
export const NOTIFICATIONS_MARK_READ_SUCCESS = 'NOTIFICATIONS_MARK_READ_SUCCESS';
|
||||
export const NOTIFICATIONS_MARK_READ_FAIL = 'NOTIFICATIONS_MARK_READ_FAIL';
|
||||
const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
|
||||
const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||
|
||||
export const MAX_QUEUED_NOTIFICATIONS = 40;
|
||||
const NOTIFICATIONS_MARK_READ_REQUEST = 'NOTIFICATIONS_MARK_READ_REQUEST';
|
||||
const NOTIFICATIONS_MARK_READ_SUCCESS = 'NOTIFICATIONS_MARK_READ_SUCCESS';
|
||||
const NOTIFICATIONS_MARK_READ_FAIL = 'NOTIFICATIONS_MARK_READ_FAIL';
|
||||
|
||||
const MAX_QUEUED_NOTIFICATIONS = 40;
|
||||
|
||||
defineMessages({
|
||||
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
|
||||
group: { id: 'notifications.group', defaultMessage: '{count} notifications' },
|
||||
});
|
||||
|
||||
const fetchRelatedRelationships = (dispatch, notifications) => {
|
||||
const fetchRelatedRelationships = (dispatch: AppDispatch, notifications: APIEntity[]) => {
|
||||
const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id);
|
||||
|
||||
if (accountIds.length > 0) {
|
||||
|
@ -58,8 +60,8 @@ const fetchRelatedRelationships = (dispatch, notifications) => {
|
|||
}
|
||||
};
|
||||
|
||||
export function updateNotifications(notification, intlMessages, intlLocale) {
|
||||
return (dispatch, getState) => {
|
||||
const updateNotifications = (notification: APIEntity) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const showInColumn = getSettings(getState()).getIn(['notifications', 'shows', notification.type], true);
|
||||
|
||||
if (notification.account) {
|
||||
|
@ -84,17 +86,16 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
|
|||
fetchRelatedRelationships(dispatch, [notification]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function updateNotificationsQueue(notification, intlMessages, intlLocale, curPath) {
|
||||
return (dispatch, getState) => {
|
||||
const updateNotificationsQueue = (notification: APIEntity, intlMessages: Record<string, string>, intlLocale: string, curPath: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (notification.type === 'pleroma:chat_mention') return; // Drop chat notifications, handle them per-chat
|
||||
|
||||
const showAlert = getSettings(getState()).getIn(['notifications', 'alerts', notification.type]);
|
||||
const filters = getFilters(getState(), { contextType: 'notifications' });
|
||||
const playSound = getSettings(getState()).getIn(['notifications', 'sounds', notification.type]);
|
||||
|
||||
let filtered = false;
|
||||
let filtered: boolean | null = false;
|
||||
|
||||
const isOnNotificationsPage = curPath === '/notifications';
|
||||
|
||||
|
@ -140,21 +141,20 @@ export function updateNotificationsQueue(notification, intlMessages, intlLocale,
|
|||
intlLocale,
|
||||
});
|
||||
} else {
|
||||
dispatch(updateNotifications(notification, intlMessages, intlLocale));
|
||||
dispatch(updateNotifications(notification));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function dequeueNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
const queuedNotifications = getState().getIn(['notifications', 'queuedNotifications'], ImmutableOrderedMap());
|
||||
const totalQueuedNotificationsCount = getState().getIn(['notifications', 'totalQueuedNotificationsCount'], 0);
|
||||
const dequeueNotifications = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const queuedNotifications = getState().notifications.get('queuedNotifications');
|
||||
const totalQueuedNotificationsCount = getState().notifications.get('totalQueuedNotificationsCount');
|
||||
|
||||
if (totalQueuedNotificationsCount === 0) {
|
||||
return;
|
||||
} else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
||||
queuedNotifications.forEach(block => {
|
||||
dispatch(updateNotifications(block.notification, block.intlMessages, block.intlLocale));
|
||||
queuedNotifications.forEach((block: APIEntity) => {
|
||||
dispatch(updateNotifications(block.notification));
|
||||
});
|
||||
} else {
|
||||
dispatch(expandNotifications());
|
||||
|
@ -165,23 +165,22 @@ export function dequeueNotifications() {
|
|||
});
|
||||
dispatch(markReadNotifications());
|
||||
};
|
||||
}
|
||||
|
||||
const excludeTypesFromSettings = getState => getSettings(getState()).getIn(['notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
|
||||
const excludeTypesFromSettings = (getState: () => RootState) => (getSettings(getState()).getIn(['notifications', 'shows']) as ImmutableMap<string, boolean>).filter(enabled => !enabled).keySeq().toJS();
|
||||
|
||||
const excludeTypesFromFilter = filter => {
|
||||
const excludeTypesFromFilter = (filter: string) => {
|
||||
const allTypes = ImmutableList(['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'status', 'poll', 'move', 'pleroma:emoji_reaction']);
|
||||
return allTypes.filterNot(item => item === filter).toJS();
|
||||
};
|
||||
|
||||
const noOp = () => {};
|
||||
|
||||
export function expandNotifications({ maxId } = {}, done = noOp) {
|
||||
return (dispatch, getState) => {
|
||||
const expandNotifications = ({ maxId }: Record<string, any> = {}, done = noOp) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return dispatch(noOp);
|
||||
|
||||
const activeFilter = getSettings(getState()).getIn(['notifications', 'quickFilter', 'active']);
|
||||
const notifications = getState().get('notifications');
|
||||
const activeFilter = getSettings(getState()).getIn(['notifications', 'quickFilter', 'active']) as string;
|
||||
const notifications = getState().notifications;
|
||||
const isLoadingMore = !!maxId;
|
||||
|
||||
if (notifications.get('isLoading')) {
|
||||
|
@ -189,7 +188,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
|||
return dispatch(noOp);
|
||||
}
|
||||
|
||||
const params = {
|
||||
const params: Record<string, any> = {
|
||||
max_id: maxId,
|
||||
exclude_types: activeFilter === 'all'
|
||||
? excludeTypesFromSettings(getState)
|
||||
|
@ -205,7 +204,7 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
|||
return api(getState).get('/api/v1/notifications', { params }).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === 'next');
|
||||
|
||||
const entries = response.data.reduce((acc, item) => {
|
||||
const entries = (response.data as APIEntity[]).reduce((acc, item) => {
|
||||
if (item.account?.id) {
|
||||
acc.accounts[item.account.id] = item.account;
|
||||
}
|
||||
|
@ -233,34 +232,27 @@ export function expandNotifications({ maxId } = {}, done = noOp) {
|
|||
done();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function expandNotificationsRequest(isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
}
|
||||
const expandNotificationsRequest = (isLoadingMore: boolean) => ({
|
||||
type: NOTIFICATIONS_EXPAND_REQUEST,
|
||||
skipLoading: !isLoadingMore,
|
||||
});
|
||||
|
||||
export function expandNotificationsSuccess(notifications, next, isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
notifications,
|
||||
next,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
}
|
||||
const expandNotificationsSuccess = (notifications: APIEntity[], next: string | null, isLoadingMore: boolean) => ({
|
||||
type: NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
notifications,
|
||||
next,
|
||||
skipLoading: !isLoadingMore,
|
||||
});
|
||||
|
||||
export function expandNotificationsFail(error, isLoadingMore) {
|
||||
return {
|
||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
};
|
||||
}
|
||||
const expandNotificationsFail = (error: AxiosError, isLoadingMore: boolean) => ({
|
||||
type: NOTIFICATIONS_EXPAND_FAIL,
|
||||
error,
|
||||
skipLoading: !isLoadingMore,
|
||||
});
|
||||
|
||||
export function clearNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
const clearNotifications = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
dispatch({
|
||||
|
@ -269,20 +261,18 @@ export function clearNotifications() {
|
|||
|
||||
api(getState).post('/api/v1/notifications/clear');
|
||||
};
|
||||
}
|
||||
|
||||
export function scrollTopNotifications(top) {
|
||||
return (dispatch, getState) => {
|
||||
const scrollTopNotifications = (top: boolean) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_SCROLL_TOP,
|
||||
top,
|
||||
});
|
||||
dispatch(markReadNotifications());
|
||||
};
|
||||
}
|
||||
|
||||
export function setFilter(filterType) {
|
||||
return dispatch => {
|
||||
const setFilter = (filterType: string) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({
|
||||
type: NOTIFICATIONS_FILTER_SET,
|
||||
path: ['notifications', 'quickFilter', 'active'],
|
||||
|
@ -291,25 +281,23 @@ export function setFilter(filterType) {
|
|||
dispatch(expandNotifications());
|
||||
dispatch(saveSettings());
|
||||
};
|
||||
}
|
||||
|
||||
// Of course Markers don't work properly in Pleroma.
|
||||
// https://git.pleroma.social/pleroma/pleroma/-/issues/2769
|
||||
export function markReadPleroma(max_id) {
|
||||
return (dispatch, getState) => {
|
||||
const markReadPleroma = (max_id: string | number) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
return api(getState).post('/api/v1/pleroma/notifications/read', { max_id });
|
||||
};
|
||||
}
|
||||
|
||||
export function markReadNotifications() {
|
||||
return (dispatch, getState) => {
|
||||
const markReadNotifications = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const state = getState();
|
||||
const instance = state.get('instance');
|
||||
const topNotificationId = state.getIn(['notifications', 'items'], ImmutableOrderedMap()).first(ImmutableMap()).get('id');
|
||||
const lastReadId = state.getIn(['notifications', 'lastRead']);
|
||||
const v = parseVersion(instance.get('version'));
|
||||
const instance = state.instance;
|
||||
const topNotificationId = state.notifications.get('items').first(ImmutableMap()).get('id');
|
||||
const lastReadId = state.notifications.get('lastRead');
|
||||
const v = parseVersion(instance.version);
|
||||
|
||||
if (!(topNotificationId && topNotificationId > lastReadId)) return;
|
||||
|
||||
|
@ -325,4 +313,32 @@ export function markReadNotifications() {
|
|||
dispatch(markReadPleroma(topNotificationId));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
NOTIFICATIONS_UPDATE,
|
||||
NOTIFICATIONS_UPDATE_NOOP,
|
||||
NOTIFICATIONS_UPDATE_QUEUE,
|
||||
NOTIFICATIONS_DEQUEUE,
|
||||
NOTIFICATIONS_EXPAND_REQUEST,
|
||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||
NOTIFICATIONS_EXPAND_FAIL,
|
||||
NOTIFICATIONS_FILTER_SET,
|
||||
NOTIFICATIONS_CLEAR,
|
||||
NOTIFICATIONS_SCROLL_TOP,
|
||||
NOTIFICATIONS_MARK_READ_REQUEST,
|
||||
NOTIFICATIONS_MARK_READ_SUCCESS,
|
||||
NOTIFICATIONS_MARK_READ_FAIL,
|
||||
MAX_QUEUED_NOTIFICATIONS,
|
||||
updateNotifications,
|
||||
updateNotificationsQueue,
|
||||
dequeueNotifications,
|
||||
expandNotifications,
|
||||
expandNotificationsRequest,
|
||||
expandNotificationsSuccess,
|
||||
expandNotificationsFail,
|
||||
clearNotifications,
|
||||
scrollTopNotifications,
|
||||
setFilter,
|
||||
markReadPleroma,
|
||||
markReadNotifications,
|
||||
};
|
|
@ -3,32 +3,34 @@ import mapValues from 'lodash/mapValues';
|
|||
import { verifyCredentials } from './auth';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
|
||||
export const PLEROMA_PRELOAD_IMPORT = 'PLEROMA_PRELOAD_IMPORT';
|
||||
export const MASTODON_PRELOAD_IMPORT = 'MASTODON_PRELOAD_IMPORT';
|
||||
import type { AppDispatch } from 'soapbox/store';
|
||||
|
||||
const PLEROMA_PRELOAD_IMPORT = 'PLEROMA_PRELOAD_IMPORT';
|
||||
const MASTODON_PRELOAD_IMPORT = 'MASTODON_PRELOAD_IMPORT';
|
||||
|
||||
// https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1176/diffs
|
||||
const decodeUTF8Base64 = data => {
|
||||
const decodeUTF8Base64 = (data: string) => {
|
||||
const rawData = atob(data);
|
||||
const array = Uint8Array.from(rawData.split('').map((char) => char.charCodeAt(0)));
|
||||
const text = new TextDecoder().decode(array);
|
||||
return text;
|
||||
};
|
||||
|
||||
const decodePleromaData = data => {
|
||||
const decodePleromaData = (data: Record<string, any>) => {
|
||||
return mapValues(data, base64string => JSON.parse(decodeUTF8Base64(base64string)));
|
||||
};
|
||||
|
||||
const pleromaDecoder = json => decodePleromaData(JSON.parse(json));
|
||||
const pleromaDecoder = (json: string) => decodePleromaData(JSON.parse(json));
|
||||
|
||||
// This will throw if it fails.
|
||||
// Should be called inside a try-catch.
|
||||
const decodeFromMarkup = (elementId, decoder) => {
|
||||
const { textContent } = document.getElementById(elementId);
|
||||
return decoder(textContent);
|
||||
const decodeFromMarkup = (elementId: string, decoder: (json: string) => Record<string, any>) => {
|
||||
const { textContent } = document.getElementById(elementId)!;
|
||||
return decoder(textContent as string);
|
||||
};
|
||||
|
||||
function preloadFromMarkup(elementId, decoder, action) {
|
||||
return (dispatch, getState) => {
|
||||
const preloadFromMarkup = (elementId: string, decoder: (json: string) => Record<string, any>, action: (data: Record<string, any>) => any) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
try {
|
||||
const data = decodeFromMarkup(elementId, decoder);
|
||||
dispatch(action(data));
|
||||
|
@ -36,24 +38,20 @@ function preloadFromMarkup(elementId, decoder, action) {
|
|||
// Do nothing
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function preload() {
|
||||
return (dispatch, getState) => {
|
||||
const preload = () =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch(preloadFromMarkup('initial-results', pleromaDecoder, preloadPleroma));
|
||||
dispatch(preloadFromMarkup('initial-state', JSON.parse, preloadMastodon));
|
||||
};
|
||||
}
|
||||
|
||||
export function preloadPleroma(data) {
|
||||
return {
|
||||
type: PLEROMA_PRELOAD_IMPORT,
|
||||
data,
|
||||
};
|
||||
}
|
||||
const preloadPleroma = (data: Record<string, any>) => ({
|
||||
type: PLEROMA_PRELOAD_IMPORT,
|
||||
data,
|
||||
});
|
||||
|
||||
export function preloadMastodon(data) {
|
||||
return (dispatch, getState) => {
|
||||
const preloadMastodon = (data: Record<string, any>) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
const { me, access_token } = data.meta;
|
||||
const { url } = data.accounts[me];
|
||||
|
||||
|
@ -61,4 +59,11 @@ export function preloadMastodon(data) {
|
|||
dispatch(verifyCredentials(access_token, url));
|
||||
dispatch({ type: MASTODON_PRELOAD_IMPORT, data });
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
PLEROMA_PRELOAD_IMPORT,
|
||||
MASTODON_PRELOAD_IMPORT,
|
||||
preload,
|
||||
preloadPleroma,
|
||||
preloadMastodon,
|
||||
};
|
|
@ -12,62 +12,62 @@ import api from '../api';
|
|||
|
||||
import { AUTH_LOGGED_OUT, messages } from './auth';
|
||||
|
||||
export const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
|
||||
export const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
|
||||
export const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
|
||||
export const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
|
||||
export const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
|
||||
export const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
|
||||
const FETCH_TOKENS_REQUEST = 'FETCH_TOKENS_REQUEST';
|
||||
const FETCH_TOKENS_SUCCESS = 'FETCH_TOKENS_SUCCESS';
|
||||
const FETCH_TOKENS_FAIL = 'FETCH_TOKENS_FAIL';
|
||||
|
||||
export const RESET_PASSWORD_REQUEST = 'RESET_PASSWORD_REQUEST';
|
||||
export const RESET_PASSWORD_SUCCESS = 'RESET_PASSWORD_SUCCESS';
|
||||
export const RESET_PASSWORD_FAIL = 'RESET_PASSWORD_FAIL';
|
||||
const REVOKE_TOKEN_REQUEST = 'REVOKE_TOKEN_REQUEST';
|
||||
const REVOKE_TOKEN_SUCCESS = 'REVOKE_TOKEN_SUCCESS';
|
||||
const REVOKE_TOKEN_FAIL = 'REVOKE_TOKEN_FAIL';
|
||||
|
||||
export const RESET_PASSWORD_CONFIRM_REQUEST = 'RESET_PASSWORD_CONFIRM_REQUEST';
|
||||
export const RESET_PASSWORD_CONFIRM_SUCCESS = 'RESET_PASSWORD_CONFIRM_SUCCESS';
|
||||
export const RESET_PASSWORD_CONFIRM_FAIL = 'RESET_PASSWORD_CONFIRM_FAIL';
|
||||
const RESET_PASSWORD_REQUEST = 'RESET_PASSWORD_REQUEST';
|
||||
const RESET_PASSWORD_SUCCESS = 'RESET_PASSWORD_SUCCESS';
|
||||
const RESET_PASSWORD_FAIL = 'RESET_PASSWORD_FAIL';
|
||||
|
||||
export const CHANGE_PASSWORD_REQUEST = 'CHANGE_PASSWORD_REQUEST';
|
||||
export const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS';
|
||||
export const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL';
|
||||
const RESET_PASSWORD_CONFIRM_REQUEST = 'RESET_PASSWORD_CONFIRM_REQUEST';
|
||||
const RESET_PASSWORD_CONFIRM_SUCCESS = 'RESET_PASSWORD_CONFIRM_SUCCESS';
|
||||
const RESET_PASSWORD_CONFIRM_FAIL = 'RESET_PASSWORD_CONFIRM_FAIL';
|
||||
|
||||
export const CHANGE_EMAIL_REQUEST = 'CHANGE_EMAIL_REQUEST';
|
||||
export const CHANGE_EMAIL_SUCCESS = 'CHANGE_EMAIL_SUCCESS';
|
||||
export const CHANGE_EMAIL_FAIL = 'CHANGE_EMAIL_FAIL';
|
||||
const CHANGE_PASSWORD_REQUEST = 'CHANGE_PASSWORD_REQUEST';
|
||||
const CHANGE_PASSWORD_SUCCESS = 'CHANGE_PASSWORD_SUCCESS';
|
||||
const CHANGE_PASSWORD_FAIL = 'CHANGE_PASSWORD_FAIL';
|
||||
|
||||
export const DELETE_ACCOUNT_REQUEST = 'DELETE_ACCOUNT_REQUEST';
|
||||
export const DELETE_ACCOUNT_SUCCESS = 'DELETE_ACCOUNT_SUCCESS';
|
||||
export const DELETE_ACCOUNT_FAIL = 'DELETE_ACCOUNT_FAIL';
|
||||
const CHANGE_EMAIL_REQUEST = 'CHANGE_EMAIL_REQUEST';
|
||||
const CHANGE_EMAIL_SUCCESS = 'CHANGE_EMAIL_SUCCESS';
|
||||
const CHANGE_EMAIL_FAIL = 'CHANGE_EMAIL_FAIL';
|
||||
|
||||
export const MOVE_ACCOUNT_REQUEST = 'MOVE_ACCOUNT_REQUEST';
|
||||
export const MOVE_ACCOUNT_SUCCESS = 'MOVE_ACCOUNT_SUCCESS';
|
||||
export const MOVE_ACCOUNT_FAIL = 'MOVE_ACCOUNT_FAIL';
|
||||
const DELETE_ACCOUNT_REQUEST = 'DELETE_ACCOUNT_REQUEST';
|
||||
const DELETE_ACCOUNT_SUCCESS = 'DELETE_ACCOUNT_SUCCESS';
|
||||
const DELETE_ACCOUNT_FAIL = 'DELETE_ACCOUNT_FAIL';
|
||||
|
||||
export function fetchOAuthTokens() {
|
||||
return (dispatch, getState) => {
|
||||
const MOVE_ACCOUNT_REQUEST = 'MOVE_ACCOUNT_REQUEST';
|
||||
const MOVE_ACCOUNT_SUCCESS = 'MOVE_ACCOUNT_SUCCESS';
|
||||
const MOVE_ACCOUNT_FAIL = 'MOVE_ACCOUNT_FAIL';
|
||||
|
||||
const fetchOAuthTokens = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: FETCH_TOKENS_REQUEST });
|
||||
return api(getState).get('/api/oauth_tokens.json').then(({ data: tokens }) => {
|
||||
dispatch({ type: FETCH_TOKENS_SUCCESS, tokens });
|
||||
}).catch(error => {
|
||||
}).catch(() => {
|
||||
dispatch({ type: FETCH_TOKENS_FAIL });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function revokeOAuthTokenById(id) {
|
||||
return (dispatch, getState) => {
|
||||
const revokeOAuthTokenById = (id: number) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: REVOKE_TOKEN_REQUEST, id });
|
||||
return api(getState).delete(`/api/oauth_tokens/${id}`).then(() => {
|
||||
dispatch({ type: REVOKE_TOKEN_SUCCESS, id });
|
||||
}).catch(error => {
|
||||
}).catch(() => {
|
||||
dispatch({ type: REVOKE_TOKEN_FAIL, id });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function changePassword(oldPassword, newPassword, confirmation) {
|
||||
return (dispatch, getState) => {
|
||||
const changePassword = (oldPassword: string, newPassword: string, confirmation: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: CHANGE_PASSWORD_REQUEST });
|
||||
return api(getState).post('/api/pleroma/change_password', {
|
||||
password: oldPassword,
|
||||
|
@ -81,10 +81,9 @@ export function changePassword(oldPassword, newPassword, confirmation) {
|
|||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function resetPassword(usernameOrEmail) {
|
||||
return (dispatch, getState) => {
|
||||
const resetPassword = (usernameOrEmail: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
const v = parseVersion(state.instance.version);
|
||||
|
||||
|
@ -107,10 +106,9 @@ export function resetPassword(usernameOrEmail) {
|
|||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function resetPasswordConfirm(password, token) {
|
||||
return (dispatch, getState) => {
|
||||
const resetPasswordConfirm = (password: string, token: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const params = { password, reset_password_token: token };
|
||||
dispatch({ type: RESET_PASSWORD_CONFIRM_REQUEST });
|
||||
|
||||
|
@ -121,10 +119,9 @@ export function resetPasswordConfirm(password, token) {
|
|||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function changeEmail(email, password) {
|
||||
return (dispatch, getState) => {
|
||||
const changeEmail = (email: string, password: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: CHANGE_EMAIL_REQUEST, email });
|
||||
return api(getState).post('/api/pleroma/change_email', {
|
||||
email,
|
||||
|
@ -137,16 +134,13 @@ export function changeEmail(email, password) {
|
|||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function confirmChangedEmail(token) {
|
||||
return (_dispatch, getState) => {
|
||||
return api(getState).get(`/api/v1/truth/email/confirm?confirmation_token=${token}`);
|
||||
};
|
||||
}
|
||||
const confirmChangedEmail = (token: string) =>
|
||||
(_dispatch: AppDispatch, getState: () => RootState) =>
|
||||
api(getState).get(`/api/v1/truth/email/confirm?confirmation_token=${token}`);
|
||||
|
||||
export function deleteAccount(intl, password) {
|
||||
return (dispatch, getState) => {
|
||||
const deleteAccount = (password: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const account = getLoggedInAccount(getState());
|
||||
|
||||
dispatch({ type: DELETE_ACCOUNT_REQUEST });
|
||||
|
@ -156,16 +150,15 @@ export function deleteAccount(intl, password) {
|
|||
if (response.data.error) throw response.data.error; // This endpoint returns HTTP 200 even on failure
|
||||
dispatch({ type: DELETE_ACCOUNT_SUCCESS, response });
|
||||
dispatch({ type: AUTH_LOGGED_OUT, account });
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.loggedOut)));
|
||||
dispatch(snackbar.success(messages.loggedOut));
|
||||
}).catch(error => {
|
||||
dispatch({ type: DELETE_ACCOUNT_FAIL, error, skipAlert: true });
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function moveAccount(targetAccount, password) {
|
||||
return (dispatch, getState) => {
|
||||
const moveAccount = (targetAccount: string, password: string) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
dispatch({ type: MOVE_ACCOUNT_REQUEST });
|
||||
return api(getState).post('/api/pleroma/move_account', {
|
||||
password,
|
||||
|
@ -178,4 +171,39 @@ export function moveAccount(targetAccount, password) {
|
|||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
FETCH_TOKENS_REQUEST,
|
||||
FETCH_TOKENS_SUCCESS,
|
||||
FETCH_TOKENS_FAIL,
|
||||
REVOKE_TOKEN_REQUEST,
|
||||
REVOKE_TOKEN_SUCCESS,
|
||||
REVOKE_TOKEN_FAIL,
|
||||
RESET_PASSWORD_REQUEST,
|
||||
RESET_PASSWORD_SUCCESS,
|
||||
RESET_PASSWORD_FAIL,
|
||||
RESET_PASSWORD_CONFIRM_REQUEST,
|
||||
RESET_PASSWORD_CONFIRM_SUCCESS,
|
||||
RESET_PASSWORD_CONFIRM_FAIL,
|
||||
CHANGE_PASSWORD_REQUEST,
|
||||
CHANGE_PASSWORD_SUCCESS,
|
||||
CHANGE_PASSWORD_FAIL,
|
||||
CHANGE_EMAIL_REQUEST,
|
||||
CHANGE_EMAIL_SUCCESS,
|
||||
CHANGE_EMAIL_FAIL,
|
||||
DELETE_ACCOUNT_REQUEST,
|
||||
DELETE_ACCOUNT_SUCCESS,
|
||||
DELETE_ACCOUNT_FAIL,
|
||||
MOVE_ACCOUNT_REQUEST,
|
||||
MOVE_ACCOUNT_SUCCESS,
|
||||
MOVE_ACCOUNT_FAIL,
|
||||
fetchOAuthTokens,
|
||||
revokeOAuthTokenById,
|
||||
changePassword,
|
||||
resetPassword,
|
||||
resetPasswordConfirm,
|
||||
changeEmail,
|
||||
confirmChangedEmail,
|
||||
deleteAccount,
|
||||
moveAccount,
|
||||
};
|
|
@ -8,16 +8,20 @@ import { getFeatures } from 'soapbox/utils/features';
|
|||
|
||||
import api, { staticClient } from '../api';
|
||||
|
||||
export const SOAPBOX_CONFIG_REQUEST_SUCCESS = 'SOAPBOX_CONFIG_REQUEST_SUCCESS';
|
||||
export const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
import type { APIEntity } from 'soapbox/types/entities';
|
||||
|
||||
export const SOAPBOX_CONFIG_REMEMBER_REQUEST = 'SOAPBOX_CONFIG_REMEMBER_REQUEST';
|
||||
export const SOAPBOX_CONFIG_REMEMBER_SUCCESS = 'SOAPBOX_CONFIG_REMEMBER_SUCCESS';
|
||||
export const SOAPBOX_CONFIG_REMEMBER_FAIL = 'SOAPBOX_CONFIG_REMEMBER_FAIL';
|
||||
const SOAPBOX_CONFIG_REQUEST_SUCCESS = 'SOAPBOX_CONFIG_REQUEST_SUCCESS';
|
||||
const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL';
|
||||
|
||||
export const getSoapboxConfig = createSelector([
|
||||
state => state.soapbox,
|
||||
state => getFeatures(state.instance),
|
||||
const SOAPBOX_CONFIG_REMEMBER_REQUEST = 'SOAPBOX_CONFIG_REMEMBER_REQUEST';
|
||||
const SOAPBOX_CONFIG_REMEMBER_SUCCESS = 'SOAPBOX_CONFIG_REMEMBER_SUCCESS';
|
||||
const SOAPBOX_CONFIG_REMEMBER_FAIL = 'SOAPBOX_CONFIG_REMEMBER_FAIL';
|
||||
|
||||
const getSoapboxConfig = createSelector([
|
||||
(state: RootState) => state.soapbox,
|
||||
(state: RootState) => getFeatures(state.instance),
|
||||
], (soapbox, features) => {
|
||||
// Do some additional normalization with the state
|
||||
return normalizeSoapboxConfig(soapbox).withMutations(soapboxConfig => {
|
||||
|
@ -35,8 +39,8 @@ export const getSoapboxConfig = createSelector([
|
|||
});
|
||||
});
|
||||
|
||||
export function rememberSoapboxConfig(host) {
|
||||
return (dispatch, getState) => {
|
||||
const rememberSoapboxConfig = (host: string | null) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_REQUEST, host });
|
||||
return KVStore.getItemOrError(`soapbox_config:${host}`).then(soapboxConfig => {
|
||||
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_SUCCESS, host, soapboxConfig });
|
||||
|
@ -45,19 +49,16 @@ export function rememberSoapboxConfig(host) {
|
|||
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_FAIL, host, error, skipAlert: true });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchFrontendConfigurations() {
|
||||
return (dispatch, getState) => {
|
||||
return api(getState)
|
||||
const fetchFrontendConfigurations = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) =>
|
||||
api(getState)
|
||||
.get('/api/pleroma/frontend_configurations')
|
||||
.then(({ data }) => data);
|
||||
};
|
||||
}
|
||||
|
||||
/** Conditionally fetches Soapbox config depending on backend features */
|
||||
export function fetchSoapboxConfig(host) {
|
||||
return (dispatch, getState) => {
|
||||
const fetchSoapboxConfig = (host: string | null) =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const features = getFeatures(getState().instance);
|
||||
|
||||
if (features.frontendConfigurations) {
|
||||
|
@ -73,32 +74,28 @@ export function fetchSoapboxConfig(host) {
|
|||
return dispatch(fetchSoapboxJson(host));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Tries to remember the config from browser storage before fetching it */
|
||||
export function loadSoapboxConfig() {
|
||||
return (dispatch, getState) => {
|
||||
const loadSoapboxConfig = () =>
|
||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const host = getHost(getState());
|
||||
|
||||
return dispatch(rememberSoapboxConfig(host)).then(() => {
|
||||
return dispatch(fetchSoapboxConfig(host));
|
||||
});
|
||||
return dispatch(rememberSoapboxConfig(host)).then(() =>
|
||||
dispatch(fetchSoapboxConfig(host)),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchSoapboxJson(host) {
|
||||
return (dispatch, getState) => {
|
||||
return staticClient.get('/instance/soapbox.json').then(({ data }) => {
|
||||
const fetchSoapboxJson = (host: string | null) =>
|
||||
(dispatch: AppDispatch) =>
|
||||
staticClient.get('/instance/soapbox.json').then(({ data }) => {
|
||||
if (!isObject(data)) throw 'soapbox.json failed';
|
||||
dispatch(importSoapboxConfig(data, host));
|
||||
return data;
|
||||
}).catch(error => {
|
||||
dispatch(soapboxConfigFail(error, host));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function importSoapboxConfig(soapboxConfig, host) {
|
||||
const importSoapboxConfig = (soapboxConfig: APIEntity, host: string | null) => {
|
||||
if (!soapboxConfig.brandColor) {
|
||||
soapboxConfig.brandColor = '#0482d8';
|
||||
}
|
||||
|
@ -107,18 +104,30 @@ export function importSoapboxConfig(soapboxConfig, host) {
|
|||
soapboxConfig,
|
||||
host,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export function soapboxConfigFail(error, host) {
|
||||
return {
|
||||
type: SOAPBOX_CONFIG_REQUEST_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
host,
|
||||
};
|
||||
}
|
||||
const soapboxConfigFail = (error: AxiosError, host: string | null) => ({
|
||||
type: SOAPBOX_CONFIG_REQUEST_FAIL,
|
||||
error,
|
||||
skipAlert: true,
|
||||
host,
|
||||
});
|
||||
|
||||
// https://stackoverflow.com/a/46663081
|
||||
function isObject(o) {
|
||||
return o instanceof Object && o.constructor === Object;
|
||||
}
|
||||
const isObject = (o: any) => o instanceof Object && o.constructor === Object;
|
||||
|
||||
export {
|
||||
SOAPBOX_CONFIG_REQUEST_SUCCESS,
|
||||
SOAPBOX_CONFIG_REQUEST_FAIL,
|
||||
SOAPBOX_CONFIG_REMEMBER_REQUEST,
|
||||
SOAPBOX_CONFIG_REMEMBER_SUCCESS,
|
||||
SOAPBOX_CONFIG_REMEMBER_FAIL,
|
||||
getSoapboxConfig,
|
||||
rememberSoapboxConfig,
|
||||
fetchFrontendConfigurations,
|
||||
fetchSoapboxConfig,
|
||||
loadSoapboxConfig,
|
||||
fetchSoapboxJson,
|
||||
importSoapboxConfig,
|
||||
soapboxConfigFail,
|
||||
};
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||
|
||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
|
||||
import { shortNumberFormat } from '../utils/numbers';
|
||||
|
||||
|
@ -18,7 +18,7 @@ interface IHashtag {
|
|||
|
||||
const Hashtag: React.FC<IHashtag> = ({ hashtag }) => {
|
||||
const count = Number(hashtag.history?.get(0)?.accounts);
|
||||
const brandColor = useSelector((state) => getSoapboxConfig(state).brandColor);
|
||||
const brandColor = useAppSelector((state) => getSoapboxConfig(state).brandColor);
|
||||
|
||||
return (
|
||||
<HStack alignItems='center' justifyContent='between' data-testid='hashtag'>
|
||||
|
|
|
@ -39,7 +39,7 @@ const Account: React.FC<IAccount> = ({ accountId, aliases }) => {
|
|||
});
|
||||
const me = useAppSelector((state) => state.me);
|
||||
|
||||
const handleOnAdd = () => dispatch(addToAliases(account));
|
||||
const handleOnAdd = () => dispatch(addToAliases(account!));
|
||||
|
||||
if (!account) return null;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ const Aliases = () => {
|
|||
}, []);
|
||||
|
||||
const handleFilterDelete: React.MouseEventHandler<HTMLDivElement> = e => {
|
||||
dispatch(removeFromAliases(e.currentTarget.dataset.value));
|
||||
dispatch(removeFromAliases(e.currentTarget.dataset.value as string));
|
||||
};
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.aliases' defaultMessage="You haven't created any account alias yet." />;
|
||||
|
|
|
@ -35,7 +35,7 @@ const PasswordResetConfirm = () => {
|
|||
event.preventDefault();
|
||||
|
||||
setStatus(Statuses.LOADING);
|
||||
dispatch(resetPasswordConfirm(password, token))
|
||||
dispatch(resetPasswordConfirm(password, token as string))
|
||||
.then(() => setStatus(Statuses.SUCCESS))
|
||||
.catch(() => setStatus(Statuses.FAIL));
|
||||
}, [password]);
|
||||
|
|
|
@ -32,7 +32,7 @@ const DeleteAccount = () => {
|
|||
|
||||
const handleSubmit = React.useCallback(() => {
|
||||
setLoading(true);
|
||||
dispatch(deleteAccount(intl, password)).then(() => {
|
||||
dispatch(deleteAccount(password)).then(() => {
|
||||
setPassword('');
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.deleteAccountSuccess)));
|
||||
}).finally(() => {
|
||||
|
|
|
@ -432,12 +432,12 @@ class Status extends ImmutablePureComponent<IStatus, IStatusState> {
|
|||
|
||||
handleDeactivateUser = (status: StatusEntity) => {
|
||||
const { dispatch, intl } = this.props;
|
||||
dispatch(deactivateUserModal(intl, status.getIn(['account', 'id'])));
|
||||
dispatch(deactivateUserModal(intl, status.getIn(['account', 'id']) as string));
|
||||
}
|
||||
|
||||
handleDeleteUser = (status: StatusEntity) => {
|
||||
const { dispatch, intl } = this.props;
|
||||
dispatch(deleteUserModal(intl, status.getIn(['account', 'id'])));
|
||||
dispatch(deleteUserModal(intl, status.getIn(['account', 'id']) as string));
|
||||
}
|
||||
|
||||
handleToggleStatusSensitivity = (status: StatusEntity) => {
|
||||
|
|
|
@ -33,7 +33,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
|
|||
const statusIds = useAppSelector((state) => OrderedSet(state.timelines.getIn([`account:${account.id}:with_replies`, 'items'])).union(state.reports.new.status_ids) as OrderedSet<string>);
|
||||
const isBlocked = useAppSelector((state) => state.reports.new.block);
|
||||
const isForward = useAppSelector((state) => state.reports.new.forward);
|
||||
const canForward = isRemote(account as any) && features.federating;
|
||||
const canForward = isRemote(account) && features.federating;
|
||||
const isSubmitting = useAppSelector((state) => state.reports.new.isSubmitting);
|
||||
|
||||
const [showAdditionalStatuses, setShowAdditionalStatuses] = useState<boolean>(false);
|
||||
|
|
|
@ -172,7 +172,7 @@ const ProfileInfoPanel: React.FC<IProfileInfoPanel> = ({ account, username }) =>
|
|||
)}
|
||||
|
||||
<div className='flex flex-col md:flex-row items-start md:flex-wrap md:items-center gap-2'>
|
||||
{isLocal(account as any) ? (
|
||||
{isLocal(account) ? (
|
||||
<HStack alignItems='center' space={0.5}>
|
||||
<Icon
|
||||
src={require('@tabler/icons/icons/calendar.svg')}
|
||||
|
|
|
@ -34,9 +34,9 @@ export const getFollowDifference = (state: ImmutableMap<string, any>, accountId:
|
|||
return Math.max(counter - items.size, 0);
|
||||
};
|
||||
|
||||
export const isLocal = (account: ImmutableMap<string, any>): boolean => {
|
||||
const domain: string = account.get('acct').split('@')[1];
|
||||
export const isLocal = (account: Account): boolean => {
|
||||
const domain: string = account.acct.split('@')[1];
|
||||
return domain === undefined ? true : false;
|
||||
};
|
||||
|
||||
export const isRemote = (account: ImmutableMap<string, any>): boolean => !isLocal(account);
|
||||
export const isRemote = (account: Account): boolean => !isLocal(account);
|
||||
|
|
Ładowanie…
Reference in New Issue