Refactor chat functions
This commit is contained in:
parent
b5aca1649d
commit
5816659a09
5 changed files with 96 additions and 49 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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']));
|
||||
|
|
74
app/soapbox/utils/chats.ts
Normal file
74
app/soapbox/utils/chats.ts
Normal file
|
@ -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 };
|
|
@ -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 };
|
Loading…
Reference in a new issue