Skip to content

Commit

Permalink
Merge branch 'epic-base' of https://github.com/dappforce/grillchat in…
Browse files Browse the repository at this point in the history
…to epic-base
  • Loading branch information
teodorus-nathaniel committed Jul 15, 2024
2 parents 0f3dc63 + 6dcabc8 commit c1a7fc7
Show file tree
Hide file tree
Showing 30 changed files with 1,019 additions and 190 deletions.
1 change: 1 addition & 0 deletions src/@types/subsocial.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ declare module '@subsocial/api/types' {
dataType?: 'persistent' | 'optimistic' | 'offChain'
parentPostId?: string | null
approvedInRootPost?: boolean
approvedInRootPostAtTime: number
},
PostContent
> & { requestedId?: string }
Expand Down
197 changes: 157 additions & 40 deletions src/components/chats/ChatItem/ChatItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Thumbsup from '@/assets/emojis/thumbsup.png'
import AddressAvatar from '@/components/AddressAvatar'
import { SuperLikeWrapper } from '@/components/content-staking/SuperLike'
import { FloatingWrapperProps } from '@/components/floating/FloatingWrapper'
import useLongTouch from '@/hooks/useLongTouch'
import { PostRewards } from '@/services/datahub/content-staking/query'
import { useProfilePostsModal } from '@/stores/profile-posts-modal'
import { cx } from '@/utils/class-names'
import { isTouchDevice } from '@/utils/device'
import { PostData } from '@subsocial/api/types'
import { ComponentProps } from 'react'
import { useHapticFeedbackRaw } from '@tma.js/sdk-react'
import { ComponentProps, useRef } from 'react'
import { ScrollToMessage } from '../ChatList/hooks/useScrollToMessage'
import ChatItemMenus from './ChatItemMenus'
import ChatItemWithExtension from './ChatItemWithExtension'
Expand Down Expand Up @@ -86,46 +93,45 @@ export default function ChatItem({
enableChatMenu={enableChatMenu}
hubId={hubId}
>
{(config) => {
const { toggleDisplay, referenceProps } = config || {}

return (
<div
className={cx('relative flex flex-col')}
onContextMenu={(e) => {
e.preventDefault()
toggleDisplay?.(e)
}}
{...referenceProps}
id={messageBubbleId}
>
{extensions && extensions.length > 0 ? (
<ChatItemWithExtension
scrollToMessage={scrollToMessage}
message={message}
isMyMessage={isMyMessage}
chatId={chatId}
hubId={hubId}
enableProfileModal={enableProfileModal}
{(config) => (
<SuperLikeWrapper postId={messageId} withPostReward={false}>
{(props) => {
return (
<ChatItemMenuWrapper
config={config}
superLikeProps={props}
messageBubbleId={messageBubbleId}
disableSuperLike={disableSuperLike}
bg={bg}
showApproveButton={showApproveButton}
/>
) : (
<ChatItemContentVariant
message={message}
isMyMessage={isMyMessage}
scrollToMessage={scrollToMessage}
chatId={chatId}
enableProfileModal={enableProfileModal}
hubId={hubId}
disableSuperLike={disableSuperLike}
bg={bg}
/>
)}
</div>
)
}}
>
{extensions && extensions.length > 0 ? (
<ChatItemWithExtension
scrollToMessage={scrollToMessage}
message={message}
isMyMessage={isMyMessage}
chatId={chatId}
hubId={hubId}
disableSuperLike={disableSuperLike}
enableProfileModal={enableProfileModal}
bg={bg}
showApproveButton={showApproveButton}
/>
) : (
<ChatItemContentVariant
message={message}
isMyMessage={isMyMessage}
scrollToMessage={scrollToMessage}
disableSuperLike={disableSuperLike}
chatId={chatId}
enableProfileModal={enableProfileModal}
hubId={hubId}
bg={bg}
/>
)}
</ChatItemMenuWrapper>
)
}}
</SuperLikeWrapper>
)}
</ChatItemMenus>
</div>
{canRenderEmbed && (
Expand All @@ -141,3 +147,114 @@ export default function ChatItem({
</>
)
}

type ChatItemMenuWrapperProps = {
config?: Parameters<FloatingWrapperProps['children']>[0]
superLikeProps: {
hasILiked: boolean
isDisabled: boolean
disabledCause: string
superLikeCount: number
handleClick: () => void
postRewards?: PostRewards | undefined | null
}
children: React.ReactNode
disableSuperLike?: boolean
messageBubbleId?: string
}

const animateHeart = (x: number, y: number) => {
const container = document.getElementById('__next')
if (container) {
const like = document.createElement('img')

like.src = Thumbsup.src
like.classList.add('big-floating-like')

like.style.left = `${x - 50}px`
like.style.top = `${y - 50}px`

container.appendChild(like)

like.addEventListener(
'animationend',
() => {
like.remove()
},
{ once: true }
)
}
}

const ChatItemMenuWrapper = ({
config,
superLikeProps,
children,
messageBubbleId,
disableSuperLike,
}: ChatItemMenuWrapperProps) => {
const containerRef = useRef<HTMLDivElement>(null)
const { toggleDisplay, referenceProps } = config || {}
const haptic = useHapticFeedbackRaw(true)

const { hasILiked, isDisabled, handleClick } = superLikeProps

const onLongPress = useLongTouch(
(e) => {
if (isTouchDevice()) {
toggleDisplay?.(e)
}
},
{ delay: 500 },
{
startAnimation: () => {
if (containerRef.current) {
containerRef.current.classList.add('scale-section')

containerRef.current.addEventListener(
'animationend',
() => {
if (containerRef.current) {
containerRef.current.classList.remove('scale-section')
}
},
{ once: true }
)
}
},
endAnimation: () => {
if (containerRef.current) {
containerRef.current.classList.remove('scale-section')
}
},
}
)

return (
<div
ref={containerRef}
className={cx('relative flex flex-col')}
onContextMenu={(e) => {
if (!isTouchDevice()) {
e.preventDefault()
toggleDisplay?.(e)
}
}}
{...onLongPress}
onDoubleClick={(e) => {
e.preventDefault()
e.stopPropagation()

if (!isDisabled && !disableSuperLike && !hasILiked) {
haptic?.result?.impactOccurred('medium')
handleClick()
animateHeart(e.clientX, e.clientY)
}
}}
{...referenceProps}
id={messageBubbleId}
>
{children}
</div>
)
}
32 changes: 30 additions & 2 deletions src/components/chats/ChatItem/ChatItemMenus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ import MetadataModal from '@/components/modals/MetadataModal'
import ModerationModal from '@/components/moderation/ModerationModal'
import { sendEventWithRef } from '@/components/referral/analytics'
import useAuthorizedForModeration from '@/hooks/useAuthorizedForModeration'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import useIsOwnerOfPost from '@/hooks/useIsOwnerOfPost'
import useRerender from '@/hooks/useRerender'
import useToastError from '@/hooks/useToastError'
import { getPostQuery } from '@/services/api/query'
import { getSocialProfileQuery } from '@/services/datahub/identity/query'
import { useModerationActions } from '@/services/datahub/moderation/mutation'
import { getModerationReasonsQuery } from '@/services/datahub/moderation/query'
import { useApproveUser } from '@/services/datahub/posts/mutation'
import { usePinMessage } from '@/services/subsocial/posts/mutation'
import { useSendEvent } from '@/stores/analytics'
import { useChatMenu } from '@/stores/chat-menu'
Expand All @@ -32,6 +35,7 @@ import { ImageProperties, PostData } from '@subsocial/api/types'
import { SocialCallDataArgs } from '@subsocial/data-hub-sdk'
import { useEffect, useState } from 'react'
import { BsFillPinAngleFill } from 'react-icons/bs'
import { FaCheck } from 'react-icons/fa6'
import {
HiChevronRight,
HiMiniArrowUturnLeft,
Expand Down Expand Up @@ -73,7 +77,14 @@ export default function ChatItemMenus({

const { data: post } = getPostQuery.useQuery(messageId)
const ownerId = post?.struct.ownerId ?? ''
const { ref } = useInView({ triggerOnce: true })
const { ref, inView } = useInView({ triggerOnce: true })

const isAdmin = useIsModerationAdmin()
const { data: socialProfile, isLoading: loadingSocialProfile } =
getSocialProfileQuery.useQuery(ownerId, {
enabled: inView && isAdmin,
})
const { mutate: approveUser } = useApproveUser()

const { data: message } = getPostQuery.useQuery(messageId)
const [modalState, setModalState] = useState<ModalState>(null)
Expand Down Expand Up @@ -144,6 +155,22 @@ export default function ChatItemMenus({
})
},
})
if (
!loadingSocialProfile &&
!socialProfile?.allowedCreateCommentRootPostIds.includes(chatId)
) {
menus.unshift({
text: 'Approve User',
icon: FaCheck,
onClick: () => {
sendEvent('approve_user', { hubId, chatId })
approveUser({
address: ownerId,
allow: { createCommentRootPostIds: [chatId] },
})
},
})
}
}

if (isOptimisticMessage) return menus
Expand All @@ -160,6 +187,7 @@ export default function ChatItemMenus({
return (
<>
<FloatingMenus
preventOnClickOpen
beforeMenus={
!isOptimisticMessage && (
<SuperLikeWrapper postId={messageId} withPostReward={false}>
Expand Down Expand Up @@ -258,7 +286,7 @@ export default function ChatItemMenus({
>
{children}
</FloatingMenus>
<div ref={ref} className='absolute' />
<div ref={ref} />
{message && (
<MetadataModal
isOpen={modalState === 'metadata'}
Expand Down
Loading

0 comments on commit c1a7fc7

Please sign in to comment.