diff --git a/packages/pl-api/lib/client.ts b/packages/pl-api/lib/client.ts index a1dd33ae9..407c41851 100644 --- a/packages/pl-api/lib/client.ts +++ b/packages/pl-api/lib/client.ts @@ -2214,11 +2214,8 @@ class PlApiClient { * Requires features{@link Features['statusDislikes']}. * @see {@link https://github.com/friendica/friendica/blob/2024.06-rc/doc/API-Friendica.md#get-apifriendicastatusesiddisliked_by} */ - getDislikedBy: async (statusId: string) => { - const response = await this.request(`/api/friendica/statuses/${statusId}/disliked_by`); - - return v.parse(filteredArray(accountSchema), response.json); - }, + getDislikedBy: async (statusId: string) => + this.#paginatedGet(`/api/v1/statuses/${statusId}/disliked_by`, {}, accountSchema), /** * Marks the given status as disliked by this user diff --git a/packages/pl-fe/src/actions/compose.ts b/packages/pl-fe/src/actions/compose.ts index 417e0a2f7..7d246fdbe 100644 --- a/packages/pl-fe/src/actions/compose.ts +++ b/packages/pl-fe/src/actions/compose.ts @@ -343,7 +343,6 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}) => const compose = state.compose[composeId]!; - const status = compose.text; const media = compose.media_attachments; const statusId = compose.id; @@ -782,7 +781,6 @@ const deleteComposeLanguage = (composeId: string, value: Language) => ({ value, }); - const addPoll = (composeId: string) => ({ type: COMPOSE_POLL_ADD, composeId, diff --git a/packages/pl-fe/src/actions/interactions.ts b/packages/pl-fe/src/actions/interactions.ts index 16cf7cdb0..5c224eebe 100644 --- a/packages/pl-fe/src/actions/interactions.ts +++ b/packages/pl-fe/src/actions/interactions.ts @@ -6,10 +6,9 @@ import { isLoggedIn } from 'pl-fe/utils/auth'; import { getClient } from '../api'; -import { fetchRelationships } from './accounts'; import { importEntities } from './importer'; -import type { Account, EmojiReaction, PaginatedResponse, Status } from 'pl-api'; +import type { Status } from 'pl-api'; import type { AppDispatch, RootState } from 'pl-fe/store'; const REBLOG_REQUEST = 'REBLOG_REQUEST' as const; @@ -36,22 +35,6 @@ const UNDISLIKE_REQUEST = 'UNDISLIKE_REQUEST' as const; const UNDISLIKE_SUCCESS = 'UNDISLIKE_SUCCESS' as const; const UNDISLIKE_FAIL = 'UNDISLIKE_FAIL' as const; -const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST' as const; -const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS' as const; -const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL' as const; - -const FAVOURITES_FETCH_REQUEST = 'FAVOURITES_FETCH_REQUEST' as const; -const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS' as const; -const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL' as const; - -const DISLIKES_FETCH_REQUEST = 'DISLIKES_FETCH_REQUEST' as const; -const DISLIKES_FETCH_SUCCESS = 'DISLIKES_FETCH_SUCCESS' as const; -const DISLIKES_FETCH_FAIL = 'DISLIKES_FETCH_FAIL' as const; - -const REACTIONS_FETCH_REQUEST = 'REACTIONS_FETCH_REQUEST' as const; -const REACTIONS_FETCH_SUCCESS = 'REACTIONS_FETCH_SUCCESS' as const; -const REACTIONS_FETCH_FAIL = 'REACTIONS_FETCH_FAIL' as const; - const PIN_REQUEST = 'PIN_REQUEST' as const; const PIN_SUCCESS = 'PIN_SUCCESS' as const; const PIN_FAIL = 'PIN_FAIL' as const; @@ -80,8 +63,6 @@ const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL' as const; const noOp = () => new Promise(f => f(undefined)); -type AccountListLink = () => Promise>; - const messages = defineMessages({ bookmarkAdded: { id: 'status.bookmarked', defaultMessage: 'Bookmark added.' }, bookmarkRemoved: { id: 'status.unbookmarked', defaultMessage: 'Bookmark removed.' }, @@ -386,175 +367,6 @@ const unbookmarkFail = (statusId: string, error: unknown) => ({ error, }); -const fetchReblogs = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchReblogsRequest(statusId)); - - return getClient(getState()).statuses.getRebloggedBy(statusId).then(response => { - dispatch(importEntities({ accounts: response.items })); - dispatch(fetchRelationships(response.items.map((item) => item.id))); - dispatch(fetchReblogsSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(fetchReblogsFail(statusId, error)); - }); - }; - -const fetchReblogsRequest = (statusId: string) => ({ - type: REBLOGS_FETCH_REQUEST, - statusId, -}); - -const fetchReblogsSuccess = (statusId: string, accounts: Array, next: AccountListLink | null) => ({ - type: REBLOGS_FETCH_SUCCESS, - statusId, - accounts, - next, -}); - -const fetchReblogsFail = (statusId: string, error: unknown) => ({ - type: REBLOGS_FETCH_FAIL, - statusId, - error, -}); - -const expandReblogs = (statusId: string, next: AccountListLink) => - (dispatch: AppDispatch, getState: () => RootState) => { - next().then(response => { - dispatch(importEntities({ accounts: response.items })); - dispatch(fetchRelationships(response.items.map((item) => item.id))); - dispatch(expandReblogsSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(expandReblogsFail(statusId, error)); - }); - }; - -const expandReblogsSuccess = (statusId: string, accounts: Array, next: AccountListLink | null) => ({ - type: REBLOGS_EXPAND_SUCCESS, - statusId, - accounts, - next, -}); - -const expandReblogsFail = (statusId: string, error: unknown) => ({ - type: REBLOGS_EXPAND_FAIL, - statusId, - error, -}); - -const fetchFavourites = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchFavouritesRequest(statusId)); - - return getClient(getState()).statuses.getFavouritedBy(statusId).then(response => { - dispatch(importEntities({ accounts: response.items })); - dispatch(fetchRelationships(response.items.map((item) => item.id))); - dispatch(fetchFavouritesSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(fetchFavouritesFail(statusId, error)); - }); - }; - -const fetchFavouritesRequest = (statusId: string) => ({ - type: FAVOURITES_FETCH_REQUEST, - statusId, -}); - -const fetchFavouritesSuccess = (statusId: string, accounts: Array, next: AccountListLink | null) => ({ - type: FAVOURITES_FETCH_SUCCESS, - statusId, - accounts, - next, -}); - -const fetchFavouritesFail = (statusId: string, error: unknown) => ({ - type: FAVOURITES_FETCH_FAIL, - statusId, - error, -}); - -const expandFavourites = (statusId: string, next: AccountListLink) => - (dispatch: AppDispatch) => { - next().then(response => { - dispatch(importEntities({ accounts: response.items })); - dispatch(fetchRelationships(response.items.map((item) => item.id))); - dispatch(expandFavouritesSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(expandFavouritesFail(statusId, error)); - }); - }; - -const expandFavouritesSuccess = (statusId: string, accounts: Array, next: AccountListLink | null) => ({ - type: FAVOURITES_EXPAND_SUCCESS, - statusId, - accounts, - next, -}); - -const expandFavouritesFail = (statusId: string, error: unknown) => ({ - type: FAVOURITES_EXPAND_FAIL, - statusId, - error, -}); - -const fetchDislikes = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchDislikesRequest(statusId)); - - return getClient(getState).statuses.getDislikedBy(statusId).then(response => { - dispatch(importEntities({ accounts: response })); - dispatch(fetchRelationships(response.map((item) => item.id))); - dispatch(fetchDislikesSuccess(statusId, response)); - }).catch(error => { - dispatch(fetchDislikesFail(statusId, error)); - }); - }; - -const fetchDislikesRequest = (statusId: string) => ({ - type: DISLIKES_FETCH_REQUEST, - statusId, -}); - -const fetchDislikesSuccess = (statusId: string, accounts: Array) => ({ - type: DISLIKES_FETCH_SUCCESS, - statusId, - accounts, -}); - -const fetchDislikesFail = (statusId: string, error: unknown) => ({ - type: DISLIKES_FETCH_FAIL, - statusId, - error, -}); - -const fetchReactions = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchReactionsRequest(statusId)); - - return getClient(getState).statuses.getStatusReactions(statusId).then(response => { - dispatch(importEntities({ accounts: (response).map(({ accounts }) => accounts).flat() })); - dispatch(fetchReactionsSuccess(statusId, response)); - }).catch(error => { - dispatch(fetchReactionsFail(statusId, error)); - }); - }; - -const fetchReactionsRequest = (statusId: string) => ({ - type: REACTIONS_FETCH_REQUEST, - statusId, -}); - -const fetchReactionsSuccess = (statusId: string, reactions: EmojiReaction[]) => ({ - type: REACTIONS_FETCH_SUCCESS, - statusId, - reactions, -}); - -const fetchReactionsFail = (statusId: string, error: unknown) => ({ - type: REACTIONS_FETCH_FAIL, - statusId, - error, -}); - const pin = (status: Pick, accountId: string) => (dispatch: AppDispatch, getState: () => RootState) => { if (!isLoggedIn(getState)) return; @@ -695,22 +507,6 @@ type InteractionsAction = | ReturnType | ReturnType | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType | ReturnType | ReturnType | ReturnType @@ -740,18 +536,6 @@ export { UNDISLIKE_REQUEST, UNDISLIKE_SUCCESS, UNDISLIKE_FAIL, - REBLOGS_FETCH_REQUEST, - REBLOGS_FETCH_SUCCESS, - REBLOGS_FETCH_FAIL, - FAVOURITES_FETCH_REQUEST, - FAVOURITES_FETCH_SUCCESS, - FAVOURITES_FETCH_FAIL, - DISLIKES_FETCH_REQUEST, - DISLIKES_FETCH_SUCCESS, - DISLIKES_FETCH_FAIL, - REACTIONS_FETCH_REQUEST, - REACTIONS_FETCH_SUCCESS, - REACTIONS_FETCH_FAIL, PIN_REQUEST, PIN_SUCCESS, PIN_FAIL, @@ -783,12 +567,6 @@ export { bookmark, unbookmark, toggleBookmark, - fetchReblogs, - expandReblogs, - fetchFavourites, - expandFavourites, - fetchDislikes, - fetchReactions, pin, unpin, togglePin, diff --git a/packages/pl-fe/src/api/hooks/account-lists/use-status-interactions.ts b/packages/pl-fe/src/api/hooks/account-lists/use-status-interactions.ts new file mode 100644 index 000000000..524413547 --- /dev/null +++ b/packages/pl-fe/src/api/hooks/account-lists/use-status-interactions.ts @@ -0,0 +1,47 @@ +import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; + +import { importEntities } from 'pl-fe/actions/importer'; +import { minifyAccountList } from 'pl-fe/api/normalizers/minify-list'; +import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; +import { useClient } from 'pl-fe/hooks/use-client'; + +import type { PaginatedResponse } from 'pl-api'; + +const useStatusInteractions = (statusId: string, method: 'getDislikedBy' | 'getFavouritedBy' | 'getRebloggedBy') => { + const client = useClient(); + + const queryKey = { + getDislikedBy: 'statusDislikes', + getFavouritedBy: 'statusFavourites', + getRebloggedBy: 'statusReblogs', + }[method]; + + return useInfiniteQuery({ + queryKey: ['accountsLists', queryKey, statusId], + queryFn: ({ pageParam }) => pageParam.next?.() || client.statuses[method](statusId).then(minifyAccountList), + initialPageParam: { previous: null, next: null, items: [], partial: false } as PaginatedResponse, + getNextPageParam: (page) => page.next ? page : undefined, + select: (data) => data.pages.map(page => page.items).flat(), + }); +}; + +const useStatusDislikes = (statusId: string) => useStatusInteractions(statusId, 'getDislikedBy'); +const useStatusFavourites = (statusId: string) => useStatusInteractions(statusId, 'getFavouritedBy'); +const useStatusReblogs = (statusId: string) => useStatusInteractions(statusId, 'getRebloggedBy'); + +const useStatusReactions = (statusId: string, emoji?: string) => { + const client = useClient(); + const dispatch = useAppDispatch(); + + return useQuery({ + queryKey: ['accountsLists', 'statusReactions', statusId, emoji], + queryFn: () => client.statuses.getStatusReactions(statusId, emoji).then((reactions) => { + dispatch(importEntities({ accounts: reactions.map(({ accounts }) => accounts).flat() })); + + return reactions.map(({ accounts, ...reactions }) => reactions); + }), + placeholderData: (previousData) => previousData?.filter(({ name }) => name === emoji), + }); +}; + +export { useStatusDislikes, useStatusFavourites, useStatusReactions, useStatusReblogs }; diff --git a/packages/pl-fe/src/features/ui/components/modals/dislikes-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/dislikes-modal.tsx index f204c2dde..75f001db3 100644 --- a/packages/pl-fe/src/features/ui/components/modals/dislikes-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/dislikes-modal.tsx @@ -1,13 +1,11 @@ -import React, { useEffect } from 'react'; +import React, { useRef } from 'react'; import { FormattedMessage } from 'react-intl'; -import { fetchDislikes } from 'pl-fe/actions/interactions'; +import { useStatusDislikes } from 'pl-fe/api/hooks/account-lists/use-status-interactions'; 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,9 @@ interface DislikesModalProps { } const DislikesModal: React.FC = ({ onClose, statusId }) => { - const dispatch = useAppDispatch(); + const modalRef = useRef(null); - const accountIds = useAppSelector((state) => state.user_lists.disliked_by[statusId]?.items); - - const fetchData = () => { - dispatch(fetchDislikes(statusId)); - }; - - useEffect(() => { - fetchData(); - }, []); + const { data: accountIds, isLoading, hasNextPage, fetchNextPage } = useStatusDislikes(statusId); const onClickClose = () => { onClose('DISLIKES'); @@ -44,7 +34,12 @@ const DislikesModal: React.FC = ({ onClose, emptyMessage={emptyMessage} listClassName='max-w-full' itemClassName='pb-3' + style={{ height: 'calc(80vh - 88px)' }} + hasMore={hasNextPage} + isLoading={typeof isLoading === 'boolean' ? isLoading : true} + onLoadMore={() => fetchNextPage({ cancelRefetch: false })} estimatedSize={42} + parentRef={modalRef} > {accountIds.map(id => , @@ -57,6 +52,7 @@ const DislikesModal: React.FC = ({ onClose, } onClose={onClickClose} + ref={modalRef} > {body} diff --git a/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx index bf9de64fa..f0db47e6a 100644 --- a/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/favourites-modal.tsx @@ -1,13 +1,11 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useRef } from 'react'; import { FormattedMessage } from 'react-intl'; -import { fetchFavourites, expandFavourites } from 'pl-fe/actions/interactions'; +import { useStatusFavourites } from 'pl-fe/api/hooks/account-lists/use-status-interactions'; 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'; @@ -17,29 +15,13 @@ interface FavouritesModalProps { const FavouritesModal: React.FC = ({ onClose, statusId }) => { const modalRef = useRef(null); - const dispatch = useAppDispatch(); - const accountIds = useAppSelector((state) => state.user_lists.favourited_by[statusId]?.items); - const next = useAppSelector((state) => state.user_lists.favourited_by[statusId]?.next); - - const fetchData = () => { - dispatch(fetchFavourites(statusId)); - }; - - useEffect(() => { - fetchData(); - }, []); + const { data: accountIds, isLoading, hasNextPage, fetchNextPage } = useStatusFavourites(statusId); const onClickClose = () => { onClose('FAVOURITES'); }; - const handleLoadMore = () => { - if (next) { - dispatch(expandFavourites(statusId, next!)); - } - }; - let body; if (!accountIds) { @@ -53,8 +35,9 @@ const FavouritesModal: React.FC = ({ onCl listClassName='max-w-full' itemClassName='pb-3' style={{ height: 'calc(80vh - 88px)' }} - onLoadMore={handleLoadMore} - hasMore={!!next} + hasMore={hasNextPage} + isLoading={typeof isLoading === 'boolean' ? isLoading : true} + onLoadMore={() => fetchNextPage({ cancelRefetch: false })} estimatedSize={42} parentRef={modalRef} > diff --git a/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx index c91d0b7ce..1b06421b4 100644 --- a/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/reactions-modal.tsx @@ -1,16 +1,14 @@ import clsx from 'clsx'; -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { useMemo, useRef, useState } from 'react'; import { FormattedMessage, defineMessages, useIntl } from 'react-intl'; -import { fetchReactions } from 'pl-fe/actions/interactions'; +import { useStatusReactions } from 'pl-fe/api/hooks/account-lists/use-status-interactions'; import ScrollableList from 'pl-fe/components/scrollable-list'; import Emoji from 'pl-fe/components/ui/emoji'; import Modal from 'pl-fe/components/ui/modal'; import Spinner from 'pl-fe/components/ui/spinner'; import Tabs from 'pl-fe/components/ui/tabs'; 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'; import type { Item } from 'pl-fe/components/ui/tabs'; @@ -32,10 +30,10 @@ interface ReactionsModalProps { const ReactionsModal: React.FC = ({ onClose, statusId, reaction: initialReaction }) => { const modalRef = useRef(null); - const dispatch = useAppDispatch(); const intl = useIntl(); const [reaction, setReaction] = useState(initialReaction); - const reactions = useAppSelector((state) => state.user_lists.reactions[statusId]?.items); + + const { data: reactions, isLoading } = useStatusReactions(statusId); const onClickClose = () => { onClose('REACTIONS'); @@ -70,16 +68,12 @@ const ReactionsModal: React.FC = ({ onClos if (reaction) { const reactionRecord = reactions.find(({ name }) => name === reaction); - if (reactionRecord) return reactionRecord.accounts.map(account => ({ id: account, reaction: reaction, reactionUrl: reactionRecord.url || undefined })); + if (reactionRecord) return reactionRecord.account_ids.map(account => ({ id: account, reaction: reaction, reactionUrl: reactionRecord.url || undefined })); } else { - return reactions.map(({ accounts, name, url }) => accounts.map(account => ({ id: account, reaction: name, reactionUrl: url || undefined }))).flat(); + return reactions.map(({ account_ids, name, url }) => account_ids.map(account => ({ id: account, reaction: name, reactionUrl: url || undefined }))).flat(); } }, [reactions, reaction]); - useEffect(() => { - dispatch(fetchReactions(statusId)); - }, []); - let body; if (!accounts || !reactions) { @@ -96,6 +90,7 @@ const ReactionsModal: React.FC = ({ onClos })} itemClassName='pb-3' style={{ height: 'calc(80vh - 88px)' }} + isLoading={typeof isLoading === 'boolean' ? isLoading : true} estimatedSize={42} parentRef={modalRef} > diff --git a/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx index 45fc91a84..e7579ac87 100644 --- a/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/reblogs-modal.tsx @@ -1,14 +1,11 @@ -import React, { useEffect, useRef } from 'react'; -import { FormattedMessage, useIntl } from 'react-intl'; +import React, { useRef } from 'react'; +import { FormattedMessage } from 'react-intl'; -import { fetchReblogs, expandReblogs } from 'pl-fe/actions/interactions'; -import { fetchStatus } from 'pl-fe/actions/statuses'; +import { useStatusReblogs } from 'pl-fe/api/hooks/account-lists/use-status-interactions'; 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'; @@ -17,31 +14,14 @@ interface ReblogsModalProps { } const ReblogsModal: React.FC = ({ onClose, statusId }) => { - const dispatch = useAppDispatch(); - const intl = useIntl(); - const accountIds = useAppSelector((state) => state.user_lists.reblogged_by[statusId]?.items); - const next = useAppSelector((state) => state.user_lists.reblogged_by[statusId]?.next); const modalRef = useRef(null); - const fetchData = () => { - dispatch(fetchReblogs(statusId)); - dispatch(fetchStatus(statusId, intl)); - }; - - useEffect(() => { - fetchData(); - }, []); + const { data: accountIds, isLoading, hasNextPage, fetchNextPage } = useStatusReblogs(statusId); const onClickClose = () => { onClose('REBLOGS'); }; - const handleLoadMore = () => { - if (next) { - dispatch(expandReblogs(statusId, next!)); - } - }; - let body; if (!accountIds) { @@ -55,8 +35,9 @@ const ReblogsModal: React.FC = ({ onClose, s listClassName='max-w-full' itemClassName='pb-3' style={{ height: 'calc(80vh - 88px)' }} - onLoadMore={handleLoadMore} - hasMore={!!next} + hasMore={hasNextPage} + isLoading={typeof isLoading === 'boolean' ? isLoading : true} + onLoadMore={() => fetchNextPage({ cancelRefetch: false })} estimatedSize={42} parentRef={modalRef} > diff --git a/packages/pl-fe/src/reducers/user-lists.test.ts b/packages/pl-fe/src/reducers/user-lists.test.ts index a2477ada7..a42d8c31f 100644 --- a/packages/pl-fe/src/reducers/user-lists.test.ts +++ b/packages/pl-fe/src/reducers/user-lists.test.ts @@ -13,9 +13,7 @@ describe('user_lists reducer', () => { follow_requests: { next: null, items: ImmutableOrderedSet(), isLoading: false }, blocks: { next: null, items: ImmutableOrderedSet(), isLoading: false }, mutes: { next: null, items: ImmutableOrderedSet(), isLoading: false }, - directory: { next: null, items: ImmutableOrderedSet(), isLoading: true }, pinned: {}, - birthday_reminders: {}, familiar_followers: {}, }); }); diff --git a/packages/pl-fe/src/reducers/user-lists.ts b/packages/pl-fe/src/reducers/user-lists.ts index 0c37787b5..6da9da99b 100644 --- a/packages/pl-fe/src/reducers/user-lists.ts +++ b/packages/pl-fe/src/reducers/user-lists.ts @@ -16,15 +16,6 @@ import { GROUP_UNBLOCK_SUCCESS, type GroupsAction, } from 'pl-fe/actions/groups'; -import { - REBLOGS_FETCH_SUCCESS, - REBLOGS_EXPAND_SUCCESS, - FAVOURITES_FETCH_SUCCESS, - FAVOURITES_EXPAND_SUCCESS, - DISLIKES_FETCH_SUCCESS, - REACTIONS_FETCH_SUCCESS, - type InteractionsAction, -} from 'pl-fe/actions/interactions'; import { NOTIFICATIONS_UPDATE, type NotificationsAction } from 'pl-fe/actions/notifications'; import type { Account, NotificationGroup, PaginatedResponse } from 'pl-api'; @@ -35,31 +26,12 @@ interface List { isLoading: boolean; } -interface Reaction { - accounts: Array; - count: number | null; - name: string; - url: string | undefined; -} - -interface ReactionList { - next: (() => Promise>) | null; - items: Array; - isLoading: boolean; -} - type ListKey = 'follow_requests'; -type NestedListKey = 'reblogged_by' | 'favourited_by' | 'disliked_by' | 'pinned' | 'familiar_followers' | 'membership_requests' | 'group_blocks'; +type NestedListKey = 'pinned' | 'familiar_followers' | 'membership_requests' | 'group_blocks'; -type State = Record & Record> & { - reactions: Record; -}; +type State = Record & Record>; const initialState: State = { - reblogged_by: {}, - favourited_by: {}, - disliked_by: {}, - reactions: {}, follow_requests: { next: null, items: [], isLoading: false }, pinned: {}, familiar_followers: {}, @@ -122,26 +94,8 @@ const normalizeFollowRequest = (state: State, notification: NotificationGroup) = draft.follow_requests.items = [...new Set([...notification.sample_account_ids, ...draft.follow_requests.items])]; }); -const userLists = (state = initialState, action: AccountsAction | FamiliarFollowersAction | GroupsAction | InteractionsAction | NotificationsAction): State => { +const userLists = (state = initialState, action: AccountsAction | FamiliarFollowersAction | GroupsAction | NotificationsAction): State => { switch (action.type) { - case REBLOGS_FETCH_SUCCESS: - return normalizeList(state, ['reblogged_by', action.statusId], action.accounts, action.next); - case REBLOGS_EXPAND_SUCCESS: - return appendToList(state, ['reblogged_by', action.statusId], action.accounts, action.next); - case FAVOURITES_FETCH_SUCCESS: - return normalizeList(state, ['favourited_by', action.statusId], action.accounts, action.next); - case FAVOURITES_EXPAND_SUCCESS: - return appendToList(state, ['favourited_by', action.statusId], action.accounts, action.next); - case DISLIKES_FETCH_SUCCESS: - return normalizeList(state, ['disliked_by', action.statusId], action.accounts); - case REACTIONS_FETCH_SUCCESS: - return create(state, (draft) => { - draft.reactions[action.statusId] = { - items: action.reactions.map((reaction) => ({ ...reaction, accounts: reaction.accounts.map(({ id }) => id) })), - next: null, - isLoading: false, - }; - }); case NOTIFICATIONS_UPDATE: return action.notification.type === 'follow_request' ? normalizeFollowRequest(state, action.notification) : state; case FOLLOW_REQUESTS_FETCH_SUCCESS: