Skip to content

Dev to staging #2698

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 4 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions src/pages/common/components/ChatComponent/ChatComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,22 @@ import { debounce, delay, omit } from "lodash";
import { v4 as uuidv4 } from "uuid";
import { selectUser } from "@/pages/Auth/store/selectors";
import { ChatService, DiscussionMessageService, FileService } from "@/services";
import { Separator } from "@/shared/components";
import {
ChatType,
DiscussionMessageOwnerType,
GovernanceActions,
LastSeenEntity,
QueryParamKey,
} from "@/shared/constants";
import { FILES_ACCEPTED_EXTENSIONS } from "@/shared/constants";
import { HotKeys } from "@/shared/constants/keyboardKeys";
import { ChatMessageToUserDiscussionMessageConverter } from "@/shared/converters";
import { useZoomDisabling, useImageSizeCheck } from "@/shared/hooks";
import {
useZoomDisabling,
useImageSizeCheck,
useQueryParams,
} from "@/shared/hooks";
import { ArrowInCircleIcon, PlusIcon, SendIcon } from "@/shared/icons";
import { LinkPreviewData } from "@/shared/interfaces";
import { CreateDiscussionMessageDto } from "@/shared/interfaces/api/discussionMessages";
Expand Down Expand Up @@ -73,7 +79,9 @@ import {
MessageLinkPreview,
MessageReply,
ChatFilePreview,
MessageInfoWithDateList,
} from "./components";
import { checkIsLastSeenInPreviousDay } from "./components/ChatContent/utils";
import { useChatChannelChatAdapter, useDiscussionChatAdapter } from "./hooks";
import { getLastNonUserMessage } from "./utils";
import styles from "./ChatComponent.module.scss";
Expand Down Expand Up @@ -152,6 +160,9 @@ export default function ChatComponent({
onInternalLinkClick,
}: ChatComponentInterface) {
const dispatch = useDispatch();
const queryParams = useQueryParams();
const shouldDisplayMessagesOnlyWithUncheckedItems =
queryParams[QueryParamKey.Unchecked] === "true";
const { checkImageSize } = useImageSizeCheck();
useZoomDisabling();
const editorRef = useRef<HTMLElement>(null);
Expand Down Expand Up @@ -289,7 +300,43 @@ export default function ChatComponent({
),
[discussionMessages],
);
const dateList = useMemo(() => Object.keys(messages), [messages]);

const dateList: MessageInfoWithDateList = useMemo(() => {
const messagesDates = Object.keys(messages);
const messagesWithInfo = messagesDates.map((day, dayIndex) => {
const date = new Date(Number(day));
const currentMessages = shouldDisplayMessagesOnlyWithUncheckedItems
? messages[Number(day)].filter((message) => message.hasUncheckedItems)
: messages[Number(day)];
const previousDayMessages =
messages[Number(messagesDates[dayIndex + 1])] || [];
const isLastSeenInPreviousDay = checkIsLastSeenInPreviousDay(
previousDayMessages,
lastSeenItem?.id,
);
const isMyMessageFirst =
checkIsUserDiscussionMessage(currentMessages[0]) &&
currentMessages[0].ownerId === userId;
const newSeparatorEl = (
<li>
<Separator>New</Separator>
</li>
);

return {
day,
date,
currentMessages,
isLastSeenInPreviousDay,
isMyMessageFirst,
newSeparatorEl,
};
});

return messagesWithInfo;
}, [messages]);

// const dateListWith

const [newMessages, setMessages] = useState<
CreateDiscussionMessageDtoWithFilesPreview[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import React, {
ForwardRefRenderFunction,
useImperativeHandle,
forwardRef,
memo,
} from "react";
import { useSelector } from "react-redux";
import { scroller, animateScroll } from "react-scroll";
Expand Down Expand Up @@ -34,22 +33,31 @@ import {
import { Loader } from "@/shared/ui-kit";
import { InternalLinkData } from "@/shared/utils";
import { formatDate } from "@/shared/utils";
import { Separator } from "./components";
import { checkIsLastSeenInPreviousDay } from "./utils";
import styles from "./ChatContent.module.scss";

export interface ChatContentRef {
scrollToContainerBottom: () => void;
}

export type MessageInfoWithDate = {
day: string;
date: Date;
currentMessages: DiscussionMessageWithParsedText[];
isLastSeenInPreviousDay: boolean;
isMyMessageFirst: boolean;
newSeparatorEl: JSX.Element;
};

export type MessageInfoWithDateList = MessageInfoWithDate[];

interface ChatContentInterface {
type: ChatType;
commonMember: CommonMember | null;
governanceCircles?: Circles;
chatWrapperId: string;
messages: Record<number, DiscussionMessageWithParsedText[]>;
discussionMessages: DiscussionMessageWithParsedText[] | null;
dateList: string[];
dateList: MessageInfoWithDateList;
lastSeenItem?: CommonFeedObjectUserUnique["lastSeen"];
hasPermissionToHide: boolean;
users: User[];
Expand Down Expand Up @@ -101,7 +109,6 @@ const ChatContent: ForwardRefRenderFunction<
onFeedItemClick,
onInternalLinkClick,
isEmpty,
messages,
isChatChannel,
isMessageEditAllowed,
fetchReplied,
Expand All @@ -115,8 +122,6 @@ const ChatContent: ForwardRefRenderFunction<
const isTabletView = useIsTabletView();
const queryParams = useQueryParams();
const messageIdParam = queryParams[QueryParamKey.Message];
const shouldDisplayMessagesOnlyWithUncheckedItems =
queryParams[QueryParamKey.Unchecked] === "true";

const [highlightedMessageId, setHighlightedMessageId] = useState(
() => (typeof messageIdParam === "string" && messageIdParam) || null,
Expand Down Expand Up @@ -238,107 +243,102 @@ const ChatContent: ForwardRefRenderFunction<

return (
<>
{dateListReverse.map((day, dayIndex) => {
const date = new Date(Number(day));
const currentMessages = shouldDisplayMessagesOnlyWithUncheckedItems
? messages[Number(day)].filter((message) => message.hasUncheckedItems)
: messages[Number(day)];
const previousDayMessages =
messages[Number(dateListReverse[dayIndex + 1])] || [];
const isLastSeenInPreviousDay = checkIsLastSeenInPreviousDay(
previousDayMessages,
lastSeenItem?.id,
);
const isMyMessageFirst =
checkIsUserDiscussionMessage(currentMessages[0]) &&
currentMessages[0].ownerId === userId;
const newSeparatorEl = (
<li>
<Separator>New</Separator>
</li>
);
{dateListReverse.map(
(
{
day,
currentMessages,
date,
isLastSeenInPreviousDay,
isMyMessageFirst,
newSeparatorEl,
},
dayIndex,
) => {
return (
<Transition
key={day}
show={currentMessages.length > 0}
transition={isTabletView ? ModalTransition.FadeIn : null}
className={styles.messageListTransitionContainer}
style={{ zIndex: dateListReverse.length - dayIndex }}
>
{currentMessages.length > 0 && (
<ul id={chatId} className={styles.messageList}>
{isLastSeenInPreviousDay &&
!isMyMessageFirst &&
newSeparatorEl}
<li className={styles.dateTitle}>
{isToday(date) ? "Today" : formatDate(date)}
</li>
{currentMessages.map((message, messageIndex) => {
const nextMessage = currentMessages[messageIndex + 1];
const isMyMessageNext =
checkIsUserDiscussionMessage(nextMessage) &&
nextMessage.ownerId === userId;
const messageEl = isChatChannel ? (
<DMChatMessage
key={message.id}
user={user}
discussionMessage={message}
chatType={type}
scrollToRepliedMessage={scrollToRepliedMessageDMChat}
highlighted={message.id === highlightedMessageId}
hasPermissionToHide={hasPermissionToHide}
users={users}
feedItemId={feedItemId}
commonMember={commonMember}
governanceCircles={governanceCircles}
onMessageDelete={onMessageDelete}
directParent={directParent}
onUserClick={onUserClick}
onFeedItemClick={onFeedItemClick}
onInternalLinkClick={onInternalLinkClick}
chatChannelId={chatChannelId}
/>
) : (
<ChatMessage
key={message.id}
user={user}
discussionMessage={message}
chatType={type}
scrollToRepliedMessage={scrollToRepliedMessage}
highlighted={message.id === highlightedMessageId}
hasPermissionToHide={hasPermissionToHide}
users={users}
feedItemId={feedItemId}
commonMember={commonMember}
governanceCircles={governanceCircles}
onMessageDelete={onMessageDelete}
directParent={directParent}
onUserClick={onUserClick}
onFeedItemClick={onFeedItemClick}
onInternalLinkClick={onInternalLinkClick}
isMessageEditAllowed={isMessageEditAllowed}
/>
);

return (
<Transition
key={day}
show={currentMessages.length > 0}
transition={isTabletView ? ModalTransition.FadeIn : null}
className={styles.messageListTransitionContainer}
style={{ zIndex: dateListReverse.length - dayIndex }}
>
{currentMessages.length > 0 && (
<ul id={chatId} className={styles.messageList}>
{isLastSeenInPreviousDay && !isMyMessageFirst && newSeparatorEl}
<li className={styles.dateTitle}>
{isToday(date) ? "Today" : formatDate(date)}
</li>
{currentMessages.map((message, messageIndex) => {
const nextMessage = currentMessages[messageIndex + 1];
const isMyMessageNext =
checkIsUserDiscussionMessage(nextMessage) &&
nextMessage.ownerId === userId;
const messageEl = isChatChannel ? (
<DMChatMessage
key={message.id}
user={user}
discussionMessage={message}
chatType={type}
scrollToRepliedMessage={scrollToRepliedMessageDMChat}
highlighted={message.id === highlightedMessageId}
hasPermissionToHide={hasPermissionToHide}
users={users}
feedItemId={feedItemId}
commonMember={commonMember}
governanceCircles={governanceCircles}
onMessageDelete={onMessageDelete}
directParent={directParent}
onUserClick={onUserClick}
onFeedItemClick={onFeedItemClick}
onInternalLinkClick={onInternalLinkClick}
chatChannelId={chatChannelId}
/>
) : (
<ChatMessage
key={message.id}
user={user}
discussionMessage={message}
chatType={type}
scrollToRepliedMessage={scrollToRepliedMessage}
highlighted={message.id === highlightedMessageId}
hasPermissionToHide={hasPermissionToHide}
users={users}
feedItemId={feedItemId}
commonMember={commonMember}
governanceCircles={governanceCircles}
onMessageDelete={onMessageDelete}
directParent={directParent}
onUserClick={onUserClick}
onFeedItemClick={onFeedItemClick}
onInternalLinkClick={onInternalLinkClick}
isMessageEditAllowed={isMessageEditAllowed}
/>
);
if (
message.id !== lastSeenItem?.id ||
messageIndex === currentMessages.length - 1 ||
isMyMessageNext
) {
return messageEl;
}

if (
message.id !== lastSeenItem?.id ||
messageIndex === currentMessages.length - 1 ||
isMyMessageNext
) {
return messageEl;
}

return (
<React.Fragment key={message.id}>
{messageEl}
{newSeparatorEl}
</React.Fragment>
);
})}
</ul>
)}
</Transition>
);
})}
return (
<React.Fragment key={message.id}>
{messageEl}
{newSeparatorEl}
</React.Fragment>
);
})}
</ul>
)}
</Transition>
);
},
)}
{isLoading && (
<div className={styles.loaderContainer}>
<Loader />
Expand All @@ -356,4 +356,4 @@ const ChatContent: ForwardRefRenderFunction<
);
};

export default memo(forwardRef(ChatContent));
export default forwardRef(ChatContent);
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as ChatContent } from "./ChatContent";
export type { ChatContentRef } from "./ChatContent";
export type { MessageInfoWithDateList } from "./ChatContent";
12 changes: 8 additions & 4 deletions src/shared/components/Chat/ChatMessage/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const getStaticLinkByChatType = (chatType: ChatType): StaticLinkType => {

const FILE_NAME_LIMIT = 20;

export default function ChatMessage({
const ChatMessage = ({
discussionMessage,
chatType,
highlighted = false,
Expand All @@ -112,7 +112,7 @@ export default function ChatMessage({
onFeedItemClick,
onInternalLinkClick,
isMessageEditAllowed,
}: ChatMessageProps) {
}: ChatMessageProps) => {
const dispatch = useDispatch();
const { notify } = useNotification();
const updateMessageRef = useRef<{
Expand Down Expand Up @@ -268,7 +268,7 @@ export default function ChatMessage({
setIsMessageEditLoading(true);

try {
const updatedMessage = await ChatService.updateChatMessage({
await ChatService.updateChatMessage({
chatMessageId: discussionMessage.id,
text: JSON.stringify(message),
hasUncheckedItems: checkUncheckedItemsInTextEditorValue(message),
Expand Down Expand Up @@ -582,4 +582,8 @@ export default function ChatMessage({
</li>
</ChatMessageContext.Provider>
);
}
};

const MemoizedChatMessage = React.memo(ChatMessage)

export default MemoizedChatMessage;
Loading
Loading