Skip to content

Commit

Permalink
Merge pull request #2698 from daostack/dev
Browse files Browse the repository at this point in the history
Dev to staging
  • Loading branch information
MeyerPV authored Jun 10, 2024
2 parents 836e6fb + 35cdb79 commit fa455b0
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 116 deletions.
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

0 comments on commit fa455b0

Please sign in to comment.