Skip to content

Commit

Permalink
Add approve message in chat menu
Browse files Browse the repository at this point in the history
  • Loading branch information
teodorus-nathaniel committed Jul 12, 2024
1 parent 2758da2 commit dcbfd42
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 7 deletions.
28 changes: 26 additions & 2 deletions src/components/chats/ChatItem/ChatItemMenus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ 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 +34,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 +76,12 @@ 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 { data: socialProfile, isLoading: loadingSocialProfile } =
getSocialProfileQuery.useQuery(ownerId, {
enabled: inView,
})
const { mutate: approveUser } = useApproveUser()

const { data: message } = getPostQuery.useQuery(messageId)
const [modalState, setModalState] = useState<ModalState>(null)
Expand Down Expand Up @@ -144,6 +152,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 Down Expand Up @@ -259,7 +283,7 @@ export default function ChatItemMenus({
>
{children}
</FloatingMenus>
<div ref={ref} className='absolute' />
<div ref={ref} />
{message && (
<MetadataModal
isOpen={modalState === 'metadata'}
Expand Down
14 changes: 14 additions & 0 deletions src/components/chats/UnapprovedUserChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { getSocialProfileQuery } from '@/services/datahub/identity/query'

export default function UnapprovedUserChip({
address,
chatId,
}: {
address: string
chatId: string
}) {
const { data, isLoading } = getSocialProfileQuery.useQuery(address)
if (isLoading || data?.allowedCreateCommentRootPostIds.includes(chatId))
return null
return <span></span>
}
11 changes: 8 additions & 3 deletions src/components/extensions/common/CommonChatItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import ChatRelativeTime from '@/components/chats/ChatItem/ChatRelativeTime'
import MessageStatusIndicator from '@/components/chats/ChatItem/MessageStatusIndicator'
import RepliedMessagePreview from '@/components/chats/ChatItem/RepliedMessagePreview'
import UnapprovedMemeCount from '@/components/chats/UnapprovedMemeCount'
import UnapprovedUserChip from '@/components/chats/UnapprovedUserChip'
import { getRepliedMessageId } from '@/components/chats/utils'
import SuperLike, {
SuperLikeButton,
} from '@/components/content-staking/SuperLike'
import useAuthorizedForModeration from '@/hooks/useAuthorizedForModeration'
import useIsMessageBlocked from '@/hooks/useIsMessageBlocked'
import useIsModerationAdmin from '@/hooks/useIsModerationAdmin'
import { getSuperLikeCountQuery } from '@/services/datahub/content-staking/query'
import { getModerationReasonsQuery } from '@/services/datahub/moderation/query'
import {
Expand Down Expand Up @@ -97,6 +99,7 @@ export default function CommonChatItem({
const relativeTime = getTimeRelativeToNow(createdAtTime)
const isSent = isMessageSent(message.id, dataType)

const isAdmin = useIsModerationAdmin()
const isMessageBlockedInCurrentHub = useIsMessageBlocked(
hubId,
message,
Expand Down Expand Up @@ -172,7 +175,7 @@ export default function CommonChatItem({
className={cx(
'absolute bottom-1.5 right-1.5 z-10 flex items-center gap-1 self-end rounded-full px-1.5 py-0.5',
(isMyMessageChildrenOnBottom || showApproveButton) && 'bg-black/45',
showApproveButton && 'bottom-16'
showApproveButton && 'bottom-14'
)}
>
{myMessageCheckMarkElement(
Expand Down Expand Up @@ -220,8 +223,7 @@ export default function CommonChatItem({
{!isMyMessage && (
<div
className={cx(
'flex items-baseline gap-2 overflow-hidden px-2.5 first:pt-1.5',
othersMessage.checkMark !== 'top' && 'justify-between'
'flex items-baseline gap-2 overflow-hidden px-2.5 first:pt-1.5'
)}
ref={ref}
>
Expand All @@ -238,6 +240,9 @@ export default function CommonChatItem({
className={cx('text-sm font-medium text-text-secondary')}
/>
{/* <SubTeamLabel address={ownerId} /> */}
{inView && isAdmin && (
<UnapprovedUserChip chatId={chatId} address={ownerId} />
)}
{othersMessage.checkMark === 'top' &&
otherMessageCheckMarkElement()}
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/services/datahub/events/subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
SubscribeEventsSubscription,
SubscribeEventsSubscriptionVariables,
} from '../generated-query'
import { getSocialProfileQuery } from '../identity/query'
import { callIdToPostIdMap } from '../posts/mutation'
import { getProfileQuery } from '../profiles/query'
import { getGamificationTasksErrorQuery } from '../tasks/query'
Expand Down Expand Up @@ -224,6 +225,10 @@ async function processSubscriptionEvent(
}`}
/>
))
getSocialProfileQuery.invalidate(
client,
eventData.meta.extension?.updatedCreatorAddress
)
return
}

Expand Down
30 changes: 29 additions & 1 deletion src/services/datahub/generated-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ export type Post = {
activeStakingSuperLikes?: Maybe<Array<ActiveStakingSuperLike>>
activeStakingSuperLikesCount?: Maybe<Scalars['Int']['output']>
approvedInRootPost: Scalars['Boolean']['output']
approvedInRootPostAtTime?: Maybe<Scalars['DateTime']['output']>
/** is off-chain data CID backed up in blockchain */
backupInBlockchain?: Maybe<Scalars['Boolean']['output']>
blockchainSyncFailed: Scalars['Boolean']['output']
Expand Down Expand Up @@ -1555,6 +1556,7 @@ export enum SocialCallName {
SynthModerationForceUnblockResource = 'synth_moderation_force_unblock_resource',
SynthModerationInitModerator = 'synth_moderation_init_moderator',
SynthModerationUnblockResource = 'synth_moderation_unblock_resource',
SynthSetPostApproveStatus = 'synth_set_post_approve_status',
SynthSocialProfileAddReferrerId = 'synth_social_profile_add_referrer_id',
SynthSocialProfileSetActionPermissions = 'synth_social_profile_set_action_permissions',
SynthUpdatePostTxFailed = 'synth_update_post_tx_failed',
Expand Down Expand Up @@ -2290,6 +2292,22 @@ export type GetLinkedIdentitiesFromProviderIdQuery = {
} | null
}

export type GetSocialProfileQueryVariables = Exact<{
addresses: Array<Scalars['String']['input']> | Scalars['String']['input']
}>

export type GetSocialProfileQuery = {
__typename?: 'Query'
socialProfiles: {
__typename?: 'SocialProfilesResponse'
data: Array<{
__typename?: 'SocialProfile'
id: string
allowedCreateCommentRootPostIds: Array<string>
}>
}
}

export type SubscribeIdentitySubscriptionVariables = Exact<{
[key: string]: never
}>
Expand Down Expand Up @@ -3287,6 +3305,16 @@ export const GetLinkedIdentitiesFromProviderId = gql`
}
}
`
export const GetSocialProfile = gql`
query GetSocialProfile($addresses: [String!]!) {
socialProfiles(args: { where: { substrateAddresses: $addresses } }) {
data {
id
allowedCreateCommentRootPostIds
}
}
}
`
export const SubscribeIdentity = gql`
subscription SubscribeIdentity {
linkedIdentitySubscription {
Expand Down Expand Up @@ -3632,7 +3660,7 @@ export const GetUnapprovedMemesCount = gql`
posts(
args: {
filter: {
createdAtTimeGt: "2024-07-10T16:17:49.243Z"
createdAtTimeGt: "2024-07-10T17:37:35.000Z"
createdByAccountAddress: $address
rootPostId: $postId
}
Expand Down
47 changes: 46 additions & 1 deletion src/services/datahub/identity/query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { apiInstance } from '@/services/api/utils'
import { useMyAccount } from '@/stores/my-account'
import { createQuery } from '@/subsocial-query'
import { createQuery, poolQuery } from '@/subsocial-query'
import { LocalStorage } from '@/utils/storage'
import { parseJSONData } from '@/utils/strings'
import { gql } from 'graphql-request'
import {
GetSocialProfileQuery,
GetSocialProfileQueryVariables,
} from '../generated-query'
import { datahubQueryRequest } from '../utils'
import { getLinkedIdentity } from './fetcher'

// NOTE: need to be careful when changing the structure of these cached data, because it can cause the app to crash if you access unavailable data
Expand Down Expand Up @@ -53,3 +59,42 @@ export const getEvmLinkedIdentityMessageQuery = createQuery({
retry: false,
}),
})

const GET_SOCIAL_PROFILE = gql`
query GetSocialProfile($addresses: [String!]!) {
socialProfiles(args: { where: { substrateAddresses: $addresses } }) {
data {
id
allowedCreateCommentRootPostIds
}
}
}
`
const getSocialProfile = poolQuery<
string,
{ id: string; allowedCreateCommentRootPostIds: string[] }
>({
name: 'getSocialProfile',
multiCall: async (addresses) => {
const data = await datahubQueryRequest<
GetSocialProfileQuery,
GetSocialProfileQueryVariables
>({
document: GET_SOCIAL_PROFILE,
variables: { addresses },
})

return data.socialProfiles.data
},
resultMapper: {
paramToKey: (address) => address,
resultToKey: (result) => result.id || '',
},
})
export const getSocialProfileQuery = createQuery({
key: 'getSocialProfile',
fetcher: (address: string) => getSocialProfile(address),
defaultConfigGenerator: (data) => ({
enabled: !!data,
}),
})

0 comments on commit dcbfd42

Please sign in to comment.