Add ability to remove members from a group clip clop (#10287)
This commit is contained in:
@@ -21,12 +21,13 @@ import {ConvoProvider, useConvo} from '#/state/messages/convo'
|
||||
import {ConvoStatus} from '#/state/messages/convo/types'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useAddGroupMembers} from '#/state/queries/messages/add-group-members'
|
||||
import {useEditGroupName} from '#/state/queries/messages/edit-group-name'
|
||||
import {useEditGroupChatName} from '#/state/queries/messages/edit-group-chat-name'
|
||||
import {useGetConvoAvailabilityQuery} from '#/state/queries/messages/get-convo-availability'
|
||||
import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members'
|
||||
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
|
||||
import {useListJoinRequestsQuery} from '#/state/queries/messages/list-join-requests'
|
||||
import {useMuteConvo} from '#/state/queries/messages/mute-conversation'
|
||||
import {useRemoveFromGroupChat} from '#/state/queries/messages/remove-from-group'
|
||||
import {useProfileBlockMutationQueue} from '#/state/queries/profile'
|
||||
import {useSession} from '#/state/session'
|
||||
import {List} from '#/view/com/util/List'
|
||||
@@ -189,6 +190,7 @@ function SettingsInner({convoId}: {convoId: string}) {
|
||||
case 'CHAT_MEMBER':
|
||||
return (
|
||||
<Member
|
||||
convo={convo}
|
||||
profile={item.profile}
|
||||
status={item.status}
|
||||
isOwner={isOwner}
|
||||
@@ -391,10 +393,12 @@ function AddMembersLink({
|
||||
}
|
||||
|
||||
function Member({
|
||||
convo,
|
||||
profile,
|
||||
status,
|
||||
isOwner,
|
||||
}: {
|
||||
convo: ConvoWithDetails | null
|
||||
profile: Shadow<bsky.profile.AnyProfileView>
|
||||
status: 'owner' | 'standard' | 'invited'
|
||||
isOwner: boolean
|
||||
@@ -429,9 +433,14 @@ function Member({
|
||||
break
|
||||
}
|
||||
} else {
|
||||
statusBadge = (
|
||||
<MemberMenu profile={profile} type={status} isOwner={isOwner} />
|
||||
)
|
||||
statusBadge = convo ? (
|
||||
<MemberMenu
|
||||
convo={convo}
|
||||
profile={profile}
|
||||
type={status}
|
||||
isOwner={isOwner}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -537,10 +546,12 @@ function StatusButton({
|
||||
}
|
||||
|
||||
function MemberMenu({
|
||||
convo,
|
||||
profile,
|
||||
type,
|
||||
isOwner,
|
||||
}: {
|
||||
convo: ConvoWithDetails
|
||||
profile: Shadow<bsky.profile.AnyProfileView>
|
||||
type: 'owner' | 'standard' | 'invited'
|
||||
isOwner: boolean
|
||||
@@ -564,6 +575,13 @@ function MemberMenu({
|
||||
Toast.show(l`Failed to create conversation`)
|
||||
},
|
||||
})
|
||||
const convoId = convo?.view.id
|
||||
const {mutate: removeMembers} = useRemoveFromGroupChat(convoId, {
|
||||
onError: e => {
|
||||
logger.error('Failed to remove group chat member', {message: e})
|
||||
Toast.show(l`Failed to remove group chat member`)
|
||||
},
|
||||
})
|
||||
const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
|
||||
|
||||
const messageMember = () => {
|
||||
@@ -714,7 +732,7 @@ function MemberMenu({
|
||||
{isOwner ? (
|
||||
<Menu.Item
|
||||
label={l`Remove ${displayName} from this group chat`}
|
||||
onPress={() => {}}>
|
||||
onPress={() => removeMembers({members: [profile.did]})}>
|
||||
<Menu.ItemText>
|
||||
<Trans>Remove from chat</Trans>
|
||||
</Menu.ItemText>
|
||||
@@ -759,7 +777,7 @@ function SettingsHeader({
|
||||
|
||||
const [isLocked, setIsLocked] = useState(false)
|
||||
|
||||
const {mutate: editGroupName} = useEditGroupName(convo.view.id, {
|
||||
const {mutate: editGroupName} = useEditGroupChatName(convo.view.id, {
|
||||
onError: e => {
|
||||
setNewGroupName(groupName)
|
||||
logger.error('Failed to edit group chat name', {message: e})
|
||||
|
||||
@@ -116,11 +116,11 @@ export function ConvoProvider({
|
||||
switch (event.type) {
|
||||
case 'invalidate-block-state': {
|
||||
for (const did of event.accountDids) {
|
||||
queryClient.invalidateQueries({
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: createProfileQueryKey(did),
|
||||
})
|
||||
}
|
||||
queryClient.invalidateQueries({
|
||||
void queryClient.invalidateQueries({
|
||||
queryKey: [ListConvosQueryKeyRoot],
|
||||
})
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import {useAgent} from '#/state/session'
|
||||
import {RQKEY as CONVO_KEY} from './conversation'
|
||||
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
|
||||
|
||||
export function useEditGroupName(
|
||||
export function useEditGroupChatName(
|
||||
convoId: string | undefined,
|
||||
{
|
||||
onSuccess,
|
||||
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
type ChatBskyConvoDefs,
|
||||
type ChatBskyConvoListConvos,
|
||||
type ChatBskyGroupRemoveMembers,
|
||||
} from '@atproto/api'
|
||||
import {
|
||||
type InfiniteData,
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
||||
import {logger} from '#/logger'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {RQKEY as CONVO_KEY} from './conversation'
|
||||
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
|
||||
|
||||
export function useRemoveFromGroupChat(
|
||||
convoId: string | undefined,
|
||||
{
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: (data: ChatBskyGroupRemoveMembers.OutputSchema) => void
|
||||
onError?: (error: Error) => void
|
||||
},
|
||||
) {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({members}: {members: string[]}) => {
|
||||
if (!convoId) throw new Error('No convoId provided')
|
||||
const {data} = await agent.chat.bsky.group.removeMembers(
|
||||
{convoId, members},
|
||||
{headers: DM_SERVICE_HEADERS, encoding: 'application/json'},
|
||||
)
|
||||
return data
|
||||
},
|
||||
onMutate: ({members}) => {
|
||||
if (!convoId) return
|
||||
|
||||
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
|
||||
CONVO_KEY(convoId),
|
||||
)
|
||||
const prevListEntries = queryClient.getQueriesData<
|
||||
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
|
||||
>({queryKey: [CONVO_LIST_KEY]})
|
||||
|
||||
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
|
||||
CONVO_KEY(convoId),
|
||||
prev => {
|
||||
if (!prev) return
|
||||
return {
|
||||
...prev,
|
||||
members: prev.members.filter(m => !members.includes(m.did)),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
queryClient.setQueriesData<
|
||||
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
|
||||
>({queryKey: [CONVO_LIST_KEY]}, prev => {
|
||||
if (!prev?.pages) return
|
||||
return {
|
||||
...prev,
|
||||
pages: prev.pages.map(page => ({
|
||||
...page,
|
||||
convos: page.convos.map(convo => {
|
||||
if (convo.id !== convoId) return convo
|
||||
return {
|
||||
...convo,
|
||||
members: convo.members.filter(m => !members.includes(m.did)),
|
||||
}
|
||||
}),
|
||||
})),
|
||||
}
|
||||
})
|
||||
|
||||
return {prevConvo, prevListEntries}
|
||||
},
|
||||
onSuccess: data => {
|
||||
onSuccess?.(data)
|
||||
},
|
||||
onError: (e, _variables, context) => {
|
||||
logger.error(e)
|
||||
if (context?.prevConvo && convoId) {
|
||||
queryClient.setQueryData(CONVO_KEY(convoId), context.prevConvo)
|
||||
}
|
||||
if (context?.prevListEntries) {
|
||||
for (const [key, data] of context.prevListEntries) {
|
||||
queryClient.setQueryData(key, data)
|
||||
}
|
||||
}
|
||||
onError?.(e)
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user