diff --git a/src/components/ProfilePreviewModalWrapper.tsx b/src/components/ProfilePreviewModalWrapper.tsx index 3caf97638..6fa3bda28 100644 --- a/src/components/ProfilePreviewModalWrapper.tsx +++ b/src/components/ProfilePreviewModalWrapper.tsx @@ -1,8 +1,8 @@ +import { useProfilePostsModal } from '@/stores/profile-posts-modal' import { cx } from '@/utils/class-names' import { useState } from 'react' import Name, { NameProps } from './Name' import ProfilePreview from './ProfilePreview' -import ProfilePostsListModalWrapper from './chats/ChatItem/profilePosts/ProfileProstsListModal' import Modal from './modals/Modal' export type ProfilePreviewModalWrapperProps = { @@ -49,26 +49,20 @@ export function ProfilePreviewModalName({ hubId: string enableProfileModal?: boolean }) { + const { openModal } = useProfilePostsModal() + return ( - { + if (enableProfileModal) { + e.preventDefault() + openModal({ messageId, chatId, hubId, address: props.address }) + props.onClick?.(e) + } + }} + className={cx('cursor-pointer', props.className)} address={props.address} - messageId={messageId} - chatId={chatId} - hubId={hubId} - > - {(onClick) => ( - { - if (enableProfileModal) { - onClick(e) - props.onClick?.(e) - } - }} - className={cx('cursor-pointer', props.className)} - address={props.address} - /> - )} - + /> ) } diff --git a/src/components/chats/ChatItem/ChatItem.tsx b/src/components/chats/ChatItem/ChatItem.tsx index 627b5fe0b..d9d04e823 100644 --- a/src/components/chats/ChatItem/ChatItem.tsx +++ b/src/components/chats/ChatItem/ChatItem.tsx @@ -1,4 +1,5 @@ import AddressAvatar from '@/components/AddressAvatar' +import { useProfilePostsModal } from '@/stores/profile-posts-modal' import { cx } from '@/utils/class-names' import { PostData } from '@subsocial/api/types' import { ComponentProps } from 'react' @@ -6,7 +7,6 @@ import { ScrollToMessage } from '../ChatList/hooks/useScrollToMessage' import ChatItemMenus from './ChatItemMenus' import ChatItemWithExtension from './ChatItemWithExtension' import Embed, { useCanRenderEmbed } from './Embed' -import ProfilePostsListModalWrapper from './profilePosts/ProfileProstsListModal' import DefaultChatItem from './variants/DefaultChatItem' import EmojiChatItem, { shouldRenderEmojiChatItem, @@ -40,6 +40,7 @@ export default function ChatItem({ }: ChatItemProps) { const { ownerId, id: messageId } = message.struct const { body, extensions, link } = message.content || {} + const { openModal } = useProfilePostsModal() const canRenderEmbed = useCanRenderEmbed(link ?? '') @@ -61,20 +62,17 @@ export default function ChatItem({ )} > {!isMyMessage && ( - { + e.preventDefault() + + if (enableProfileModal) { + openModal({ chatId, hubId, messageId, address: ownerId }) + } + }} address={ownerId} - chatId={chatId} - hubId={hubId} - messageId={messageId} - > - {(onClick) => ( - - )} - + className='flex-shrink-0 cursor-pointer' + /> )} setMessageAsReply()} {...referenceProps} id={messageBubbleId} > diff --git a/src/components/chats/ChatItem/ChatItemMenus.tsx b/src/components/chats/ChatItem/ChatItemMenus.tsx index f227d6a65..0253f4a1d 100644 --- a/src/components/chats/ChatItem/ChatItemMenus.tsx +++ b/src/components/chats/ChatItem/ChatItemMenus.tsx @@ -62,7 +62,6 @@ export default function ChatItemMenus({ hubId, enableChatMenu = true, }: ChatItemMenusProps) { - // const canSendMessage = useCanSendMessage(hubId, chatId) const myAddress = useMyMainAddress() const isOpen = useChatMenu((state) => state.openedChatId === messageId) @@ -71,26 +70,14 @@ export default function ChatItemMenus({ const { data: post } = getPostQuery.useQuery(messageId) const ownerId = post?.struct.ownerId ?? '' - const { ref, inView } = useInView({ triggerOnce: true }) - // const { evmAddress } = useLinkedEvmAddress(ownerId, { enabled: inView }) - // const refSearchParam = useReferralSearchParam() + const { ref } = useInView({ triggerOnce: true }) - // const router = useRouter() - - // const address = useMyMainAddress() const { data: message } = getPostQuery.useQuery(messageId) const [modalState, setModalState] = useState(null) const { mutate: moderate } = useModerateWithSuccessToast(messageId, chatId) const sendEvent = useSendEvent() - // const openDonateExtension = useOpenDonateExtension( - // message?.id, - // message?.struct.ownerId ?? '' - // ) - - // const setReplyTo = useMessageData((state) => state.setReplyTo) - // const setMessageToEdit = useMessageData((state) => state.setMessageToEdit) const { isAuthorized } = useAuthorizedForModeration(chatId) const { data: reasons } = getModerationReasonsQuery.useQuery(null) @@ -102,40 +89,7 @@ export default function ChatItemMenus({ const pinUnpinMenu = usePinUnpinMenuItem(chatId, messageId) const getChatMenus = (): FloatingMenusProps['menus'] => { - const menus: FloatingMenusProps['menus'] = [ - // { - // text: 'Copy Text', - // icon: MdContentCopy, - // onClick: () => { - // copyToClipboard(message?.content?.body ?? '') - // toast.custom((t) => ( - // - // )) - // }, - // }, - // { - // text: 'Copy Message Link', - // icon: FiLink, - // onClick: () => { - // const messageLink = urlJoin( - // getCurrentUrlOrigin(), - // env.NEXT_PUBLIC_BASE_PATH, - // '/message', - // `/${messageId}`, - // refSearchParam - // ) - // copyToClipboard(messageLink) - // toast.custom((t) => ( - // - // )) - // }, - // }, - // { - // text: 'Show Metadata', - // icon: RiDatabase2Line, - // onClick: () => setModalState('metadata'), - // }, - ] + const menus: FloatingMenusProps['menus'] = [] const hideMenu: FloatingMenusProps['menus'][number] = { text: 'Hide', @@ -191,56 +145,7 @@ export default function ChatItemMenus({ if (isOptimisticMessage) return menus - // const donateMenuItem: FloatingMenusProps['menus'][number] = { - // text: 'Donate', - // icon: RiCopperCoinLine, - // onClick: () => { - // sendEventWithRef(myAddress ?? '', (refId) => { - // sendEvent('click_donate', { postId: messageId }, { ref: refId }) - // }) - // if (!address) { - // useLoginModal.getState().setIsOpen(true) - // return - // } - - // sendEvent('open_donate_action_modal', { hubId, chatId }) - // openDonateExtension() - // }, - // } - // const replyItem: FloatingMenusProps['menus'][number] = { - // text: 'Reply', - // icon: LuReply, - // onClick: () => { - // sendEventWithRef(myAddress ?? '', (refId) => { - // sendEvent( - // 'click_reply', - // { - // eventSource: 'message_menu', - // postId: messageId, - // }, - // { ref: refId } - // ) - // }) - // setReplyTo(messageId) - // }, - // } - // const editItem: FloatingMenusProps['menus'][number] = { - // text: 'Edit', - // icon: LuPencil, - // onClick: () => setMessageToEdit(messageId), - // } - // const showDonateMenuItem = canSendMessage && !isMessageOwner && evmAddress - - // if (showDonateMenuItem) menus.unshift(donateMenuItem) if (pinUnpinMenu) menus.unshift(pinUnpinMenu) - // if (canSendMessage && isMessageOwner) menus.unshift(editItem) - // if (message) - // menus.unshift({ - // text: 'Share', - // icon: GrShareOption, - // submenus: getShareMessageMenus(message), - // }) - // if (canSendMessage) menus.unshift(replyItem) return menus } diff --git a/src/components/chats/ChatItem/profilePosts/ProfileProstsListModal.tsx b/src/components/chats/ChatItem/profilePosts/ProfileProstsListModal.tsx index 06c15ceab..292f3b89c 100644 --- a/src/components/chats/ChatItem/profilePosts/ProfileProstsListModal.tsx +++ b/src/components/chats/ChatItem/profilePosts/ProfileProstsListModal.tsx @@ -5,38 +5,28 @@ import useAuthorizedForModeration from '@/hooks/useAuthorizedForModeration' import { getModerationReasonsQuery } from '@/services/datahub/moderation/query' import { getPaginatedPostIdsByPostIdAndAccount } from '@/services/datahub/posts/queryByAccount' import { useSendEvent } from '@/stores/analytics' +import { useProfilePostsModal } from '@/stores/profile-posts-modal' import { cx } from '@/utils/class-names' import { Transition } from '@headlessui/react' -import { useQueryClient } from '@tanstack/react-query' -import { useState } from 'react' import { createPortal } from 'react-dom' import { HiOutlineChevronLeft } from 'react-icons/hi2' import SkeletonFallback from '../../../SkeletonFallback' import { useModerateWithSuccessToast } from '../ChatItemMenus' import ProfilePostsList from './ProfilePostsList' -type ProfilePostsListModalProps = { - address: string - children: ( - onClick: (e: { stopPropagation: () => void }) => void - ) => React.ReactNode - messageId: string - chatId: string - hubId: string -} +const ProfilePostsListModal = () => { + const { + isOpen, + closeModal, + messageId = '', + chatId = '', + hubId = '', + address = '', + } = useProfilePostsModal() -const ProfilePostsListModalWrapper = ({ - children, - address, - messageId, - chatId, - hubId, -}: ProfilePostsListModalProps) => { - const [isOpen, setIsOpen] = useState(false) const { mutate: moderate } = useModerateWithSuccessToast(messageId, chatId) const sendEvent = useSendEvent() const { isAuthorized } = useAuthorizedForModeration(chatId) - const client = useQueryClient() const { data: reasons } = getModerationReasonsQuery.useQuery(null) const firstReasonId = reasons?.[0].id @@ -58,90 +48,84 @@ const ProfilePostsListModalWrapper = ({ }, chatId, }) + + closeModal() } - return ( + return createPortal( <> - {children((e) => { - e.stopPropagation() - setIsOpen(true) - })} - {createPortal( - <> - - -
-
-
- - -
- - - Memes: - - {totalPostsCount} - - -
-
+ + +
+
+
+ + +
+ + + Memes: + - Block user - - )} -
-
- + {totalPostsCount} + +
- - , - document.body - )} - + + {isAuthorized && ( + + )} +
+
+ +
+
+
+ , + document.body ) } -export default ProfilePostsListModalWrapper +export default ProfilePostsListModal diff --git a/src/components/chats/ChatList/ChatList.tsx b/src/components/chats/ChatList/ChatList.tsx index 9164e89b4..b341a7c55 100644 --- a/src/components/chats/ChatList/ChatList.tsx +++ b/src/components/chats/ChatList/ChatList.tsx @@ -10,6 +10,7 @@ import { cx } from '@/utils/class-names' import { sendMessageToParentWindow } from '@/utils/window' import { ComponentProps, Fragment, useEffect, useId, useRef } from 'react' import InfiniteScroll from 'react-infinite-scroll-component' +import ProfilePostsListModal from '../ChatItem/profilePosts/ProfileProstsListModal' import usePaginatedMessageIds from '../hooks/usePaginatedMessageIds' import usePinnedMessage from '../hooks/usePinnedMessage' import CenterChatNotice from './CenterChatNotice' @@ -231,6 +232,7 @@ function ChatListContent({ newMessageNoticeClassName={newMessageNoticeClassName} />
+ ) } diff --git a/src/stores/profile-posts-modal.ts b/src/stores/profile-posts-modal.ts new file mode 100644 index 000000000..5e5c8dd5f --- /dev/null +++ b/src/stores/profile-posts-modal.ts @@ -0,0 +1,33 @@ +import { create, createSelectors } from './utils' + +type State = { + isOpen: boolean + chatId?: string + address?: string + hubId?: string + messageId?: string +} + +type Actions = { + closeModal: () => void + openModal: (config?: Omit) => void +} + +const initialState: State = { + isOpen: false, + chatId: undefined, + address: undefined, + hubId: undefined, + messageId: undefined, +} + +const useProfilePostsModalBase = create()((set) => ({ + ...initialState, + openModal: (config) => { + set({ isOpen: true, ...config }) + }, + closeModal: () => { + set(initialState) + }, +})) +export const useProfilePostsModal = createSelectors(useProfilePostsModalBase)