diff --git a/packages/pl-fe/src/actions/accounts.ts b/packages/pl-fe/src/actions/accounts.ts index 61470d086..c98dbe871 100644 --- a/packages/pl-fe/src/actions/accounts.ts +++ b/packages/pl-fe/src/actions/accounts.ts @@ -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({ type: ACCOUNT_CREATE_REQUEST, params }); return getClient(getState()).settings.createAccount(params).then((token) => - dispatch({ type: ACCOUNT_CREATE_SUCCESS, params, token }), + dispatch({ type: ACCOUNT_CREATE_SUCCESS, params, token }), ).catch(error => { - dispatch({ type: ACCOUNT_CREATE_FAIL, error, params }); + dispatch({ 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)['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({ type: NOTIFICATION_SETTINGS_REQUEST, params }); return getClient(getState).settings.updateNotificationSettings(params).then((data) => { - dispatch({ type: NOTIFICATION_SETTINGS_SUCCESS, params, data }); + dispatch({ type: NOTIFICATION_SETTINGS_SUCCESS, params, data }); }).catch(error => { - dispatch({ type: NOTIFICATION_SETTINGS_FAIL, params, error }); + dispatch({ 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; +} + +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({ 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({ type: ACCOUNT_SEARCH_SUCCESS, accounts }); return accounts; }).catch(error => { - dispatch({ type: ACCOUNT_SEARCH_FAIL, skipAlert: true }); + dispatch({ 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({ 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({ type: ACCOUNT_LOOKUP_SUCCESS, account }); return account; }).catch(error => { - dispatch({ type: ACCOUNT_LOOKUP_FAIL }); + dispatch({ 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; +} + +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({ type: BIRTHDAY_REMINDERS_FETCH_REQUEST, day, month, accountId: me }); return getClient(getState).accounts.getBirthdays(day, month).then(response => { dispatch(importEntities({ accounts: response })); - dispatch({ + dispatch({ 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({ 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 + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | NotificationSettingsRequestAction + | NotificationSettingsSuccessAction + | NotificationSettingsFailAction + | ReturnType + | ReturnType + | ReturnType + | 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, }; diff --git a/packages/pl-fe/src/reducers/contexts.ts b/packages/pl-fe/src/reducers/contexts.ts index 070fc7030..6e4b4d676 100644 --- a/packages/pl-fe/src/reducers/contexts.ts +++ b/packages/pl-fe/src/reducers/contexts.ts @@ -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, + statuses: Record>, ) => { const ownedStatusIds = Object.values(statuses) .filter(status => status.account.id === relationship.id) @@ -171,7 +171,7 @@ const deletePendingStatus = (state: State, params: Pick { +const replies = (state = initialState, action: AccountsAction | AnyAction | ImporterAction | StatusesAction | TimelineAction): State => { switch (action.type) { case ACCOUNT_BLOCK_SUCCESS: case ACCOUNT_MUTE_SUCCESS: diff --git a/packages/pl-fe/src/reducers/notifications.ts b/packages/pl-fe/src/reducers/notifications.ts index 6d027a6be..6b907ed99 100644 --- a/packages/pl-fe/src/reducers/notifications.ts +++ b/packages/pl-fe/src/reducers/notifications.ts @@ -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); diff --git a/packages/pl-fe/src/reducers/suggestions.ts b/packages/pl-fe/src/reducers/suggestions.ts index 991dd31c8..e33f767f0 100644 --- a/packages/pl-fe/src/reducers/suggestions.ts +++ b/packages/pl-fe/src/reducers/suggestions.ts @@ -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(), @@ -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); diff --git a/packages/pl-fe/src/reducers/timelines.ts b/packages/pl-fe/src/reducers/timelines.ts index 55d63b1c2..19bc6289f 100644 --- a/packages/pl-fe/src/reducers/timelines.ts +++ b/packages/pl-fe/src/reducers/timelines.ts @@ -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; diff --git a/packages/pl-fe/src/reducers/user-lists.ts b/packages/pl-fe/src/reducers/user-lists.ts index b27673c68..669dd451c 100644 --- a/packages/pl-fe/src/reducers/user-lists.ts +++ b/packages/pl-fe/src/reducers/user-lists.ts @@ -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);