diff --git a/craco.config.js b/craco.config.js index f4477e6d2f..b6b64b015c 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,6 +1,18 @@ const CracoAlias = require("craco-alias"); module.exports = { + webpack: { + configure: (webpackConfig, { env, paths }) => { + const reactAppEnv = process.env.REACT_APP_ENV; + if (reactAppEnv === "dev" || reactAppEnv === "stage") { + webpackConfig.optimization.minimize = false; + webpackConfig.devtool = "source-map"; + } else { + webpackConfig.devtool = false; + } + return webpackConfig; + }, + }, style: { css: { loaderOptions: () => ({ diff --git a/public/manifest.json b/public/manifest.json index 62f5748add..77bc04692d 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,6 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "Common.io", + "name": "Common.io", "icons": [ { "src": "favicon.ico", @@ -38,7 +38,7 @@ "sizes": "512x512" } ], - "start_url": ".", + "start_url": "./inbox", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" diff --git a/src/pages/OldCommon/hooks/useCommonMembers.ts b/src/pages/OldCommon/hooks/useCommonMembers.ts index cbf0987095..34aa60f0ea 100644 --- a/src/pages/OldCommon/hooks/useCommonMembers.ts +++ b/src/pages/OldCommon/hooks/useCommonMembers.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useRef, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { CommonService, Logger, UserService } from "@/services"; import { store } from "@/shared/appConfig"; @@ -9,6 +9,7 @@ import { selectCommonMembersStateByCommonId, selectUserStates, } from "@/store/states"; +import { useDeepCompareEffect } from "react-use"; interface Options { commonId?: string; @@ -93,7 +94,7 @@ export const useCommonMembers = ({ commonId }: Options): Return => { [dispatch, commonId], ); - useEffect(() => { + useDeepCompareEffect(() => { const commonMembers = commonMembersState.data; if (!commonMembers) { diff --git a/src/pages/common/components/ChatComponent/ChatComponent.module.scss b/src/pages/common/components/ChatComponent/ChatComponent.module.scss index 36a3cdbb2e..1e96fcb2bf 100644 --- a/src/pages/common/components/ChatComponent/ChatComponent.module.scss +++ b/src/pages/common/components/ChatComponent/ChatComponent.module.scss @@ -50,59 +50,6 @@ align-items: flex-end; } -.messageInput { - width: 100%; - min-height: 2.625rem; - line-height: 1.5rem; - border-radius: 1.25rem; - background-color: var(--secondary-background); - border: 0.0625rem solid var(--gentle-stroke); - outline: none; - resize: none; - font-size: 0.875rem; - color: var(--primary-text); - box-sizing: border-box; - text-align: left; - display: flex; - flex-direction: column; - justify-content: center; - word-break: break-word; - padding: 0.125rem 2.5rem 0.125rem 0.75rem; - margin: 0.3rem 0; - overflow-x: hidden; - min-height: 2.625rem !important; -} - -.messageInputRtl { - padding: 0.125rem 2.5rem 0.125rem 0.75rem; -} - -.messageInputEmpty { - padding-left: 0.75rem; - overflow-x: hidden; -} - -.addFilesIcon { - margin-bottom: 0.8rem; - margin-right: 0.5rem; - height: 1.5rem; - color: var(--primary-text); -} - -.sendIcon { - display: flex; - justify-content: center; - align-items: center; - margin-bottom: 0.8rem; - border: none; - outline: none; - background: transparent; - - &:disabled { - cursor: not-allowed; - opacity: 0.5; - } -} $phone-breakpoint: 415px; .container { diff --git a/src/pages/common/components/ChatComponent/ChatComponent.tsx b/src/pages/common/components/ChatComponent/ChatComponent.tsx index f3c0788469..096516ceaa 100644 --- a/src/pages/common/components/ChatComponent/ChatComponent.tsx +++ b/src/pages/common/components/ChatComponent/ChatComponent.tsx @@ -23,7 +23,6 @@ import { LastSeenEntity, QueryParamKey, } from "@/shared/constants"; -import { FILES_ACCEPTED_EXTENSIONS } from "@/shared/constants"; import { HotKeys } from "@/shared/constants/keyboardKeys"; import { ChatMessageToUserDiscussionMessageConverter } from "@/shared/converters"; import { @@ -31,7 +30,7 @@ import { useImageSizeCheck, useQueryParams, } from "@/shared/hooks"; -import { ArrowInCircleIcon, PlusIcon, SendIcon } from "@/shared/icons"; +import { ArrowInCircleIcon } from "@/shared/icons"; import { LinkPreviewData } from "@/shared/interfaces"; import { CreateDiscussionMessageDto } from "@/shared/interfaces/api/discussionMessages"; import { @@ -47,24 +46,16 @@ import { UserDiscussionMessage, } from "@/shared/models"; import { - BaseTextEditor, TextEditorValue, getMentionTags, parseStringToTextEditorValue, - ButtonIcon, checkIsTextEditorValueEmpty, - TextEditorSize, removeTextEditorEmptyEndLinesValues, countTextEditorEmojiElements, } from "@/shared/ui-kit"; import { checkUncheckedItemsInTextEditorValue } from "@/shared/ui-kit/TextEditor/utils"; import { InternalLinkData, notEmpty } from "@/shared/utils"; -import { - emptyFunction, - getUserName, - hasPermission, - isMobile, -} from "@/shared/utils"; +import { getUserName, hasPermission, isMobile } from "@/shared/utils"; import { cacheActions, chatActions, @@ -80,6 +71,7 @@ import { MessageReply, ChatFilePreview, MessageInfoWithDateList, + ChatInput, } from "./components"; import { checkIsLastSeenInPreviousDay } from "./components/ChatContent/utils"; import { useChatChannelChatAdapter, useDiscussionChatAdapter } from "./hooks"; @@ -336,8 +328,6 @@ export default function ChatComponent({ return messagesWithInfo; }, [messages]); - // const dateListWith - const [newMessages, setMessages] = useState< CreateDiscussionMessageDtoWithFilesPreview[] >([]); @@ -761,73 +751,6 @@ export default function ChatComponent({ }; }, []); - const renderChatInput = (): ReactNode => { - if (shouldHideChatInput) { - return null; - } - if (!isChatChannel) { - const chatInputEl = renderChatInputOuter?.(); - - if (chatInputEl || chatInputEl === null) { - return chatInputEl; - } - } - if (!isAuthorized) { - return null; - } - - return ( - <> - { - document.getElementById("file")?.click(); - }} - > - - - - - - - ); - }; - const { y } = useScroll(chatContainerRef); const isScrolledToTop = Boolean(chatContainerRef.current && Math.abs(y) > 20); @@ -924,7 +847,26 @@ export default function ChatComponent({ [styles.chatInputWrapperMultiLine]: isMultiLineInput, })} > - {renderChatInput()} + React.ReactElement + } + isChatChannel={isChatChannel} + shouldHideChatInput={shouldHideChatInput} + sendChatMessage={sendChatMessage} + canSendMessage={Boolean(canSendMessage)} + inputContainerRef={inputContainerRef} + editorRef={editorRef} + /> ); diff --git a/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.module.scss b/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.module.scss new file mode 100644 index 0000000000..7e4cc911fe --- /dev/null +++ b/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.module.scss @@ -0,0 +1,75 @@ +@import "../../../../../../constants.scss"; +@import "../../../../../../styles/sizes"; + +.messageInput { + width: 100%; + min-height: 2.625rem; + line-height: 1.5rem; + border-radius: 1.25rem; + background-color: var(--secondary-background); + border: 0.0625rem solid var(--gentle-stroke); + outline: none; + resize: none; + font-size: 0.875rem; + color: var(--primary-text); + box-sizing: border-box; + text-align: left; + display: flex; + flex-direction: column; + justify-content: center; + word-break: break-word; + padding: 0.125rem 2.5rem 0.125rem 0.75rem; + margin: 0.3rem 0; + overflow-x: hidden; + min-height: 2.625rem !important; +} + +.messageInputRtl { + padding: 0.125rem 2.5rem 0.125rem 0.75rem; +} + +.messageInputEmpty { + padding-left: 0.75rem; + overflow-x: hidden; +} + +.addFilesIcon { + margin-bottom: 0.8rem; + margin-right: 0.5rem; + height: 1.5rem; + color: var(--primary-text); +} + +.sendIcon { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 0.8rem; + border: none; + outline: none; + background: transparent; + + &:disabled { + cursor: not-allowed; + opacity: 0.5; + } +} +$phone-breakpoint: 415px; + +.singleEmojiText { + font-size: $xlarge; + line-height: 2.8125rem; +} + +.multipleEmojiText { + font-size: $large; + line-height: 2.125rem; +} + +.singleEmojiText { + font-size: $xlarge; +} + +.multipleEmojiText { + font-size: $large; +} diff --git a/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.tsx b/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.tsx new file mode 100644 index 0000000000..6c7b44f35c --- /dev/null +++ b/src/pages/common/components/ChatComponent/components/ChatInput/ChatInput.tsx @@ -0,0 +1,127 @@ +import React, { + ChangeEvent, + MutableRefObject, + ReactElement, + RefCallback, +} from "react"; +import classNames from "classnames"; +import { FILES_ACCEPTED_EXTENSIONS } from "@/shared/constants"; +import { PlusIcon, SendIcon } from "@/shared/icons"; +import { User } from "@/shared/models"; +import { + BaseTextEditor, + ButtonIcon, + checkIsTextEditorValueEmpty, + TextEditorSize, + TextEditorValue, +} from "@/shared/ui-kit"; +import { EmojiCount } from "@/shared/ui-kit/TextEditor/utils"; +import { emptyFunction } from "@/shared/utils"; +import styles from "./ChatInput.module.scss"; + +interface ChatInputProps { + shouldHideChatInput: boolean; + isChatChannel: boolean; + uploadFiles: (event: ChangeEvent | ClipboardEvent) => void; + message: TextEditorValue; + setMessage: React.Dispatch>; + emojiCount: EmojiCount; + onEnterKeyDown: (event: React.KeyboardEvent) => void; + users: User[]; + shouldReinitializeEditor: boolean; + onClearFinished: () => void; + canSendMessage?: boolean; + sendChatMessage: () => void; + inputContainerRef?: + | MutableRefObject + | RefCallback; + editorRef?: MutableRefObject | RefCallback; + renderChatInputOuter?: () => ReactElement; + isAuthorized?: boolean; +} + +export const ChatInput = (props: ChatInputProps): ReactElement | null => { + const { + inputContainerRef, + editorRef, + canSendMessage, + sendChatMessage, + shouldHideChatInput, + isChatChannel, + renderChatInputOuter, + isAuthorized, + uploadFiles, + message, + setMessage, + emojiCount, + onEnterKeyDown, + users, + shouldReinitializeEditor, + onClearFinished, + } = props; + + if (shouldHideChatInput) { + return null; + } + if (!isChatChannel) { + const chatInputEl = renderChatInputOuter?.(); + + if (chatInputEl || chatInputEl === null) { + return chatInputEl; + } + } + if (!isAuthorized) { + return null; + } + + return ( + <> + { + document.getElementById("file")?.click(); + }} + > + + + + + + + ); +}; diff --git a/src/pages/common/components/ChatComponent/components/ChatInput/index.ts b/src/pages/common/components/ChatComponent/components/ChatInput/index.ts new file mode 100644 index 0000000000..8d680f8752 --- /dev/null +++ b/src/pages/common/components/ChatComponent/components/ChatInput/index.ts @@ -0,0 +1 @@ +export * from "./ChatInput"; \ No newline at end of file diff --git a/src/pages/common/components/ChatComponent/components/index.ts b/src/pages/common/components/ChatComponent/components/index.ts index 8261e733fe..8bd7b3acf1 100644 --- a/src/pages/common/components/ChatComponent/components/index.ts +++ b/src/pages/common/components/ChatComponent/components/index.ts @@ -2,3 +2,4 @@ export * from "./ChatContent"; export * from "./MessageLinkPreview"; export * from "./MessageReply"; export * from "./ChatFilePreview"; +export * from "./ChatInput"; diff --git a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx index df3498c3f4..3da4b2a801 100644 --- a/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx +++ b/src/pages/common/components/DiscussionFeedCard/DiscussionFeedCard.tsx @@ -1,6 +1,5 @@ import React, { forwardRef, - ReactNode, useCallback, useEffect, useMemo, @@ -36,13 +35,7 @@ import { import { TextEditorValue } from "@/shared/ui-kit"; import { StaticLinkType, getUserName, InternalLinkData } from "@/shared/utils"; import { useChatContext } from "../ChatComponent"; -import { - FeedCard, - FeedCardHeader, - FeedCardContent, - FeedCountdown, -} from "../FeedCard"; -import { getVisibilityString } from "../FeedCard"; +import { FeedCard } from "../FeedCard"; import { FeedCardShare } from "../FeedCard"; import { FeedItemRef, @@ -403,23 +396,25 @@ const DiscussionFeedCard = forwardRef( originalCommonIdForLinking={discussion?.commonId} linkedCommonIds={discussion?.linkedCommonIds} > - onUserClick(item.userId))} - discussionCreator={discussionCreator} - isHome={isHome} - menuItems={menuItems} - discussion={discussion} - common={common} - discussionNotion={discussionNotion} - handleOpenChat={handleOpenChat} - onHover={onHover} - isLoading={isLoading} - /> + {(isExpanded || isActive) && ( + onUserClick(item.userId))} + discussionCreator={discussionCreator} + isHome={isHome} + menuItems={menuItems} + discussion={discussion} + common={common} + discussionNotion={discussionNotion} + handleOpenChat={handleOpenChat} + onHover={onHover} + isLoading={isLoading} + /> + )} {userId && discussion && ( ( } }, [item.data.lastMessage?.content]); - const renderContent = (): ReactNode => { - if (isLoading) { - return null; - } - - const isCountdownState = checkIsCountdownState(proposal); - const userHasPermissionsToVote = checkUserPermissionsToVote({ - proposal, - commonMember, - }); - const isVotingAllowed = - userHasPermissionsToVote && - checkIsVotingAllowed({ - userVote, - proposal, - }); - const circleVisibility = getVisibilityString( - governanceCircles, - item.circleVisibility, - proposal?.type, - getUserName(feedItemUser), - ); - - return ( - <> - - Created:{" "} - - - } - type={getProposalTypeString(proposal.type)} - circleVisibility={circleVisibility} - commonId={commonId} - userId={item.userId} - menuItems={menuItems} - onUserSelect={onUserClick && (() => onUserClick(item.userId))} - /> - { - onHover(true); - }} - onMouseLeave={() => { - onHover(false); - }} - > - {proposal.resolutionType === ResolutionType.WAIT_FOR_EXPIRATION && ( - <> - - - - )} - - {proposal.resolutionType === ResolutionType.IMMEDIATE && ( - <> - - - - )} - - {isVotingAllowed && ( - - )} - - - ); - }; - return ( <> ( feedItemUserMetadata?.hasUnseenMention } > - {renderContent()} + {(isActive || isExpanded) && ( + + )} {discussion && ( void; + isLoading: boolean; + proposal: Proposal | null; + commonMember: (CommonMember & CirclesPermissions) | null; + userVote: Vote | null; + setVote: (vote: Vote) => void; + feedItemUser: User | null; + proposalSpecificData: ProposalSpecificData; + menuItems: ContextMenuItem[]; + discussionNotion?: DiscussionNotion; + discussion: Discussion | null; + handleOpenChat: () => void; + onHover: (isMouseEnter: boolean) => void; + getCommonPagePath: GetCommonPagePath; +} + +export function ProposalFeedCardContent(props: ProposalFeedCardContentProps) { + const { + isLoading, + proposal, + commonMember, + userVote, + governanceCircles, + feedItemUser, + setVote, + commonId, + item, + onUserClick, + proposalSpecificData, + menuItems, + discussionNotion, + discussion, + handleOpenChat, + onHover, + getCommonPagePath, + } = props; + + if (isLoading || !governanceCircles || !commonId || !proposal) { + return null; + } + + const isCountdownState = checkIsCountdownState(proposal); + const userHasPermissionsToVote = checkUserPermissionsToVote({ + proposal, + commonMember, + }); + const isVotingAllowed = + userHasPermissionsToVote && + checkIsVotingAllowed({ + userVote, + proposal, + }); + const circleVisibility = getVisibilityString( + governanceCircles, + item.circleVisibility, + proposal?.type, + getUserName(feedItemUser), + ); + + return ( + <> + + Created:{" "} + + + } + type={getProposalTypeString(proposal.type)} + circleVisibility={circleVisibility} + commonId={commonId} + userId={item.userId} + menuItems={menuItems} + onUserSelect={onUserClick && (() => onUserClick(item.userId))} + /> + { + onHover(true); + }} + onMouseLeave={() => { + onHover(false); + }} + > + {proposal.resolutionType === ResolutionType.WAIT_FOR_EXPIRATION && ( + <> + + + + )} + + {proposal.resolutionType === ResolutionType.IMMEDIATE && ( + <> + + + + )} + + {isVotingAllowed && ( + + )} + + + ); +} diff --git a/src/pages/common/components/ProposalFeedCard/components/ProposalFeedCardContent/index.ts b/src/pages/common/components/ProposalFeedCard/components/ProposalFeedCardContent/index.ts new file mode 100644 index 0000000000..9a15137c9e --- /dev/null +++ b/src/pages/common/components/ProposalFeedCard/components/ProposalFeedCardContent/index.ts @@ -0,0 +1 @@ +export * from "./ProposalFeedCardContent"; \ No newline at end of file diff --git a/src/pages/common/components/ProposalFeedCard/components/index.ts b/src/pages/common/components/ProposalFeedCard/components/index.ts index e954d85739..f59372267e 100644 --- a/src/pages/common/components/ProposalFeedCard/components/index.ts +++ b/src/pages/common/components/ProposalFeedCard/components/index.ts @@ -2,3 +2,4 @@ export * from "./ProposalFeedButtonContainer"; export * from "./ProposalFeedVotingInfo"; export * from "./UserVoteInfo"; export * from "./ImmediateProposalInfo"; +export * from "./ProposalFeedCardContent"; diff --git a/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/ActionsButton.tsx b/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/ActionsButton.tsx index 5047ad139e..fce9e0ac3a 100644 --- a/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/ActionsButton.tsx +++ b/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/ActionsButton.tsx @@ -6,6 +6,7 @@ import { CirclesPermissions, Common, CommonMember } from "@/shared/models"; import { DesktopMenu, MenuButton } from "@/shared/ui-kit"; import { StaticLinkType, generateStaticShareLink } from "@/shared/utils"; import { useMenuItems } from "./hooks"; +import { useUpdateCommonSeenState } from "@/shared/hooks/useCases"; interface ActionsButtonProps { common: Common; @@ -22,6 +23,7 @@ const ActionsButton: FC = (props) => { onOpen: onShareModalOpen, onClose: onShareModalClose, } = useModal(false); + const { markCommonAsSeen } = useUpdateCommonSeenState(); const items = useMenuItems( { common, @@ -33,6 +35,7 @@ const ActionsButton: FC = (props) => { share: onShareModalOpen, onFollowToggle: commonFollow.onFollowToggle, onSearchClick, + markCommonAsSeen }, ); const shareLink = generateStaticShareLink(StaticLinkType.Common, common); diff --git a/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/hooks/useMenuItems.tsx b/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/hooks/useMenuItems.tsx index 0eb66064cd..e36c7305e7 100644 --- a/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/hooks/useMenuItems.tsx +++ b/src/pages/commonFeed/components/HeaderContent/components/ActionsButton/hooks/useMenuItems.tsx @@ -2,6 +2,7 @@ import React from "react"; import { CommonFollowState } from "@/shared/hooks/useCases"; import { FollowIcon, + Message3Icon, SearchIcon, Share3Icon, UnfollowIcon, @@ -17,6 +18,7 @@ interface Actions { share: () => void; onSearchClick?: () => void; onFollowToggle: CommonFollowState["onFollowToggle"]; + markCommonAsSeen: (commonId: string) => void; } export const useMenuItems = ( @@ -24,7 +26,7 @@ export const useMenuItems = ( actions: Actions, ): Item[] => { const { common } = options; - const { share, onFollowToggle, onSearchClick } = actions; + const { share, onFollowToggle, onSearchClick, markCommonAsSeen } = actions; const items: Item[] = [ { @@ -51,6 +53,18 @@ export const useMenuItems = ( onClick: () => onFollowToggle(), icon: , }, + { + id: CommonFeedMenuItem.MarkRead, + text: "Mark all as read", + onClick: () => { + if (!common.id) { + return; + } + + markCommonAsSeen(common.id); + }, + icon: , + }, ]; return getAllowedItems(items, options); diff --git a/src/pages/commonFeed/constants/commonFeedMenuItem.ts b/src/pages/commonFeed/constants/commonFeedMenuItem.ts index 6aea242f55..3dde29d002 100644 --- a/src/pages/commonFeed/constants/commonFeedMenuItem.ts +++ b/src/pages/commonFeed/constants/commonFeedMenuItem.ts @@ -3,4 +3,5 @@ export enum CommonFeedMenuItem { Share = "share", Follow = "follow", Mute = "mute", + MarkRead = "markRead", } diff --git a/src/pages/commonFeed/utils/getAllowedItems.ts b/src/pages/commonFeed/utils/getAllowedItems.ts index 0e02ecc1e2..8be993be32 100644 --- a/src/pages/commonFeed/utils/getAllowedItems.ts +++ b/src/pages/commonFeed/utils/getAllowedItems.ts @@ -20,6 +20,7 @@ const MENU_ITEM_TO_CHECK_FUNCTION_MAP: Record< !isFollowInProgress && Boolean(commonMember && !commonMember.isFollowing), [CommonFeedMenuItem.Mute]: ({ commonMember, isFollowInProgress }) => !isFollowInProgress && Boolean(commonMember?.isFollowing), + [CommonFeedMenuItem.MarkRead]: () => true, }; export const getAllowedItems = (items: Item[], options: Options): Item[] => diff --git a/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/DirectMessageModal.tsx b/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/DirectMessageModal.tsx index b86014c59d..f2916a7e99 100644 --- a/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/DirectMessageModal.tsx +++ b/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/DirectMessageModal.tsx @@ -40,7 +40,6 @@ const DirectMessageModal: FC = (props) => { const { loading: areDMUsersLoading, dmUsers, - fetchDMUsers, error: dmUsersFetchError, } = useDMUsers(); const { @@ -57,11 +56,6 @@ const DirectMessageModal: FC = (props) => { }; useEffect(() => { - if (isOpen) { - fetchDMUsers(); - return; - } - resetDMUserChatChannel(); }, [isOpen]); diff --git a/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/hooks/useDMUsers.ts b/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/hooks/useDMUsers.ts index ec1f35dd72..76ab93e8b3 100644 --- a/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/hooks/useDMUsers.ts +++ b/src/pages/inbox/components/DirectMessageButton/components/DirectMessageModal/hooks/useDMUsers.ts @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback, useState, useEffect } from "react"; import { useSelector } from "react-redux"; import { selectUser } from "@/pages/Auth/store/selectors"; import { ChatService } from "@/services"; @@ -47,9 +47,18 @@ export const useDMUsers = (): Return => { } } }, - [state, userId], + [state.loading, state.fetched, userId], ); + + useEffect(() => { + if(!userId) { + return; + } + + fetchDMUsers(); + },[userId]); + return { fetchDMUsers, loading: state.loading || !state.fetched, diff --git a/src/services/Common.ts b/src/services/Common.ts index 2c053e6a87..7429ff78d6 100644 --- a/src/services/Common.ts +++ b/src/services/Common.ts @@ -609,6 +609,19 @@ class CommonService { return snapshot.data() || null; }; + + public markCommonAsSeen = async ( + commonId: string, + userId: string, + ): Promise => { + await Api.post( + ApiEndpoint.MarkCommonSeenForUser, + { + commonId, + userId + }, + ); + }; } export default new CommonService(); diff --git a/src/shared/components/Chat/ChatMessage/ChatMessage.tsx b/src/shared/components/Chat/ChatMessage/ChatMessage.tsx index 67b6734e29..8b4b56a0bf 100644 --- a/src/shared/components/Chat/ChatMessage/ChatMessage.tsx +++ b/src/shared/components/Chat/ChatMessage/ChatMessage.tsx @@ -253,12 +253,12 @@ const ChatMessage = ({ isProposalMessage: chatType === ChatType.ProposalComments, discussionId: discussionMessage.discussionId, callback(isSucceed) { + setIsMessageEditLoading(false); if (isSucceed) { handleEditModeClose(); } else { notify("Something went wrong"); } - setIsMessageEditLoading(false); }, }), ); @@ -405,24 +405,30 @@ const ChatMessage = ({ [isMessageEditLoading, handleCheckboxChange, isMessageEditAllowed], ); + const EmojiButton = useCallback(() => { + return ( + + ); + }, [ + discussionMessage.discussionId, + discussionMessage.id, + isNotCurrentUserMessage, + ]); + if (isSystemMessage && discussionMessage.parsedText.length === 0) { return null; } - const emojiButton = ( - - ); - return (
  • - {!isSystemMessage && !isNotCurrentUserMessage && emojiButton} + {!isSystemMessage && !isNotCurrentUserMessage && } {isNotCurrentUserMessage && (isUserDiscussionMessage || isBotMessage) && (
    @@ -577,13 +583,13 @@ const ChatMessage = ({
    )} - {!isSystemMessage && isNotCurrentUserMessage && emojiButton} + {!isSystemMessage && isNotCurrentUserMessage && }
  • ); }; -const MemoizedChatMessage = React.memo(ChatMessage) +const MemoizedChatMessage = React.memo(ChatMessage); export default MemoizedChatMessage; diff --git a/src/shared/constants/endpoint.ts b/src/shared/constants/endpoint.ts index 45ac8aab6c..cf5c27a9af 100644 --- a/src/shared/constants/endpoint.ts +++ b/src/shared/constants/endpoint.ts @@ -8,6 +8,7 @@ export const ApiEndpoint = { CreateCommon: "/commons/create", UpdateCommon: "/commons/update", CreateSubCommon: "/commons/subcommon/create", + MarkCommonSeenForUser: "/commons/mark-seen-for-user", MarkFeedObjectSeenForUser: "/commons/mark-feed-object-seen-for-user", MarkFeedObjectUnseenForUser: "/commons/mark-feed-object-unseen-for-user", LinkStream: "/commons/link-stream", diff --git a/src/shared/hooks/useCases/index.ts b/src/shared/hooks/useCases/index.ts index 3b63789e06..683dbce471 100644 --- a/src/shared/hooks/useCases/index.ts +++ b/src/shared/hooks/useCases/index.ts @@ -47,5 +47,6 @@ export { useEligibleVoters } from "./useEligibleVoters"; export { useDiscussionMessageReaction } from "./useDiscussionMessageReaction"; export { useChatMessageReaction } from "./useChatMessageReaction"; export { useUserReaction } from "./useUserReaction"; +export { useUpdateCommonSeenState } from "./useUpdateCommonSeenState"; export * from "./useCommonFollow"; export * from "./usePreloadDiscussionMessagesById"; diff --git a/src/shared/hooks/useCases/useDiscussionMessagesById.ts b/src/shared/hooks/useCases/useDiscussionMessagesById.ts index 1b7370a5b5..a2921fb4a1 100644 --- a/src/shared/hooks/useCases/useDiscussionMessagesById.ts +++ b/src/shared/hooks/useCases/useDiscussionMessagesById.ts @@ -238,148 +238,164 @@ export const useDiscussionMessagesById = ({ setIsBatchLoading(true); } - DiscussionMessageService.subscribeToDiscussionMessagesByDiscussionId( - discussionId, - lastVisible && lastVisible[discussionId], - async ( - addedDiscussionMessages, - modifiedDiscussionMessages, - removedDiscussionMessages, - lastVisibleDocument, - ) => { - const updatedDiscussionMessages = [ - ...addedDiscussionMessages, - ...modifiedDiscussionMessages, - ]; - setLastVisible((prevVisible) => ({ - ...prevVisible, - [discussionId]: lastVisibleDocument, - })); - - const hasLastVisibleDocument = !!lastVisibleDocument?.data(); - - const discussionsWithText = await Promise.all( - updatedDiscussionMessages.map(async (discussionMessage) => { - const isUserDiscussionMessage = - checkIsUserDiscussionMessage(discussionMessage); - const isSystemMessage = - checkIsSystemDiscussionMessage(discussionMessage); - - const parsedText = await getTextFromTextEditorString({ - userId, - ownerId: isUserDiscussionMessage - ? discussionMessage.ownerId - : null, - textEditorString: discussionMessage.text, - users, - commonId: discussionMessage.commonId, - systemMessage: isSystemMessage ? discussionMessage : undefined, - getCommonPagePath, - getCommonPageAboutTabPath, - directParent, - onUserClick, - onFeedItemClick, - onInternalLinkClick, - }); - - return { - ...discussionMessage, - parsedText, - }; - }), - ); - if ( - discussionsWithText.length < MESSAGES_NUMBER_IN_BATCH && - !hasLastVisibleDocument - ) { - setIsEndOfList((prevIsEndOfList) => ({ - ...prevIsEndOfList, - [discussionId]: true, + try { + DiscussionMessageService.subscribeToDiscussionMessagesByDiscussionId( + discussionId, + lastVisible && lastVisible[discussionId], + async ( + addedDiscussionMessages, + modifiedDiscussionMessages, + removedDiscussionMessages, + lastVisibleDocument, + ) => { + const updatedDiscussionMessages = [ + ...addedDiscussionMessages, + ...modifiedDiscussionMessages, + ]; + setLastVisible((prevVisible) => ({ + ...prevVisible, + [discussionId]: lastVisibleDocument, })); - } - dispatch( - cacheActions.updateDiscussionMessagesStateByDiscussionId({ - discussionId, - removedDiscussionMessages, - updatedDiscussionMessages: discussionsWithText, - }), - ); - setIsBatchLoading(false); - }, - ); + + const hasLastVisibleDocument = !!lastVisibleDocument?.data(); + + const discussionsWithText = await Promise.all( + updatedDiscussionMessages.map(async (discussionMessage) => { + const isUserDiscussionMessage = + checkIsUserDiscussionMessage(discussionMessage); + const isSystemMessage = + checkIsSystemDiscussionMessage(discussionMessage); + + const parsedText = await getTextFromTextEditorString({ + userId, + ownerId: isUserDiscussionMessage + ? discussionMessage.ownerId + : null, + textEditorString: discussionMessage.text, + users, + commonId: discussionMessage.commonId, + systemMessage: isSystemMessage ? discussionMessage : undefined, + getCommonPagePath, + getCommonPageAboutTabPath, + directParent, + onUserClick, + onFeedItemClick, + onInternalLinkClick, + }); + + return { + ...discussionMessage, + parsedText, + }; + }), + ); + if ( + discussionsWithText.length < MESSAGES_NUMBER_IN_BATCH && + !hasLastVisibleDocument + ) { + setIsEndOfList((prevIsEndOfList) => ({ + ...prevIsEndOfList, + [discussionId]: true, + })); + } + dispatch( + cacheActions.updateDiscussionMessagesStateByDiscussionId({ + discussionId, + removedDiscussionMessages, + updatedDiscussionMessages: discussionsWithText, + }), + ); + setIsBatchLoading(false); + }, + ); + } catch(err) { + setIsBatchLoading(false); + } }; useDeepCompareEffect(() => { (async () => { - if (!state.data || state.data.length === 0) { + if(Array.isArray(state.data) && state.data.length === 0) { + setIsFirstBatchLoaded((prev) => ({ + ...prev, + [discussionId]: true, + })); setDiscussionMessagesWithOwners([]); - return; } - const discussionMessages = [...state.data]; + if (!state.data) { + setDiscussionMessagesWithOwners([]); + return; + } - // if (discussionMessages.length > 0 && users.length === 0) { - // return; - // } + try { + const discussionMessages = [...state.data]; - const filteredMessages = discussionMessages.filter( - ({ moderation }) => - moderation?.flag !== ModerationFlags.Hidden || hasPermissionToHide, - ); - const loadedDiscussionMessages = await Promise.all( - filteredMessages.map(async (d) => { - const newDiscussionMessage = { ...d }; - const parentMessage = filteredMessages.find( - ({ id }) => id === d.parentId, - ); - if ( - checkIsUserDiscussionMessage(d) && - checkIsUserDiscussionMessage(newDiscussionMessage) - ) { - const commonMemberMessageOwner = [ - AI_USER, - AI_PRO_USER, - ...users, - ...externalCommonUsers, - ].find((o) => o.uid === d.ownerId); - const messageOwner = - commonMemberMessageOwner || - (await UserService.getUserById(d.ownerId)); - newDiscussionMessage.owner = messageOwner; - if (!commonMemberMessageOwner && messageOwner) { - dispatch( - cacheActions.addUserToExternalCommonUsers({ - user: messageOwner, - }), - ); - } - } - newDiscussionMessage.parentMessage = parentMessage - ? { - id: parentMessage.id, - text: parentMessage.text, - ownerName: parentMessage?.ownerName, - ...(checkIsUserDiscussionMessage(parentMessage) && { - ownerId: parentMessage.ownerId, - }), - moderation: parentMessage?.moderation, - images: parentMessage?.images, - files: parentMessage?.files, - createdAt: parentMessage.createdAt, + const filteredMessages = discussionMessages.filter( + ({ moderation }) => + moderation?.flag !== ModerationFlags.Hidden || hasPermissionToHide, + ); + const loadedDiscussionMessages = await Promise.all( + filteredMessages.map(async (d) => { + const newDiscussionMessage = { ...d }; + const parentMessage = filteredMessages.find( + ({ id }) => id === d.parentId, + ); + if ( + checkIsUserDiscussionMessage(d) && + checkIsUserDiscussionMessage(newDiscussionMessage) + ) { + const commonMemberMessageOwner = [ + AI_USER, + AI_PRO_USER, + ...users, + ...externalCommonUsers, + ].find((o) => o.uid === d.ownerId); + const messageOwner = + commonMemberMessageOwner || + (await UserService.getUserById(d.ownerId)); + newDiscussionMessage.owner = messageOwner; + if (!commonMemberMessageOwner && messageOwner) { + dispatch( + cacheActions.addUserToExternalCommonUsers({ + user: messageOwner, + }), + ); } - : null; - - return newDiscussionMessage; - }), - ); - - setDiscussionMessagesWithOwners(loadedDiscussionMessages); - setIsFirstBatchLoaded((prev) => ({ - ...prev, - [discussionId]: true, - })); + } + newDiscussionMessage.parentMessage = parentMessage + ? { + id: parentMessage.id, + text: parentMessage.text, + ownerName: parentMessage?.ownerName, + ...(checkIsUserDiscussionMessage(parentMessage) && { + ownerId: parentMessage.ownerId, + }), + moderation: parentMessage?.moderation, + images: parentMessage?.images, + files: parentMessage?.files, + createdAt: parentMessage.createdAt, + } + : null; + + return newDiscussionMessage; + }), + ); + + setDiscussionMessagesWithOwners(loadedDiscussionMessages); + setIsFirstBatchLoaded((prev) => ({ + ...prev, + [discussionId]: true, + })); + } catch(err) { + setDiscussionMessagesWithOwners([]); + setIsFirstBatchLoaded((prev) => ({ + ...prev, + [discussionId]: true, + })); + } })(); - }, [state.data, hasPermissionToHide, users, externalCommonUsers]); + }, [state.data, hasPermissionToHide, users, externalCommonUsers, discussionId]); return { ...state, diff --git a/src/shared/hooks/useCases/usePreloadDiscussionMessagesById.ts b/src/shared/hooks/useCases/usePreloadDiscussionMessagesById.ts index 00a0343d6e..2fba3af495 100644 --- a/src/shared/hooks/useCases/usePreloadDiscussionMessagesById.ts +++ b/src/shared/hooks/useCases/usePreloadDiscussionMessagesById.ts @@ -59,48 +59,58 @@ export const usePreloadDiscussionMessagesById = ({ return; } - const discussionMessages = - await DiscussionMessageService.getPreloadDiscussionMessagesByDiscussionId( - discussionId, + try { + const discussionMessages = + await DiscussionMessageService.getPreloadDiscussionMessagesByDiscussionId( + discussionId, + ); + + const users = commonMembers.map(({ user }) => user); + + const discussionsWithText = await Promise.all( + discussionMessages.map(async (discussionMessage) => { + const isUserDiscussionMessage = + checkIsUserDiscussionMessage(discussionMessage); + const isSystemMessage = + checkIsSystemDiscussionMessage(discussionMessage); + + const parsedText = await getTextFromTextEditorString({ + userId, + ownerId: isUserDiscussionMessage ? discussionMessage.ownerId : null, + textEditorString: discussionMessage.text, + users, + commonId: discussionMessage.commonId, + systemMessage: isSystemMessage ? discussionMessage : undefined, + getCommonPagePath, + getCommonPageAboutTabPath, + onUserClick, + onFeedItemClick, + onInternalLinkClick, + }); + + return { + ...discussionMessage, + parsedText, + }; + }), ); - - const users = commonMembers.map(({ user }) => user); - - const discussionsWithText = await Promise.all( - discussionMessages.map(async (discussionMessage) => { - const isUserDiscussionMessage = - checkIsUserDiscussionMessage(discussionMessage); - const isSystemMessage = - checkIsSystemDiscussionMessage(discussionMessage); - - const parsedText = await getTextFromTextEditorString({ - userId, - ownerId: isUserDiscussionMessage ? discussionMessage.ownerId : null, - textEditorString: discussionMessage.text, - users, - commonId: discussionMessage.commonId, - systemMessage: isSystemMessage ? discussionMessage : undefined, - getCommonPagePath, - getCommonPageAboutTabPath, - onUserClick, - onFeedItemClick, - onInternalLinkClick, - }); - - return { - ...discussionMessage, - parsedText, - }; - }), - ); - - dispatch( - cacheActions.updateDiscussionMessagesStateByDiscussionId({ - discussionId, - updatedDiscussionMessages: discussionsWithText, - removedDiscussionMessages: [], - }), - ); + + dispatch( + cacheActions.updateDiscussionMessagesStateByDiscussionId({ + discussionId, + updatedDiscussionMessages: discussionsWithText, + removedDiscussionMessages: [], + }), + ); + } catch(err) { + dispatch( + cacheActions.updateDiscussionMessagesStateByDiscussionId({ + discussionId, + updatedDiscussionMessages: [], + removedDiscussionMessages: [], + }), + ); + } }; useEffect(() => { diff --git a/src/shared/hooks/useCases/useUpdateCommonSeenState.ts b/src/shared/hooks/useCases/useUpdateCommonSeenState.ts new file mode 100644 index 0000000000..fc7b1f91e5 --- /dev/null +++ b/src/shared/hooks/useCases/useUpdateCommonSeenState.ts @@ -0,0 +1,43 @@ +import { useCallback } from "react"; +import { useSelector } from "react-redux"; +import { selectUser } from "@/pages/Auth/store/selectors"; +import { CommonService } from "@/services"; +import useNotification from "../useNotification"; + +interface Return { + markCommonAsSeen: ( + commonId: string, + delay?: number, + ) => ReturnType; +} + +export const useUpdateCommonSeenState = (): Return => { + const user = useSelector(selectUser()); + const userId = user?.uid; + const { notify } = useNotification(); + + const updateSeenState = async ( + commonId: string, + ) => { + if (!userId) { + return; + } + + try { + await CommonService.markCommonAsSeen(commonId, userId); + } catch (error) { + notify("Something went wrong"); + } + }; + + const markCommonAsSeen = useCallback( + (commonId: string, delay = 0) => { + return setTimeout(() => { + updateSeenState(commonId); + }, delay); + }, + [userId], + ); + + return { markCommonAsSeen }; +}; diff --git a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Breadcrumbs/components/BreadcrumbsMenu/hooks/useMenuItems.tsx b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Breadcrumbs/components/BreadcrumbsMenu/hooks/useMenuItems.tsx index ac4606adc3..cd29ca3074 100644 --- a/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Breadcrumbs/components/BreadcrumbsMenu/hooks/useMenuItems.tsx +++ b/src/shared/layouts/MultipleSpacesLayout/components/Header/components/Breadcrumbs/components/BreadcrumbsMenu/hooks/useMenuItems.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useMemo } from "react"; import { useHistory } from "react-router"; import classNames from "classnames"; import { useRoutesContext } from "@/shared/contexts"; @@ -19,43 +19,52 @@ export const useMenuItems = (options: Options): ContextMenuItem[] => { const history = useHistory(); const { getCommonPagePath, getProjectCreationPagePath } = useRoutesContext(); - const menuItems: ContextMenuItem[] = items.map((item) => ({ - id: item.commonId, - text: item.name, - onClick: () => history.push(getCommonPagePath(item.commonId)), - className: classNames(styles.contextMenuItem, { - [styles.contextMenuItemWithoutMembership]: !item.hasMembership, - }), - renderContent: () => ( - - ), - })); - - if (onCommonCreate) { - menuItems.push({ - id: "create-a-common", - text: "Create a common", - onClick: onCommonCreate, - className: classNames( - styles.contextMenuItem, - styles.contextMenuItemToAddProject, - ), - renderContent: () => , - }); - } - if (commonIdToAddProject) { - menuItems.push({ - id: "add-a-space", - text: "Add a space", - onClick: () => - history.push(getProjectCreationPagePath(commonIdToAddProject)), - className: classNames( - styles.contextMenuItem, - styles.contextMenuItemToAddProject, + const menuItems: ContextMenuItem[] = useMemo(() => { + const initialMenuItems = items.map((item) => ({ + id: item.commonId, + text: item.name, + onClick: () => history.push(getCommonPagePath(item.commonId)), + className: classNames(styles.contextMenuItem, { + [styles.contextMenuItemWithoutMembership]: !item.hasMembership, + }), + renderContent: () => ( + ), - renderContent: () => , - }); - } + })); + + if (onCommonCreate) { + initialMenuItems.push({ + id: "create-a-common", + text: "Create a common", + onClick: onCommonCreate, + className: classNames( + styles.contextMenuItem, + styles.contextMenuItemToAddProject, + ), + renderContent: () => ( + + ), + }); + } + if (commonIdToAddProject) { + initialMenuItems.push({ + id: "add-a-space", + text: "Add a space", + onClick: () => + history.push(getProjectCreationPagePath(commonIdToAddProject)), + className: classNames( + styles.contextMenuItem, + styles.contextMenuItemToAddProject, + ), + renderContent: () => , + }); + } + + return initialMenuItems; + }, [items, onCommonCreate, commonIdToAddProject]); return menuItems; }; diff --git a/src/shared/ui-kit/ImageGallery/ChatImageGallery.tsx b/src/shared/ui-kit/ImageGallery/ChatImageGallery.tsx index a36e8ca768..655b47b5c8 100644 --- a/src/shared/ui-kit/ImageGallery/ChatImageGallery.tsx +++ b/src/shared/ui-kit/ImageGallery/ChatImageGallery.tsx @@ -24,14 +24,26 @@ const ChatImageGallery: FC = (props) => { const isTabletView = useIsTabletView(); const { isShowing, onOpen, onClose } = useModal(false); const [initialSlide, setInitialSlide] = useState(0); - const images = (gallery || []).map(({ value }) => + const images = (gallery || []).map(({ value }) => value); + + const imagesWithSrcSets = (gallery || []).map(({ value }) => useResizedFile - ? getResizedFileUrl(value, ResizeType.Images, FilePrefix.Image) + ? `${getResizedFileUrl( + value, + ResizeType.Images, + FilePrefix.Image, + )} 1x, ${value} 2x` : value, ); const [leftImage, rightImage, secondRowLeftImage, secondRowRightImage] = images; + const [ + leftImageSrcSet, + rightImageSrcSet, + secondRowLeftImageSrcSet, + secondRowRightImageSrcSet, + ] = imagesWithSrcSets; const hasOneImage = Boolean(leftImage && !rightImage); const singleImageWithoutVideo = hasOneImage && !videoSrc; @@ -61,6 +73,7 @@ const ChatImageGallery: FC = (props) => { @@ -79,6 +92,7 @@ const ChatImageGallery: FC = (props) => { [styles.leftItem]: !hasOneImage, })} src={leftImage} + srcSet={leftImageSrcSet} imageOverlayClassName={styles.imageOverlay} alt="1st Image" onClick={() => handleOpenSlide(0)} @@ -88,6 +102,7 @@ const ChatImageGallery: FC = (props) => { 2nd Image = (props) => { })} imageOverlayClassName={styles.imageOverlay} src={secondRowLeftImage} + srcSet={secondRowLeftImageSrcSet} alt="3st Image" onClick={() => handleOpenSlide(2)} /> @@ -120,6 +136,7 @@ const ChatImageGallery: FC = (props) => { className={styles.image} imageContainerClassName={styles.rightItem} src={secondRowRightImage} + srcSet={secondRowRightImageSrcSet} imageOverlayClassName={styles.imageOverlay} alt="4nd Image" onClick={() => handleOpenSlide(3)} diff --git a/src/shared/ui-kit/ImageGallery/ImageGallery.tsx b/src/shared/ui-kit/ImageGallery/ImageGallery.tsx index 186306aa26..ea3b3c267b 100644 --- a/src/shared/ui-kit/ImageGallery/ImageGallery.tsx +++ b/src/shared/ui-kit/ImageGallery/ImageGallery.tsx @@ -18,13 +18,21 @@ const ImageGallery: FC = (props) => { const { gallery, videoSrc, useResizedFile = true } = props; const [videoContainerRef, { width: videoContainerWidth }] = useMeasure(); const { isShowing, onOpen, onClose } = useModal(false); - const images = (gallery || []).map(({ value }) => + const images = (gallery || []).map(({ value }) => value); + + const imagesWithSrcSets = (gallery || []).map(({ value }) => useResizedFile - ? getResizedFileUrl(value, ResizeType.Images, FilePrefix.Image) + ? `${getResizedFileUrl( + value, + ResizeType.Images, + FilePrefix.Image, + )} 1x, ${value} 2x` : value, ); const [leftImage, rightImage, mainImage] = images; + const [leftImageSrcSet, rightImageSrcSet, mainImageSrcSet] = + imagesWithSrcSets; const hasOneImage = Boolean(leftImage && !rightImage); const singleImageWithoutVideo = hasOneImage && !videoSrc; @@ -56,6 +64,7 @@ const ImageGallery: FC = (props) => { @@ -73,6 +82,7 @@ const ImageGallery: FC = (props) => { })} style={singleImageWithoutVideo ? {} : imagePreviewStyle} src={leftImage} + srcSet={leftImageSrcSet} alt="1st Image" /> )} @@ -81,6 +91,7 @@ const ImageGallery: FC = (props) => { className={classNames(styles.image, styles.rightItem)} style={imagePreviewStyle} src={rightImage} + srcSet={rightImageSrcSet} alt="2nd Image" /> )} diff --git a/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.tsx b/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.tsx index 6227941748..93df03ea60 100644 --- a/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.tsx +++ b/src/shared/ui-kit/ImageGallery/components/GalleryMainContent/GalleryMainContent.tsx @@ -7,12 +7,13 @@ import styles from "./GalleryMainContent.module.scss"; interface GalleryMainContentProps { videoSrc?: string; mainImage: string; + srcSet?: string; hasOneImage: boolean; imagePreviewStyle?: React.CSSProperties; } const GalleryMainContent: FC = (props) => { - const { mainImage, videoSrc, hasOneImage, imagePreviewStyle } = props; + const { mainImage, srcSet, videoSrc, hasOneImage, imagePreviewStyle } = props; if (!videoSrc && !mainImage) { return null; @@ -34,6 +35,7 @@ const GalleryMainContent: FC = (props) => {