Fix: TypeScript and Lint Errors in Chat List/Page, Message, and Content Modules (#18648)
* rules addition and ts errors fixed on chat list component * TS fixes and list for chat list:page, content and message * Additional fixes * additional changes * any type removed * Update componet.tsx * Update .eslintrc.js * fixes * fixing chat issues
This commit is contained in:
parent
75dd624d80
commit
cd922c2c2c
@ -16,6 +16,8 @@ import { Chat } from '/imports/ui/Types/chat';
|
||||
import { Message } from '/imports/ui/Types/message';
|
||||
import { useCurrentUser } from '/imports/ui/core/hooks/useCurrentUser';
|
||||
import { User } from '/imports/ui/Types/user';
|
||||
import ChatPopupContainer from '../chat-popup/component';
|
||||
import { defineMessages, useIntl } from "react-intl";
|
||||
import { Layout } from '/imports/ui/Types/layout';
|
||||
import ChatPopupContainer from '../chat-popup/component';
|
||||
import { ChatEvents } from "/imports/ui/core/enums/chat";
|
||||
@ -42,9 +44,8 @@ interface ChatListProps {
|
||||
totalPages: number;
|
||||
chatId: string;
|
||||
currentUserId: string;
|
||||
setMessageAsSeenMutation: (variables: any) => void;
|
||||
totalUnread?: number;
|
||||
lastSeenAt: number;
|
||||
setMessageAsSeenMutation: (variables: {chatId: string,
|
||||
lastSeenAt: number}) => void;
|
||||
}
|
||||
const isElement = (el: any): el is HTMLElement => {
|
||||
return el instanceof HTMLElement;
|
||||
@ -267,7 +268,7 @@ const ChatMessageList: React.FC<ChatListProps> = ({
|
||||
}
|
||||
setUserLoadedBackUntilPage(userLoadedBackUntilPage - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.loadMoreButtonLabel)}
|
||||
</ButtonLoadMore>
|
||||
@ -278,7 +279,7 @@ const ChatMessageList: React.FC<ChatListProps> = ({
|
||||
<ChatPopupContainer />
|
||||
{
|
||||
// @ts-ignore
|
||||
Array.from({ length: pagesToLoad }, (_v, k) => k + firstPageToLoad).map((page) => {
|
||||
Array.from({ length: pagesToLoad }, (v, k) => k + firstPageToLoad).map((page) => {
|
||||
return (
|
||||
<ChatListPage
|
||||
key={`page-${page}`}
|
||||
@ -297,12 +298,11 @@ const ChatMessageList: React.FC<ChatListProps> = ({
|
||||
</div>
|
||||
</MessageList>
|
||||
</MessageListWrapper >
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
const ChatMessageListContainer: React.FC<Layout> = ({ }) => {
|
||||
const idChatOpen = layoutSelect((i: idChatOpen) => i.idChatOpen);
|
||||
const ChatMessageListContainer: React.FC = ({ }) => {
|
||||
const idChatOpen = layoutSelect((i: { idChatOpen: any; }) => i.idChatOpen);
|
||||
const isPublicChat = idChatOpen === PUBLIC_CHAT_KEY;
|
||||
const chatId = !isPublicChat ? idChatOpen : PUBLIC_GROUP_CHAT_KEY;
|
||||
const currentChat = useChat((chat) => {
|
||||
|
@ -1,26 +1,25 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { Message } from '/imports/ui/Types/message';
|
||||
import ChatMessageHeader from './message-header/component';
|
||||
import ChatMessageTextContent from './message-content/text-content/component';
|
||||
import ChatPollContent from './message-content/poll-content/component';
|
||||
import ChatMessagePresentationContent from './message-content/presentation-content/component';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import {
|
||||
ChatWrapper,
|
||||
ChatContent,
|
||||
ChatAvatar,
|
||||
} from "./styles";
|
||||
import ChatMessageHeader from "./message-header/component";
|
||||
import ChatMessageTextContent from "./message-content/text-content/component";
|
||||
import ChatPollContent from "./message-content/poll-content/component";
|
||||
import ChatMessagePresentationContent from "./message-content/presentation-content/component";
|
||||
import { defineMessages, useIntl } from "react-intl";
|
||||
import { ChatMessageType } from '/imports/ui/core/enums/chat';
|
||||
|
||||
interface ChatMessageProps {
|
||||
message: Message;
|
||||
previousMessage?: Message;
|
||||
lastSenderPreviousPage?: string | null;
|
||||
previousMessage: Message;
|
||||
lastSenderPreviousPage: string | null;
|
||||
scrollRef: React.RefObject<HTMLDivElement>;
|
||||
markMessageAsSeen: Function;
|
||||
markMessageAsSeen: (message: Message) => void;
|
||||
}
|
||||
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
pollResult: {
|
||||
id: 'app.chat.pollResult',
|
||||
@ -44,31 +43,32 @@ function isInViewport(el: HTMLDivElement) {
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
|
||||
rect.bottom >= 0
|
||||
rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.bottom >= 0
|
||||
);
|
||||
}
|
||||
|
||||
const messageRef = React.createRef<HTMLDivElement | null>();
|
||||
|
||||
const ChatMesssage: React.FC<ChatMessageProps> = ({
|
||||
message,
|
||||
previousMessage,
|
||||
lastSenderPreviousPage,
|
||||
scrollRef,
|
||||
message,
|
||||
markMessageAsSeen,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const messageRef = useRef<HTMLDivElement>(null);
|
||||
const markMessageAsSeenOnScrollEnd = useCallback((message, messageRef) => {
|
||||
const markMessageAsSeenOnScrollEnd = useCallback(() => {
|
||||
if (messageRef.current && isInViewport(messageRef.current)) {
|
||||
markMessageAsSeen(message);
|
||||
}
|
||||
}, []);
|
||||
}, [message, messageRef]);
|
||||
|
||||
useEffect(() => {
|
||||
// I use a function here to remove the event listener using the same reference
|
||||
const callbackFunction = () => {
|
||||
markMessageAsSeenOnScrollEnd(message, messageRef);
|
||||
}
|
||||
if (messageRef.current && isInViewport(messageRef.current)) {
|
||||
markMessageAsSeen(message); // Pass the 'message' argument here
|
||||
}
|
||||
};
|
||||
if (message && scrollRef.current && messageRef.current) {
|
||||
if (isInViewport(messageRef.current)) {
|
||||
markMessageAsSeen(message);
|
||||
@ -77,14 +77,14 @@ const ChatMesssage: React.FC<ChatMessageProps> = ({
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
scrollRef?.current
|
||||
?.removeEventListener('scrollend', callbackFunction);
|
||||
}
|
||||
}, [message, messageRef]);
|
||||
scrollRef?.current?.removeEventListener('scrollend', callbackFunction);
|
||||
};
|
||||
}, [message, messageRef, markMessageAsSeenOnScrollEnd]);
|
||||
|
||||
if (!message) return null;
|
||||
|
||||
const sameSender = (previousMessage?.user?.userId || lastSenderPreviousPage) === message?.user?.userId;
|
||||
const sameSender = (previousMessage?.user?.userId
|
||||
|| lastSenderPreviousPage) === message?.user?.userId;
|
||||
const dateTime = new Date(message?.createdTime);
|
||||
const messageContent: {
|
||||
name: string,
|
||||
@ -118,7 +118,7 @@ const ChatMesssage: React.FC<ChatMessageProps> = ({
|
||||
isModerator: true,
|
||||
component: (
|
||||
<ChatMessageTextContent
|
||||
emphasizedMessage={true}
|
||||
emphasizedMessage
|
||||
text={intl.formatMessage(intlMessages.chatClear)}
|
||||
/>
|
||||
),
|
||||
@ -135,35 +135,28 @@ const ChatMesssage: React.FC<ChatMessageProps> = ({
|
||||
text={message.message}
|
||||
/>
|
||||
),
|
||||
}
|
||||
};
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<ChatWrapper
|
||||
sameSender={sameSender}
|
||||
ref={messageRef}
|
||||
>
|
||||
{(!message?.user || !sameSender)
|
||||
&& (
|
||||
<ChatAvatar
|
||||
avatar={message.user?.avatar}
|
||||
color={messageContent.color}
|
||||
moderator={messageContent.isModerator}
|
||||
>
|
||||
{messageContent.name.toLowerCase().slice(0, 2) || " "}
|
||||
</ChatAvatar>
|
||||
)
|
||||
}
|
||||
<ChatWrapper sameSender={sameSender} ref={messageRef}>
|
||||
{(!message?.user || !sameSender) && (
|
||||
<ChatAvatar
|
||||
avatar={message.user?.avatar}
|
||||
color={messageContent.color}
|
||||
moderator={messageContent.isModerator}
|
||||
>
|
||||
{messageContent.name.toLowerCase().slice(0, 2) || ' '}
|
||||
</ChatAvatar>
|
||||
)}
|
||||
<ChatContent sameSender={message?.user ? sameSender : false}>
|
||||
<ChatMessageHeader
|
||||
sameSender={message?.user ? sameSender : false}
|
||||
name={messageContent.name}
|
||||
isOnline={message.user?.isOnline ?? true}
|
||||
dateTime={dateTime}
|
||||
/>
|
||||
{
|
||||
messageContent.component
|
||||
}
|
||||
<ChatMessageHeader
|
||||
sameSender={message?.user ? sameSender : false}
|
||||
name={messageContent.name}
|
||||
isOnline={message.user?.isOnline ?? true}
|
||||
dateTime={dateTime}
|
||||
/>
|
||||
{messageContent.component}
|
||||
</ChatContent>
|
||||
</ChatWrapper>
|
||||
);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import Styled from './styles';
|
||||
|
||||
interface ChatMessageTextContentProps {
|
||||
text: string;
|
||||
emphasizedMessage: boolean;
|
||||
@ -9,7 +10,13 @@ interface ChatMessageTextContentProps {
|
||||
const ChatMessageTextContent: React.FC<ChatMessageTextContentProps> = ({
|
||||
text,
|
||||
emphasizedMessage,
|
||||
}) => {
|
||||
}) => (
|
||||
<Styled.ChatMessage
|
||||
emphasizedMessage={emphasizedMessage}
|
||||
dangerouslySetInnerHTML={{ __html: text }}
|
||||
/>
|
||||
);
|
||||
() => {
|
||||
// @ts-ignore - temporary, while meteor exists in the project
|
||||
const { allowedElements } = Meteor.settings.public.chat;
|
||||
|
||||
@ -18,9 +25,9 @@ const ChatMessageTextContent: React.FC<ChatMessageTextContentProps> = ({
|
||||
<ReactMarkdown
|
||||
linkTarget="_blank"
|
||||
allowedElements={allowedElements}
|
||||
unwrapDisallowed={true}
|
||||
unwrapDisallowed
|
||||
>
|
||||
{text}
|
||||
{Text}
|
||||
</ReactMarkdown>
|
||||
</Styled.ChatMessage>
|
||||
);
|
||||
|
@ -1,16 +1,18 @@
|
||||
import styled from 'styled-components';
|
||||
import { colorText } from '/imports/ui/stylesheets/styled-components/palette';
|
||||
|
||||
export const ChatMessage = styled.div`
|
||||
interface ChatMessageProps {
|
||||
emphasizedMessage: boolean;
|
||||
}
|
||||
|
||||
export const ChatMessage = styled.div<ChatMessageProps>`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
flex-direction: column;
|
||||
color: ${colorText};
|
||||
word-break: break-word;
|
||||
${({ emphasizedMessage }) =>
|
||||
emphasizedMessage &&
|
||||
`
|
||||
${({ emphasizedMessage }) => emphasizedMessage && `
|
||||
font-weight: bold;
|
||||
`}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
colorSuccess,
|
||||
} from '/imports/ui/stylesheets/styled-components/palette';
|
||||
|
||||
|
||||
interface ChatWrapperProps {
|
||||
sameSender: boolean;
|
||||
}
|
||||
@ -24,6 +23,13 @@ interface ChatContentProps {
|
||||
sameSender: boolean;
|
||||
}
|
||||
|
||||
interface ChatAvatarProps {
|
||||
avatar: string;
|
||||
color: string;
|
||||
moderator: boolean;
|
||||
emoji?: string;
|
||||
}
|
||||
|
||||
export const ChatWrapper = styled.div<ChatWrapperProps>`
|
||||
pointer-events: auto;
|
||||
[dir='rtl'] & {
|
||||
@ -32,9 +38,7 @@ export const ChatWrapper = styled.div<ChatWrapperProps>`
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
position: relative;
|
||||
${({ sameSender }) =>
|
||||
sameSender &&
|
||||
`
|
||||
${({ sameSender }) => sameSender && `
|
||||
flex: 1;
|
||||
margin: ${borderSize} 0 0 ${borderSize};
|
||||
margin-top: calc(${lineHeightComputed} / 3);
|
||||
@ -55,15 +59,13 @@ export const ChatContent = styled.div<ChatContentProps>`
|
||||
flex-flow: column;
|
||||
width: 100%;
|
||||
|
||||
${({ sameSender }) =>
|
||||
sameSender &&
|
||||
`
|
||||
${({ sameSender }) => sameSender && `
|
||||
margin-left: 2.6rem;
|
||||
`}
|
||||
`;
|
||||
|
||||
|
||||
export const ChatAvatar = styled.div`
|
||||
export const ChatAvatar = styled.div<ChatAvatarProps>`
|
||||
flex: 0 0 2.25rem;
|
||||
margin: 0px calc(0.5rem) 0px 0px;
|
||||
box-flex: 0;
|
||||
@ -116,17 +118,12 @@ export const ChatAvatar = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
${({ moderator }) =>
|
||||
moderator &&
|
||||
`
|
||||
${({ moderator }) => moderator && `
|
||||
border-radius: 5px;
|
||||
`}
|
||||
|
||||
// ================ image ================
|
||||
${({ avatar, emoji }) =>
|
||||
avatar?.length !== 0 &&
|
||||
!emoji &&
|
||||
css`
|
||||
${({ avatar, emoji }) => avatar?.length !== 0 && !emoji && css`
|
||||
background-image: url(${avatar});
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React from "react";
|
||||
import { useSubscription } from "@apollo/client";
|
||||
import React from 'react';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import {
|
||||
CHAT_MESSAGE_PUBLIC_SUBSCRIPTION,
|
||||
CHAT_MESSAGE_PRIVATE_SUBSCRIPTION,
|
||||
ChatMessagePrivateSubscriptionResponse,
|
||||
ChatMessagePublicSubscriptionResponse,
|
||||
} from "./queries";
|
||||
} from './queries';
|
||||
import { Message } from '/imports/ui/Types/message';
|
||||
import ChatMessage from './chat-message/componet';
|
||||
|
||||
@ -16,11 +16,12 @@ const PUBLIC_GROUP_CHAT_KEY = CHAT_CONFIG.public_group_id;
|
||||
interface ChatListPageContainerProps {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
setLastSender: Function;
|
||||
setLastSender: (page: number, message: string) => void;
|
||||
lastSenderPreviousPage: string | undefined;
|
||||
// eslint-disable-next-line react/no-unused-prop-types
|
||||
lastSeenAt: number,
|
||||
chatId: string;
|
||||
markMessageAsSeen: Function;
|
||||
markMessageAsSeen: () => void;
|
||||
scrollRef: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
@ -28,17 +29,16 @@ interface ChatListPageProps {
|
||||
messages: Array<Message>;
|
||||
lastSenderPreviousPage: string | undefined;
|
||||
page: number;
|
||||
markMessageAsSeen: Function;
|
||||
markMessageAsSeen: ()=> void;
|
||||
scrollRef: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
const verifyIfIsPublicChat = (message: unknown): message is ChatMessagePublicSubscriptionResponse => {
|
||||
return (message as ChatMessagePublicSubscriptionResponse).chat_message_public !== undefined;
|
||||
}
|
||||
const verifyIfIsPublicChat = (message: unknown):
|
||||
// eslint-disable-next-line max-len
|
||||
message is ChatMessagePublicSubscriptionResponse => (message as ChatMessagePublicSubscriptionResponse).chat_message_public !== undefined;
|
||||
|
||||
const verifyIfIsPrivateChat = (message: unknown): message is ChatMessagePrivateSubscriptionResponse => {
|
||||
return (message as ChatMessagePrivateSubscriptionResponse).chat_message_private !== undefined;
|
||||
}
|
||||
// eslint-disable-next-line max-len
|
||||
const verifyIfIsPrivateChat = (message: unknown): message is ChatMessagePrivateSubscriptionResponse => (message as ChatMessagePrivateSubscriptionResponse).chat_message_private !== undefined
|
||||
|
||||
const ChatListPage: React.FC<ChatListPageProps> = ({
|
||||
messages,
|
||||
@ -46,28 +46,26 @@ const ChatListPage: React.FC<ChatListPageProps> = ({
|
||||
page,
|
||||
markMessageAsSeen,
|
||||
scrollRef,
|
||||
|
||||
}) => {
|
||||
return (
|
||||
<div key={`messagePage-${page}`} id={`${page}`} >
|
||||
{
|
||||
messages.map((message, index, Array) => {
|
||||
const previousMessage = Array[index - 1];
|
||||
return (
|
||||
<ChatMessage
|
||||
key={message.createdTime}
|
||||
message={message}
|
||||
previousMessage={previousMessage}
|
||||
lastSenderPreviousPage={!previousMessage ? lastSenderPreviousPage : null}
|
||||
scrollRef={scrollRef}
|
||||
markMessageAsSeen={markMessageAsSeen}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}) => (
|
||||
// eslint-disable-next-line react/jsx-filename-extension
|
||||
<div key={`messagePage-${page}`} id={`${page}`}>
|
||||
{messages.map((message, index, Array) => {
|
||||
const previousMessage = Array[index - 1];
|
||||
return (
|
||||
<ChatMessage
|
||||
key={message.createdTime}
|
||||
message={message}
|
||||
previousMessage={previousMessage}
|
||||
lastSenderPreviousPage={
|
||||
!previousMessage ? lastSenderPreviousPage : null
|
||||
}
|
||||
scrollRef={scrollRef}
|
||||
markMessageAsSeen={markMessageAsSeen}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
|
||||
page,
|
||||
@ -83,17 +81,25 @@ const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
|
||||
? CHAT_MESSAGE_PUBLIC_SUBSCRIPTION
|
||||
: CHAT_MESSAGE_PRIVATE_SUBSCRIPTION;
|
||||
const defaultVariables = { offset: (page) * pageSize, limit: pageSize };
|
||||
const variables = isPublicChat ? defaultVariables : { ...defaultVariables, requestedChatId: chatId };
|
||||
const variables = isPublicChat
|
||||
? defaultVariables : { ...defaultVariables, requestedChatId: chatId };
|
||||
const {
|
||||
data: chatMessageData,
|
||||
loading: chatMessageLoading,
|
||||
error: chatMessageError,
|
||||
} = useSubscription<ChatMessagePublicSubscriptionResponse | ChatMessagePrivateSubscriptionResponse>(
|
||||
} = useSubscription<ChatMessagePublicSubscriptionResponse|ChatMessagePrivateSubscriptionResponse>(
|
||||
chatQuery,
|
||||
{ variables }
|
||||
{ variables },
|
||||
);
|
||||
|
||||
if (chatMessageError) return (<p>chatMessageError: {JSON.stringify(chatMessageError)}</p>);
|
||||
if (chatMessageError) {
|
||||
return (
|
||||
<p>
|
||||
chatMessageError:
|
||||
{JSON.stringify(chatMessageError)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
if (chatMessageLoading) return null;
|
||||
let messages: Array<Message> = [];
|
||||
if (verifyIfIsPublicChat(chatMessageData)) {
|
||||
@ -104,7 +110,6 @@ const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
|
||||
|
||||
if (messages.length > 0) {
|
||||
setLastSender(page, messages[messages.length - 1].user?.userId);
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
@ -116,6 +121,6 @@ const ChatListPageContainer: React.FC<ChatListPageContainerProps> = ({
|
||||
scrollRef={scrollRef}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ChatListPageContainer;
|
||||
|
@ -3,7 +3,11 @@ import { colorWhite, colorPrimary } from '/imports/ui/stylesheets/styled-compone
|
||||
import { smallOnly } from '/imports/ui/stylesheets/styled-components/breakpoints';
|
||||
import { mdPaddingX } from '/imports/ui/stylesheets/styled-components/general';
|
||||
|
||||
export const Chat = styled.div`
|
||||
interface ChatProps {
|
||||
isChrome: boolean;
|
||||
}
|
||||
|
||||
export const Chat = styled.div<ChatProps>`
|
||||
background-color: ${colorWhite};
|
||||
padding: ${mdPaddingX};
|
||||
padding-bottom: 0;
|
||||
@ -43,9 +47,7 @@ export const Chat = styled.div`
|
||||
text-decoration-line: none;
|
||||
}
|
||||
|
||||
${({ isChrome }) =>
|
||||
isChrome &&
|
||||
`
|
||||
${({ isChrome }) => isChrome && `
|
||||
transform: translateZ(0);
|
||||
`}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user