diff --git a/app/soapbox/actions/streaming.ts b/app/soapbox/actions/streaming.ts index 9e99b0d2f..8c4ea2cba 100644 --- a/app/soapbox/actions/streaming.ts +++ b/app/soapbox/actions/streaming.ts @@ -1,7 +1,10 @@ +import { InfiniteData } from '@tanstack/react-query'; + import { getSettings } from 'soapbox/actions/settings'; import messages from 'soapbox/locales/messages'; +import { ChatKeys } from 'soapbox/queries/chats'; import { queryClient } from 'soapbox/queries/client'; -import { updatePageItem, appendPageItem } from 'soapbox/utils/queries'; +import { updatePageItem, appendPageItem, flattenPages, PaginatedResult } from 'soapbox/utils/queries'; import { play, soundCache } from 'soapbox/utils/sounds'; import { connectStream } from '../stream'; @@ -55,11 +58,22 @@ interface ChatPayload extends Omit { const updateChat = (payload: ChatPayload) => { const { id: chatId, last_message: lastMessage } = payload; - queryClient.setQueryData(['chats', 'chat', chatId], payload as any); - updatePageItem(['chats', 'search'], payload as any, (o, n) => o.id === n.id); + const currentChats = flattenPages(queryClient.getQueryData>>(ChatKeys.chatSearch())); + + // Update the specific Chat query data. + queryClient.setQueryData(ChatKeys.chat(chatId), payload as any); + + if (currentChats?.find((chat: any) => chat.id === chatId)) { + // If the chat exists in the client, let's update it. + updatePageItem(ChatKeys.chatSearch(), payload as any, (o, n) => o.id === n.id); + } else { + // If this is a brand-new chat, let's invalid the queries. + queryClient.invalidateQueries(ChatKeys.chatSearch()); + } if (lastMessage) { - appendPageItem(['chats', 'messages', payload.id], lastMessage); + // Update the Chat Messages query data. + appendPageItem(ChatKeys.chatMessages(payload.id), lastMessage); } }; diff --git a/app/soapbox/features/ads/components/ad.tsx b/app/soapbox/features/ads/components/ad.tsx index 9da3f1387..c19eec6ef 100644 --- a/app/soapbox/features/ads/components/ad.tsx +++ b/app/soapbox/features/ads/components/ad.tsx @@ -6,7 +6,7 @@ import { Stack, HStack, Card, Avatar, Text, Icon } from 'soapbox/components/ui'; import IconButton from 'soapbox/components/ui/icon-button/icon-button'; import StatusCard from 'soapbox/features/status/components/card'; import { useAppSelector } from 'soapbox/hooks'; -import { adKeys } from 'soapbox/queries/ads'; +import { AdKeys } from 'soapbox/queries/ads'; import type { Card as CardEntity } from 'soapbox/types/entities'; @@ -30,7 +30,7 @@ const Ad: React.FC = ({ card, impression, expires }) => { /** Invalidate query cache for ads. */ const bustCache = (): void => { - queryClient.invalidateQueries(adKeys.ads); + queryClient.invalidateQueries(AdKeys.ads); }; /** Toggle the info box on click. */ @@ -113,7 +113,7 @@ const Ad: React.FC = ({ card, impression, expires }) => { - {}} horizontal /> + { }} horizontal /> diff --git a/app/soapbox/features/chats/components/chat-message-list.tsx b/app/soapbox/features/chats/components/chat-message-list.tsx index b98db7c81..887cca4f0 100644 --- a/app/soapbox/features/chats/components/chat-message-list.tsx +++ b/app/soapbox/features/chats/components/chat-message-list.tsx @@ -16,7 +16,7 @@ import Bundle from 'soapbox/features/ui/components/bundle'; import { MediaGallery } from 'soapbox/features/ui/util/async-components'; import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks'; import { normalizeAccount } from 'soapbox/normalizers'; -import { chatKeys, IChat, IChatMessage, useChatActions, useChatMessages } from 'soapbox/queries/chats'; +import { ChatKeys, IChat, IChatMessage, useChatActions, useChatMessages } from 'soapbox/queries/chats'; import { queryClient } from 'soapbox/queries/client'; import { stripHTML } from 'soapbox/utils/html'; import { onlyEmoji } from 'soapbox/utils/rich_content'; @@ -96,7 +96,7 @@ const ChatMessageList: React.FC = ({ chat, autosize }) => { const handleDeleteMessage = useMutation((chatMessageId: string) => deleteChatMessage(chatMessageId), { onSettled: () => { - queryClient.invalidateQueries(chatKeys.chatMessages(chat.id)); + queryClient.invalidateQueries(ChatKeys.chatMessages(chat.id)); }, }); diff --git a/app/soapbox/features/chats/components/chat-search/chat-search.tsx b/app/soapbox/features/chats/components/chat-search/chat-search.tsx index 915d8552f..ed946f3c0 100644 --- a/app/soapbox/features/chats/components/chat-search/chat-search.tsx +++ b/app/soapbox/features/chats/components/chat-search/chat-search.tsx @@ -11,7 +11,7 @@ import { useChats } from 'soapbox/queries/chats'; import { queryClient } from 'soapbox/queries/client'; import useAccountSearch from 'soapbox/queries/search'; -import { chatKeys } from '../../../../queries/chats'; +import { ChatKeys } from '../../../../queries/chats'; import ChatPaneHeader from '../chat-pane-header'; import { Pane } from '../ui'; @@ -48,7 +48,7 @@ const ChatSearch = () => { }, onSuccess: (response) => { setChat(response.data); - queryClient.invalidateQueries(chatKeys.chatSearch()); + queryClient.invalidateQueries(ChatKeys.chatSearch()); }, }); diff --git a/app/soapbox/features/chats/components/chat.tsx b/app/soapbox/features/chats/components/chat.tsx index 58cccd4dd..686c840fd 100644 --- a/app/soapbox/features/chats/components/chat.tsx +++ b/app/soapbox/features/chats/components/chat.tsx @@ -8,7 +8,7 @@ import { HStack, IconButton, Stack, Text, Textarea } from 'soapbox/components/ui import UploadProgress from 'soapbox/components/upload-progress'; import UploadButton from 'soapbox/features/compose/components/upload_button'; import { useAppDispatch, useOwnAccount } from 'soapbox/hooks'; -import { chatKeys, IChat, useChatActions } from 'soapbox/queries/chats'; +import { ChatKeys, IChat, useChatActions } from 'soapbox/queries/chats'; import { queryClient } from 'soapbox/queries/client'; import { truncateFilename } from 'soapbox/utils/media'; @@ -91,7 +91,7 @@ const Chat: React.FC = ({ chat, autosize, inputRef, className }) }, // Always refetch after error or success: onSuccess: () => { - queryClient.invalidateQueries(chatKeys.chatMessages(chat.id)); + queryClient.invalidateQueries(ChatKeys.chatMessages(chat.id)); }, }); diff --git a/app/soapbox/queries/ads.ts b/app/soapbox/queries/ads.ts index 13cad46fa..e950005b3 100644 --- a/app/soapbox/queries/ads.ts +++ b/app/soapbox/queries/ads.ts @@ -4,15 +4,15 @@ import { Ad, getProvider } from 'soapbox/features/ads/providers'; import { useAppDispatch } from 'soapbox/hooks'; import { isExpired } from 'soapbox/utils/ads'; -const adKeys = { +const AdKeys = { ads: ['ads'] as const, }; function useAds() { const dispatch = useAppDispatch(); - const getAds = async() => { - return dispatch(async(_, getState) => { + const getAds = async () => { + return dispatch(async (_, getState) => { const provider = await getProvider(getState); if (provider) { return provider.getAds(getState); @@ -22,7 +22,7 @@ function useAds() { }); }; - const result = useQuery(adKeys.ads, getAds, { + const result = useQuery(AdKeys.ads, getAds, { placeholderData: [], }); @@ -35,4 +35,4 @@ function useAds() { }; } -export { useAds as default, adKeys }; +export { useAds as default, AdKeys }; diff --git a/app/soapbox/queries/chats.ts b/app/soapbox/queries/chats.ts index 9424fa494..413bf364f 100644 --- a/app/soapbox/queries/chats.ts +++ b/app/soapbox/queries/chats.ts @@ -52,7 +52,7 @@ export interface IChatSilence { target_account_id: number } -const chatKeys = { +const ChatKeys = { chat: (chatId?: string) => ['chats', 'chat', chatId] as const, chatMessages: (chatId: string) => ['chats', 'messages', chatId] as const, chatSearch: (searchQuery?: string) => searchQuery ? ['chats', 'search', searchQuery] : ['chats', 'search'] as const, @@ -81,7 +81,7 @@ const useChatMessages = (chatId: string) => { }; }; - const queryInfo = useInfiniteQuery(chatKeys.chatMessages(chatId), ({ pageParam }) => getChatMessages(chatId, pageParam), { + const queryInfo = useInfiniteQuery(ChatKeys.chatMessages(chatId), ({ pageParam }) => getChatMessages(chatId, pageParam), { getNextPageParam: (config) => { if (config.hasMore) { return { link: config.link }; @@ -91,7 +91,7 @@ const useChatMessages = (chatId: string) => { }, }); - const data = flattenPages(queryInfo); + const data = flattenPages(queryInfo.data); return { ...queryInfo, @@ -133,7 +133,7 @@ const useChats = (search?: string) => { }; }; - const queryInfo = useInfiniteQuery(chatKeys.chatSearch(search), ({ pageParam }) => getChats(pageParam), { + const queryInfo = useInfiniteQuery(ChatKeys.chatSearch(search), ({ pageParam }) => getChats(pageParam), { keepPreviousData: true, getNextPageParam: (config) => { if (config.hasMore) { @@ -144,7 +144,7 @@ const useChats = (search?: string) => { }, }); - const data = flattenPages(queryInfo); + const data = flattenPages(queryInfo.data); const chatsQuery = { ...queryInfo, @@ -171,7 +171,7 @@ const useChat = (chatId?: string) => { } }; - const chat = useQuery(chatKeys.chat(chatId), getChat); + const chat = useQuery(ChatKeys.chat(chatId), getChat); return { ...actions, chat }; }; @@ -195,8 +195,8 @@ const useChatActions = (chatId: string) => { const acceptChat = useMutation(() => api.post(`/api/v1/pleroma/chats/${chatId}/accept`), { onSuccess(response) { setChat(response.data); - queryClient.invalidateQueries(chatKeys.chatMessages(chatId)); - queryClient.invalidateQueries(chatKeys.chatSearch()); + queryClient.invalidateQueries(ChatKeys.chatMessages(chatId)); + queryClient.invalidateQueries(ChatKeys.chatSearch()); }, }); @@ -204,8 +204,8 @@ const useChatActions = (chatId: string) => { onSuccess(response) { setChat(null); setEditing(false); - queryClient.invalidateQueries(chatKeys.chatMessages(chatId)); - queryClient.invalidateQueries(chatKeys.chatSearch()); + queryClient.invalidateQueries(ChatKeys.chatMessages(chatId)); + queryClient.invalidateQueries(ChatKeys.chatSearch()); }, }); @@ -221,7 +221,7 @@ const useChatSilences = () => { return data; }; - return useQuery(chatKeys.chatSilences, getChatSilences, { + return useQuery(ChatKeys.chatSilences, getChatSilences, { placeholderData: [], }); }; @@ -260,7 +260,7 @@ const useChatSilence = (chat: IChat | null) => { api.post(`api/v1/pleroma/chats/silence?account_id=${chat?.account.id}`) .then(() => { dispatch(snackbar.success('Successfully silenced this chat.')); - queryClient.invalidateQueries(chatKeys.chatSilences); + queryClient.invalidateQueries(ChatKeys.chatSilences); }) .catch(() => { dispatch(snackbar.error('Something went wrong trying to silence this chat. Please try again.')); @@ -274,7 +274,7 @@ const useChatSilence = (chat: IChat | null) => { api.delete(`api/v1/pleroma/chats/silence?account_id=${chat?.account.id}`) .then(() => { dispatch(snackbar.success('Successfully unsilenced this chat.')); - queryClient.invalidateQueries(chatKeys.chatSilences); + queryClient.invalidateQueries(ChatKeys.chatSilences); }) .catch(() => { dispatch(snackbar.error('Something went wrong trying to unsilence this chat. Please try again.')); @@ -285,4 +285,4 @@ const useChatSilence = (chat: IChat | null) => { return { isSilenced, handleSilence, fetchChatSilence }; }; -export { chatKeys, useChat, useChatActions, useChats, useChatMessages, useChatSilences, useChatSilence }; +export { ChatKeys, useChat, useChatActions, useChats, useChatMessages, useChatSilences, useChatSilence }; diff --git a/app/soapbox/queries/suggestions.ts b/app/soapbox/queries/suggestions.ts index 96cab48ee..b6cea5278 100644 --- a/app/soapbox/queries/suggestions.ts +++ b/app/soapbox/queries/suggestions.ts @@ -32,7 +32,7 @@ type PageParam = { link?: string } -const suggestionKeys = { +const SuggestionKeys = { suggestions: ['suggestions'] as const, }; @@ -94,7 +94,7 @@ const useSuggestions = () => { }; const result = useInfiniteQuery( - suggestionKeys.suggestions, + SuggestionKeys.suggestions, ({ pageParam }: any) => getSuggestions(pageParam), { keepPreviousData: true, @@ -123,7 +123,7 @@ const useDismissSuggestion = () => { return useMutation((accountId: string) => api.delete(`/api/v1/suggestions/${accountId}`), { onMutate(accountId: string) { - removePageItem(suggestionKeys.suggestions, accountId, (o: any, n: any) => o.account_id === n); + removePageItem(SuggestionKeys.suggestions, accountId, (o: any, n: any) => o.account_id === n); }, }); }; diff --git a/app/soapbox/utils/queries.ts b/app/soapbox/utils/queries.ts index 7361d017b..b39579de1 100644 --- a/app/soapbox/utils/queries.ts +++ b/app/soapbox/utils/queries.ts @@ -9,8 +9,8 @@ export interface PaginatedResult { } /** Flatten paginated results into a single array. */ -const flattenPages = (queryInfo: UseInfiniteQueryResult>) => { - return queryInfo.data?.pages.reduce( +const flattenPages = (queryData: UseInfiniteQueryResult>['data']) => { + return queryData?.pages.reduce( (prev: T[], curr) => [...curr.result, ...prev], [], );