Disable group convos when owner has chats disabled

Show a compact "owner suspended" footer in place of the composer when
a group's owner has been chat-disabled. Self-disabled state is
unchanged (still shows ChatDisabled with the appeal flow).

Closes APP-2216

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-05-19 16:31:49 +03:00
parent b47948dca7
commit 543cbe328c
2 changed files with 75 additions and 1 deletions
+4 -1
View File
@@ -49,6 +49,7 @@ import {ChatDisabled} from './components/ChatDisabled'
import {ChatEnded} from './components/ChatEnded' import {ChatEnded} from './components/ChatEnded'
import {ChatLocked} from './components/ChatLocked' import {ChatLocked} from './components/ChatLocked'
import {RequestStatus} from './components/RequestStatus' import {RequestStatus} from './components/RequestStatus'
import {GroupOwnerChatDisabled} from './components/GroupOwnerChatDisabled'
type Props = NativeStackScreenProps< type Props = NativeStackScreenProps<
CommonNavigatorParams, CommonNavigatorParams,
@@ -250,7 +251,9 @@ function InnerReady({
/> />
) )
} else if (convo?.kind === 'group') { } else if (convo?.kind === 'group') {
if (convo.details.lockStatus === 'locked') { if (convo.primaryMember?.chatDisabled) {
footer = <GroupOwnerChatDisabled convo={convo} />
} else if (convo.details.lockStatus === 'locked') {
footer = <ChatLocked convo={convo} /> footer = <ChatLocked convo={convo} />
} else if (convo.details.lockStatus === 'locked-permanently') { } else if (convo.details.lockStatus === 'locked-permanently') {
footer = <ChatEnded convo={convo} /> footer = <ChatEnded convo={convo} />
@@ -0,0 +1,71 @@
import {Pressable} from 'react-native'
import {Trans, useLingui} from '@lingui/react/macro'
import {StackActions, useNavigation} from '@react-navigation/native'
import {HITSLOP_10} from '#/lib/constants'
import {type NavigationProp} from '#/lib/routes/types'
import {logger} from '#/logger'
import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
import {atoms as a, useTheme} from '#/alf'
import {type ConvoWithDetails} from '#/components/dms/util'
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
import * as Prompt from '#/components/Prompt'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
import {LeaveChatPrompt} from '../ConversationSettings/prompts'
import {ChatFooter} from './ChatFooter'
export function GroupOwnerChatDisabled({
convo,
}: {
convo: Extract<ConvoWithDetails, {kind: 'group'}>
}) {
const t = useTheme()
const {t: l} = useLingui()
const leaveChatPrompt = Prompt.usePromptControl()
const navigation = useNavigation<NavigationProp>()
const {mutate: leaveConvo} = useLeaveConvo(convo.view.id, {
onSuccess: () => {
navigation.dispatch(StackActions.pop(2))
},
onError: e => {
logger.error('Failed to leave group chat', {message: e})
Toast.show(l({message: 'Failed to leave group chat', context: 'toast'}), {
type: 'error',
})
},
})
return (
<ChatFooter
heading={l`This chat is unavailable`}
subheading={l`The group owner has been suspended`}
icon={WarningIcon}>
<Pressable
accessibilityRole="button"
hitSlop={HITSLOP_10}
style={[a.mx_md]}
onPress={leaveChatPrompt.open}>
<Text
numberOfLines={1}
style={[
a.text_sm,
a.font_semi_bold,
a.leading_snug,
{
color: t.palette.negative_500,
},
]}>
<Trans>Leave chat</Trans>
</Text>
</Pressable>
<LeaveChatPrompt
control={leaveChatPrompt}
groupName={convo.details.name}
onConfirm={leaveConvo}
/>
</ChatFooter>
)
}