diff --git a/src/pages/common/components/ChatComponent/ChatComponent.tsx b/src/pages/common/components/ChatComponent/ChatComponent.tsx index d48bd19438..d8d116f625 100644 --- a/src/pages/common/components/ChatComponent/ChatComponent.tsx +++ b/src/pages/common/components/ChatComponent/ChatComponent.tsx @@ -114,7 +114,7 @@ interface ChatComponentInterface { directParent?: DirectParent | null; renderChatInput?: () => ReactNode; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; } diff --git a/src/pages/common/components/ChatComponent/components/ChatContent/ChatContent.tsx b/src/pages/common/components/ChatComponent/components/ChatContent/ChatContent.tsx index 819964cb81..cb955420b3 100644 --- a/src/pages/common/components/ChatComponent/components/ChatContent/ChatContent.tsx +++ b/src/pages/common/components/ChatComponent/components/ChatContent/ChatContent.tsx @@ -68,7 +68,7 @@ interface ChatContentInterface { onMessageDelete?: (messageId: string) => void; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (link: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; isEmpty?: boolean; diff --git a/src/pages/common/components/ChatComponent/hooks/useDiscussionChatAdapter.ts b/src/pages/common/components/ChatComponent/hooks/useDiscussionChatAdapter.ts index 2bd2df4ba4..a754349959 100644 --- a/src/pages/common/components/ChatComponent/hooks/useDiscussionChatAdapter.ts +++ b/src/pages/common/components/ChatComponent/hooks/useDiscussionChatAdapter.ts @@ -13,7 +13,7 @@ import { InternalLinkData } from "@/shared/utils"; interface Options { hasPermissionToHide: boolean; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; directParent?: DirectParent | null; diff --git a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx index 76b20f3d0f..0987d5cf1d 100644 --- a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx +++ b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx @@ -1,12 +1,3 @@ -// import { scan } from 'react-scan'; // import this BEFORE react - -// if (typeof window !== 'undefined') { -// scan({ -// enabled: true, -// log: true, // logs render info to console (default: false) -// }); -// } - import React, { forwardRef, useCallback, @@ -86,6 +77,7 @@ interface DiscussionFeedCardProps { onUserClick?: (userId: string) => void; onFeedItemClick: (feedItemId: string) => void; onInternalLinkClick: (data: InternalLinkData) => void; + onExpand?: (isExpanded: boolean) => void; isOptimisticallyCreated?: boolean; } @@ -125,6 +117,7 @@ function DiscussionFeedCard(props, ref) { onFeedItemClick, onInternalLinkClick, isOptimisticallyCreated, + onExpand, } = props; const { isShowing: isReportModalOpen, @@ -412,6 +405,7 @@ function DiscussionFeedCard(props, ref) { unreadMessages={feedItemUserMetadata?.count || 0} isActive={isActive} isExpanded={isExpanded} + onExpand={onExpand} onClick={handleOpenChat} title={cardTitle} lastMessage={lastMessage} diff --git a/src/pages/common/components/FeedCard/FeedCard.tsx b/src/pages/common/components/FeedCard/FeedCard.tsx index 5fac7dcb50..cbaa6d9239 100644 --- a/src/pages/common/components/FeedCard/FeedCard.tsx +++ b/src/pages/common/components/FeedCard/FeedCard.tsx @@ -60,6 +60,7 @@ type FeedCardProps = PropsWithChildren<{ notion?: CommonNotion; originalCommonIdForLinking?: string; linkedCommonIds?: string[]; + onExpand?: (isExpanded: boolean) => void; }>; const FeedCard = (props, ref) => { @@ -96,6 +97,7 @@ const FeedCard = (props, ref) => { notion, originalCommonIdForLinking, linkedCommonIds, + onExpand, } = props; const scrollTimeoutRef = useRef | null>(null); const isTabletView = useIsTabletView(); @@ -105,6 +107,13 @@ const FeedCard = (props, ref) => { const { getCollapseProps, getToggleProps } = useCollapse({ isExpanded: isContentVisible, duration: COLLAPSE_DURATION, + onTransitionStateChange: (state) => { + if(state === "expandEnd") { + onExpand && onExpand(true); + } else if (state === "collapseEnd") { + onExpand && onExpand(false); + } + } }); const containerRef = useRef(null); diff --git a/src/pages/common/components/FeedItem/FeedItem.tsx b/src/pages/common/components/FeedItem/FeedItem.tsx index 4ee33282d1..30850337af 100644 --- a/src/pages/common/components/FeedItem/FeedItem.tsx +++ b/src/pages/common/components/FeedItem/FeedItem.tsx @@ -57,6 +57,7 @@ interface FeedItemProps { onFeedItemUpdate?: (item: CommonFeed, isRemoved: boolean) => void; getNonAllowedItems?: GetNonAllowedItemsOptions; isOptimisticallyCreated?: boolean; + onExpand?: (isExpanded: boolean) => void; } const FeedItem = forwardRef((props, ref) => { @@ -88,6 +89,7 @@ const FeedItem = forwardRef((props, ref) => { onFeedItemUpdate: outerOnFeedItemUpdate, getNonAllowedItems: outerGetNonAllowedItems, isOptimisticallyCreated = false, + onExpand, } = props; const { onFeedItemUpdate, @@ -177,6 +179,7 @@ const FeedItem = forwardRef((props, ref) => { onStreamMentionClick: onFeedItemClick, onFeedItemClick, onInternalLinkClick, + onExpand }), [ ref, @@ -206,6 +209,7 @@ const FeedItem = forwardRef((props, ref) => { handleUserClick, onFeedItemClick, onInternalLinkClick, + onExpand ], ); diff --git a/src/pages/common/components/OptimisticFeedCard/OptimisticFeedCard.tsx b/src/pages/common/components/OptimisticFeedCard/OptimisticFeedCard.tsx index 458e664088..109cb12286 100644 --- a/src/pages/common/components/OptimisticFeedCard/OptimisticFeedCard.tsx +++ b/src/pages/common/components/OptimisticFeedCard/OptimisticFeedCard.tsx @@ -63,6 +63,7 @@ interface OptimisticFeedCardProps { onUserClick?: (userId: string) => void; onFeedItemClick: (feedItemId: string) => void; onInternalLinkClick: (data: InternalLinkData) => void; + onExpand?: (isExpanded: boolean) => void; type: CommonFeedType; } @@ -94,6 +95,7 @@ const OptimisticFeedCard = forwardRef< onUserClick, onFeedItemClick, onInternalLinkClick, + onExpand, } = props; const isHome = false; @@ -234,6 +236,7 @@ const OptimisticFeedCard = forwardRef< unreadMessages={feedItemUserMetadata?.count || 0} isActive={isActive} isExpanded={isExpanded} + onExpand={onExpand} onClick={handleOpenChat} title={cardTitle} lastMessage={getLastMessage({ lastMessage: discussion?.lastMessageContent, isProject: false, commonName, commonFeedType: CommonFeedType.Discussion})} diff --git a/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx b/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx index 050ddf0b9d..bf475438ca 100644 --- a/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx +++ b/src/pages/common/components/ProposalFeedCard/ProposalFeedCard.tsx @@ -71,6 +71,7 @@ interface ProposalFeedCardProps { onUserClick?: (userId: string) => void; onFeedItemClick: (feedItemId: string) => void; onInternalLinkClick: (data: InternalLinkData) => void; + onExpand?: (isExpanded: boolean) => void; } const ProposalFeedCard = forwardRef( @@ -98,6 +99,7 @@ const ProposalFeedCard = forwardRef( onUserClick, onFeedItemClick, onInternalLinkClick, + onExpand, } = props; const user = useSelector(selectUser()); const userId = user?.uid; @@ -411,6 +413,7 @@ const ProposalFeedCard = forwardRef( lastActivity={item.updatedAt.seconds * 1000} isActive={isActive} isExpanded={isExpanded} + onExpand={onExpand} unreadMessages={feedItemUserMetadata?.count || 0} title={cardTitle} lastMessage={lastMessage} diff --git a/src/pages/commonFeed/CommonFeed.tsx b/src/pages/commonFeed/CommonFeed.tsx index d6f9c1dc96..7b7508f834 100644 --- a/src/pages/commonFeed/CommonFeed.tsx +++ b/src/pages/commonFeed/CommonFeed.tsx @@ -167,9 +167,6 @@ const CommonFeedComponent: FC = (props) => { if (commonPinnedFeedItems) { items.push(...commonPinnedFeedItems.map((item) => item.itemId)); } - if (sharedFeedItemId) { - items.push(sharedFeedItemId); - } return Array.from(new Set(items)); }, [sharedFeedItemId, pinnedItemIds, commonPinnedFeedItems]); const { @@ -222,9 +219,6 @@ const CommonFeedComponent: FC = (props) => { if (filteredPinnedItems.length > 0) { items.push(...filteredPinnedItems); } - if (sharedFeedItem) { - items.push(sharedFeedItem); - } return items; }, [sharedFeedItem, sharedFeedItemId, commonPinnedFeedItems]); @@ -257,6 +251,7 @@ const CommonFeedComponent: FC = (props) => { fetchUserRelatedData(); }; + const fetchMoreCommonFeedItems = useCallback( (feedItemId?: string) => { if (hasMoreCommonFeedItems && !isSearchingFeedItems) { @@ -716,4 +711,4 @@ const CommonFeedComponent: FC = (props) => { ); }; -export default React.memo(CommonFeedComponent); +export default CommonFeedComponent; diff --git a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx index 0a1d585e1a..662c8d0852 100644 --- a/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx +++ b/src/pages/commonFeed/components/FeedLayout/FeedLayout.tsx @@ -10,9 +10,8 @@ import React, { ReactNode, ForwardRefRenderFunction, } from "react"; -import { useSelector } from "react-redux"; -import { useHistory } from "react-router-dom"; -import PullToRefresh from "react-simple-pull-to-refresh"; +import { useDispatch, useSelector } from "react-redux"; +import { useHistory, useLocation } from "react-router-dom"; import { useDeepCompareEffect, useKey, useWindowSize } from "react-use"; import classNames from "classnames"; import { selectUser } from "@/pages/Auth/store/selectors"; @@ -39,7 +38,6 @@ import { AI_PRO_USER, AI_USER, InboxItemType, - LOADER_APPEARANCE_DELAY, QueryParamKey, ROUTE_PATHS, } from "@/shared/constants"; @@ -72,7 +70,7 @@ import { Governance, User, } from "@/shared/models"; -import { InfiniteScroll, Loader, TextEditorValue } from "@/shared/ui-kit"; +import { TextEditorValue } from "@/shared/ui-kit"; import { InternalLinkData } from "@/shared/utils"; import { addQueryParam, @@ -81,7 +79,9 @@ import { getUserName, } from "@/shared/utils"; import { + commonActions, selectCreatedOptimisticFeedItems, + selectPendingFeedItemId, selectRecentStreamId, } from "@/store/states"; import { MIN_CONTENT_WIDTH } from "../../constants"; @@ -97,6 +97,7 @@ import { } from "./components"; import { BATCHES_AMOUNT_TO_PRELOAD, + FeedCardHeights, ITEMS_AMOUNT_TO_PRE_LOAD_MESSAGES, MENTION_TAG_ELEMENT, } from "./constants"; @@ -110,6 +111,8 @@ import { saveContentSize, } from "./utils"; import styles from "./FeedLayout.module.scss"; +import { List, InfiniteLoader, AutoSizer, CellMeasurerCache, CellMeasurer } from "react-virtualized"; +import useAllFeedItems from "./hooks/useAllFeedItems"; export interface FeedLayoutOuterStyles { splitView?: string; @@ -198,16 +201,21 @@ const FeedLayout: ForwardRefRenderFunction = ( outerStyles, settings, renderChatInput, - onPullToRefresh, } = props; useDisableOverscroll(); const { getCommonPagePath } = useRoutesContext(); + const dispatch = useDispatch(); const refsByItemId = useRef>({}); const { width: windowWidth } = useWindowSize(); const history = useHistory(); const queryParams = useQueryParams(); const isTabletView = useIsTabletView(); const user = useSelector(selectUser()); + const pendingFeedItemId = useSelector(selectPendingFeedItemId); + const location = useLocation(); + + const isInboxItems = useMemo(() => location.pathname === ROUTE_PATHS.INBOX, [location.pathname]); + const createdOptimisticFeedItems = useSelector( selectCreatedOptimisticFeedItems, ); @@ -285,20 +293,25 @@ const FeedLayout: ForwardRefRenderFunction = ( const [expandedFeedItemId, setExpandedFeedItemId] = useState( null, ); - const [isLoaderAfterRefresh, setIsLoaderAfterRefresh] = useState(false); - const allFeedItems = useMemo(() => { - const items: FeedLayoutItem[] = []; - - if (topFeedItems) { - items.push(...topFeedItems); - } - if (feedItems) { - items.push(...feedItems); - } + const getUserCircleIds = useCallback( + (commonId) => { + return Object.values( + commonMemberForSpecificCommonIds[commonId]?.circles.map ?? + commonMember?.circles.map ?? + {}, + ) as string[]; + }, + [commonMemberForSpecificCommonIds, commonMember?.circles.map], + ); - return items; - }, [topFeedItems, feedItems]); + const allFeedItems = useAllFeedItems( + topFeedItems, + feedItems, + userId, + getUserCircleIds, + outerCommon + ); const dmChatChannelItemForProfile = useMemo( () => @@ -370,17 +383,6 @@ const FeedLayout: ForwardRefRenderFunction = ( [activeFeedItemId, allFeedItems], ); - const getUserCircleIds = useCallback( - (commonId) => { - return Object.values( - commonMemberForSpecificCommonIds[commonId]?.circles.map ?? - commonMember?.circles.map ?? - {}, - ) as string[]; - }, - [commonMemberForSpecificCommonIds, commonMember?.circles.map], - ); - const selectedFeedItem = useMemo( () => chatItem?.nestedItemData?.feedItem || @@ -417,10 +419,42 @@ const FeedLayout: ForwardRefRenderFunction = ( [handleUserWithCommonClick, selectedItemCommonData?.id], ); + + const allFeedItemsRef = useRef([]); + useEffect(() => { + allFeedItemsRef.current = allFeedItems; // Update the ref when items change + }, [allFeedItems]); + +const scrollToFeedItem = useCallback( + (feedItemId: string) => { + dispatch(commonActions.setPendingFeedItemId(feedItemId)); + }, + [allFeedItems, isInboxItems] +); + + +// Scroll effect +useEffect(() => { + if (pendingFeedItemId) { + const itemIndex = allFeedItems.findIndex( + (item) => + item.itemId === pendingFeedItemId || + (item as FeedItemFollowLayoutItem)?.feedItem?.data.id === + pendingFeedItemId + ); + + if (itemIndex !== -1 && listRef.current) { + setTimeout(() => listRef.current?.scrollToRow(itemIndex), 200); + dispatch(commonActions.setPendingFeedItemId(null)); + } + } +}, [pendingFeedItemId, allFeedItems]); + const setActiveChatItem = useCallback((nextChatItem: ChatItem | null) => { setShouldAllowChatAutoOpen(false); setChatItem(nextChatItem); - }, []); + nextChatItem?.feedItemId && scrollToFeedItem(nextChatItem?.feedItemId); + }, [scrollToFeedItem, allFeedItems]); const isMentionOpen = useElementPresence( MENTION_TAG_ELEMENT.key, @@ -441,7 +475,7 @@ const FeedLayout: ForwardRefRenderFunction = ( if (activeFeedItemIndex > 0) { const nextFeedItemId = allFeedItems[activeFeedItemIndex - 1]?.itemId; - + setExpandedFeedItemId(null); setChatItem({ feedItemId: nextFeedItemId }); } } @@ -460,7 +494,7 @@ const FeedLayout: ForwardRefRenderFunction = ( if (activeFeedItemIndex < allFeedItems.length - 1) { const nextFeedItemId = allFeedItems[activeFeedItemIndex + 1]?.itemId; - + setExpandedFeedItemId(null); setChatItem({ feedItemId: nextFeedItemId }); } } @@ -509,7 +543,8 @@ const FeedLayout: ForwardRefRenderFunction = ( const setActiveItem = useCallback((item: ChatItem) => { setShouldAllowChatAutoOpen(false); setChatItem(item); - }, []); + item.feedItemId && scrollToFeedItem(item.feedItemId); + }, [scrollToFeedItem]); const handleMessagesAmountChange = useCallback( (newMessagesAmount: number) => { @@ -614,75 +649,112 @@ const FeedLayout: ForwardRefRenderFunction = ( ) => { const { commonId = selectedItemCommonData?.id, messageId } = options; - if (commonId) { - onFeedItemSelect?.(commonId, feedItemId, messageId); + if (commonId && onFeedItemSelect) { + onFeedItemSelect(commonId, feedItemId, messageId); + setActiveChatItem({ feedItemId }); + } else { + const isInbox = window.location.pathname === ROUTE_PATHS.INBOX; + if (isInbox && commonId && feedItemId) { + const queryParamsForPath = { + item: feedItemId, + }; + history.push(getCommonPagePath(commonId, queryParamsForPath)); + } + + setActiveChatItem({ feedItemId }); } + + }, [selectedItemCommonData?.id, onFeedItemSelect], ); - const handleFeedItemClickInternal = ( - feedItemId: string, - options: { commonId?: string; messageId?: string } = {}, - ) => { - const { commonId, messageId } = options; - - if (chatItem?.feedItemId === feedItemId && !messageId) { - return; - } - - const queryParamsForPath = { - item: feedItemId, - message: messageId, - }; - - if (commonId && commonId !== outerCommon?.id) { - history.push(getCommonPagePath(commonId, queryParamsForPath)); - return; - } - if (chatItem?.nestedItemData) { - history.push( - getCommonPagePath( - chatItem?.nestedItemData.common.id, - queryParamsForPath, - ), - ); - return; - } - - setActiveChatItem({ feedItemId }); + const handleFeedItemClickInternal = useCallback( + ( + feedItemId: string, + options: { commonId?: string; messageId?: string } = {} + ) => { + const { commonId, messageId } = options; - const itemExists = allFeedItems.some((item) => item.itemId === feedItemId); + const queryParamsForPath = { + item: feedItemId, + message: messageId, + }; - if (itemExists) { - refsByItemId.current[feedItemId]?.scrollToItem(); - } else { - onFetchNext(feedItemId); - const paneEl = document.getElementsByClassName("Pane Pane1")[0]; - const containerEl = isTabletView ? window : paneEl; - const scrollHeight = isTabletView - ? document.body.scrollHeight - : paneEl?.scrollHeight; - - if (containerEl) { - setTimeout(() => { - containerEl.scrollTo({ - top: scrollHeight, - behavior: "smooth", - }); - }, 50); + const isInbox = window.location.pathname === ROUTE_PATHS.INBOX; + if (isInbox && commonId && feedItemId) { + history.push(getCommonPagePath(commonId, queryParamsForPath)); + setActiveChatItem({ feedItemId }); + return; } - } - - if (messageId) { - addQueryParam(QueryParamKey.Message, messageId); - } - }; - - const handleFeedItemClick = useMemoizedFunction( - onFeedItemSelect - ? handleFeedItemClickExternal - : handleFeedItemClickInternal, + + if (chatItem?.feedItemId === feedItemId && !messageId) { + setActiveChatItem({ feedItemId }); + return; + } + + if (commonId && commonId !== outerCommon?.id) { + history.push(getCommonPagePath(commonId, queryParamsForPath)); + return; + } + + if (chatItem?.nestedItemData) { + history.push( + getCommonPagePath( + chatItem?.nestedItemData.common.id, + queryParamsForPath + ) + ); + return; + } + + setActiveChatItem({ feedItemId }); + + const itemExists = allFeedItems.some((item) => item.itemId === feedItemId); + + if (itemExists) { + refsByItemId.current[feedItemId]?.scrollToItem(); + } else { + onFetchNext(feedItemId); + const paneEl = document.getElementsByClassName('Pane Pane1')[0]; + const containerEl = isTabletView ? window : paneEl; + const scrollHeight = isTabletView + ? document.body.scrollHeight + : paneEl?.scrollHeight; + + if (containerEl) { + setTimeout(() => { + containerEl.scrollTo({ + top: scrollHeight, + behavior: 'smooth', + }); + }, 50); + } + } + + if (messageId) { + addQueryParam(QueryParamKey.Message, messageId); + } + }, + [ + chatItem?.feedItemId, + chatItem?.nestedItemData, + outerCommon?.id, + history, + getCommonPagePath, + setActiveChatItem, + allFeedItems, + isInboxItems, + refsByItemId, + onFetchNext, + isTabletView, + addQueryParam, + ] + ); + + const handleFeedItemClick = useCallback( + onFeedItemSelect ? handleFeedItemClickExternal : handleFeedItemClickInternal, + [onFeedItemSelect, handleFeedItemClickExternal, handleFeedItemClickInternal, isInboxItems] ); const handleInternalLinkClick = useMemoizedFunction( @@ -697,6 +769,7 @@ const FeedLayout: ForwardRefRenderFunction = ( } const itemId = data.params[QueryParamKey.Item]; + const discussionItemId = data.params[QueryParamKey.discussionItem]; const messageId = data.params[QueryParamKey.Message]; @@ -729,20 +802,6 @@ const FeedLayout: ForwardRefRenderFunction = ( }, ); - const handleRefresh = async () => { - setIsLoaderAfterRefresh(true); - onPullToRefresh?.(); - }; - - const handleRefSet = useCallback( - (ref: FeedItemRef | null) => { - if (ref) { - refsByItemId.current[ref.itemId] = ref; - } - }, - [refsByItemId], - ); - // We should try to set here only the data which rarely can be changed, // so we will not have extra re-renders of ALL rendered items const feedItemContextValue = useMemo( @@ -871,12 +930,6 @@ const FeedLayout: ForwardRefRenderFunction = ( } }, [sharedFeedItemId, isTabletView, allFeedItems]); - useEffect(() => { - if (allFeedItems.length) { - setIsLoaderAfterRefresh(false); - } - }, [Boolean(allFeedItems.length)]); - useEffect(() => { if (isTabletView) { setSplitPaneRef(null); @@ -915,6 +968,189 @@ const FeedLayout: ForwardRefRenderFunction = ( commonId={selectedItemCommonData.id} /> ) : null; + + // Determine if a row has already been loaded + const isRowLoaded = ({ index }) => index < allFeedItems.length; + + // Load more rows when needed + const loadMoreRows = async () => { + if (!loading) { + await onFetchNext(); + } + }; + + const rowRefs = useRef({}); + + const setRowRef = (index, node) => { + if (node) { + rowRefs.current[index] = node; // Store the reference to the DOM node + } else { + delete rowRefs.current[index]; // Remove the reference if node is unmounted + } + }; + + // Render each row + const rowRenderer = ({ index, key, parent, style }) => { + const item = allFeedItems[index]; + if (!item) return null; + + const isActive = item.itemId === activeFeedItemId; + const shouldPreLoadMessages = index < ITEMS_AMOUNT_TO_PRE_LOAD_MESSAGES; + if (checkIsFeedItemFollowLayoutItem(item)) { + const commonData = getItemCommonData( + item.feedItemFollowWithMetadata, + outerCommon + ); + + const isPinned = (outerCommon?.pinnedFeedItems || []).some( + (pinnedItem) => pinnedItem.feedObjectId === item.feedItem.id + ); + + const isExpanded = item.feedItem?.id === expandedFeedItemId; + + return ( + +
setRowRef(index, node)}> + { + if(isExpanding) { + recomputeRowHeight(index); + } else { + cache.clear(index, 0); + listRef.current?.recomputeRowHeights(index); // Recompute row heights + } + }} + isExpanded={isExpanded} + sizeKey={isActive ? sizeKey : undefined} + currentUserId={userId} + shouldCheckItemVisibility={ + !item.feedItemFollowWithMetadata || + item.feedItemFollowWithMetadata.userId !== userId + } + directParent={outerCommon?.directParent} + rootCommonId={outerCommon?.rootCommonId} + shouldPreLoadMessages={shouldPreLoadMessages} + /> +
+
+ ); + } + + if (renderChatChannelItem && checkIsChatChannelLayoutItem(item)) { + return ( + +
+ {renderChatChannelItem({ + chatChannel: item.chatChannel, + isActive, + onActiveItemDataChange: handleActiveChatChannelItemDataChange, + })} +
+
+ ); + } + + return null; + }; + + const cache = new CellMeasurerCache({ + fixedWidth: true, + defaultHeight: FeedCardHeights[isInboxItems ? "inboxItemHeight" : "commonFeedItemHeight"], // Default row height + }); + + useEffect(() => { + return () => { + cache.clearAll(); + }; + }, []); + + const [previousIndex, setPreviousIndex] = React.useState(null); + + // Handle row expansion + const recomputeRowHeight = useCallback((index) => { + const node = rowRefs.current[index]; + if (!node) return; + + const images = node.querySelectorAll("img"); + + if(images.length === 2) { + cache.clear(index, 0); + cache.set(index, 0, 0, FeedCardHeights.oneImageItem); + } else if (images.length === 3) { + cache.clear(index, 0); + cache.set(index, 0, 0, FeedCardHeights.twoImageItem); + } else if (images.length >= 4) { + cache.clear(index, 0); + cache.set(index, 0, 0, FeedCardHeights.threeImageItem); + } + }, []); + + + + // Reference to the List component + const listRef = React.useRef(null); + + React.useLayoutEffect(() => { + if (expandedFeedItemId && allFeedItems.length > 0) { + const itemIndex = allFeedItems.findIndex((item) => (item as FeedItemFollowLayoutItem)?.feedItem?.id === expandedFeedItemId); + if (itemIndex >= 0) { + recomputeRowHeight(itemIndex); + if (previousIndex !== null) { + recomputeRowHeight(previousIndex); // Recompute the previous expanded row + } + setPreviousIndex(itemIndex); // Update the previous index + } + } else if( previousIndex !== null ) { + recomputeRowHeight(previousIndex); + setPreviousIndex(null); + } + }, [expandedFeedItemId, allFeedItems, recomputeRowHeight, previousIndex]); + + // Calculate dynamic row height + const getRowHeight = ({ index }) => { + const item = allFeedItems[index] as FeedItemFollowLayoutItem; + if (!item) return cache.defaultHeight; // Use default height if no item + + const isExpanded = item.feedItem?.id === expandedFeedItemId; + + const cachedHeight = cache.rowHeight({ index }); + + if (cachedHeight && isExpanded) { + return cachedHeight; + } + + const basicHeight = isInboxItems ? 80.54 : 59.54; + return basicHeight; + }; + const contentEl = renderContentWrapper( @@ -929,93 +1165,29 @@ const FeedLayout: ForwardRefRenderFunction = ( {isContentEmpty ? (

{emptyText}

) : ( - } - > - 7 - ? styles.infiniteScrollMarker - : "" - } - onFetchNext={onFetchNext} - isLoading={loading} - loaderDelay={ - isLoaderAfterRefresh ? 0 : LOADER_APPEARANCE_DELAY - } + - {allFeedItems?.map((item, index) => { - const isActive = item.itemId === activeFeedItemId; - const shouldPreLoadMessages = - index < ITEMS_AMOUNT_TO_PRE_LOAD_MESSAGES; - - if (checkIsFeedItemFollowLayoutItem(item)) { - const commonData = getItemCommonData( - item.feedItemFollowWithMetadata, - outerCommon, - ); - - const isPinned = ( - outerCommon?.pinnedFeedItems || [] - ).some( - (pinnedItem) => - pinnedItem.feedObjectId === item.feedItem.id, - ); - - return ( - ( + + {({ height, width }) => ( + - ); - } - if ( - renderChatChannelItem && - checkIsChatChannelLayoutItem(item) - ) { - return ( - - {renderChatChannelItem({ - chatChannel: item.chatChannel, - isActive, - onActiveItemDataChange: - handleActiveChatChannelItemDataChange, - })} - - ); - } - })} - - + )} + + )} + )} {!isTabletView && (chatItem?.discussion ? ( @@ -1032,6 +1204,7 @@ const FeedLayout: ForwardRefRenderFunction = ( renderChatInput={renderChatInput} onUserClick={handleUserClick} onFeedItemClick={handleFeedItemClick} + onStreamMentionClick={handleFeedItemClickExternal} onInternalLinkClick={handleInternalLinkClick} /> ) : ( @@ -1058,6 +1231,7 @@ const FeedLayout: ForwardRefRenderFunction = ( renderChatInput={renderChatInput} onUserClick={handleUserClick} onFeedItemClick={handleFeedItemClick} + onStreamMentionClick={handleFeedItemClickExternal} onInternalLinkClick={handleInternalLinkClick} > {selectedItemCommonData && diff --git a/src/pages/commonFeed/components/FeedLayout/components/DesktopChat/DesktopChat.tsx b/src/pages/commonFeed/components/FeedLayout/components/DesktopChat/DesktopChat.tsx index 73a15ed04a..d3b52c5e25 100644 --- a/src/pages/commonFeed/components/FeedLayout/components/DesktopChat/DesktopChat.tsx +++ b/src/pages/commonFeed/components/FeedLayout/components/DesktopChat/DesktopChat.tsx @@ -34,6 +34,7 @@ interface ChatProps { renderChatInput?: () => ReactNode; onUserClick?: (userId: string) => void; onFeedItemClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onInternalLinkClick?: (data: InternalLinkData) => void; } @@ -51,6 +52,7 @@ const DesktopChat: FC = (props) => { renderChatInput, onUserClick, onFeedItemClick, + onStreamMentionClick, onInternalLinkClick, } = props; const { @@ -131,7 +133,7 @@ const DesktopChat: FC = (props) => { directParent={directParent} renderChatInput={renderChatInput} onUserClick={onUserClick} - onStreamMentionClick={onFeedItemClick} + onStreamMentionClick={onStreamMentionClick} onFeedItemClick={onFeedItemClick} onInternalLinkClick={onInternalLinkClick} /> diff --git a/src/pages/commonFeed/components/FeedLayout/components/MobileChat/MobileChat.tsx b/src/pages/commonFeed/components/FeedLayout/components/MobileChat/MobileChat.tsx index 62a1f3244b..e19e4205ac 100644 --- a/src/pages/commonFeed/components/FeedLayout/components/MobileChat/MobileChat.tsx +++ b/src/pages/commonFeed/components/FeedLayout/components/MobileChat/MobileChat.tsx @@ -38,6 +38,7 @@ interface ChatProps { renderChatInput?: () => ReactNode; onClose: () => void; onUserClick?: (userId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; } @@ -60,6 +61,7 @@ const MobileChat: FC = (props) => { onClose, onUserClick, onFeedItemClick, + onStreamMentionClick, onInternalLinkClick, } = props; const { setIsShowFeedItemDetailsModal } = useChatContext(); @@ -167,7 +169,7 @@ const MobileChat: FC = (props) => { directParent={directParent} renderChatInput={renderChatInput} onUserClick={onUserClick} - onStreamMentionClick={onFeedItemClick} + onStreamMentionClick={onStreamMentionClick} onFeedItemClick={onFeedItemClick} onInternalLinkClick={onInternalLinkClick} /> diff --git a/src/pages/commonFeed/components/FeedLayout/constants/index.ts b/src/pages/commonFeed/components/FeedLayout/constants/index.ts index b64b9cd957..4bacb222c5 100644 --- a/src/pages/commonFeed/components/FeedLayout/constants/index.ts +++ b/src/pages/commonFeed/components/FeedLayout/constants/index.ts @@ -4,3 +4,11 @@ export const MENTION_TAG_ELEMENT = { key: "data-cy", value: "mentions-portal" } + +export const FeedCardHeights = { + inboxItemHeight: 80.54, + commonFeedItemHeight: 59.54, + oneImageItem: 466, + twoImageItem: 486, + threeImageItem: 687, +} \ No newline at end of file diff --git a/src/pages/commonFeed/components/FeedLayout/hooks/index.ts b/src/pages/commonFeed/components/FeedLayout/hooks/index.ts index 1086a27025..71ee11dcc5 100644 --- a/src/pages/commonFeed/components/FeedLayout/hooks/index.ts +++ b/src/pages/commonFeed/components/FeedLayout/hooks/index.ts @@ -1 +1,2 @@ export * from "./useUserForProfile"; +export * from "./useAllFeedItems"; \ No newline at end of file diff --git a/src/pages/commonFeed/components/FeedLayout/hooks/useAllFeedItems.ts b/src/pages/commonFeed/components/FeedLayout/hooks/useAllFeedItems.ts new file mode 100644 index 0000000000..90abc4b2f5 --- /dev/null +++ b/src/pages/commonFeed/components/FeedLayout/hooks/useAllFeedItems.ts @@ -0,0 +1,77 @@ +import { useMemo, useRef } from 'react'; +import { isEqual } from 'lodash'; +import { checkIsFeedItemFollowLayoutItem, FeedItemFollowLayoutItem, FeedLayoutItem } from '@/shared/interfaces'; +import { getItemCommonData } from '../utils'; +import { checkIsItemVisibleForUser } from '@/shared/utils'; +import { CommonFeedType } from '@/shared/models'; + +const useAllFeedItems = ( + topFeedItems, + feedItems, + userId, + getUserCircleIds, + outerCommon +) => { + const prevAllFeedItems = useRef([]); + + const stableAllFeedItems = useMemo(() => { + const items: FeedLayoutItem[] = []; + + if (topFeedItems) { + items.push(...topFeedItems); + } + + if (feedItems) { + items.push(...feedItems); + } + + // Apply filtering logic + const filteredItems = items.filter((item) => { + const feedItem = (item as FeedItemFollowLayoutItem)?.feedItem; + if (checkIsFeedItemFollowLayoutItem(item)) { + const commonData = getItemCommonData( + item.feedItemFollowWithMetadata, + outerCommon + ); + // Check if the item is visible for the user + if ( + !checkIsItemVisibleForUser({ + itemCircleVisibility: feedItem.circleVisibility, + userCircleIds: getUserCircleIds(commonData?.id), // Pass the user's circle IDs + itemUserId: feedItem.userId, + currentUserId: userId, // Pass the current user ID + itemDataType: feedItem.data?.type, // Adjust for item data type + }) + ) { + return false; + } + + // Additional filtering logic if needed (e.g., based on type) + if ( + feedItem.data?.type !== CommonFeedType.Discussion && + feedItem.data?.type !== CommonFeedType.Proposal && + feedItem.data?.type !== CommonFeedType.Project && + feedItem.data?.type !== CommonFeedType.OptimisticDiscussion && + feedItem.data?.type !== CommonFeedType.OptimisticProposal + ) { + return false; + } + + return true; // Keep the item if it passes all checks + } else { + return true; // Keep non-FeedItemFollowLayoutItems + } + }); + + // Only update the stable array if the filteredItems deeply differ + if (!isEqual(prevAllFeedItems.current, filteredItems)) { + prevAllFeedItems.current = filteredItems; + } + + return prevAllFeedItems.current; + }, [topFeedItems, feedItems, userId, getUserCircleIds, outerCommon]); + + return stableAllFeedItems; +}; + +export default useAllFeedItems; diff --git a/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.module.scss b/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.module.scss index 2deb57621b..584da03de6 100644 --- a/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.module.scss +++ b/src/pages/inbox/components/FeedItemBaseContent/FeedItemBaseContent.module.scss @@ -9,6 +9,7 @@ border-bottom: 0.0625rem solid var(--gentle-stroke); cursor: pointer; user-select: none; + background-color: var(--feed-item-background); &:hover { background-color: var(--hover-fill); diff --git a/src/shared/components/Chat/ChatMessage/ChatMessage.tsx b/src/shared/components/Chat/ChatMessage/ChatMessage.tsx index 9d1438d928..766fcb4dd6 100644 --- a/src/shared/components/Chat/ChatMessage/ChatMessage.tsx +++ b/src/shared/components/Chat/ChatMessage/ChatMessage.tsx @@ -78,7 +78,7 @@ interface ChatMessageProps { onMessageDelete?: (messageId: string) => void; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemID: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; isMessageEditAllowed: boolean; diff --git a/src/shared/components/Chat/ChatMessage/DMChatMessage.tsx b/src/shared/components/Chat/ChatMessage/DMChatMessage.tsx index 8863bc506a..a07008d59e 100644 --- a/src/shared/components/Chat/ChatMessage/DMChatMessage.tsx +++ b/src/shared/components/Chat/ChatMessage/DMChatMessage.tsx @@ -76,7 +76,7 @@ interface ChatMessageProps { onMessageDelete?: (messageId: string) => void; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onInternalLinkClick?: (data: InternalLinkData) => void; chatChannelId?: string; diff --git a/src/shared/components/Chat/ChatMessage/components/StreamMention/StreamMention.tsx b/src/shared/components/Chat/ChatMessage/components/StreamMention/StreamMention.tsx index 9fd2d74142..852badb383 100644 --- a/src/shared/components/Chat/ChatMessage/components/StreamMention/StreamMention.tsx +++ b/src/shared/components/Chat/ChatMessage/components/StreamMention/StreamMention.tsx @@ -3,18 +3,22 @@ import classNames from "classnames"; import styles from "../../ChatMessage.module.scss"; import { useQuery } from "@tanstack/react-query"; import { CommonFeedService } from "@/services"; +import { useDispatch } from "react-redux"; +import { commonActions } from "@/store/states"; +import { InternalLinkData } from "@/shared/utils"; interface StreamMentionProps { commonId: string; discussionId: string; title: string; mentionTextClassName?: string; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); } const StreamMention: FC = (props) => { const { discussionId, title, commonId, mentionTextClassName, onStreamMentionClick } = props; + const dispatch = useDispatch(); const { data } = useQuery({ queryKey: ["stream-mention", discussionId], @@ -27,7 +31,15 @@ const StreamMention: FC = (props) => { const handleStreamNameClick = () => { if (onStreamMentionClick && feedItemId) { - onStreamMentionClick(feedItemId); + dispatch( + commonActions.getFeedItems.request({ + commonId, + feedItemId, + limit: 15, + }), + ); + + (onStreamMentionClick as ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void))(feedItemId, { commonId }); } }; diff --git a/src/shared/components/Chat/ChatMessage/types.ts b/src/shared/components/Chat/ChatMessage/types.ts index 0b812d28a3..721441a9e5 100644 --- a/src/shared/components/Chat/ChatMessage/types.ts +++ b/src/shared/components/Chat/ChatMessage/types.ts @@ -18,7 +18,7 @@ export interface TextData { getCommonPageAboutTabPath?: GetCommonPageAboutTabPath; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; onMessageUpdate?: (message: TextEditorValue) => void; onInternalLinkClick?: (data: InternalLinkData) => void; diff --git a/src/shared/components/Chat/ChatMessage/utils/getTextFromTextEditorString.tsx b/src/shared/components/Chat/ChatMessage/utils/getTextFromTextEditorString.tsx index 613c8e60f3..fc9fa4bfbd 100644 --- a/src/shared/components/Chat/ChatMessage/utils/getTextFromTextEditorString.tsx +++ b/src/shared/components/Chat/ChatMessage/utils/getTextFromTextEditorString.tsx @@ -35,7 +35,7 @@ interface TextFromDescendant { commonId?: string; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onInternalLinkClick?: (data: InternalLinkData) => void; showPlainText?: boolean; } diff --git a/src/shared/hooks/useCases/useDiscussionMessagesById.ts b/src/shared/hooks/useCases/useDiscussionMessagesById.ts index 11601e0072..8c28f8cf07 100644 --- a/src/shared/hooks/useCases/useDiscussionMessagesById.ts +++ b/src/shared/hooks/useCases/useDiscussionMessagesById.ts @@ -40,7 +40,7 @@ interface Options { discussionId: string; directParent?: DirectParent | null; onUserClick?: (userId: string) => void; - onStreamMentionClick?: (feedItemId: string) => void; + onStreamMentionClick?: ((feedItemId: string, options?: { commonId?: string; messageId?: string }) => void) | ((data: InternalLinkData) => void); onFeedItemClick?: (feedItemId: string) => void; users: User[]; textStyles: TextStyles; @@ -199,7 +199,7 @@ export const useDiscussionMessagesById = ({ getCommonPageAboutTabPath, directParent, onUserClick, - onStreamMentionClick: onStreamMentionClick ?? onFeedItemClick, + onStreamMentionClick: onStreamMentionClick ?? onFeedItemClick, onFeedItemClick, onInternalLinkClick, }); diff --git a/src/shared/ui-kit/ImageGallery/ImageGallery.module.scss b/src/shared/ui-kit/ImageGallery/ImageGallery.module.scss index d2c8b05671..d5a9d39277 100644 --- a/src/shared/ui-kit/ImageGallery/ImageGallery.module.scss +++ b/src/shared/ui-kit/ImageGallery/ImageGallery.module.scss @@ -36,7 +36,7 @@ .singleImage { max-width: 100%; - max-height: 31.25rem; + height: 12.5rem; border-radius: 0.25rem; margin: auto; } diff --git a/src/shared/ui-kit/ImageGallery/ImageGallery.tsx b/src/shared/ui-kit/ImageGallery/ImageGallery.tsx index ea3b3c267b..4ed5276229 100644 --- a/src/shared/ui-kit/ImageGallery/ImageGallery.tsx +++ b/src/shared/ui-kit/ImageGallery/ImageGallery.tsx @@ -40,7 +40,7 @@ const ImageGallery: FC = (props) => { const imagePreviewStyle = useMemo( () => ({ - height: `calc(${videoContainerWidth / 2}px - 0.875rem)`, + height: "9.375rem", width: `calc(${videoContainerWidth / 2}px - 0.15625rem)`, }), [videoContainerWidth], diff --git a/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.module.scss b/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.module.scss index 3d8e111b6b..d83d69c36b 100644 --- a/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.module.scss +++ b/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.module.scss @@ -6,7 +6,7 @@ .mainContent { width: 100%; - max-height: 24rem; + height: 12.5rem; object-fit: cover; box-sizing: border-box; border-radius: 0.25rem; diff --git a/src/store/states/cache/saga/copyFeedStateByCommonId.ts b/src/store/states/cache/saga/copyFeedStateByCommonId.ts index a35d5a453d..2d73905ba6 100644 --- a/src/store/states/cache/saga/copyFeedStateByCommonId.ts +++ b/src/store/states/cache/saga/copyFeedStateByCommonId.ts @@ -9,7 +9,7 @@ export function* copyFeedStateByCommonId({ const commonState = (yield select(selectCommonState)) as CommonState; const specificCommonFeedItems = commonState.feedItems[commonId]; const data = - specificCommonFeedItems?.data && specificCommonFeedItems.data.slice(0, 30); + specificCommonFeedItems?.data && specificCommonFeedItems.data; const feedItems = { ...specificCommonFeedItems, data, diff --git a/src/store/states/common/actions.ts b/src/store/states/common/actions.ts index 6c6fcb2adf..8d1a71906b 100644 --- a/src/store/states/common/actions.ts +++ b/src/store/states/common/actions.ts @@ -269,6 +269,10 @@ export const setRecentStreamId = createStandardAction( CommonActionType.SET_RECENT_STREAM_ID, )(); +export const setPendingFeedItemId = createStandardAction( + CommonActionType.SET_PENDING_FEED_ITEM_ID, +)(); + export const setRecentAssignedCircleByMember = createStandardAction( CommonActionType.SET_RECENT_ASSIGNED_CIRCLE_BY_MEMBER, )<{ diff --git a/src/store/states/common/constants.ts b/src/store/states/common/constants.ts index cc9839c909..ed2afd5571 100644 --- a/src/store/states/common/constants.ts +++ b/src/store/states/common/constants.ts @@ -57,6 +57,7 @@ export enum CommonActionType { SET_SHARED_FEED_ITEM = "@COMMON/SET_SHARED_FEED_ITEM", SET_RECENT_STREAM_ID = "@COMMON/SET_RECENT_STREAM_ID", + SET_PENDING_FEED_ITEM_ID = "@COMMON/SET_PENDING_FEED_ITEM_ID", SET_RECENT_ASSIGNED_CIRCLE_BY_MEMBER = "@COMMON/SET_RECENT_ASSIGNED_CIRCLE_BY_MEMBER", RESET_RECENT_ASSIGNED_CIRCLE_BY_MEMBER = "@COMMON/RESET_RECENT_ASSIGNED_CIRCLE_BY_MEMBER", diff --git a/src/store/states/common/reducer.ts b/src/store/states/common/reducer.ts index 261e53c008..1254c7f11c 100644 --- a/src/store/states/common/reducer.ts +++ b/src/store/states/common/reducer.ts @@ -56,6 +56,7 @@ const initialState: CommonState = { commonMembers: {}, governance: {}, recentStreamId: "", + pendingFeedItemId: "", recentAssignedCircleByMember: {}, }; @@ -524,6 +525,7 @@ export const reducer = createReducer(initialState) nextState.feedItems[commonId] = { ...feedItems, data: [...existingData, ...newData], + hasMore: newItems.length === 14, }; }), ) @@ -895,6 +897,11 @@ export const reducer = createReducer(initialState) nextState.recentStreamId = payload; }), ) + .handleAction(actions.setPendingFeedItemId, (state, { payload }) => + produce(state, (nextState) => { + nextState.pendingFeedItemId = payload; + }), + ) .handleAction(actions.setRecentAssignedCircleByMember, (state, { payload }) => produce(state, (nextState) => { const { commonId, memberId, circle } = payload; diff --git a/src/store/states/common/selectors.ts b/src/store/states/common/selectors.ts index 51d8faaf33..78fc573b0b 100644 --- a/src/store/states/common/selectors.ts +++ b/src/store/states/common/selectors.ts @@ -126,6 +126,11 @@ export const selectRecentStreamId = createSelector( (common) => common.recentStreamId || "" ); +export const selectPendingFeedItemId = createSelector( + selectCommonState, + (common) => common.pendingFeedItemId || "" +); + // Recent Assigned Circle export const selectRecentAssignedCircle = (commonId: string, memberId: string) => createSelector( diff --git a/src/store/states/common/types.ts b/src/store/states/common/types.ts index 8d32f682bc..0543e83072 100644 --- a/src/store/states/common/types.ts +++ b/src/store/states/common/types.ts @@ -58,5 +58,6 @@ export interface CommonState { recentAssignedCircleByMember: Record>; governance: Record; recentStreamId: string; + pendingFeedItemId: string | null; searchState: Record; } diff --git a/src/store/transforms.ts b/src/store/transforms.ts index d0a052a834..c0dfbc1568 100644 --- a/src/store/transforms.ts +++ b/src/store/transforms.ts @@ -40,7 +40,7 @@ export const inboxTransform = createTransform( } const data = - inboundState.items.data && inboundState.items.data.slice(0, 30); + inboundState.items.data && inboundState.items.data; return { ...inboundState, diff --git a/src/styles/theme.scss b/src/styles/theme.scss index 960c17a8eb..67164eba62 100644 --- a/src/styles/theme.scss +++ b/src/styles/theme.scss @@ -19,6 +19,7 @@ --mention-primary: #d84c7f; --mention-secondary: #ffa6d7; --highlight: #d84ca0; + --feed-item-background: #ffffff; } :root[data-theme="dark"] { @@ -42,4 +43,5 @@ --mention-primary: #d84c7f; --mention-secondary: #ffa6d7; --highlight: #d84ca0; + --feed-item-background: rgb(16, 16, 16); }