Remove Truth Social-specific features
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@ -26,12 +26,10 @@ export type IAccount = {
|
||||
url: string;
|
||||
username: string;
|
||||
verified: boolean;
|
||||
website: string;
|
||||
}
|
||||
|
||||
type UpdateCredentialsData = {
|
||||
accepts_chat_messages?: boolean;
|
||||
chats_onboarded?: boolean;
|
||||
}
|
||||
|
||||
const useUpdateCredentials = () => {
|
||||
|
||||
@ -7,13 +7,11 @@ import { buildAccount, buildRelationship } from 'soapbox/jest/factory';
|
||||
import { createTestStore, mockStore, queryClient, renderHook, rootState, waitFor } from 'soapbox/jest/test-helpers';
|
||||
import { normalizeChatMessage } from 'soapbox/normalizers';
|
||||
import { Store } from 'soapbox/store';
|
||||
import { ChatMessage } from 'soapbox/types/entities';
|
||||
import { flattenPages } from 'soapbox/utils/queries';
|
||||
|
||||
import { ChatKeys, IChat, isLastMessage, useChat, useChatActions, useChatMessages, useChats } from './chats';
|
||||
import { ChatKeys, IChat, useChat, useChatActions, useChatMessages, useChats } from './chats';
|
||||
|
||||
const chat: IChat = {
|
||||
accepted: true,
|
||||
account: buildAccount({
|
||||
username: 'username',
|
||||
verified: true,
|
||||
@ -23,15 +21,9 @@ const chat: IChat = {
|
||||
avatar_static: 'avatar',
|
||||
display_name: 'my name',
|
||||
}),
|
||||
chat_type: 'direct',
|
||||
created_at: '2020-06-10T02:05:06.000Z',
|
||||
created_by_account: '1',
|
||||
discarded_at: null,
|
||||
id: '1',
|
||||
last_message: null,
|
||||
latest_read_message_by_account: [],
|
||||
latest_read_message_created_at: null,
|
||||
message_expiration: 1209600,
|
||||
unread: 0,
|
||||
};
|
||||
|
||||
@ -41,7 +33,6 @@ const buildChatMessage = (id: string) => normalizeChatMessage({
|
||||
account_id: '1',
|
||||
content: `chat message #${id}`,
|
||||
created_at: '2020-06-10T02:05:06.000Z',
|
||||
emoji_reactions: null,
|
||||
expiration: 1209600,
|
||||
unread: true,
|
||||
});
|
||||
@ -58,53 +49,6 @@ describe('ChatKeys', () => {
|
||||
|
||||
expect(ChatKeys.chatMessages(id)).toEqual(['chats', 'messages', id]);
|
||||
});
|
||||
|
||||
it('has a "chatSearch" key', () => {
|
||||
const searchQuery = 'che';
|
||||
|
||||
expect(ChatKeys.chatSearch()).toEqual(['chats', 'search']);
|
||||
expect(ChatKeys.chatSearch(searchQuery)).toEqual(['chats', 'search', searchQuery]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isLastMessage', () => {
|
||||
describe('when its the last message', () => {
|
||||
it('is truthy', () => {
|
||||
const id = '5';
|
||||
const newChat = { ...chat, last_message: { id } } as any;
|
||||
const initialQueryData = {
|
||||
pages: [
|
||||
{ result: [newChat], hasMore: false, link: undefined },
|
||||
],
|
||||
pageParams: [undefined],
|
||||
};
|
||||
const initialFlattenedData = flattenPages(initialQueryData);
|
||||
expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
|
||||
|
||||
queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
|
||||
|
||||
expect(isLastMessage(id)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when its not the last message', () => {
|
||||
it('is not truthy', () => {
|
||||
const id = '5';
|
||||
const newChat = { ...chat, last_message: { id } } as any;
|
||||
const initialQueryData = {
|
||||
pages: [
|
||||
{ result: [newChat], hasMore: false, link: undefined },
|
||||
],
|
||||
pageParams: [undefined],
|
||||
};
|
||||
const initialFlattenedData = flattenPages(initialQueryData);
|
||||
expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
|
||||
|
||||
queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
|
||||
|
||||
expect(isLastMessage('10')).not.toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('useChatMessages', () => {
|
||||
@ -298,7 +242,7 @@ describe('useChatActions', () => {
|
||||
const initialFlattenedData = flattenPages(initialQueryData);
|
||||
expect(sumBy(initialFlattenedData, (chat: IChat) => chat.unread)).toBe(0);
|
||||
|
||||
queryClient.setQueryData(ChatKeys.chatSearch(), initialQueryData);
|
||||
queryClient.setQueryData(['chats', 'search'], initialQueryData);
|
||||
|
||||
const { result } = renderHook(() => useChatActions(chat.id).markChatAsRead('2'));
|
||||
|
||||
@ -306,7 +250,7 @@ describe('useChatActions', () => {
|
||||
expect(result.current).resolves.toBeDefined();
|
||||
});
|
||||
|
||||
const nextQueryData = queryClient.getQueryData(ChatKeys.chatSearch());
|
||||
const nextQueryData = queryClient.getQueryData(['chats', 'search']);
|
||||
const nextFlattenedData = flattenPages(nextQueryData as any);
|
||||
expect(sumBy(nextFlattenedData as any, (chat: IChat) => chat.unread)).toBe(nextUnreadCount);
|
||||
});
|
||||
@ -348,87 +292,4 @@ describe('useChatActions', () => {
|
||||
expect(result.current.data.data).toEqual({ hello: 'world' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateChat()', () => {
|
||||
const nextUnreadCount = 5;
|
||||
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock
|
||||
.onPatch(`/api/v1/pleroma/chats/${chat.id}`)
|
||||
.reply(200, { ...chat, unread: nextUnreadCount });
|
||||
});
|
||||
});
|
||||
|
||||
it('updates the queryCache for the chat', async() => {
|
||||
const initialQueryData = { ...chat };
|
||||
expect(initialQueryData.message_expiration).toBe(1209600);
|
||||
queryClient.setQueryData(ChatKeys.chat(chat.id), initialQueryData);
|
||||
|
||||
const { result } = renderHook(() => {
|
||||
const { updateChat } = useChatActions(chat.id);
|
||||
|
||||
useEffect(() => {
|
||||
updateChat.mutate({ message_expiration: 1200 });
|
||||
}, []);
|
||||
|
||||
return updateChat;
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
const nextQueryData = queryClient.getQueryData(ChatKeys.chat(chat.id));
|
||||
expect((nextQueryData as any).message_expiration).toBe(1200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createReaction()', () => {
|
||||
const chatMessage = buildChatMessage('1');
|
||||
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock
|
||||
.onPost(`/api/v1/pleroma/chats/${chat.id}/messages/${chatMessage.id}/reactions`)
|
||||
.reply(200, { ...chatMessage.toJS(), emoji_reactions: [{ name: '👍', count: 1, me: true }] });
|
||||
});
|
||||
});
|
||||
|
||||
it('successfully updates the Chat Message record', async () => {
|
||||
const initialQueryData = {
|
||||
pages: [
|
||||
{ result: [chatMessage], hasMore: false, link: undefined },
|
||||
],
|
||||
pageParams: [undefined],
|
||||
};
|
||||
|
||||
queryClient.setQueryData(ChatKeys.chatMessages(chat.id), initialQueryData);
|
||||
|
||||
const { result } = renderHook(() => {
|
||||
const { createReaction } = useChatActions(chat.id);
|
||||
|
||||
useEffect(() => {
|
||||
createReaction.mutate({
|
||||
messageId: chatMessage.id,
|
||||
emoji: '👍',
|
||||
chatMessage,
|
||||
});
|
||||
}, []);
|
||||
|
||||
return createReaction;
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
const updatedChatMessage = (queryClient.getQueryData(ChatKeys.chatMessages(chat.id)) as any).pages[0].result[0] as ChatMessage;
|
||||
expect(updatedChatMessage.emoji_reactions).toEqual([{
|
||||
name: '👍',
|
||||
count: 1,
|
||||
me: true,
|
||||
}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -7,9 +7,8 @@ import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context
|
||||
import { useStatContext } from 'soapbox/contexts/stat-context';
|
||||
import { useApi, useAppDispatch, useAppSelector, useFeatures, useOwnAccount } from 'soapbox/hooks';
|
||||
import { normalizeChatMessage } from 'soapbox/normalizers';
|
||||
import toast from 'soapbox/toast';
|
||||
import { ChatMessage } from 'soapbox/types/entities';
|
||||
import { reOrderChatListItems, updateChatMessage } from 'soapbox/utils/chats';
|
||||
import { reOrderChatListItems } from 'soapbox/utils/chats';
|
||||
import { flattenPages, PaginatedResult, updatePageItem } from 'soapbox/utils/queries';
|
||||
|
||||
import { queryClient } from './client';
|
||||
@ -17,64 +16,24 @@ import { useFetchRelationships } from './relationships';
|
||||
|
||||
import type { Account } from 'soapbox/schemas';
|
||||
|
||||
export const messageExpirationOptions = [604800, 1209600, 2592000, 7776000];
|
||||
|
||||
export enum MessageExpirationValues {
|
||||
'SEVEN' = messageExpirationOptions[0],
|
||||
'FOURTEEN' = messageExpirationOptions[1],
|
||||
'THIRTY' = messageExpirationOptions[2],
|
||||
'NINETY' = messageExpirationOptions[3]
|
||||
}
|
||||
|
||||
export interface IChat {
|
||||
accepted: boolean;
|
||||
account: Account;
|
||||
chat_type: 'channel' | 'direct';
|
||||
created_at: string;
|
||||
created_by_account: string;
|
||||
discarded_at: null | string;
|
||||
id: string;
|
||||
last_message: null | {
|
||||
account_id: string;
|
||||
chat_id: string;
|
||||
content: string;
|
||||
created_at: string;
|
||||
discarded_at: string | null;
|
||||
id: string;
|
||||
unread: boolean;
|
||||
};
|
||||
latest_read_message_by_account?: {
|
||||
id: string;
|
||||
date: string;
|
||||
}[];
|
||||
latest_read_message_created_at: null | string;
|
||||
message_expiration?: MessageExpirationValues;
|
||||
unread: number;
|
||||
}
|
||||
|
||||
type UpdateChatVariables = {
|
||||
message_expiration: MessageExpirationValues;
|
||||
}
|
||||
|
||||
type CreateReactionVariables = {
|
||||
messageId: string;
|
||||
emoji: string;
|
||||
chatMessage?: ChatMessage;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
/** Check if item is most recent */
|
||||
const isLastMessage = (chatMessageId: string): boolean => {
|
||||
const queryData = queryClient.getQueryData<InfiniteData<PaginatedResult<IChat>>>(ChatKeys.chatSearch());
|
||||
const items = flattenPages<IChat>(queryData);
|
||||
const chat = items?.find((item) => item.last_message?.id === chatMessageId);
|
||||
|
||||
return !!chat;
|
||||
};
|
||||
|
||||
const useChatMessages = (chat: IChat) => {
|
||||
@ -122,7 +81,7 @@ const useChatMessages = (chat: IChat) => {
|
||||
};
|
||||
};
|
||||
|
||||
const useChats = (search?: string) => {
|
||||
const useChats = () => {
|
||||
const api = useApi();
|
||||
const dispatch = useAppDispatch();
|
||||
const features = useFeatures();
|
||||
@ -133,11 +92,7 @@ const useChats = (search?: string) => {
|
||||
const endpoint = features.chatsV2 ? '/api/v2/pleroma/chats' : '/api/v1/pleroma/chats';
|
||||
const nextPageLink = pageParam?.link;
|
||||
const uri = nextPageLink || endpoint;
|
||||
const response = await api.get<IChat[]>(uri, {
|
||||
params: search ? {
|
||||
search,
|
||||
} : undefined,
|
||||
});
|
||||
const response = await api.get<IChat[]>(uri);
|
||||
const { data } = response;
|
||||
|
||||
const link = getNextLink(response);
|
||||
@ -157,7 +112,7 @@ const useChats = (search?: string) => {
|
||||
};
|
||||
|
||||
const queryInfo = useInfiniteQuery({
|
||||
queryKey: ChatKeys.chatSearch(search),
|
||||
queryKey: ['chats', 'search'],
|
||||
queryFn: ({ pageParam }) => getChats(pageParam),
|
||||
placeholderData: keepPreviousData,
|
||||
enabled: features.chats,
|
||||
@ -219,8 +174,8 @@ const useChatActions = (chatId: string) => {
|
||||
const markChatAsRead = async (lastReadId: string) => {
|
||||
return api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/read`, { last_read_id: lastReadId })
|
||||
.then(({ data }) => {
|
||||
updatePageItem(ChatKeys.chatSearch(), data, (o, n) => o.id === n.id);
|
||||
const queryData = queryClient.getQueryData<InfiniteData<PaginatedResult<unknown>>>(ChatKeys.chatSearch());
|
||||
updatePageItem(['chats', 'search'], data, (o, n) => o.id === n.id);
|
||||
const queryData = queryClient.getQueryData<InfiniteData<PaginatedResult<unknown>>>(['chats', 'search']);
|
||||
|
||||
if (queryData) {
|
||||
const flattenedQueryData: any = flattenPages(queryData)?.map((chat: any) => {
|
||||
@ -293,7 +248,7 @@ const useChatActions = (chatId: string) => {
|
||||
},
|
||||
onSuccess: (response: any, variables, context) => {
|
||||
const nextChat = { ...chat, last_message: response.data };
|
||||
updatePageItem(ChatKeys.chatSearch(), nextChat, (o, n) => o.id === n.id);
|
||||
updatePageItem(['chats', 'search'], nextChat, (o, n) => o.id === n.id);
|
||||
updatePageItem(
|
||||
ChatKeys.chatMessages(variables.chatId),
|
||||
normalizeChatMessage(response.data),
|
||||
@ -302,86 +257,23 @@ const useChatActions = (chatId: string) => {
|
||||
reOrderChatListItems();
|
||||
},
|
||||
});
|
||||
|
||||
const updateChat = useMutation({
|
||||
mutationFn: (data: UpdateChatVariables) => api.patch<IChat>(`/api/v1/pleroma/chats/${chatId}`, data),
|
||||
onMutate: async (data) => {
|
||||
// Cancel any outgoing refetches (so they don't overwrite our optimistic update)
|
||||
await queryClient.cancelQueries({
|
||||
queryKey: ChatKeys.chat(chatId),
|
||||
});
|
||||
|
||||
// Snapshot the previous value
|
||||
const prevChat = { ...chat };
|
||||
const nextChat = { ...chat, ...data };
|
||||
|
||||
// Optimistically update to the new value
|
||||
queryClient.setQueryData(ChatKeys.chat(chatId), nextChat);
|
||||
|
||||
// Return a context object with the snapshotted value
|
||||
return { prevChat };
|
||||
},
|
||||
// If the mutation fails, use the context returned from onMutate to roll back
|
||||
onError: (_error: any, _newData: any, context: any) => {
|
||||
changeScreen(ChatWidgetScreens.CHAT, context.prevChat.id);
|
||||
queryClient.setQueryData(ChatKeys.chat(chatId), context.prevChat);
|
||||
toast.error('Chat Settings failed to update.');
|
||||
},
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chat(chatId) });
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
|
||||
toast.success('Chat Settings updated successfully');
|
||||
},
|
||||
});
|
||||
|
||||
const deleteChatMessage = (chatMessageId: string) => api.delete<IChat>(`/api/v1/pleroma/chats/${chatId}/messages/${chatMessageId}`);
|
||||
|
||||
const acceptChat = useMutation({
|
||||
mutationFn: () => api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/accept`),
|
||||
onSuccess(response) {
|
||||
changeScreen(ChatWidgetScreens.CHAT, response.data.id);
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chat(chatId) });
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
|
||||
},
|
||||
});
|
||||
|
||||
const deleteChat = useMutation({
|
||||
mutationFn: () => api.delete<IChat>(`/api/v1/pleroma/chats/${chatId}`),
|
||||
onSuccess() {
|
||||
changeScreen(ChatWidgetScreens.INBOX);
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatSearch() });
|
||||
},
|
||||
});
|
||||
|
||||
const createReaction = useMutation({
|
||||
mutationFn: (data: CreateReactionVariables) => api.post(`/api/v1/pleroma/chats/${chatId}/messages/${data.messageId}/reactions`, {
|
||||
emoji: data.emoji,
|
||||
}),
|
||||
// TODO: add optimistic updates
|
||||
onSuccess(response) {
|
||||
updateChatMessage(response.data);
|
||||
},
|
||||
});
|
||||
|
||||
const deleteReaction = useMutation({
|
||||
mutationFn: (data: CreateReactionVariables) => api.delete(`/api/v1/pleroma/chats/${chatId}/messages/${data.messageId}/reactions/${data.emoji}`),
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries({ queryKey: ChatKeys.chatMessages(chatId) });
|
||||
queryClient.invalidateQueries({ queryKey: ['chats', 'search'] });
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
acceptChat,
|
||||
createChatMessage,
|
||||
createReaction,
|
||||
deleteChat,
|
||||
deleteChatMessage,
|
||||
deleteReaction,
|
||||
markChatAsRead,
|
||||
updateChat,
|
||||
};
|
||||
};
|
||||
|
||||
export { ChatKeys, useChat, useChatActions, useChats, useChatMessages, isLastMessage };
|
||||
export { ChatKeys, useChat, useChatActions, useChats, useChatMessages };
|
||||
|
||||
Reference in New Issue
Block a user