From 456658d71de9b50b54b5235f77dc87a5dbae2d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Sun, 1 Mar 2026 19:03:15 +0100 Subject: [PATCH] nicolium: don't make unneeded mfa settings request MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- .../queries/accounts/use-follow-requests.ts | 5 +-- .../src/queries/admin/use-announcements.ts | 12 ++--- packages/nicolium/src/queries/chats.ts | 42 +++++++++-------- .../src/queries/groups/use-group-blocks.ts | 3 +- .../src/queries/groups/use-group-members.ts | 19 +++----- .../notifications/use-notifications.ts | 16 ++++--- .../src/queries/security/oauth-tokens.ts | 15 +++---- .../nicolium/src/queries/security/use-mfa.ts | 3 ++ .../queries/statuses/scheduled-statuses.ts | 14 +++--- .../src/queries/timelines/use-events-lists.ts | 8 ++-- .../nicolium/src/queries/utils/filter-id.ts | 45 ++++++++++--------- .../utils/update-paginated-response.ts | 8 ++-- packages/nicolium/src/utils/queries.ts | 38 +++++++++------- 13 files changed, 115 insertions(+), 113 deletions(-) diff --git a/packages/nicolium/src/queries/accounts/use-follow-requests.ts b/packages/nicolium/src/queries/accounts/use-follow-requests.ts index 666d568d9..e73eaace5 100644 --- a/packages/nicolium/src/queries/accounts/use-follow-requests.ts +++ b/packages/nicolium/src/queries/accounts/use-follow-requests.ts @@ -1,4 +1,5 @@ import { useMutation, useQueryClient, type InfiniteData } from '@tanstack/react-query'; +import { PaginatedResponse, type PlApiClient } from 'pl-api'; import { useClient } from '@/hooks/use-client'; import { queryClient } from '@/queries/client'; @@ -8,8 +9,6 @@ import { minifyAccountList } from '@/queries/utils/minify-list'; import { filterById } from '../utils/filter-id'; -import type { PaginatedResponse, PlApiClient } from 'pl-api'; - const appendFollowRequest = (accountId: string) => queryClient.setQueryData(queryKeys.accountsLists.followRequests, (data) => { if (!data || data.pages.some((page) => page.items.includes(accountId))) return data; @@ -17,7 +16,7 @@ const appendFollowRequest = (accountId: string) => return { ...data, pages: data.pages.map((page, index) => - index === 0 ? { ...page, items: [accountId, ...page.items] } : page, + index === 0 ? new PaginatedResponse([accountId, ...page.items], page) : page, ), }; }); diff --git a/packages/nicolium/src/queries/admin/use-announcements.ts b/packages/nicolium/src/queries/admin/use-announcements.ts index 15de8f72a..c79e3348a 100644 --- a/packages/nicolium/src/queries/admin/use-announcements.ts +++ b/packages/nicolium/src/queries/admin/use-announcements.ts @@ -9,6 +9,7 @@ import * as v from 'valibot'; import { useClient } from '@/hooks/use-client'; import { queryClient } from '@/queries/client'; +import { removePageItem } from '@/utils/queries'; import { queryKeys } from '../keys'; import { makePaginatedResponseQuery } from '../utils/make-paginated-response-query'; @@ -67,12 +68,11 @@ const useDeleteAnnouncementMutation = () => { mutationFn: (id: string) => client.admin.announcements.deleteAnnouncement(id), retry: false, onSuccess: (_, deletedAnnouncementId) => { - queryClient.setQueryData(queryKeys.admin.announcements, (prevData) => - create(prevData, (draft) => { - draft?.pages.forEach( - (page) => (page.items = page.items.filter(({ id }) => id !== deletedAnnouncementId)), - ); - }), + removePageItem( + queryKeys.admin.announcements, + deletedAnnouncementId, + (announcement: { id: string }, id: string) => announcement.id === id, + true, ); queryClient.invalidateQueries({ queryKey: queryKeys.announcements.root }); }, diff --git a/packages/nicolium/src/queries/chats.ts b/packages/nicolium/src/queries/chats.ts index 468653788..2679715f5 100644 --- a/packages/nicolium/src/queries/chats.ts +++ b/packages/nicolium/src/queries/chats.ts @@ -207,29 +207,27 @@ const useCreateChatMessage = () => { queryClient.setQueryData(queryKeys.chats.chatMessages(variables.chatId), (prevResult) => { if (!prevResult?.pages) return prevResult; const newResult = { ...prevResult }; - newResult.pages = newResult.pages.map((page, idx: number) => { - if (idx === 0) { - return { - ...page, - items: [ - normalizeChatMessage({ - ...v.parse(chatMessageSchema, { - chat_id: variables.chatId, - content: variables.content, - id: pendingId, - created_at: new Date().toISOString(), - account_id: account?.id, - unread: true, - }), - pending: true, + const [firstPage, ...restPages] = newResult.pages; + newResult.pages = [ + new PaginatedResponse( + [ + normalizeChatMessage({ + ...v.parse(chatMessageSchema, { + chat_id: variables.chatId, + content: variables.content, + id: pendingId, + created_at: new Date().toISOString(), + account_id: account?.id, + unread: true, }), - ...page.items, - ], - }; - } - - return page; - }); + pending: true, + }), + ...firstPage.items, + ], + firstPage, + ), + ...restPages, + ]; return newResult; }); diff --git a/packages/nicolium/src/queries/groups/use-group-blocks.ts b/packages/nicolium/src/queries/groups/use-group-blocks.ts index a909d1552..828d85d94 100644 --- a/packages/nicolium/src/queries/groups/use-group-blocks.ts +++ b/packages/nicolium/src/queries/groups/use-group-blocks.ts @@ -1,4 +1,5 @@ import { useMutation } from '@tanstack/react-query'; +import { PaginatedResponse } from 'pl-api'; import { useClient } from '@/hooks/use-client'; import { queryClient } from '@/queries/client'; @@ -17,7 +18,7 @@ const appendGroupBlock = (groupId: string, accountId: string) => return { ...data, pages: data.pages.map((page, index) => - index === 0 ? { ...page, items: [accountId, ...page.items] } : page, + index === 0 ? new PaginatedResponse([accountId, ...page.items], page) : page, ), }; }); diff --git a/packages/nicolium/src/queries/groups/use-group-members.ts b/packages/nicolium/src/queries/groups/use-group-members.ts index c5801c8d1..adcde9493 100644 --- a/packages/nicolium/src/queries/groups/use-group-members.ts +++ b/packages/nicolium/src/queries/groups/use-group-members.ts @@ -1,7 +1,8 @@ -import { type InfiniteData, useMutation, useQueryClient } from '@tanstack/react-query'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useClient } from '@/hooks/use-client'; import { makePaginatedResponseQuery } from '@/queries/utils/make-paginated-response-query'; +import { removePageItem } from '@/utils/queries'; import { queryClient } from '../client'; import { queryKeys } from '../keys'; @@ -10,18 +11,10 @@ import { minifyAccountList, minifyList } from '../utils/minify-list'; import type { GroupMember, GroupRole, PaginatedResponse } from 'pl-api'; const removeGroupMember = (groupId: string, accountId: string) => - queryClient.setQueriesData>>( - { queryKey: queryKeys.accountsLists.groupMembers.root(groupId) }, - (data) => - data - ? { - ...data, - pages: data.pages.map((page) => ({ - ...page, - items: page.items.filter((member) => member.account_id !== accountId), - })), - } - : undefined, + removePageItem( + queryKeys.accountsLists.groupMembers.root(groupId), + accountId, + (member: MinifiedGroupMember, accountId: string) => member.account_id === accountId, ); const minifyGroupMember = ({ account, ...groupMember }: GroupMember) => ({ diff --git a/packages/nicolium/src/queries/notifications/use-notifications.ts b/packages/nicolium/src/queries/notifications/use-notifications.ts index 1bae8c83e..a838c510d 100644 --- a/packages/nicolium/src/queries/notifications/use-notifications.ts +++ b/packages/nicolium/src/queries/notifications/use-notifications.ts @@ -1,6 +1,12 @@ import { useInfiniteQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import 'intl-pluralrules'; import omit from 'lodash/omit'; +import { + PaginatedResponse, + type GetGroupedNotificationsParams, + type Notification, + type NotificationGroup, +} from 'pl-api'; import { useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; @@ -30,8 +36,6 @@ import { useFiltersByContext } from '../settings/use-filters'; import { useStatus } from '../statuses/use-status'; import { minifyGroupedNotifications } from '../utils/minify-list'; -import type { GetGroupedNotificationsParams, Notification, NotificationGroup } from 'pl-api'; - const FILTER_TYPES = { all: undefined, mention: ['mention', 'quote'], @@ -338,10 +342,10 @@ const prependNotification = (notification: NotificationGroup, filter: FilterType return { ...data, pages: [ - { - ...firstPage, - items: [notification, ...firstPage.items].toSorted(comparator).filter(filterUnique), - }, + new PaginatedResponse, false>( + [notification, ...firstPage.items].toSorted(comparator).filter(filterUnique), + firstPage, + ), ...restPages, ], }; diff --git a/packages/nicolium/src/queries/security/oauth-tokens.ts b/packages/nicolium/src/queries/security/oauth-tokens.ts index 9f9b25a6b..925f3012c 100644 --- a/packages/nicolium/src/queries/security/oauth-tokens.ts +++ b/packages/nicolium/src/queries/security/oauth-tokens.ts @@ -1,8 +1,6 @@ -import { create } from 'mutative'; - import { getClient } from '@/api'; +import { removePageItem } from '@/utils/queries'; -import { queryClient } from '../client'; import { queryKeys } from '../keys'; import { makePaginatedResponseQueryOptions } from '../utils/make-paginated-response-query-options'; import { mutationOptions } from '../utils/mutation-options'; @@ -17,12 +15,11 @@ const revokeOauthTokenMutationOptions = (oauthTokenId: string) => mutationKey: ['security', 'oauthTokens', oauthTokenId], mutationFn: () => getClient().settings.deleteOauthToken(oauthTokenId), onSettled: () => { - queryClient.setQueryData(oauthTokensQueryOptions.queryKey, (data) => - create(data, (draft) => { - draft?.pages.forEach( - (page) => (page.items = page.items.filter(({ id }) => id !== oauthTokenId)), - ); - }), + removePageItem( + queryKeys.security.oauthTokens, + oauthTokenId, + (token: { id: string }, tokenId: string) => token.id === tokenId, + true, ); }, }); diff --git a/packages/nicolium/src/queries/security/use-mfa.ts b/packages/nicolium/src/queries/security/use-mfa.ts index d91440b5c..5314c4a0b 100644 --- a/packages/nicolium/src/queries/security/use-mfa.ts +++ b/packages/nicolium/src/queries/security/use-mfa.ts @@ -1,15 +1,18 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useClient } from '@/hooks/use-client'; +import { useFeatures } from '@/hooks/use-features'; import { queryKeys } from '../keys'; const useMfaConfig = () => { const client = useClient(); + const features = useFeatures(); return useQuery({ queryKey: queryKeys.settings.mfa, queryFn: () => client.settings.mfa.getMfaSettings(), + enabled: features.manageMfa, }); }; diff --git a/packages/nicolium/src/queries/statuses/scheduled-statuses.ts b/packages/nicolium/src/queries/statuses/scheduled-statuses.ts index de6541504..dc961b42b 100644 --- a/packages/nicolium/src/queries/statuses/scheduled-statuses.ts +++ b/packages/nicolium/src/queries/statuses/scheduled-statuses.ts @@ -1,9 +1,8 @@ import { infiniteQueryOptions } from '@tanstack/react-query'; -import { create } from 'mutative'; import { getClient } from '@/api'; +import { removePageItem } from '@/utils/queries'; -import { queryClient } from '../client'; import { queryKeys } from '../keys'; import { makePaginatedResponseQueryOptions } from '../utils/make-paginated-response-query-options'; import { mutationOptions } from '../utils/mutation-options'; @@ -23,12 +22,11 @@ const cancelScheduledStatusMutationOptions = (scheduledStatusId: string) => mutationKey: ['scheduledStatuses', scheduledStatusId], mutationFn: () => getClient().scheduledStatuses.cancelScheduledStatus(scheduledStatusId), onSettled: () => { - queryClient.setQueryData(scheduledStatusesQueryOptions.queryKey, (data) => - create(data, (draft) => { - draft?.pages.forEach( - (page) => (page.items = page.items.filter(({ id }) => id !== scheduledStatusId)), - ); - }), + removePageItem( + queryKeys.scheduledStatuses.all, + scheduledStatusId, + (status: { id: string }, id: string) => status.id === id, + true, ); }, }); diff --git a/packages/nicolium/src/queries/timelines/use-events-lists.ts b/packages/nicolium/src/queries/timelines/use-events-lists.ts index 163ccddb8..e431ef8df 100644 --- a/packages/nicolium/src/queries/timelines/use-events-lists.ts +++ b/packages/nicolium/src/queries/timelines/use-events-lists.ts @@ -11,10 +11,10 @@ const recentEventsQueryOptions = makePaginatedResponseQueryOptions( .publicTimeline({ only_events: true, }) - .then((res) => ({ - ...res, - items: res.items.filter(({ event }) => event), - })) + .then((res) => { + res.items = res.items.filter(({ event }) => event); + return res; + }) .then(minifyStatusList), )(); diff --git a/packages/nicolium/src/queries/utils/filter-id.ts b/packages/nicolium/src/queries/utils/filter-id.ts index 77da75fb1..3a59a69b2 100644 --- a/packages/nicolium/src/queries/utils/filter-id.ts +++ b/packages/nicolium/src/queries/utils/filter-id.ts @@ -1,31 +1,36 @@ -import { create } from 'mutative'; +import { PaginatedResponse } from 'pl-api'; import type { InfiniteData } from '@tanstack/react-query'; -import type { PaginatedResponse } from 'pl-api'; const filterById = (filteredId: string | Array) => (data: InfiniteData> | undefined) => { if (data) { - return create(data, (data) => { - let found = 0; - data.pages.forEach((page) => { - page.items = page.items.filter((id) => { - if (Array.isArray(filteredId)) { - const includes = filteredId.includes(id); - if (includes) found += 1; - return !includes; - } - if (id === filteredId) found = 1; - return id !== filteredId; - }); + let found = 0; + let pages = data.pages.map( + (page) => + new PaginatedResponse( + page.items.filter((id) => { + if (Array.isArray(filteredId)) { + const includes = filteredId.includes(id); + if (includes) found += 1; + return !includes; + } + if (id === filteredId) found = 1; + return id !== filteredId; + }), + page, + ), + ); + if (found) { + pages.forEach((page) => { + if (page.total) page.total -= found; }); - - if (found) - data.pages.forEach((page) => { - if (page.total) page.total -= found; - }); - }); + } + return { + ...data, + pages, + }; } }; diff --git a/packages/nicolium/src/queries/utils/update-paginated-response.ts b/packages/nicolium/src/queries/utils/update-paginated-response.ts index c0fc674cf..95a0bfb0a 100644 --- a/packages/nicolium/src/queries/utils/update-paginated-response.ts +++ b/packages/nicolium/src/queries/utils/update-paginated-response.ts @@ -1,7 +1,8 @@ +import { PaginatedResponse } from 'pl-api'; + import { queryClient } from '@/queries/client'; import type { DataTag, InfiniteData, QueryKey } from '@tanstack/react-query'; -import type { PaginatedResponse } from 'pl-api'; type InferPaginatedItem = TKey extends DataTag>> ? U : never; @@ -18,10 +19,7 @@ const updatePaginatedResponse = < if (!data) return undefined; return { ...data, - pages: data.pages.map((page) => ({ - ...page, - items: updater(page.items), - })), + pages: data.pages.map((page) => new PaginatedResponse(updater(page.items), page)), }; }); diff --git a/packages/nicolium/src/utils/queries.ts b/packages/nicolium/src/utils/queries.ts index 631b24320..b265051ba 100644 --- a/packages/nicolium/src/utils/queries.ts +++ b/packages/nicolium/src/utils/queries.ts @@ -1,7 +1,8 @@ +import { PaginatedResponse } from 'pl-api'; + import { queryClient } from '@/queries/client'; import type { DataTag, InfiniteData, QueryKey } from '@tanstack/react-query'; -import type { PaginatedResponse } from 'pl-api'; interface Entity { id: string; @@ -44,7 +45,7 @@ const updatePageItem = ( if (data) { const pages = data.pages.map((page) => { const result = page.items.map((item) => (isItem(item, newItem) ? newItem : item)); - return { ...page, result }; + return new PaginatedResponse(result, page); }); return { ...data, pages }; } @@ -59,27 +60,34 @@ const appendPageItem = ( queryClient.setQueryData(queryKey, (data) => { if (data) { const pages = [...data.pages]; - pages[0] = { ...pages[0], items: [newItem, ...pages[0].items] }; + pages[0] = new PaginatedResponse([newItem, ...pages[0].items], pages[0]); return { ...data, pages }; } }); }; /** Remove an item inside if found. */ -const removePageItem = ( +const removePageItem = ( queryKey: QueryKey, - itemToRemove: T, - isItem: (item: T, newItem: T) => boolean, + itemToRemove: T2, + isItem: (item: T1, itemToRemove: T2) => boolean, + exact = false, ) => { - queryClient.setQueriesData>>({ queryKey }, (data) => { + const updater = (data: InfiniteData> | undefined) => { if (data) { - const pages = data.pages.map((page) => { - const items = page.items.filter((item) => !isItem(item, itemToRemove)); - return { ...page, items }; - }); + const pages = data.pages.map( + (page) => + new PaginatedResponse( + page.items.filter((item) => !isItem(item, itemToRemove)), + page, + ), + ); return { ...data, pages }; } - }); + }; + + if (exact) queryClient.setQueryData(queryKey, updater); + else queryClient.setQueriesData({ queryKey }, updater); }; const paginateQueryData = (array: T[] | undefined) => @@ -104,10 +112,8 @@ const sortQueryData = ( const sortedQueryData = flattenedQueryData?.toSorted(comparator); const paginatedPages = paginateQueryData(sortedQueryData); const newPages = - paginatedPages?.map((page, idx) => ({ - ...prevResult.pages[idx], - result: page, - })) ?? []; + paginatedPages?.map((page, idx) => new PaginatedResponse(page, prevResult.pages[idx])) ?? + []; nextResult.pages = newPages; return nextResult;