Add Leave chat button to settings for chat owners (#10764)
Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
@@ -58,7 +58,12 @@ import {InviteLinkDialog} from '../components/InviteLinkDialog'
|
||||
import {AddMembersLink} from './AddMembersLink'
|
||||
import {Member, MemberPlaceholder} from './Member'
|
||||
import {MembersAndRequests} from './MembersAndRequests'
|
||||
import {EditNamePrompt, LeaveChatPrompt, LockChatPrompt} from './prompts'
|
||||
import {
|
||||
EditNamePrompt,
|
||||
LeaveAndLockChatPrompt,
|
||||
LeaveChatPrompt,
|
||||
LockChatPrompt,
|
||||
} from './prompts'
|
||||
|
||||
type Item =
|
||||
| {type: 'MEMBERS_AND_REQUESTS'; key: string}
|
||||
@@ -374,33 +379,49 @@ function SettingsHeader({
|
||||
},
|
||||
)
|
||||
|
||||
const {mutate: lockConvo, isPending: isLocking} = useLockConvo(
|
||||
convo.view.id,
|
||||
{
|
||||
onSuccess: data => {
|
||||
if (!ChatBskyConvoDefs.isGroupConvo(data.convo.kind)) return
|
||||
if (data.convo.kind.lockStatus === 'locked') {
|
||||
Toast.show(l({message: 'Group chat locked', context: 'toast'}))
|
||||
} else {
|
||||
Toast.show(l({message: 'Group chat unlocked', context: 'toast'}))
|
||||
}
|
||||
},
|
||||
onError: (e, {lock}) => {
|
||||
if (lock) {
|
||||
logger.error('Failed to lock group chat', {message: e})
|
||||
Toast.show(l`Failed to lock group chat`, {type: 'error'})
|
||||
} else {
|
||||
logger.error('Failed to unlock group chat', {message: e})
|
||||
Toast.show(l`Failed to unlock group chat`, {type: 'error'})
|
||||
}
|
||||
},
|
||||
const {
|
||||
mutate: lockConvo,
|
||||
mutateAsync: lockConvoAsync,
|
||||
isPending: isLocking,
|
||||
} = useLockConvo(convo.view.id, {
|
||||
onSuccess: (data, {silent}) => {
|
||||
if (!ChatBskyConvoDefs.isGroupConvo(data.convo.kind)) return
|
||||
if (silent) return
|
||||
if (data.convo.kind.lockStatus === 'locked') {
|
||||
Toast.show(l({message: 'Group chat locked', context: 'toast'}))
|
||||
} else {
|
||||
Toast.show(l({message: 'Group chat unlocked', context: 'toast'}))
|
||||
}
|
||||
},
|
||||
)
|
||||
onError: (e, {lock}) => {
|
||||
if (lock) {
|
||||
logger.error('Failed to lock group chat', {message: e})
|
||||
Toast.show(l`Failed to lock group chat`, {type: 'error'})
|
||||
} else {
|
||||
logger.error('Failed to unlock group chat', {message: e})
|
||||
Toast.show(l`Failed to unlock group chat`, {type: 'error'})
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const leaveAndLockConvo = async () => {
|
||||
try {
|
||||
if (lockStatus === 'unlocked') {
|
||||
await lockConvoAsync({lock: true, silent: true})
|
||||
}
|
||||
} catch {
|
||||
// Handled by onError in useLockConvo
|
||||
return
|
||||
}
|
||||
// Owners can only leave a locked chat
|
||||
leaveConvo()
|
||||
}
|
||||
|
||||
const inviteLinkDialog = Dialog.useDialogControl()
|
||||
const editNamePrompt = Prompt.usePromptControl()
|
||||
const lockChatPrompt = Prompt.usePromptControl()
|
||||
const leaveChatPrompt = Prompt.usePromptControl()
|
||||
const leaveAndLockChatPrompt = Prompt.usePromptControl()
|
||||
const reportControl = Prompt.usePromptControl()
|
||||
const deleteControl = Prompt.usePromptControl()
|
||||
|
||||
@@ -452,6 +473,7 @@ function SettingsHeader({
|
||||
a.justify_center,
|
||||
a.gap_2xl,
|
||||
a.pt_2xl,
|
||||
a.flex_wrap,
|
||||
]}>
|
||||
<SettingsButton
|
||||
color={convo.view.muted ? 'negative_subtle' : 'secondary'}
|
||||
@@ -517,15 +539,15 @@ function SettingsHeader({
|
||||
onPress={reportControl.open}
|
||||
/>
|
||||
) : null}
|
||||
{!isOwner ? (
|
||||
<SettingsButton
|
||||
disabled={!isReady || isLeaving}
|
||||
icon={ArrowBoxLeftIcon}
|
||||
label={l`Leave this group chat`}
|
||||
text={l`Leave`}
|
||||
onPress={leaveChatPrompt.open}
|
||||
/>
|
||||
) : null}
|
||||
<SettingsButton
|
||||
disabled={!isReady || isLeaving || (isOwner && isLocking)}
|
||||
icon={ArrowBoxLeftIcon}
|
||||
label={l`Leave this group chat`}
|
||||
text={l`Leave`}
|
||||
onPress={
|
||||
isOwner ? leaveAndLockChatPrompt.open : leaveChatPrompt.open
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<EditNamePrompt
|
||||
@@ -552,6 +574,13 @@ function SettingsHeader({
|
||||
groupName={groupName}
|
||||
onConfirm={leaveConvo}
|
||||
/>
|
||||
<LeaveAndLockChatPrompt
|
||||
control={leaveAndLockChatPrompt}
|
||||
groupName={groupName}
|
||||
onConfirm={() => {
|
||||
void leaveAndLockConvo()
|
||||
}}
|
||||
/>
|
||||
{reportSubjectDid ? (
|
||||
<>
|
||||
<ReportConversationDialog
|
||||
@@ -610,6 +639,7 @@ function SettingsButton({
|
||||
</Button>
|
||||
<Text
|
||||
numberOfLines={1}
|
||||
maxFontSizeMultiplier={2.5}
|
||||
style={[
|
||||
a.text_xs,
|
||||
a.font_medium,
|
||||
|
||||
@@ -127,6 +127,30 @@ export function LeaveChatPrompt({
|
||||
)
|
||||
}
|
||||
|
||||
export function LeaveAndLockChatPrompt({
|
||||
control,
|
||||
groupName,
|
||||
onConfirm,
|
||||
}: {
|
||||
control: Dialog.DialogOuterProps['control']
|
||||
groupName: string
|
||||
onConfirm: () => void
|
||||
}) {
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<Prompt.Basic
|
||||
control={control}
|
||||
title={l`Are you sure you want to leave ${groupName}?`}
|
||||
description={l`Leaving this chat will lock it permanently and you won’t be able to rejoin.`}
|
||||
confirmButtonCta={l`Leave group chat`}
|
||||
confirmButtonColor="negative"
|
||||
cancelButtonCta={l`Cancel`}
|
||||
onConfirm={onConfirm}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function BlockMemberPrompt({
|
||||
control,
|
||||
onConfirm,
|
||||
|
||||
@@ -14,15 +14,21 @@ export function useLockConvo(
|
||||
onSuccess,
|
||||
onError,
|
||||
}: {
|
||||
onSuccess?: (data: ChatBskyConvoLockConvo.OutputSchema) => void
|
||||
onError?: (error: Error, variables: {lock: boolean}) => void
|
||||
onSuccess?: (
|
||||
data: ChatBskyConvoLockConvo.OutputSchema,
|
||||
variables: {lock: boolean; silent?: boolean},
|
||||
) => void
|
||||
onError?: (
|
||||
error: Error,
|
||||
variables: {lock: boolean; silent?: boolean},
|
||||
) => void
|
||||
},
|
||||
) {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({lock}: {lock: boolean}) => {
|
||||
mutationFn: async ({lock}: {lock: boolean; silent?: boolean}) => {
|
||||
if (!convoId) throw new Error('No convoId provided')
|
||||
if (lock) {
|
||||
const {data} = await agent.chat.bsky.convo.lockConvo(
|
||||
@@ -51,8 +57,8 @@ export function useLockConvo(
|
||||
}
|
||||
})
|
||||
},
|
||||
onSuccess: data => {
|
||||
onSuccess?.(data)
|
||||
onSuccess: (data, variables) => {
|
||||
onSuccess?.(data, variables)
|
||||
},
|
||||
onError: (e, variables, context) => {
|
||||
if (convoId && context) {
|
||||
|
||||
Reference in New Issue
Block a user