Skip to content

Commit

Permalink
CW-optimistic-streams
Browse files Browse the repository at this point in the history
Improvements to optimistic:
1. Fixed glitched in card while transitioning from Optimistic to Real
2. Added focuses for ChatComponent and DiscussionCreation
3. Remove unnecessary  proposalCreation modal
  • Loading branch information
MeyerPV committed Sep 30, 2024
1 parent a80e269 commit 6c332c7
Show file tree
Hide file tree
Showing 28 changed files with 216 additions and 99 deletions.
10 changes: 9 additions & 1 deletion src/pages/common/components/ChatComponent/ChatComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, {
ChangeEvent,
useRef,
ReactNode,
useLayoutEffect,
} from "react";
import { useDispatch, useSelector } from "react-redux";
import { useDebounce, useMeasure, useScroll } from "react-use";
Expand Down Expand Up @@ -83,6 +84,7 @@ import {
uploadFilesAndImages,
} from "./utils";
import styles from "./ChatComponent.module.scss";
import { BaseTextEditorHandles } from "@/shared/ui-kit/TextEditor/BaseTextEditor";

const BASE_CHAT_INPUT_HEIGHT = 48;

Expand Down Expand Up @@ -163,6 +165,7 @@ export default function ChatComponent({
queryParams[QueryParamKey.Unchecked] === "true";
const { checkImageSize } = useImageSizeCheck();
useZoomDisabling();
const textInputRef = useRef<BaseTextEditorHandles>(null);
const editorRef = useRef<HTMLElement>(null);
const [inputContainerRef, { height: chatInputHeight }] =
useMeasure<HTMLDivElement>();
Expand Down Expand Up @@ -268,7 +271,6 @@ export default function ChatComponent({

const optimisticFeedItems = useSelector(selectOptimisticFeedItems);

// console.log("--optimisticFeedItems", optimisticFeedItems);
const optimisticDiscussionMessages = useSelector(
selectOptimisticDiscussionMessages,
);
Expand Down Expand Up @@ -718,6 +720,11 @@ export default function ChatComponent({
}
}, [discussionMessageReply, currentFilesPreview]);

useLayoutEffect(() => {
textInputRef?.current?.clear?.();
textInputRef?.current?.focus?.();
},[discussionId]);

useEffect(() => {
if (isFetchedDiscussionMessages) {
onMessagesAmountChange?.(discussionMessages.length);
Expand Down Expand Up @@ -852,6 +859,7 @@ export default function ChatComponent({
})}
>
<ChatInput
ref={textInputRef}
onClearFinished={onClearFinished}
shouldReinitializeEditor={shouldReinitializeEditor}
users={users}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
.messageInputEmpty {
padding-left: 0.75rem;
overflow-x: hidden;
opacity: 1; /* Ensure it's fully visible */
transition: none; /* Disable any transitions or animations */
}

.addFilesIcon {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {
ChangeEvent,
forwardRef,
MutableRefObject,
ReactElement,
RefCallback,
Expand All @@ -18,6 +19,7 @@ import {
import { EmojiCount } from "@/shared/ui-kit/TextEditor/utils";
import { emptyFunction } from "@/shared/utils";
import styles from "./ChatInput.module.scss";
import { BaseTextEditorHandles } from "@/shared/ui-kit/TextEditor/BaseTextEditor";

interface ChatInputProps {
shouldHideChatInput: boolean;
Expand All @@ -33,14 +35,14 @@ interface ChatInputProps {
canSendMessage?: boolean;
sendChatMessage: () => void;
inputContainerRef?:
| MutableRefObject<HTMLDivElement | null>
| RefCallback<HTMLDivElement>;
| MutableRefObject<HTMLDivElement | null>
| RefCallback<HTMLDivElement>;
editorRef?: MutableRefObject<HTMLElement | null> | RefCallback<HTMLElement>;
renderChatInputOuter?: () => ReactElement;
isAuthorized?: boolean;
}

export const ChatInput = (props: ChatInputProps): ReactElement | null => {
export const ChatInput = React.memo(forwardRef<BaseTextEditorHandles, ChatInputProps>((props, ref): ReactElement | null => {
const {
inputContainerRef,
editorRef,
Expand Down Expand Up @@ -93,6 +95,7 @@ export const ChatInput = (props: ChatInputProps): ReactElement | null => {
accept={FILES_ACCEPTED_EXTENSIONS}
/>
<BaseTextEditor
ref={ref}
inputContainerRef={inputContainerRef}
size={TextEditorSize.Auto}
editorRef={editorRef}
Expand Down Expand Up @@ -124,4 +127,4 @@ export const ChatInput = (props: ChatInputProps): ReactElement | null => {
</button>
</>
);
};
}));
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ import {
TextEditorValue,
parseStringToTextEditorValue,
} from "@/shared/ui-kit/TextEditor";
import { generateOptimisticFeedItem } from "@/shared/utils";
import { generateFirstMessage, generateOptimisticFeedItem, getUserName } from "@/shared/utils";
import {
selectDiscussionCreationData,
selectIsDiscussionCreationLoading,
} from "@/store/states";
import { commonActions } from "@/store/states";
import { DiscussionCreationCard, DiscussionCreationModal } from "./components";
import { DiscussionMessageOwnerType } from "@/shared/constants";

interface NewDiscussionCreationProps {
common: Common;
Expand Down Expand Up @@ -120,7 +121,7 @@ const NewDiscussionCreation: FC<NewDiscussionCreationProps> = (props) => {
);
} else {
const discussionId = uuidv4();

const userName = getUserName(user);
dispatch(
commonActions.setOptimisticFeedItem(
generateOptimisticFeedItem({
Expand All @@ -131,6 +132,12 @@ const NewDiscussionCreation: FC<NewDiscussionCreationProps> = (props) => {
discussionId,
title: values.title,
content: JSON.stringify(values.content),
lastMessageContent: {
ownerId: userId,
userName,
ownerType: DiscussionMessageOwnerType.System,
content: generateFirstMessage({userName, userId}),
}
}),
),
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import React, { FC, useEffect, useRef } from "react";
import classNames from "classnames";
import {
TextEditor,
Expand All @@ -17,9 +17,18 @@ interface DiscussionFormProps {
const DiscussionForm: FC<DiscussionFormProps> = (props) => {
const { className, disabled = false } = props;

const textEditorRef = useRef<HTMLTextAreaElement | null>(null);

useEffect(() => {
if (textEditorRef.current) {
textEditorRef.current.focus();
}
}, []);

return (
<div className={classNames(styles.container, className)}>
<TextField
ref={textEditorRef}
className={styles.field}
id="discussionTitle"
name="title"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useDispatch, useSelector } from "react-redux";
import { v4 as uuidv4 } from "uuid";
import { selectUser } from "@/pages/Auth/store/selectors";
import {
DiscussionMessageOwnerType,
PROPOSAL_TYPE_SELECT_OPTIONS,
ProposalsTypes,
} from "@/shared/constants";
Expand All @@ -15,7 +16,7 @@ import {
Governance,
} from "@/shared/models";
import { parseStringToTextEditorValue } from "@/shared/ui-kit/TextEditor";
import { generateOptimisticFeedItem } from "@/shared/utils";
import { generateFirstMessage, generateOptimisticFeedItem, getUserName } from "@/shared/utils";
import {
selectIsProposalCreationLoading,
selectProposalCreationData,
Expand Down Expand Up @@ -87,6 +88,7 @@ const NewProposalCreation: FC<NewProposalCreationProps> = (props) => {

const proposalId = uuidv4();
const discussionId = uuidv4();
const userName = getUserName(user);

dispatch(
commonActions.setOptimisticFeedItem(
Expand All @@ -98,6 +100,12 @@ const NewProposalCreation: FC<NewProposalCreationProps> = (props) => {
discussionId,
title: values.title,
content: JSON.stringify(values.content),
lastMessageContent: {
ownerId: userId,
userName,
ownerType: DiscussionMessageOwnerType.System,
content: generateFirstMessage({userName, userId}),
}
}),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import React, {
useMemo,
useState,
} from "react";
import { useSelector } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import { useUpdateEffect } from "react-use";
import { debounce } from "lodash";
import { selectUser } from "@/pages/Auth/store/selectors";
import { DiscussionService } from "@/services";
import { DeletePrompt, GlobalOverlay, ReportModal } from "@/shared/components";
import { EntityTypes, InboxItemType } from "@/shared/constants";
import { DiscussionMessageOwnerType, EntityTypes, InboxItemType } from "@/shared/constants";
import { useModal, useNotification } from "@/shared/hooks";
import {
FeedItemFollowState,
Expand All @@ -33,7 +33,7 @@ import {
PredefinedTypes,
} from "@/shared/models";
import { TextEditorValue } from "@/shared/ui-kit";
import { StaticLinkType, getUserName, InternalLinkData } from "@/shared/utils";
import { StaticLinkType, getUserName, InternalLinkData, generateFirstMessage } from "@/shared/utils";
import { useChatContext } from "../ChatComponent";
import { FeedCard } from "../FeedCard";
import { FeedCardShare } from "../FeedCard";
Expand All @@ -49,6 +49,7 @@ import {
DiscussionFeedCardContent,
} from "./components";
import { useMenuItems } from "./hooks";
import { commonActions } from "@/store/states";

interface DiscussionFeedCardProps {
item: CommonFeed;
Expand Down Expand Up @@ -76,6 +77,7 @@ interface DiscussionFeedCardProps {
onUserClick?: (userId: string) => void;
onFeedItemClick: (feedItemId: string) => void;
onInternalLinkClick: (data: InternalLinkData) => void;
isOptimisticallyCreated?: boolean;
}

function DiscussionFeedCard(props, ref) {
Expand All @@ -86,6 +88,7 @@ function DiscussionFeedCard(props, ref) {
nestedItemData,
} = useChatContext();
const { notify } = useNotification();
const dispatch = useDispatch();
const {
item,
governanceCircles,
Expand All @@ -112,6 +115,7 @@ function DiscussionFeedCard(props, ref) {
onUserClick,
onFeedItemClick,
onInternalLinkClick,
isOptimisticallyCreated,
} = props;
const {
isShowing: isReportModalOpen,
Expand Down Expand Up @@ -213,6 +217,12 @@ function DiscussionFeedCard(props, ref) {
const cardTitle = discussion?.title;
const commonNotion = outerCommonNotion ?? common?.notion;

// const ownerId = useMemo(() => {
// if(item.userId) {
// return item.userId
// }
// },[item.userId])

const handleOpenChat = useCallback(() => {
if (discussion && !isPreviewMode) {
setChatItem({
Expand Down Expand Up @@ -274,6 +284,13 @@ function DiscussionFeedCard(props, ref) {
[preloadDiscussionMessagesData.preloadDiscussionMessages],
);

useEffect(() => {
if(item.data.lastMessage?.content && discussion?.id && isOptimisticallyCreated) {
// markFeedItemAsSeen({feedObjectId: item.id, commonId})
dispatch(commonActions.clearCreatedOptimisticFeedItem(discussion?.id));
}
},[item.id, item.data.lastMessage?.content, discussion?.id, isOptimisticallyCreated, commonId])

useEffect(() => {
fetchDiscussionCreator(item.userId);
}, [item.userId]);
Expand Down Expand Up @@ -348,12 +365,21 @@ function DiscussionFeedCard(props, ref) {
}, [item.data.lastMessage?.content]);

const lastMessage = useMemo(() => {
const userName = getUserName(discussionCreator);

const optimisticMessage = {
userName,
ownerId: userId,
content: generateFirstMessage({userName, userId: userId ?? ""}),
ownerType: DiscussionMessageOwnerType.System,
}

return getLastMessage({
commonFeedType: item.data.type,
lastMessage: item.data.lastMessage,
lastMessage: isOptimisticallyCreated ? optimisticMessage : item.data.lastMessage,
discussion,
currentUserId: userId,
feedItemCreatorName: getUserName(discussionCreator),
feedItemCreatorName: userName,
commonName,
isProject,
hasFiles: item.data.hasFiles,
Expand All @@ -369,6 +395,7 @@ function DiscussionFeedCard(props, ref) {
isProject,
item.data.hasFiles,
item.data.hasImages,
isOptimisticallyCreated,
]);

return (
Expand All @@ -391,13 +418,13 @@ function DiscussionFeedCard(props, ref) {
image={commonImage}
imageAlt={`${commonName}'s image`}
isProject={isProject}
isFollowing={feedItemFollow.isFollowing}
isFollowing={isOptimisticallyCreated || feedItemFollow.isFollowing}
isLoading={isLoading}
menuItems={menuItems}
seenOnce={
feedItemUserMetadata?.seenOnce ?? !isFeedItemUserMetadataFetched
}
seen={feedItemUserMetadata?.seen ?? !isFeedItemUserMetadataFetched}
seen={(isOptimisticallyCreated || feedItemUserMetadata?.seen) ?? !isFeedItemUserMetadataFetched}
ownerId={item.userId}
discussionPredefinedType={discussion?.predefinedType}
notion={discussionNotion && commonNotion}
Expand Down
2 changes: 1 addition & 1 deletion src/pages/common/components/FeedCard/FeedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ const FeedCard = (props, ref) => {
onClick: handleClick,
onExpand: handleExpand,
title,
lastMessage: !isLoading ? lastMessage : undefined,
lastMessage,
menuItems,
commonName,
commonId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface FeedCardTagsProps {
hasUnseenMention?: boolean;
}

export const FeedCardTags: FC<FeedCardTagsProps> = (props) => {
export const MemoizedFeedCardTags: FC<FeedCardTagsProps> = (props) => {
const {
unreadMessages,
type,
Expand All @@ -35,9 +35,8 @@ export const FeedCardTags: FC<FeedCardTagsProps> = (props) => {
const isOwner = ownerId === user?.uid;
const isNewTagVisible =
notEmpty(seenOnce) && notEmpty(isOwner) && !seenOnce && !isOwner;
const isUnseenTagVisible =
!isNewTagVisible && !unreadMessages && notEmpty(seen) && !seen;

const isUnseenTagVisible =
!isNewTagVisible && !unreadMessages && notEmpty(seen) && !seen && !isOwner;
return (
<>
{type === CommonFeedType.Proposal && (
Expand Down Expand Up @@ -86,3 +85,5 @@ export const FeedCardTags: FC<FeedCardTagsProps> = (props) => {
</>
);
};

export const FeedCardTags = React.memo(MemoizedFeedCardTags);
Loading

0 comments on commit 6c332c7

Please sign in to comment.