Refactor chat functions

environments/review-chats-g56n7m/deployments/1665
Chewbacca 2022-12-02 15:50:54 -05:00
rodzic b5aca1649d
commit 5816659a09
5 zmienionych plików z 96 dodań i 49 usunięć

Wyświetl plik

@ -1,11 +1,9 @@
import { InfiniteData } from '@tanstack/react-query';
import { getSettings } from 'soapbox/actions/settings';
import messages from 'soapbox/locales/messages';
import { normalizeChatMessage } from 'soapbox/normalizers';
import { ChatKeys, IChat, isLastMessage } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import { updatePageItem, appendPageItem, removePageItem, flattenPages, PaginatedResult, sortQueryData } from 'soapbox/utils/queries';
import { updateChatListItem } from 'soapbox/utils/chats';
import { removePageItem } from 'soapbox/utils/queries';
// import { play, soundCache } from 'soapbox/utils/sounds';
import { connectStream } from '../stream';
@ -30,7 +28,7 @@ import {
} from './timelines';
import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity, Chat, ChatMessage } from 'soapbox/types/entities';
import type { APIEntity, Chat } from 'soapbox/types/entities';
const STREAMING_CHAT_UPDATE = 'STREAMING_CHAT_UPDATE';
const STREAMING_FOLLOW_RELATIONSHIPS_UPDATE = 'STREAMING_FOLLOW_RELATIONSHIPS_UPDATE';
@ -52,43 +50,6 @@ const updateFollowRelationships = (relationships: APIEntity) =>
});
};
interface ChatPayload extends Omit<Chat, 'last_message'> {
last_message: ChatMessage | null,
}
const dateComparator = (chatA: IChat, chatB: IChat): number => {
const chatADate = new Date(chatA.last_message?.created_at as string);
const chatBDate = new Date(chatB.last_message?.created_at as string);
if (chatBDate < chatADate) return -1;
if (chatBDate > chatADate) return 1;
return 0;
};
const updateChat = (payload: ChatPayload) => {
const { id: chatId, last_message: lastMessage } = payload;
const currentChats = flattenPages(
queryClient.getQueryData<InfiniteData<PaginatedResult<IChat>>>(ChatKeys.chatSearch()),
);
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);
// Now that we have the new chat loaded, let's re-sort to put
// the most recent on top.
sortQueryData<IChat>(ChatKeys.chatSearch(), dateComparator);
} else {
// If this is a brand-new chat, let's invalid the queries.
queryClient.invalidateQueries(ChatKeys.chatSearch());
}
if (lastMessage) {
// Update the Chat Messages query data.
appendPageItem(ChatKeys.chatMessages(payload.id), normalizeChatMessage(lastMessage));
}
};
const removeChatMessage = (payload: string) => {
const data = JSON.parse(payload);
const chatId = data.chat_id;
@ -178,7 +139,7 @@ const connectTimelineStream = (
// Don't update own messages from streaming
if (!messageOwned) {
updateChat(chat);
updateChatListItem(chat);
// Temp disable until we support disabling/enabling.
// play(soundCache.chat);
}

Wyświetl plik

@ -434,7 +434,7 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat }) => {
if (isLoading) {
return (
<div className='flex-grow flex flex-col justify-end'>
<div className='flex-grow flex flex-col justify-end pb-4'>
<div className='px-4'>
<PlaceholderChatMessage isMyMessage />
<PlaceholderChatMessage />

Wyświetl plik

@ -446,10 +446,6 @@ const UI: React.FC = ({ children }) => {
dispatch(fetchAnnouncements());
if (features.chats) {
// dispatch(fetchChats());
}
if (account.staff) {
dispatch(fetchReports({ resolved: false }));
dispatch(fetchUsers(['local', 'need_approval']));

Wyświetl plik

@ -0,0 +1,74 @@
import { InfiniteData } from '@tanstack/react-query';
import { normalizeChatMessage } from 'soapbox/normalizers';
import { ChatKeys } from 'soapbox/queries/chats';
import { queryClient } from 'soapbox/queries/client';
import { Chat, ChatMessage } from 'soapbox/types/entities';
import { compareDate } from './comparators';
import { appendPageItem, flattenPages, PaginatedResult, sortQueryData, updatePageItem } from './queries';
interface ChatPayload extends Omit<Chat, 'last_message'> {
last_message: ChatMessage | null,
}
/**
* Update the Chat entity inside the ChatSearch query.
* @param newChat - Chat entity.
*/
const updateChatInChatSearchQuery = (newChat: ChatPayload) => {
updatePageItem<ChatPayload>(ChatKeys.chatSearch(), newChat as any, (o, n) => o.id === n.id);
};
/**
* Re-order the ChatSearch query by the last message timestamp.
*/
const reOrderChatListItems = () => {
sortQueryData<ChatPayload>(ChatKeys.chatSearch(), (chatA, chatB) => {
return compareDate(chatA.last_message?.created_at as string, chatB.last_message?.created_at as string);
});
};
/**
* Check if a Chat entity exists within the cached ChatSearch query.
* @param chatId - String
* @returns Boolean
*/
const checkIfChatExists = (chatId: string) => {
const currentChats = flattenPages(
queryClient.getQueryData<InfiniteData<PaginatedResult<Chat>>>(ChatKeys.chatSearch()),
);
return currentChats?.find((chat: Chat) => chat.id === chatId);
};
/**
* Force a re-fetch of ChatSearch.
*/
const invalidateChatSearchQuery = () => {
queryClient.invalidateQueries(ChatKeys.chatSearch());
};
const updateChatListItem = (newChat: ChatPayload) => {
const { id: chatId, last_message: lastMessage } = newChat;
const isChatAlreadyLoaded = checkIfChatExists(chatId);
if (isChatAlreadyLoaded) {
// If the chat exists in the client, let's update it.
updateChatInChatSearchQuery(newChat);
// Now that we have the new chat loaded, let's re-sort to put
// the most recent on top.
reOrderChatListItems();
} else {
// If this is a brand-new chat, let's invalid the queries.
invalidateChatSearchQuery();
}
if (lastMessage) {
// Update the Chat Messages query data.
appendPageItem(ChatKeys.chatMessages(newChat.id), normalizeChatMessage(lastMessage));
}
};
export { updateChatListItem };

Wyświetl plik

@ -20,4 +20,20 @@ function compareId(id1: string, id2: string) {
}
}
export { compareId };
/**
* Compare by dates, where most recent date is returned first.
*
* @param dateString1 - string that is parsable by Date
* @param dateString2 - string that is parsable by Date
* @returns 1 | -1 | 0
*/
function compareDate(dateString1: string, dateString2: string) {
const date1 = new Date(dateString1);
const date2 = new Date(dateString2);
if (date2 < date1) return -1;
if (date2 > date1) return 1;
return 0;
}
export { compareId, compareDate };