Invalidate query cache when new chats come in
This commit is contained in:
parent
69d37a10fb
commit
c41b71c76c
9 changed files with 51 additions and 37 deletions
|
@ -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. */
|
||||
|
|
|
@ -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,7 +4,7 @@ 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,
|
||||
};
|
||||
|
||||
|
@ -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…
Reference in a new issue