2024-10-17 03:10:27 +08:00
|
|
|
import React, { useRef } from 'react';
|
2024-10-03 06:28:02 +08:00
|
|
|
import { CircularProgress } from '@mui/material';
|
2023-07-08 04:46:36 +08:00
|
|
|
import ChatHeader from './chat-header/component';
|
|
|
|
import { layoutSelect, layoutSelectInput } from '../../layout/context';
|
|
|
|
import { Input, Layout } from '../../layout/layoutTypes';
|
|
|
|
import Styled from './styles';
|
|
|
|
import ChatMessageListContainer from './chat-message-list/component';
|
|
|
|
import ChatMessageFormContainer from './chat-message-form/component';
|
|
|
|
import ChatTypingIndicatorContainer from './chat-typing-indicator/component';
|
|
|
|
import { PANELS, ACTIONS } from '/imports/ui/components/layout/enums';
|
|
|
|
import usePendingChat from '/imports/ui/core/local-states/usePendingChat';
|
|
|
|
import useChat from '/imports/ui/core/hooks/useChat';
|
2023-09-11 21:12:37 +08:00
|
|
|
import { Chat as ChatType } from '/imports/ui/Types/chat';
|
2023-07-08 04:46:36 +08:00
|
|
|
import { layoutDispatch } from '/imports/ui/components/layout/context';
|
2023-09-11 21:12:37 +08:00
|
|
|
import browserInfo from '/imports/utils/browserInfo';
|
2023-11-14 02:10:41 +08:00
|
|
|
import { GraphqlDataHookSubscriptionResponse } from '/imports/ui/Types/hook';
|
2024-10-17 03:10:27 +08:00
|
|
|
import { ChatEvents } from '/imports/ui/core/enums/chat';
|
2023-09-14 00:37:40 +08:00
|
|
|
|
2023-07-08 04:46:36 +08:00
|
|
|
interface ChatProps {
|
2024-02-23 03:19:50 +08:00
|
|
|
isRTL: boolean;
|
2023-07-08 04:46:36 +08:00
|
|
|
}
|
|
|
|
|
2024-02-23 03:19:50 +08:00
|
|
|
const Chat: React.FC<ChatProps> = ({ isRTL }) => {
|
2023-09-11 21:12:37 +08:00
|
|
|
const { isChrome } = browserInfo;
|
2024-10-17 03:10:27 +08:00
|
|
|
const isEditingMessage = useRef(false);
|
2024-08-01 22:59:27 +08:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
const handleMouseDown = () => {
|
|
|
|
if (window.getSelection) {
|
|
|
|
const selection = window.getSelection();
|
|
|
|
if (selection) {
|
|
|
|
selection.removeAllRanges();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-10-17 03:10:27 +08:00
|
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
|
|
if (e.key === 'Escape' && isEditingMessage.current) {
|
|
|
|
window.dispatchEvent(
|
|
|
|
new CustomEvent(ChatEvents.CHAT_CANCEL_EDIT_REQUEST),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleEditingMessage = (e: Event) => {
|
|
|
|
if (e instanceof CustomEvent) {
|
|
|
|
isEditingMessage.current = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleCancelEditingMessage = (e: Event) => {
|
|
|
|
if (e instanceof CustomEvent) {
|
|
|
|
isEditingMessage.current = false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-08-01 22:59:27 +08:00
|
|
|
document.addEventListener('mousedown', handleMouseDown);
|
2024-10-17 03:10:27 +08:00
|
|
|
document.addEventListener('keydown', handleKeyDown);
|
|
|
|
window.addEventListener(ChatEvents.CHAT_EDIT_REQUEST, handleEditingMessage);
|
|
|
|
window.addEventListener(ChatEvents.CHAT_CANCEL_EDIT_REQUEST, handleCancelEditingMessage);
|
2024-08-01 22:59:27 +08:00
|
|
|
|
|
|
|
return () => {
|
|
|
|
document.removeEventListener('mousedown', handleMouseDown);
|
2024-10-17 03:10:27 +08:00
|
|
|
document.removeEventListener('keydown', handleKeyDown);
|
|
|
|
window.removeEventListener(ChatEvents.CHAT_EDIT_REQUEST, handleEditingMessage);
|
|
|
|
window.removeEventListener(ChatEvents.CHAT_CANCEL_EDIT_REQUEST, handleCancelEditingMessage);
|
2024-08-01 22:59:27 +08:00
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2023-07-08 04:46:36 +08:00
|
|
|
return (
|
2024-02-23 03:19:50 +08:00
|
|
|
<Styled.Chat isRTL={isRTL} isChrome={isChrome}>
|
2023-07-08 04:46:36 +08:00
|
|
|
<ChatHeader />
|
|
|
|
<ChatMessageListContainer />
|
|
|
|
<ChatMessageFormContainer />
|
|
|
|
<ChatTypingIndicatorContainer />
|
|
|
|
</Styled.Chat>
|
|
|
|
);
|
|
|
|
};
|
2024-03-12 00:37:49 +08:00
|
|
|
export const ChatLoading: React.FC<ChatProps> = ({ isRTL }) => {
|
2023-09-11 21:12:37 +08:00
|
|
|
const { isChrome } = browserInfo;
|
|
|
|
return (
|
2024-02-23 03:19:50 +08:00
|
|
|
<Styled.Chat isRTL={isRTL} isChrome={isChrome}>
|
2023-09-11 21:12:37 +08:00
|
|
|
<CircularProgress style={{ alignSelf: 'center' }} />
|
|
|
|
</Styled.Chat>
|
|
|
|
);
|
2023-07-08 04:46:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const ChatContainer: React.FC = () => {
|
|
|
|
const idChatOpen = layoutSelect((i: Layout) => i.idChatOpen);
|
2024-02-23 03:19:50 +08:00
|
|
|
const isRTL = layoutSelect((i: Layout) => i.isRTL);
|
2023-07-08 04:46:36 +08:00
|
|
|
const sidebarContent = layoutSelectInput((i: Input) => i.sidebarContent);
|
|
|
|
const layoutContextDispatch = layoutDispatch();
|
2023-11-14 02:10:41 +08:00
|
|
|
const { data: chats } = useChat((chat) => {
|
2023-07-08 04:46:36 +08:00
|
|
|
return {
|
|
|
|
chatId: chat.chatId,
|
|
|
|
participant: chat.participant,
|
|
|
|
};
|
2023-11-14 02:10:41 +08:00
|
|
|
}) as GraphqlDataHookSubscriptionResponse<Partial<ChatType>[]>;
|
2023-07-08 04:46:36 +08:00
|
|
|
|
|
|
|
const [pendingChat, setPendingChat] = usePendingChat();
|
|
|
|
|
2023-11-14 02:10:41 +08:00
|
|
|
if (pendingChat && chats) {
|
2023-09-14 00:37:40 +08:00
|
|
|
const chat = chats.find((c) => {
|
|
|
|
return c.participant?.userId === pendingChat;
|
|
|
|
});
|
2023-07-08 04:46:36 +08:00
|
|
|
if (chat) {
|
|
|
|
setPendingChat('');
|
|
|
|
layoutContextDispatch({
|
|
|
|
type: ACTIONS.SET_ID_CHAT_OPEN,
|
|
|
|
value: chat.chatId,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sidebarContent.sidebarContentPanel !== PANELS.CHAT) return null;
|
2024-02-23 03:19:50 +08:00
|
|
|
if (!idChatOpen) return <ChatLoading isRTL={isRTL} />;
|
|
|
|
return <Chat isRTL={isRTL} />;
|
2023-07-08 04:46:36 +08:00
|
|
|
};
|
|
|
|
|
2023-09-14 00:37:40 +08:00
|
|
|
export default ChatContainer;
|