Move query into Context
This commit is contained in:
parent
9869cf6f55
commit
54466f1293
|
@ -2,7 +2,7 @@ import { InfiniteData } from '@tanstack/react-query';
|
|||
|
||||
import { getSettings } from 'soapbox/actions/settings';
|
||||
import messages from 'soapbox/locales/messages';
|
||||
import { ChatKeys, isLastMessage } from 'soapbox/queries/chats';
|
||||
import { ChatKeys, IChat, isLastMessage } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
import { updatePageItem, appendPageItem, removePageItem, flattenPages, PaginatedResult } from 'soapbox/utils/queries';
|
||||
import { play, soundCache } from 'soapbox/utils/sounds';
|
||||
|
@ -91,6 +91,21 @@ const removeChatMessage = (payload: string) => {
|
|||
removePageItem(ChatKeys.chatMessages(chatId), chatMessageId, (o: any, n: any) => String(o.id) === String(n));
|
||||
};
|
||||
|
||||
// Update the specific Chat query data.
|
||||
const updateChatQuery = (chat: IChat) => {
|
||||
const cachedChat = queryClient.getQueryData<IChat>(ChatKeys.chat(chat.id));
|
||||
if (!cachedChat) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newChat = {
|
||||
...cachedChat,
|
||||
latest_read_message_by_account: chat.latest_read_message_by_account,
|
||||
latest_read_message_created_at: chat.latest_read_message_created_at,
|
||||
};
|
||||
queryClient.setQueryData<Chat>(ChatKeys.chat(chat.id), newChat as any);
|
||||
};
|
||||
|
||||
const connectTimelineStream = (
|
||||
timelineId: string,
|
||||
path: string,
|
||||
|
@ -152,6 +167,9 @@ const connectTimelineStream = (
|
|||
case 'chat_message.deleted': // TruthSocial
|
||||
removeChatMessage(data.payload);
|
||||
break;
|
||||
case 'chat_message.read': // TruthSocial
|
||||
updateChatQuery(JSON.parse(data.payload));
|
||||
break;
|
||||
case 'pleroma:follow_relationships_update':
|
||||
dispatch(updateFollowRelationships(JSON.parse(data.payload)));
|
||||
break;
|
||||
|
|
|
@ -3,44 +3,52 @@ import { useDispatch } from 'react-redux';
|
|||
|
||||
import { toggleMainWindow } from 'soapbox/actions/chats';
|
||||
import { useOwnAccount, useSettings } from 'soapbox/hooks';
|
||||
|
||||
import type { IChat } from 'soapbox/queries/chats';
|
||||
import { IChat, useChat } from 'soapbox/queries/chats';
|
||||
|
||||
type WindowState = 'open' | 'minimized';
|
||||
|
||||
const ChatContext = createContext<any>({
|
||||
chat: null,
|
||||
isOpen: false,
|
||||
isEditing: false,
|
||||
needsAcceptance: false,
|
||||
});
|
||||
|
||||
enum ChatWidgetScreens {
|
||||
INBOX = 'INBOX',
|
||||
SEARCH = 'SEARCH',
|
||||
CHAT = 'CHAT',
|
||||
CHAT_SETTINGS = 'CHAT_SETTINGS'
|
||||
}
|
||||
|
||||
const ChatProvider: React.FC = ({ children }) => {
|
||||
const dispatch = useDispatch();
|
||||
const settings = useSettings();
|
||||
const account = useOwnAccount();
|
||||
|
||||
const [chat, setChat] = useState<IChat | null>(null);
|
||||
const [isEditing, setEditing] = useState<boolean>(false);
|
||||
const [isSearching, setSearching] = useState<boolean>(false);
|
||||
const [screen, setScreen] = useState<ChatWidgetScreens>(ChatWidgetScreens.INBOX);
|
||||
const [currentChatId, setCurrentChatId] = useState<null | string>(null);
|
||||
|
||||
const { data: chat } = useChat(currentChatId as string);
|
||||
|
||||
const mainWindowState = settings.getIn(['chats', 'mainWindow']) as WindowState;
|
||||
const needsAcceptance = !chat?.accepted && chat?.created_by_account !== account?.id;
|
||||
const isOpen = mainWindowState === 'open';
|
||||
|
||||
const changeScreen = (screen: ChatWidgetScreens, currentChatId?: string | null) => {
|
||||
setCurrentChatId(currentChatId || null);
|
||||
setScreen(screen);
|
||||
};
|
||||
|
||||
const toggleChatPane = () => dispatch(toggleMainWindow());
|
||||
|
||||
const value = useMemo(() => ({
|
||||
chat,
|
||||
setChat,
|
||||
needsAcceptance,
|
||||
isOpen,
|
||||
isEditing,
|
||||
isSearching,
|
||||
setEditing,
|
||||
setSearching,
|
||||
toggleChatPane,
|
||||
}), [chat, needsAcceptance, isOpen, isEditing, isSearching]);
|
||||
screen,
|
||||
changeScreen,
|
||||
currentChatId,
|
||||
}), [chat, currentChatId, needsAcceptance, isOpen, screen, changeScreen]);
|
||||
|
||||
return (
|
||||
<ChatContext.Provider value={value}>
|
||||
|
@ -51,16 +59,14 @@ const ChatProvider: React.FC = ({ children }) => {
|
|||
|
||||
interface IChatContext {
|
||||
chat: IChat | null
|
||||
isEditing: boolean
|
||||
isOpen: boolean
|
||||
isSearching: boolean
|
||||
needsAcceptance: boolean
|
||||
setChat: React.Dispatch<React.SetStateAction<IChat | null>>
|
||||
setEditing: React.Dispatch<React.SetStateAction<boolean>>
|
||||
setSearching: React.Dispatch<React.SetStateAction<boolean>>
|
||||
toggleChatPane(): void
|
||||
screen: ChatWidgetScreens
|
||||
currentChatId: string | null
|
||||
changeScreen(screen: ChatWidgetScreens, currentChatId?: string | null): void
|
||||
}
|
||||
|
||||
const useChatContext = (): IChatContext => useContext(ChatContext);
|
||||
|
||||
export { ChatContext, ChatProvider, useChatContext };
|
||||
export { ChatContext, ChatProvider, useChatContext, ChatWidgetScreens };
|
||||
|
|
|
@ -38,6 +38,7 @@ const ChatComposer = React.forwardRef<HTMLTextAreaElement | null, IChatComposer>
|
|||
const intl = useIntl();
|
||||
|
||||
const { chat } = useChatContext();
|
||||
|
||||
const isBlocked = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocked_by']));
|
||||
const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking']));
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import classNames from 'clsx';
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
|
||||
import { fetchChats } from 'soapbox/actions/chats';
|
||||
import PullToRefresh from 'soapbox/components/pull-to-refresh';
|
||||
import { Spinner, Stack, Text } from 'soapbox/components/ui';
|
||||
import { Spinner, Stack } from 'soapbox/components/ui';
|
||||
import PlaceholderChat from 'soapbox/features/placeholder/components/placeholder-chat';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import { useChats } from 'soapbox/queries/chats';
|
||||
|
|
|
@ -73,6 +73,8 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const account = useOwnAccount();
|
||||
const lastReadMessageDateString = chat.latest_read_message_by_account.find((latest) => latest.id === chat.account.id)?.date;
|
||||
const lastReadMessageTimestamp = lastReadMessageDateString ? new Date(lastReadMessageDateString) : null;
|
||||
|
||||
const node = useRef<VirtuosoHandle>(null);
|
||||
const [firstItemIndex, setFirstItemIndex] = useState(START_INDEX - 20);
|
||||
|
@ -211,15 +213,19 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
|
||||
const renderDivider = (key: React.Key, text: string) => <Divider key={key} text={text} textSize='sm' />;
|
||||
|
||||
const handleCopyText = (chatMessage: IChatMessage) => {
|
||||
const handleCopyText = (chatMessage: ChatMessageEntity) => {
|
||||
if (navigator.clipboard) {
|
||||
const text = stripHTML(chatMessage.content);
|
||||
navigator.clipboard.writeText(text);
|
||||
}
|
||||
};
|
||||
|
||||
const renderMessage = (chatMessage: any) => {
|
||||
const renderMessage = (chatMessage: ChatMessageEntity) => {
|
||||
const isMyMessage = chatMessage.account_id === me;
|
||||
// did this occur before this time?
|
||||
const isRead = isMyMessage
|
||||
&& lastReadMessageTimestamp
|
||||
&& lastReadMessageTimestamp >= new Date(chatMessage.created_at);
|
||||
|
||||
const menu: Menu = [];
|
||||
|
||||
|
@ -241,7 +247,7 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
} else {
|
||||
menu.push({
|
||||
text: intl.formatMessage(messages.report),
|
||||
action: () => dispatch(initReport(normalizeAccount(chat.account) as any, { chatMessage })),
|
||||
action: () => dispatch(initReport(normalizeAccount(chat.account) as any, { chatMessage } as any)),
|
||||
icon: require('@tabler/icons/flag.svg'),
|
||||
});
|
||||
menu.push({
|
||||
|
@ -336,7 +342,7 @@ const ChatMessageList: React.FC<IChatMessageList> = ({ chat, autosize }) => {
|
|||
{intl.formatTime(chatMessage.created_at)}
|
||||
</Text>
|
||||
|
||||
{isMyMessage && !chatMessage.unread ? (
|
||||
{isRead ? (
|
||||
<span className='rounded-full flex flex-col items-center justify-center h-3.5 w-3.5 dark:bg-primary-400 dark:text-primary-900'>
|
||||
<Icon src={require('@tabler/icons/check.svg')} strokeWidth={3} className='w-2.5 h-2.5' />
|
||||
</span>
|
||||
|
|
|
@ -3,7 +3,6 @@ import React, { useEffect, useRef, useState } from 'react';
|
|||
import { Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useOwnAccount } from 'soapbox/hooks';
|
||||
import { useChat } from 'soapbox/queries/chats';
|
||||
|
||||
|
@ -21,8 +20,7 @@ const ChatPage: React.FC<IChatPage> = ({ chatId }) => {
|
|||
const account = useOwnAccount();
|
||||
const isOnboarded = account?.chats_onboarded;
|
||||
|
||||
const { chat, setChat } = useChatContext();
|
||||
const { chat: chatQueryResult } = useChat(chatId);
|
||||
const { data: chat } = useChat(chatId);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [height, setHeight] = useState<string | number>('100%');
|
||||
|
@ -41,14 +39,6 @@ const ChatPage: React.FC<IChatPage> = ({ chatId }) => {
|
|||
setHeight(fullHeight - top + offset);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const data = chatQueryResult?.data;
|
||||
|
||||
if (data) {
|
||||
setChat(data);
|
||||
}
|
||||
}, [chatQueryResult?.isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
calculateHeight();
|
||||
}, [containerRef.current]);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useRef } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
|
||||
import { blockAccount, unblockAccount } from 'soapbox/actions/accounts';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import List, { ListItem } from 'soapbox/components/list';
|
||||
import { Avatar, HStack, Icon, IconButton, Menu, MenuButton, MenuItem, MenuList, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { MessageExpirationValues, useChatActions } from 'soapbox/queries/chats';
|
||||
import { MessageExpirationValues, useChat, useChatActions } from 'soapbox/queries/chats';
|
||||
import { secondsToDays } from 'soapbox/utils/numbers';
|
||||
|
||||
import Chat from '../../chat';
|
||||
|
@ -41,10 +41,14 @@ const messages = defineMessages({
|
|||
const ChatPageMain = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const history = useHistory();
|
||||
|
||||
const { chatId } = useParams<{ chatId: string }>();
|
||||
|
||||
const { data: chat } = useChat(chatId);
|
||||
|
||||
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const { chat, setChat } = useChatContext();
|
||||
const { deleteChat, updateChat } = useChatActions(chat?.id as string);
|
||||
|
||||
const handleUpdateChat = (value: MessageExpirationValues) => updateChat.mutate({ message_expiration: value });
|
||||
|
@ -93,7 +97,7 @@ const ChatPageMain = () => {
|
|||
<IconButton
|
||||
src={require('@tabler/icons/arrow-left.svg')}
|
||||
className='sm:hidden h-7 w-7 mr-2 sm:mr-0'
|
||||
onClick={() => setChat(null)}
|
||||
onClick={() => history.push('/chats')}
|
||||
/>
|
||||
|
||||
<Avatar src={chat.account?.avatar} size={40} className='flex-none' />
|
||||
|
|
|
@ -4,7 +4,6 @@ import { useHistory } from 'react-router-dom';
|
|||
|
||||
import AccountSearch from 'soapbox/components/account_search';
|
||||
import { CardTitle, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatKeys, useChats } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
|
||||
|
@ -14,12 +13,10 @@ interface IChatPageNew {
|
|||
/** New message form to create a chat. */
|
||||
const ChatPageNew: React.FC<IChatPageNew> = () => {
|
||||
const history = useHistory();
|
||||
const { setChat } = useChatContext();
|
||||
const { getOrCreateChatByAccountId } = useChats();
|
||||
|
||||
const handleAccountSelected = async (accountId: string) => {
|
||||
const { data } = await getOrCreateChatByAccountId(accountId);
|
||||
setChat(data);
|
||||
history.push(`/chats/${data.id}`);
|
||||
queryClient.invalidateQueries(ChatKeys.chatSearch());
|
||||
};
|
||||
|
|
|
@ -3,7 +3,6 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import { CardTitle, HStack, IconButton, Stack } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useDebounce, useFeatures } from 'soapbox/hooks';
|
||||
import { IChat } from 'soapbox/queries/chats';
|
||||
|
||||
|
@ -20,12 +19,10 @@ const ChatPageSidebar = () => {
|
|||
const features = useFeatures();
|
||||
|
||||
const [search, setSearch] = useState('');
|
||||
const { setChat } = useChatContext();
|
||||
|
||||
const debouncedSearch = useDebounce(search, 300);
|
||||
|
||||
const handleClickChat = (chat: IChat) => {
|
||||
setChat(chat);
|
||||
history.push(`/chats/${chat.id}`);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
import { Stack } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useStatContext } from 'soapbox/contexts/stat-context';
|
||||
import { useDebounce, useFeatures } from 'soapbox/hooks';
|
||||
import { IChat, useChats } from 'soapbox/queries/chats';
|
||||
|
@ -24,13 +24,13 @@ const ChatPane = () => {
|
|||
const [value, setValue] = useState<string>();
|
||||
const debouncedValue = debounce(value as string, 300);
|
||||
|
||||
const { chat, setChat, isOpen, isSearching, setSearching, toggleChatPane } = useChatContext();
|
||||
const { screen, changeScreen, isOpen, toggleChatPane } = useChatContext();
|
||||
const { chatsQuery: { data: chats, isLoading } } = useChats(debouncedValue);
|
||||
|
||||
const hasSearchValue = Number(debouncedValue?.length) > 0;
|
||||
|
||||
const handleClickChat = (nextChat: IChat) => {
|
||||
setChat(nextChat);
|
||||
changeScreen(ChatWidgetScreens.CHAT, nextChat.id);
|
||||
setValue(undefined);
|
||||
};
|
||||
|
||||
|
@ -66,13 +66,17 @@ const ChatPane = () => {
|
|||
);
|
||||
} else if (chats?.length === 0) {
|
||||
return (
|
||||
<Blankslate onSearch={() => setSearching(true)} />
|
||||
<Blankslate
|
||||
onSearch={() => {
|
||||
changeScreen(ChatWidgetScreens.SEARCH);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Active chat
|
||||
if (chat?.id) {
|
||||
if (screen === ChatWidgetScreens.CHAT || screen === ChatWidgetScreens.CHAT_SETTINGS) {
|
||||
return (
|
||||
<Pane isOpen={isOpen} index={0} main>
|
||||
<ChatWindow />
|
||||
|
@ -80,7 +84,7 @@ const ChatPane = () => {
|
|||
);
|
||||
}
|
||||
|
||||
if (isSearching) {
|
||||
if (screen === ChatWidgetScreens.SEARCH) {
|
||||
return <ChatSearch />;
|
||||
}
|
||||
|
||||
|
@ -92,7 +96,7 @@ const ChatPane = () => {
|
|||
isOpen={isOpen}
|
||||
onToggle={toggleChatPane}
|
||||
secondaryAction={() => {
|
||||
setSearching(true);
|
||||
changeScreen(ChatWidgetScreens.SEARCH);
|
||||
setValue(undefined);
|
||||
|
||||
if (!isOpen) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { defineMessages, useIntl } from 'react-intl';
|
|||
|
||||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { HStack, Icon, Input, Stack, Text } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useAppDispatch, useDebounce } from 'soapbox/hooks';
|
||||
import { useChats } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
|
@ -28,7 +28,7 @@ const ChatSearch = () => {
|
|||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const { isOpen, setChat, setSearching, toggleChatPane } = useChatContext();
|
||||
const { isOpen, changeScreen, toggleChatPane } = useChatContext();
|
||||
const { getOrCreateChatByAccountId } = useChats();
|
||||
|
||||
const [value, setValue] = useState<string>();
|
||||
|
@ -47,7 +47,7 @@ const ChatSearch = () => {
|
|||
dispatch(snackbar.error(data?.error));
|
||||
},
|
||||
onSuccess: (response) => {
|
||||
setChat(response.data);
|
||||
changeScreen(ChatWidgetScreens.CHAT, response.data.id);
|
||||
queryClient.invalidateQueries(ChatKeys.chatSearch());
|
||||
},
|
||||
});
|
||||
|
@ -82,7 +82,11 @@ const ChatSearch = () => {
|
|||
data-testid='pane-header'
|
||||
title={
|
||||
<HStack alignItems='center' space={2}>
|
||||
<button onClick={() => setSearching(false)}>
|
||||
<button
|
||||
onClick={() => {
|
||||
changeScreen(ChatWidgetScreens.INBOX);
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
src={require('@tabler/icons/arrow-left.svg')}
|
||||
className='h-6 w-6 text-gray-600 dark:text-gray-400'
|
||||
|
|
|
@ -5,7 +5,7 @@ import { blockAccount, unblockAccount } from 'soapbox/actions/accounts';
|
|||
import { openModal } from 'soapbox/actions/modals';
|
||||
import List, { ListItem } from 'soapbox/components/list';
|
||||
import { Avatar, HStack, Icon, Select, Stack, Text } from 'soapbox/components/ui';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||
import { messageExpirationOptions, MessageExpirationValues, useChatActions } from 'soapbox/queries/chats';
|
||||
import { secondsToDays } from 'soapbox/utils/numbers';
|
||||
|
@ -34,14 +34,16 @@ const ChatSettings = () => {
|
|||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
|
||||
const { chat, setEditing, toggleChatPane } = useChatContext();
|
||||
const { chat, changeScreen, toggleChatPane } = useChatContext();
|
||||
const { deleteChat, updateChat } = useChatActions(chat?.id as string);
|
||||
|
||||
const handleUpdateChat = (value: MessageExpirationValues) => updateChat.mutate({ message_expiration: value });
|
||||
|
||||
const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking']));
|
||||
|
||||
const closeSettings = () => setEditing(false);
|
||||
const closeSettings = () => {
|
||||
changeScreen(ChatWidgetScreens.CHAT, chat?.id);
|
||||
};
|
||||
|
||||
const minimizeChatPane = () => {
|
||||
closeSettings();
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
import { Avatar, HStack, Icon, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { secondsToDays } from 'soapbox/utils/numbers';
|
||||
|
||||
import Chat from '../chat';
|
||||
|
@ -32,19 +32,22 @@ const LinkWrapper = ({ enabled, to, children }: { enabled: boolean, to: string,
|
|||
const ChatWindow = () => {
|
||||
const intl = useIntl();
|
||||
|
||||
const { chat, setChat, isOpen, isEditing, needsAcceptance, setEditing, setSearching, toggleChatPane } = useChatContext();
|
||||
const { chat, currentChatId, screen, changeScreen, isOpen, needsAcceptance, toggleChatPane } = useChatContext();
|
||||
|
||||
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const closeChat = () => setChat(null);
|
||||
const closeChat = () => {
|
||||
changeScreen(ChatWidgetScreens.INBOX);
|
||||
};
|
||||
|
||||
const openSearch = () => {
|
||||
toggleChatPane();
|
||||
setSearching(true);
|
||||
setChat(null);
|
||||
changeScreen(ChatWidgetScreens.SEARCH);
|
||||
};
|
||||
|
||||
const openChatSettings = () => setEditing(true);
|
||||
const openChatSettings = () => {
|
||||
changeScreen(ChatWidgetScreens.CHAT_SETTINGS, currentChatId);
|
||||
};
|
||||
|
||||
const secondaryAction = () => {
|
||||
if (needsAcceptance) {
|
||||
|
@ -56,7 +59,7 @@ const ChatWindow = () => {
|
|||
|
||||
if (!chat) return null;
|
||||
|
||||
if (isEditing) {
|
||||
if (screen === ChatWidgetScreens.CHAT_SETTINGS) {
|
||||
return <ChatSettings />;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ const chat: IChat = {
|
|||
discarded_at: null,
|
||||
id: '1',
|
||||
last_message: null,
|
||||
latest_read_message_by_account: null,
|
||||
latest_read_message_by_account: [],
|
||||
latest_read_message_created_at: null,
|
||||
message_expiration: 1209600,
|
||||
unread: 0,
|
||||
|
@ -169,7 +169,7 @@ describe('useChat()', () => {
|
|||
});
|
||||
|
||||
it('is successful', async () => {
|
||||
const { result } = renderHook(() => useChat(chat.id).chat);
|
||||
const { result } = renderHook(() => useChat(chat.id));
|
||||
|
||||
await waitFor(() => expect(result.current.isFetching).toBe(false));
|
||||
|
||||
|
@ -185,7 +185,7 @@ describe('useChat()', () => {
|
|||
});
|
||||
|
||||
it('is has error state', async() => {
|
||||
const { result } = renderHook(() => useChat(chat.id).chat);
|
||||
const { result } = renderHook(() => useChat(chat.id));
|
||||
|
||||
await waitFor(() => expect(result.current.isFetching).toBe(false));
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { importFetchedAccount, importFetchedAccounts } from 'soapbox/actions/imp
|
|||
import snackbar from 'soapbox/actions/snackbar';
|
||||
import { getNextLink } from 'soapbox/api';
|
||||
import compareId from 'soapbox/compare_id';
|
||||
import { useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { ChatWidgetScreens, useChatContext } from 'soapbox/contexts/chat-context';
|
||||
import { useStatContext } from 'soapbox/contexts/stat-context';
|
||||
import { useApi, useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
|
||||
import { flattenPages, PaginatedResult, updatePageItem } from 'soapbox/utils/queries';
|
||||
|
@ -40,8 +40,9 @@ export interface IChat {
|
|||
id: string
|
||||
unread: boolean
|
||||
}
|
||||
latest_read_message_by_account: null | {
|
||||
[id: number]: string
|
||||
latest_read_message_by_account: {
|
||||
id: string,
|
||||
date: string
|
||||
}[]
|
||||
latest_read_message_created_at: null | string
|
||||
message_expiration: MessageExpirationValues
|
||||
|
@ -177,7 +178,6 @@ const useChats = (search?: string) => {
|
|||
|
||||
const useChat = (chatId?: string) => {
|
||||
const api = useApi();
|
||||
const actions = useChatActions(chatId!);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const getChat = async () => {
|
||||
|
@ -190,9 +190,9 @@ const useChat = (chatId?: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
const chat = useQuery<IChat | undefined>(ChatKeys.chat(chatId), getChat);
|
||||
|
||||
return { ...actions, chat };
|
||||
return useQuery<IChat | undefined>(ChatKeys.chat(chatId), getChat, {
|
||||
enabled: !!chatId,
|
||||
});
|
||||
};
|
||||
|
||||
const useChatActions = (chatId: string) => {
|
||||
|
@ -200,7 +200,7 @@ const useChatActions = (chatId: string) => {
|
|||
const dispatch = useAppDispatch();
|
||||
const { setUnreadChatsCount } = useStatContext();
|
||||
|
||||
const { chat, setChat, setEditing } = useChatContext();
|
||||
const { chat, changeScreen } = useChatContext();
|
||||
|
||||
const markChatAsRead = async (lastReadId: string) => {
|
||||
return api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/read`, { last_read_id: lastReadId })
|
||||
|
@ -239,21 +239,22 @@ const useChatActions = (chatId: string) => {
|
|||
|
||||
// Optimistically update to the new value
|
||||
queryClient.setQueryData(ChatKeys.chat(chatId), nextChat);
|
||||
setChat(nextChat as IChat);
|
||||
|
||||
changeScreen(ChatWidgetScreens.CHAT, nextChat.id);
|
||||
|
||||
// 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) => {
|
||||
setChat(context?.prevChat);
|
||||
changeScreen(ChatWidgetScreens.CHAT, context.prevChat.id);
|
||||
queryClient.setQueryData(ChatKeys.chat(chatId), context.prevChat);
|
||||
dispatch(snackbar.error('Chat Settings failed to update.'));
|
||||
},
|
||||
onSuccess(response) {
|
||||
queryClient.invalidateQueries(ChatKeys.chat(chatId));
|
||||
queryClient.invalidateQueries(ChatKeys.chatSearch());
|
||||
setChat(response.data);
|
||||
changeScreen(ChatWidgetScreens.CHAT, response.data.id);
|
||||
dispatch(snackbar.success('Chat Settings updated successfully'));
|
||||
},
|
||||
});
|
||||
|
@ -262,16 +263,15 @@ const useChatActions = (chatId: string) => {
|
|||
|
||||
const acceptChat = useMutation(() => api.post<IChat>(`/api/v1/pleroma/chats/${chatId}/accept`), {
|
||||
onSuccess(response) {
|
||||
setChat(response.data);
|
||||
changeScreen(ChatWidgetScreens.CHAT, response.data.id);
|
||||
queryClient.invalidateQueries(ChatKeys.chatMessages(chatId));
|
||||
queryClient.invalidateQueries(ChatKeys.chatSearch());
|
||||
},
|
||||
});
|
||||
|
||||
const deleteChat = useMutation(() => api.delete<IChat>(`/api/v1/pleroma/chats/${chatId}`), {
|
||||
onSuccess(response) {
|
||||
setChat(null);
|
||||
setEditing(false);
|
||||
onSuccess() {
|
||||
changeScreen(ChatWidgetScreens.INBOX);
|
||||
queryClient.invalidateQueries(ChatKeys.chatMessages(chatId));
|
||||
queryClient.invalidateQueries(ChatKeys.chatSearch());
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue