pl-fe: Add types for accounts actions

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2024-11-10 20:39:30 +01:00
parent cdd87d89f8
commit 781a2430e4
6 changed files with 157 additions and 26 deletions

View file

@ -1,4 +1,4 @@
import { PLEROMA, type UpdateNotificationSettingsParams, type Account, type CreateAccountParams, type PaginatedResponse, type Relationship } from 'pl-api';
import { PLEROMA, type UpdateNotificationSettingsParams, type Account, type CreateAccountParams, type PaginatedResponse, type Relationship, Token, PlApiClient } from 'pl-api';
import { Entities } from 'pl-fe/entity-store/entities';
import { selectAccount } from 'pl-fe/selectors';
@ -11,6 +11,7 @@ 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';
import type { Me } from 'pl-fe/types/pl-fe';
const ACCOUNT_CREATE_REQUEST = 'ACCOUNT_CREATE_REQUEST' as const;
const ACCOUNT_CREATE_SUCCESS = 'ACCOUNT_CREATE_SUCCESS' as const;
@ -73,13 +74,30 @@ const maybeRedirectLogin = (error: { response: PlfeResponse }, history?: History
const noOp = () => new Promise(f => f(undefined));
interface AccountCreateRequestAction {
type: typeof ACCOUNT_CREATE_REQUEST;
params: CreateAccountParams;
}
interface AccountCreateSuccessAction {
type: typeof ACCOUNT_CREATE_SUCCESS;
params: CreateAccountParams;
token: Token;
}
interface AccountCreateFailAction {
type: typeof ACCOUNT_CREATE_FAIL;
params: CreateAccountParams;
error: unknown;
}
const createAccount = (params: CreateAccountParams) =>
async (dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: ACCOUNT_CREATE_REQUEST, params });
dispatch<AccountCreateRequestAction>({ type: ACCOUNT_CREATE_REQUEST, params });
return getClient(getState()).settings.createAccount(params).then((token) =>
dispatch({ type: ACCOUNT_CREATE_SUCCESS, params, token }),
dispatch<AccountCreateSuccessAction>({ type: ACCOUNT_CREATE_SUCCESS, params, token }),
).catch(error => {
dispatch({ type: ACCOUNT_CREATE_FAIL, error, params });
dispatch<AccountCreateFailAction>({ type: ACCOUNT_CREATE_FAIL, error, params });
throw error;
});
};
@ -411,13 +429,30 @@ const unpinAccount = (accountId: string) =>
);
};
interface NotificationSettingsRequestAction {
type: typeof NOTIFICATION_SETTINGS_REQUEST;
params: UpdateNotificationSettingsParams;
}
interface NotificationSettingsSuccessAction {
type: typeof NOTIFICATION_SETTINGS_SUCCESS;
params: UpdateNotificationSettingsParams;
data: Awaited<ReturnType<(InstanceType<typeof PlApiClient>)['settings']['updateNotificationSettings']>>;
}
interface NotificationSettingsFailAction {
type: typeof NOTIFICATION_SETTINGS_FAIL;
params: UpdateNotificationSettingsParams;
error: unknown;
}
const updateNotificationSettings = (params: UpdateNotificationSettingsParams) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: NOTIFICATION_SETTINGS_REQUEST, params });
dispatch<NotificationSettingsRequestAction>({ type: NOTIFICATION_SETTINGS_REQUEST, params });
return getClient(getState).settings.updateNotificationSettings(params).then((data) => {
dispatch({ type: NOTIFICATION_SETTINGS_SUCCESS, params, data });
dispatch<NotificationSettingsSuccessAction>({ type: NOTIFICATION_SETTINGS_SUCCESS, params, data });
}).catch(error => {
dispatch({ type: NOTIFICATION_SETTINGS_FAIL, params, error });
dispatch<NotificationSettingsFailAction>({ type: NOTIFICATION_SETTINGS_FAIL, params, error });
throw error;
});
};
@ -452,43 +487,96 @@ const fetchPinnedAccountsFail = (accountId: string, error: unknown) => ({
error,
});
interface AccountSearchRequestAction {
type: typeof ACCOUNT_SEARCH_REQUEST;
params: {
q: string;
};
}
interface AccountSearchSuccessAction {
type: typeof ACCOUNT_SEARCH_SUCCESS;
accounts: Array<Account>;
}
interface AccountSearchFailAction {
type: typeof ACCOUNT_SEARCH_FAIL;
skipAlert: true;
}
const accountSearch = (q: string, signal?: AbortSignal) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: ACCOUNT_SEARCH_REQUEST, params: { q } });
dispatch<AccountSearchRequestAction>({ type: ACCOUNT_SEARCH_REQUEST, params: { q } });
return getClient(getState()).accounts.searchAccounts(q, { resolve: false, limit: 4, following: true }, { signal }).then((accounts) => {
dispatch(importEntities({ accounts }));
dispatch({ type: ACCOUNT_SEARCH_SUCCESS, accounts });
dispatch<AccountSearchSuccessAction>({ type: ACCOUNT_SEARCH_SUCCESS, accounts });
return accounts;
}).catch(error => {
dispatch({ type: ACCOUNT_SEARCH_FAIL, skipAlert: true });
dispatch<AccountSearchFailAction>({ type: ACCOUNT_SEARCH_FAIL, skipAlert: true });
throw error;
});
};
interface AccountLookupRequestAction {
type: typeof ACCOUNT_LOOKUP_REQUEST;
acct: string;
}
interface AccountLookupSuccessAction {
type: typeof ACCOUNT_LOOKUP_SUCCESS;
account: Account;
}
interface AccountLookupFailAction {
type: typeof ACCOUNT_LOOKUP_FAIL;
}
const accountLookup = (acct: string, signal?: AbortSignal) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch({ type: ACCOUNT_LOOKUP_REQUEST, acct });
dispatch<AccountLookupRequestAction>({ type: ACCOUNT_LOOKUP_REQUEST, acct });
return getClient(getState()).accounts.lookupAccount(acct, { signal }).then((account) => {
if (account && account.id) dispatch(importEntities({ accounts: [account] }));
dispatch({ type: ACCOUNT_LOOKUP_SUCCESS, account });
dispatch<AccountLookupSuccessAction>({ type: ACCOUNT_LOOKUP_SUCCESS, account });
return account;
}).catch(error => {
dispatch({ type: ACCOUNT_LOOKUP_FAIL });
dispatch<AccountLookupFailAction>({ type: ACCOUNT_LOOKUP_FAIL });
throw error;
});
};
interface BirthdayRemindersFetchRequestAction {
type: typeof BIRTHDAY_REMINDERS_FETCH_REQUEST;
day: number;
month: number;
accountId: Me;
}
interface BirthdayRemindersFetchSuccessAction {
type: typeof BIRTHDAY_REMINDERS_FETCH_SUCCESS;
day: number;
month: number;
accountId: Me;
accounts: Array<Account>;
}
interface BirthdayRemindersFetchFailAction {
type: typeof BIRTHDAY_REMINDERS_FETCH_FAIL;
day: number;
month: number;
accountId: Me;
}
const fetchBirthdayReminders = (month: number, day: number) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return;
const me = getState().me;
dispatch({ type: BIRTHDAY_REMINDERS_FETCH_REQUEST, day, month, accountId: me });
dispatch<BirthdayRemindersFetchRequestAction>({ type: BIRTHDAY_REMINDERS_FETCH_REQUEST, day, month, accountId: me });
return getClient(getState).accounts.getBirthdays(day, month).then(response => {
dispatch(importEntities({ accounts: response }));
dispatch({
dispatch<BirthdayRemindersFetchSuccessAction>({
type: BIRTHDAY_REMINDERS_FETCH_SUCCESS,
accounts: response,
day,
@ -496,7 +584,7 @@ const fetchBirthdayReminders = (month: number, day: number) =>
accountId: me,
});
}).catch(() => {
dispatch({ type: BIRTHDAY_REMINDERS_FETCH_FAIL, day, month, accountId: me });
dispatch<BirthdayRemindersFetchFailAction>({ type: BIRTHDAY_REMINDERS_FETCH_FAIL, day, month, accountId: me });
});
};
@ -507,6 +595,47 @@ const biteAccount = (accountId: string) =>
return client.accounts.biteAccount(accountId);
};
type AccountsAction =
| AccountCreateRequestAction
| AccountCreateSuccessAction
| AccountCreateFailAction
| ReturnType<typeof fetchAccountRequest>
| ReturnType<typeof fetchAccountSuccess>
| ReturnType<typeof fetchAccountFail>
| ReturnType<typeof blockAccountRequest>
| ReturnType<typeof blockAccountSuccess>
| ReturnType<typeof blockAccountFail>
| ReturnType<typeof muteAccountRequest>
| ReturnType<typeof muteAccountSuccess>
| ReturnType<typeof muteAccountFail>
| ReturnType<typeof fetchFollowRequestsRequest>
| ReturnType<typeof fetchFollowRequestsSuccess>
| ReturnType<typeof fetchFollowRequestsFail>
| ReturnType<typeof expandFollowRequestsRequest>
| ReturnType<typeof expandFollowRequestsSuccess>
| ReturnType<typeof expandFollowRequestsFail>
| ReturnType<typeof authorizeFollowRequestRequest>
| ReturnType<typeof authorizeFollowRequestSuccess>
| ReturnType<typeof authorizeFollowRequestFail>
| ReturnType<typeof rejectFollowRequestRequest>
| ReturnType<typeof rejectFollowRequestSuccess>
| ReturnType<typeof rejectFollowRequestFail>
| NotificationSettingsRequestAction
| NotificationSettingsSuccessAction
| NotificationSettingsFailAction
| ReturnType<typeof fetchPinnedAccountsRequest>
| ReturnType<typeof fetchPinnedAccountsSuccess>
| ReturnType<typeof fetchPinnedAccountsFail>
| AccountSearchRequestAction
| AccountSearchSuccessAction
| AccountSearchFailAction
| AccountLookupRequestAction
| AccountLookupSuccessAction
| AccountLookupFailAction
| BirthdayRemindersFetchSuccessAction
| BirthdayRemindersFetchRequestAction
| BirthdayRemindersFetchFailAction
export {
ACCOUNT_CREATE_REQUEST,
ACCOUNT_CREATE_SUCCESS,
@ -592,4 +721,5 @@ export {
accountLookup,
fetchBirthdayReminders,
biteAccount,
type AccountsAction,
};

View file

@ -2,7 +2,7 @@ import { create } from 'mutative';
import { STATUS_IMPORT, STATUSES_IMPORT, type ImporterAction } from 'pl-fe/actions/importer';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from '../actions/accounts';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, type AccountsAction } from '../actions/accounts';
import {
CONTEXT_FETCH_SUCCESS,
STATUS_CREATE_REQUEST,
@ -140,7 +140,7 @@ const filterContexts = (
state: State,
relationship: { id: string },
/** The entire statuses map from the store. */
statuses: Record<string, Status>,
statuses: Record<string, Pick<Status, 'account' | 'id'>>,
) => {
const ownedStatusIds = Object.values(statuses)
.filter(status => status.account.id === relationship.id)
@ -171,7 +171,7 @@ const deletePendingStatus = (state: State, params: Pick<Status, 'id' | 'in_reply
};
/** Contexts reducer. Used for building a nested tree structure for threads. */
const replies = (state = initialState, action: AnyAction | ImporterAction | StatusesAction | TimelineAction): State => {
const replies = (state = initialState, action: AccountsAction | AnyAction | ImporterAction | StatusesAction | TimelineAction): State => {
switch (action.type) {
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:

View file

@ -5,6 +5,7 @@ import {
ACCOUNT_MUTE_SUCCESS,
FOLLOW_REQUEST_AUTHORIZE_SUCCESS,
FOLLOW_REQUEST_REJECT_SUCCESS,
type AccountsAction,
} from '../actions/accounts';
import {
MARKER_FETCH_SUCCESS,
@ -149,7 +150,7 @@ const importMarker = (state: State, marker: Markers) => {
});
};
const notifications = (state: State = ReducerRecord(), action: AnyAction | TimelineAction) => {
const notifications = (state: State = ReducerRecord(), action: AccountsAction | AnyAction | TimelineAction) => {
switch (action.type) {
case NOTIFICATIONS_EXPAND_REQUEST:
return state.set('isLoading', true);

View file

@ -1,6 +1,6 @@
import { Record as ImmutableRecord } from 'immutable';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from 'pl-fe/actions/accounts';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, type AccountsAction } from 'pl-fe/actions/accounts';
import { DOMAIN_BLOCK_SUCCESS, type DomainBlocksAction } from 'pl-fe/actions/domain-blocks';
import {
SUGGESTIONS_FETCH_REQUEST,
@ -10,7 +10,6 @@ import {
} from 'pl-fe/actions/suggestions';
import type { Suggestion as SuggestionEntity } from 'pl-api';
import type { AnyAction } from 'redux';
const ReducerRecord = ImmutableRecord({
items: Array<MinifiedSuggestion>(),
@ -38,7 +37,7 @@ const dismissAccount = (state: State, accountId: string) =>
const dismissAccounts = (state: State, accountIds: string[]) =>
state.update('items', items => items.filter(item => !accountIds.includes(item.account_id)));
const suggestionsReducer = (state: State = ReducerRecord(), action: AnyAction | DomainBlocksAction | SuggestionsAction) => {
const suggestionsReducer = (state: State = ReducerRecord(), action: AccountsAction | DomainBlocksAction | SuggestionsAction) => {
switch (action.type) {
case SUGGESTIONS_FETCH_REQUEST:
return state.set('isLoading', true);

View file

@ -1,7 +1,7 @@
import sample from 'lodash/sample';
import { create } from 'mutative';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS } from '../actions/accounts';
import { ACCOUNT_BLOCK_SUCCESS, ACCOUNT_MUTE_SUCCESS, type AccountsAction } from '../actions/accounts';
import { PIN_SUCCESS, UNPIN_SUCCESS, type InteractionsAction } from '../actions/interactions';
import { STATUS_CREATE_REQUEST, STATUS_CREATE_SUCCESS, type StatusesAction } from '../actions/statuses';
import {
@ -295,7 +295,7 @@ const handleExpandFail = (state: State, timelineId: string) => {
setFailed(state, timelineId, true);
};
const timelines = (state: State = initialState, action: AnyAction | InteractionsAction | StatusesAction | TimelineAction): State => {
const timelines = (state: State = initialState, action: AccountsAction | AnyAction | InteractionsAction | StatusesAction | TimelineAction): State => {
switch (action.type) {
case STATUS_CREATE_REQUEST:
if (action.params.scheduled_at) return state;

View file

@ -8,6 +8,7 @@ import {
FOLLOW_REQUEST_REJECT_SUCCESS,
PINNED_ACCOUNTS_FETCH_SUCCESS,
BIRTHDAY_REMINDERS_FETCH_SUCCESS,
type AccountsAction,
} from 'pl-fe/actions/accounts';
import {
DIRECTORY_FETCH_REQUEST,
@ -156,7 +157,7 @@ const normalizeFollowRequest = (state: State, notification: Notification) =>
draft.follow_requests.items = [...new Set([notification.account.id, ...draft.follow_requests.items])];
});
const userLists = (state = initialState, action: DirectoryAction | InteractionsAction | AnyAction): State => {
const userLists = (state = initialState, action: AccountsAction | DirectoryAction | InteractionsAction | AnyAction): State => {
switch (action.type) {
case REBLOGS_FETCH_SUCCESS:
return normalizeList(state, ['reblogged_by', action.statusId], action.accounts, action.next);