From 075cb159409b978ba163e8bb761bb5f11e80f484 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 22 Sep 2022 16:28:05 -0500 Subject: [PATCH] Add utils/queries, refactor streaming --- app/soapbox/actions/streaming.ts | 22 +++-------------- app/soapbox/queries/chats.ts | 11 +++------ app/soapbox/utils/queries.ts | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 27 deletions(-) create mode 100644 app/soapbox/utils/queries.ts diff --git a/app/soapbox/actions/streaming.ts b/app/soapbox/actions/streaming.ts index e4434d2378..5ec4054642 100644 --- a/app/soapbox/actions/streaming.ts +++ b/app/soapbox/actions/streaming.ts @@ -1,6 +1,6 @@ import { getSettings } from 'soapbox/actions/settings'; import messages from 'soapbox/locales/messages'; -import { queryClient } from 'soapbox/queries/client'; +import { updatePageItem, appendPageItem } from 'soapbox/utils/queries'; import { play, soundCache } from 'soapbox/utils/sounds'; import { connectStream } from '../stream'; @@ -24,8 +24,6 @@ import { processTimelineUpdate, } from './timelines'; -import type { InfiniteData } from '@tanstack/react-query'; -import type { PaginatedResult } from 'soapbox/queries/chats'; import type { AppDispatch, RootState } from 'soapbox/store'; import type { APIEntity, Chat, ChatMessage } from 'soapbox/types/entities'; @@ -56,24 +54,10 @@ interface ChatPayload extends Omit { const updateChat = (payload: ChatPayload) => { const { last_message: lastMessage } = payload; - queryClient.setQueriesData>>(['chats', 'search'], (data) => { - if (data) { - const pages = data.pages.map(page => { - const result = page.result.map(chat => chat.id === payload.id ? payload as any : chat); - return { ...page, result }; - }); - return { ...data, pages }; - } - }); + updatePageItem(['chats', 'search'], payload as any, (o, n) => o.id === n.id); if (lastMessage) { - queryClient.setQueryData>>(['chats', 'messages', payload.id], (data) => { - if (data) { - const pages = [...data.pages]; - pages[0] = { ...pages[0], result: [...pages[0].result, lastMessage] }; - return { ...data, pages }; - } - }); + appendPageItem(['chats', 'messages', payload.id], lastMessage); } }; diff --git a/app/soapbox/queries/chats.ts b/app/soapbox/queries/chats.ts index 784fbb5e58..d327a4eeec 100644 --- a/app/soapbox/queries/chats.ts +++ b/app/soapbox/queries/chats.ts @@ -8,6 +8,7 @@ import compareId from 'soapbox/compare_id'; import { useChatContext } from 'soapbox/contexts/chat-context'; import { useApi, useAppDispatch, useFeatures } from 'soapbox/hooks'; import { normalizeChatMessage } from 'soapbox/normalizers'; +import { flattenPages } from 'soapbox/utils/queries'; import { queryClient } from './client'; @@ -88,10 +89,7 @@ const useChatMessages = (chatId: string) => { }, }); - const data = queryInfo.data?.pages.reduce( - (prev: IChatMessage[], curr) => [...curr.result, ...prev], - [], - ); + const data = flattenPages(queryInfo); return { ...queryInfo, @@ -139,10 +137,7 @@ const useChats = (search?: string) => { }, }); - const data = queryInfo.data?.pages.reduce( - (prev: IChat[], curr) => [...prev, ...curr.result], - [], - ); + const data = flattenPages(queryInfo); const chatsQuery = { ...queryInfo, diff --git a/app/soapbox/utils/queries.ts b/app/soapbox/utils/queries.ts new file mode 100644 index 0000000000..1a9961b43d --- /dev/null +++ b/app/soapbox/utils/queries.ts @@ -0,0 +1,42 @@ +import { queryClient } from 'soapbox/queries/client'; + +import type { InfiniteData, QueryKey, UseInfiniteQueryResult } from '@tanstack/react-query'; +import type { PaginatedResult } from 'soapbox/queries/chats'; + +/** Flatten paginated results into a single array. */ +const flattenPages = (queryInfo: UseInfiniteQueryResult>) => { + return queryInfo.data?.pages.reduce( + (prev: T[], curr) => [...prev, ...curr.result], + [], + ); +}; + +/** Traverse pages and update the item inside if found. */ +const updatePageItem = (queryKey: QueryKey, newItem: T, isItem: (item: T, newItem: T) => boolean) => { + queryClient.setQueriesData>>(queryKey, (data) => { + if (data) { + const pages = data.pages.map(page => { + const result = page.result.map(item => isItem(item, newItem) ? newItem : item); + return { ...page, result }; + }); + return { ...data, pages }; + } + }); +}; + +/** Insert the new item at the beginning of the first page. */ +const appendPageItem = (queryKey: QueryKey, newItem: T) => { + queryClient.setQueryData>>(queryKey, (data) => { + if (data) { + const pages = [...data.pages]; + pages[0] = { ...pages[0], result: [...pages[0].result, newItem] }; + return { ...data, pages }; + } + }); +}; + +export { + flattenPages, + updatePageItem, + appendPageItem, +}; \ No newline at end of file