Invalidate query cache when new chats come in

environments/review-chats-g56n7m/deployments/1169
Justin 2 years ago
parent 69d37a10fb
commit c41b71c76c

@ -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<Chat, 'last_message'> {
const updateChat = (payload: ChatPayload) => {
const { id: chatId, last_message: lastMessage } = payload;
queryClient.setQueryData<Chat>(['chats', 'chat', chatId], payload as any);
updatePageItem<Chat>(['chats', 'search'], payload as any, (o, n) => o.id === n.id);
const currentChats = flattenPages(queryClient.getQueryData<InfiniteData<PaginatedResult<unknown>>>(ChatKeys.chatSearch()));
// Update the specific Chat query data.
queryClient.setQueryData<Chat>(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<Chat>(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);
}
};

@ -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<IAd> = ({ 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<IAd> = ({ card, impression, expires }) => {
</Stack>
</HStack>
<StatusCard card={card} onOpenMedia={() => {}} horizontal />
<StatusCard card={card} onOpenMedia={() => { }} horizontal />
</Stack>
</Card>

@ -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<IChatMessageList> = ({ chat, autosize }) => {
const handleDeleteMessage = useMutation((chatMessageId: string) => deleteChatMessage(chatMessageId), {
onSettled: () => {
queryClient.invalidateQueries(chatKeys.chatMessages(chat.id));
queryClient.invalidateQueries(ChatKeys.chatMessages(chat.id));
},
});

@ -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());
},
});

@ -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<ChatInterface> = ({ chat, autosize, inputRef, className })
},
// Always refetch after error or success:
onSuccess: () => {
queryClient.invalidateQueries(chatKeys.chatMessages(chat.id));
queryClient.invalidateQueries(ChatKeys.chatMessages(chat.id));
},
});

@ -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<Ad[]>(adKeys.ads, getAds, {
const result = useQuery<Ad[]>(AdKeys.ads, getAds, {
placeholderData: [],
});
@ -35,4 +35,4 @@ function useAds() {
};
}
export { useAds as default, adKeys };
export { useAds as default, AdKeys };

@ -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<IChat | undefined>(chatKeys.chat(chatId), getChat);
const chat = useQuery<IChat | undefined>(ChatKeys.chat(chatId), getChat);
return { ...actions, chat };
};
@ -195,8 +195,8 @@ const useChatActions = (chatId: string) => {
const acceptChat = useMutation(() => api.post<IChat>(`/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<IChatSilence[]>(chatKeys.chatSilences, getChatSilences, {
return useQuery<IChatSilence[]>(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 };

@ -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);
},
});
};

@ -9,8 +9,8 @@ export interface PaginatedResult<T> {
}
/** Flatten paginated results into a single array. */
const flattenPages = <T>(queryInfo: UseInfiniteQueryResult<PaginatedResult<T>>) => {
return queryInfo.data?.pages.reduce<T[]>(
const flattenPages = <T>(queryData: UseInfiniteQueryResult<PaginatedResult<T>>['data']) => {
return queryData?.pages.reduce<T[]>(
(prev: T[], curr) => [...curr.result, ...prev],
[],
);

Loading…
Cancel
Save