Files
ncd-fe/packages/pl-fe/src/actions/accounts.ts
nicole mikołajczyk 72d86fd62d pl-fe: batch relationships requests
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2025-10-23 19:47:13 +02:00

118 lines
3.8 KiB
TypeScript

import { type CreateAccountParams, type Relationship } from 'pl-api';
import { batcher } from 'pl-fe/api/batcher';
import { queryClient } from 'pl-fe/queries/client';
import { selectAccount } from 'pl-fe/selectors';
import { isLoggedIn } from 'pl-fe/utils/auth';
import { getClient, type PlfeResponse } from '../api';
import { importEntities } from './importer';
import type { MinifiedStatus } from 'pl-fe/reducers/statuses';
import type { AppDispatch, RootState } from 'pl-fe/store';
import type { History } from 'pl-fe/types/history';
const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS' as const;
const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS' as const;
const maybeRedirectLogin = (error: { response: PlfeResponse }, history?: History) => {
// The client is unauthorized - redirect to login.
if (history && error?.response?.status === 401) {
history.push('/login');
}
};
const createAccount = (params: CreateAccountParams) =>
async (dispatch: AppDispatch, getState: () => RootState) =>
getClient(getState()).settings.createAccount(params).then((response) =>
({ params, response }),
);
const fetchAccount = (accountId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch(fetchRelationships([accountId]));
const account = selectAccount(getState(), accountId);
if (account) {
return Promise.resolve(null);
}
return getClient(getState()).accounts.getAccount(accountId)
.then(response => {
dispatch(importEntities({ accounts: [response] }));
})
.catch(error => {
});
};
const fetchAccountByUsername = (username: string, history?: History) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const { auth, me } = getState();
const features = auth.client.features;
if (features.accountByUsername && (me || !features.accountLookup)) {
return getClient(getState()).accounts.getAccount(username).then(response => {
dispatch(fetchRelationships([response.id]));
dispatch(importEntities({ accounts: [response] }));
});
} else if (features.accountLookup) {
return dispatch(accountLookup(username)).then(account => {
dispatch(fetchRelationships([account.id]));
}).catch(error => {
maybeRedirectLogin(error, history);
});
} else {
return getClient(getState()).accounts.searchAccounts(username, { resolve: true, limit: 1 }).then(accounts => {
const found = accounts.find((a) => a.acct === username);
if (found) {
dispatch(fetchRelationships([found.id]));
} else {
throw accounts;
}
});
}
};
const fetchRelationships = (accountIds: string[]) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return null;
const newAccountIds = accountIds.filter(id => !queryClient.getQueryData(['accountRelationships', id]));
if (newAccountIds.length === 0) {
return null;
}
const fetcher = batcher.relationships(getClient(getState())).fetch;
return Promise.all(newAccountIds.map(fetcher))
.then(response => dispatch(importEntities({ relationships: response })));
};
const accountLookup = (acct: string, signal?: AbortSignal) =>
(dispatch: AppDispatch, getState: () => RootState) =>
getClient(getState()).accounts.lookupAccount(acct, { signal }).then((account) => {
if (account && account.id) dispatch(importEntities({ accounts: [account] }));
return account;
});
type AccountsAction = {
type: typeof ACCOUNT_BLOCK_SUCCESS | typeof ACCOUNT_MUTE_SUCCESS;
relationship: Relationship;
statuses: Record<string, MinifiedStatus>;
};
export {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
createAccount,
fetchAccount,
fetchAccountByUsername,
fetchRelationships,
accountLookup,
type AccountsAction,
};