pl-fe: refactor, remove unused exports, migrate event participants list to tanstack query

Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
mkljczk 2024-12-04 17:31:04 +01:00
parent edf831bed9
commit 90f17de808
12 changed files with 57 additions and 171 deletions

View file

@ -410,13 +410,7 @@ export {
approveUser,
deleteStatus,
toggleStatusSensitivity,
tagUser,
untagUser,
setTags,
setBadges,
promoteToAdmin,
promoteToModerator,
demoteToUser,
setRole,
setUserIndexQuery,
fetchUserIndex,

View file

@ -163,7 +163,6 @@ export {
ALIASES_REMOVE_FAIL,
fetchAliases,
fetchAliasesSuggestions,
fetchAliasesSuggestionsReady,
clearAliasesSuggestions,
changeAliasesSuggestions,
addToAliases,

View file

@ -376,7 +376,6 @@ export {
messages,
otpVerify,
verifyCredentials,
rememberAuthAccount,
loadCredentials,
logIn,
logOut,

View file

@ -65,8 +65,6 @@ const COMPOSE_LANGUAGE_ADD = 'COMPOSE_LANGUAGE_ADD' as const;
const COMPOSE_LANGUAGE_DELETE = 'COMPOSE_LANGUAGE_DELETE' as const;
const COMPOSE_FEDERATED_CHANGE = 'COMPOSE_FEDERATED_CHANGE' as const;
const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT' as const;
const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST' as const;
const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS' as const;
const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL' as const;
@ -784,13 +782,6 @@ const deleteComposeLanguage = (composeId: string, value: Language) => ({
value,
});
const insertEmojiCompose = (composeId: string, position: number, emoji: Emoji, needsSpace: boolean) => ({
type: COMPOSE_EMOJI_INSERT,
composeId,
position,
emoji,
needsSpace,
});
const addPoll = (composeId: string) => ({
type: COMPOSE_POLL_ADD,
@ -978,7 +969,6 @@ type ComposeAction =
| ReturnType<typeof changeComposeModifiedLanguage>
| ReturnType<typeof addComposeLanguage>
| ReturnType<typeof deleteComposeLanguage>
| ReturnType<typeof insertEmojiCompose>
| ReturnType<typeof addPoll>
| ReturnType<typeof removePoll>
| ReturnType<typeof addSchedule>
@ -1029,7 +1019,6 @@ export {
COMPOSE_MODIFIED_LANGUAGE_CHANGE,
COMPOSE_LANGUAGE_ADD,
COMPOSE_LANGUAGE_DELETE,
COMPOSE_EMOJI_INSERT,
COMPOSE_UPLOAD_CHANGE_REQUEST,
COMPOSE_UPLOAD_CHANGE_SUCCESS,
COMPOSE_UPLOAD_CHANGE_FAIL,
@ -1051,7 +1040,6 @@ export {
COMPOSE_ADD_SUGGESTED_LANGUAGE,
COMPOSE_FEDERATED_CHANGE,
setComposeToStatus,
changeCompose,
replyCompose,
cancelReplyCompose,
quoteCompose,
@ -1060,7 +1048,6 @@ export {
mentionCompose,
directCompose,
directComposeById,
handleComposeSubmit,
submitCompose,
uploadFile,
uploadCompose,
@ -1071,11 +1058,7 @@ export {
groupComposeModal,
clearComposeSuggestions,
fetchComposeSuggestions,
readyComposeSuggestionsEmojis,
readyComposeSuggestionsAccounts,
selectComposeSuggestion,
updateSuggestionTags,
updateTagHistory,
changeComposeSpoilerness,
changeComposeContentType,
changeComposeSpoilerText,
@ -1084,7 +1067,6 @@ export {
changeComposeModifiedLanguage,
addComposeLanguage,
deleteComposeLanguage,
insertEmojiCompose,
addPoll,
removePoll,
addSchedule,

View file

@ -21,14 +21,6 @@ const EVENT_LEAVE_REQUEST = 'EVENT_LEAVE_REQUEST' as const;
const EVENT_LEAVE_SUCCESS = 'EVENT_LEAVE_SUCCESS' as const;
const EVENT_LEAVE_FAIL = 'EVENT_LEAVE_FAIL' as const;
const EVENT_PARTICIPATIONS_FETCH_REQUEST = 'EVENT_PARTICIPATIONS_FETCH_REQUEST' as const;
const EVENT_PARTICIPATIONS_FETCH_SUCCESS = 'EVENT_PARTICIPATIONS_FETCH_SUCCESS' as const;
const EVENT_PARTICIPATIONS_FETCH_FAIL = 'EVENT_PARTICIPATIONS_FETCH_FAIL' as const;
const EVENT_PARTICIPATIONS_EXPAND_REQUEST = 'EVENT_PARTICIPATIONS_EXPAND_REQUEST' as const;
const EVENT_PARTICIPATIONS_EXPAND_SUCCESS = 'EVENT_PARTICIPATIONS_EXPAND_SUCCESS' as const;
const EVENT_PARTICIPATIONS_EXPAND_FAIL = 'EVENT_PARTICIPATIONS_EXPAND_FAIL' as const;
const EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST = 'EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST' as const;
const EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS = 'EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS' as const;
const EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL = 'EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL' as const;
@ -221,72 +213,6 @@ const leaveEventFail = (error: unknown, statusId: string, previousState: Exclude
previousState,
});
const fetchEventParticipations = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch(fetchEventParticipationsRequest(statusId));
return getClient(getState).events.getEventParticipations(statusId).then(response => {
dispatch(importEntities({ accounts: response.items }));
return dispatch(fetchEventParticipationsSuccess(statusId, response.items, response.next));
}).catch(error => {
dispatch(fetchEventParticipationsFail(statusId, error));
});
};
const fetchEventParticipationsRequest = (statusId: string) => ({
type: EVENT_PARTICIPATIONS_FETCH_REQUEST,
statusId,
});
const fetchEventParticipationsSuccess = (statusId: string, accounts: Array<Account>, next: (() => Promise<PaginatedResponse<Account>>) | null) => ({
type: EVENT_PARTICIPATIONS_FETCH_SUCCESS,
statusId,
accounts,
next,
});
const fetchEventParticipationsFail = (statusId: string, error: unknown) => ({
type: EVENT_PARTICIPATIONS_FETCH_FAIL,
statusId,
error,
});
const expandEventParticipations = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
const next = getState().user_lists.event_participations[statusId]?.next || null;
if (next === null) {
return dispatch(noOp);
}
dispatch(expandEventParticipationsRequest(statusId));
return next().then(response => {
dispatch(importEntities({ accounts: response.items }));
return dispatch(expandEventParticipationsSuccess(statusId, response.items, response.next));
}).catch(error => {
dispatch(expandEventParticipationsFail(statusId, error));
});
};
const expandEventParticipationsRequest = (statusId: string) => ({
type: EVENT_PARTICIPATIONS_EXPAND_REQUEST,
statusId,
});
const expandEventParticipationsSuccess = (statusId: string, accounts: Array<Account>, next: (() => Promise<PaginatedResponse<Account>>) | null) => ({
type: EVENT_PARTICIPATIONS_EXPAND_SUCCESS,
statusId,
accounts,
next,
});
const expandEventParticipationsFail = (statusId: string, error: unknown) => ({
type: EVENT_PARTICIPATIONS_EXPAND_FAIL,
statusId,
error,
});
const fetchEventParticipationRequests = (statusId: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch(fetchEventParticipationRequestsRequest(statusId));
@ -499,12 +425,6 @@ type EventsAction =
| ReturnType<typeof leaveEventRequest>
| ReturnType<typeof leaveEventSuccess>
| ReturnType<typeof leaveEventFail>
| ReturnType<typeof fetchEventParticipationsRequest>
| ReturnType<typeof fetchEventParticipationsSuccess>
| ReturnType<typeof fetchEventParticipationsFail>
| ReturnType<typeof expandEventParticipationsRequest>
| ReturnType<typeof expandEventParticipationsSuccess>
| ReturnType<typeof expandEventParticipationsFail>
| ReturnType<typeof fetchEventParticipationRequestsRequest>
| ReturnType<typeof fetchEventParticipationRequestsSuccess>
| ReturnType<typeof fetchEventParticipationRequestsFail>
@ -538,12 +458,6 @@ export {
EVENT_LEAVE_REQUEST,
EVENT_LEAVE_SUCCESS,
EVENT_LEAVE_FAIL,
EVENT_PARTICIPATIONS_FETCH_REQUEST,
EVENT_PARTICIPATIONS_FETCH_SUCCESS,
EVENT_PARTICIPATIONS_FETCH_FAIL,
EVENT_PARTICIPATIONS_EXPAND_REQUEST,
EVENT_PARTICIPATIONS_EXPAND_SUCCESS,
EVENT_PARTICIPATIONS_EXPAND_FAIL,
EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST,
EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS,
EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL,
@ -567,8 +481,6 @@ export {
submitEvent,
joinEvent,
leaveEvent,
fetchEventParticipations,
expandEventParticipations,
fetchEventParticipationRequests,
expandEventParticipationRequests,
authorizeEventParticipationRequest,

View file

@ -0,0 +1,21 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { minifyAccountList } from 'pl-fe/api/normalizers/minify-list';
import { useClient } from 'pl-fe/hooks/use-client';
import type { PaginatedResponse } from 'pl-api';
const useEventParticipations = (statusId: string) => {
const client = useClient();
return useInfiniteQuery({
queryKey: ['accountsLists', 'eventParticipations', statusId],
queryFn: ({ pageParam }) => pageParam.next?.() || client.events.getEventParticipations(statusId).then(minifyAccountList),
initialPageParam: { previous: null, next: null, items: [], partial: false } as PaginatedResponse<string>,
getNextPageParam: (page) => page.next ? page : undefined,
select: (data) => data.pages.map(page => page.items).flat(),
});
};
export { useEventParticipations };

View file

@ -1,6 +1,6 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { minifyStatusList } from 'pl-fe/api/normalizers/status-list';
import { minifyStatusList } from 'pl-fe/api/normalizers/minify-list';
import { useClient } from 'pl-fe/hooks/use-client';
import type { PaginatedResponse } from 'pl-api';

View file

@ -0,0 +1,27 @@
import { Account, PaginatedResponse, Status } from 'pl-api';
import { importEntities } from 'pl-fe/actions/importer';
import { store } from 'pl-fe/store';
const minifyList = <T1, T2>({ previous, next, items, ...response }: PaginatedResponse<T1>, minifier: (value: T1) => T2, importer?: (items: Array<T1>) => void): PaginatedResponse<T2> => {
importer?.(items);
return {
...response,
previous: previous ? () => previous().then((list) => minifyList(list, minifier, importer)) : null,
next: next ? () => next().then((list) => minifyList(list, minifier, importer)) : null,
items: items.map(minifier),
};
};
const minifyStatusList = (response: PaginatedResponse<Status>): PaginatedResponse<string> =>
minifyList(response, (status) => status.id, (statuses) => {
store.dispatch(importEntities({ statuses }) as any);
});
const minifyAccountList = (response: PaginatedResponse<Account>): PaginatedResponse<string> =>
minifyList(response, (account) => account.id, (accounts) => {
store.dispatch(importEntities({ accounts }) as any);
});
export { minifyList, minifyAccountList, minifyStatusList };

View file

@ -1,17 +0,0 @@
import { PaginatedResponse, Status } from 'pl-api';
import { importEntities } from 'pl-fe/actions/importer';
import { store } from 'pl-fe/store';
const minifyStatusList = ({ previous, next, items, ...response }: PaginatedResponse<Status>): PaginatedResponse<string> => {
store.dispatch(importEntities({ statuses: items }) as any);
return {
...response,
previous: previous ? () => previous().then(minifyStatusList) : null,
next: next ? () => next().then(minifyStatusList) : null,
items: items.map(status => status.id),
};
};
export { minifyStatusList };

View file

@ -1,13 +1,11 @@
import React, { useEffect } from 'react';
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { fetchEventParticipations } from 'pl-fe/actions/events';
import { useEventParticipations } from 'pl-fe/api/hooks/account-lists/use-event-participations';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Modal from 'pl-fe/components/ui/modal';
import Spinner from 'pl-fe/components/ui/spinner';
import AccountContainer from 'pl-fe/containers/account-container';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import type { BaseModalProps } from '../modal-root';
@ -16,17 +14,7 @@ interface EventParticipantsModalProps {
}
const EventParticipantsModal: React.FC<BaseModalProps & EventParticipantsModalProps> = ({ onClose, statusId }) => {
const dispatch = useAppDispatch();
const accountIds = useAppSelector((state) => state.user_lists.event_participations[statusId]?.items);
const fetchData = () => {
dispatch(fetchEventParticipations(statusId));
};
useEffect(() => {
fetchData();
}, []);
const { data: accountIds, isLoading, hasNextPage, fetchNextPage } = useEventParticipations(statusId);
const onClickClose = () => {
onClose('EVENT_PARTICIPANTS');
@ -45,10 +33,11 @@ const EventParticipantsModal: React.FC<BaseModalProps & EventParticipantsModalPr
listClassName='max-w-full'
itemClassName='pb-3'
estimatedSize={42}
hasMore={hasNextPage}
isLoading={typeof isLoading === 'boolean' ? isLoading : true}
onLoadMore={() => fetchNextPage({ cancelRefetch: false })}
>
{accountIds.map(id =>
<AccountContainer key={id} id={id} />,
)}
{accountIds.map(id => <AccountContainer key={id} id={id} />)}
</ScrollableList>
);
}

View file

@ -2,7 +2,6 @@ import { create } from 'mutative';
import { type CredentialAccount, type Instance, type MediaAttachment, type Tag } from 'pl-api';
import { INSTANCE_FETCH_SUCCESS, type InstanceAction } from 'pl-fe/actions/instance';
import { isNativeEmoji, type Emoji } from 'pl-fe/features/emoji';
import { tagHistory } from 'pl-fe/settings';
import {
@ -36,7 +35,6 @@ import {
COMPOSE_LANGUAGE_ADD,
COMPOSE_LANGUAGE_DELETE,
COMPOSE_ADD_SUGGESTED_LANGUAGE,
COMPOSE_EMOJI_INSERT,
COMPOSE_UPLOAD_CHANGE_REQUEST,
COMPOSE_UPLOAD_CHANGE_SUCCESS,
COMPOSE_UPLOAD_CHANGE_FAIL,
@ -67,6 +65,7 @@ import { FE_NAME } from '../actions/settings';
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
import { unescapeHTML } from '../utils/html';
import type { Emoji } from 'pl-fe/features/emoji';
import type { Language } from 'pl-fe/features/preferences';
import type { Account } from 'pl-fe/normalizers/account';
import type { Status } from 'pl-fe/normalizers/status';
@ -245,17 +244,6 @@ const updateSuggestionTags = (compose: Compose, token: string, tags: Tag[]) => {
compose.suggestion_token = token;
};
const insertEmoji = (compose: Compose, position: number, emojiData: Emoji, needsSpace: boolean) => {
const oldText = compose.text;
const emojiText = isNativeEmoji(emojiData) ? emojiData.native : emojiData.colons;
const emoji = needsSpace ? ' ' + emojiText : emojiText;
compose.text = `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`;
compose.focusDate = new Date();
compose.caretPosition = position + emoji.length + 1;
compose.idempotencyKey = crypto.randomUUID();
};
const privacyPreference = (a: string, b: string) => {
const order = ['public', 'unlisted', 'mutuals_only', 'private', 'direct', 'local'];
@ -513,8 +501,6 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
compose.quote = null;
}
});
case COMPOSE_EMOJI_INSERT:
return updateCompose(state, action.composeId, compose => insertEmoji(compose, action.position, action.emoji, action.needsSpace));
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
return updateCompose(state, action.composeId, compose => {
compose.is_changing_upload = false;

View file

@ -10,8 +10,6 @@ import {
type AccountsAction,
} from 'pl-fe/actions/accounts';
import {
EVENT_PARTICIPATIONS_EXPAND_SUCCESS,
EVENT_PARTICIPATIONS_FETCH_SUCCESS,
EVENT_PARTICIPATION_REQUESTS_EXPAND_SUCCESS,
EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS,
EVENT_PARTICIPATION_REQUEST_AUTHORIZE_SUCCESS,
@ -182,10 +180,6 @@ const userLists = (state = initialState, action: AccountsAction | EventsAction |
return normalizeList(state, ['birthday_reminders', action.accountId], action.accounts);
case FAMILIAR_FOLLOWERS_FETCH_SUCCESS:
return normalizeList(state, ['familiar_followers', action.accountId], action.accounts);
case EVENT_PARTICIPATIONS_FETCH_SUCCESS:
return normalizeList(state, ['event_participations', action.statusId], action.accounts, action.next);
case EVENT_PARTICIPATIONS_EXPAND_SUCCESS:
return appendToList(state, ['event_participations', action.statusId], action.accounts, action.next);
case EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS:
return create(state, (draft) => {
draft.event_participation_requests[action.statusId] = {