Use convo view instead of convo state for driving the UI (#10290)
This commit is contained in:
@@ -2,6 +2,7 @@ import {useMemo} from 'react'
|
||||
import {View} from 'react-native'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
ChatBskyConvoDefs,
|
||||
type ModerationCause,
|
||||
type ModerationDecision,
|
||||
} from '@atproto/api'
|
||||
@@ -11,14 +12,7 @@ import {useNavigation} from '@react-navigation/native'
|
||||
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {logger} from '#/logger'
|
||||
import {type Shadow} from '#/state/cache/profile-shadow'
|
||||
import {
|
||||
type ActiveConvoStates,
|
||||
isConvoActive,
|
||||
useConvo,
|
||||
} from '#/state/messages/convo'
|
||||
import {type ConvoItem} from '#/state/messages/convo/types'
|
||||
import {useSession} from '#/state/session'
|
||||
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
@@ -32,20 +26,22 @@ import {Link} from '#/components/Link'
|
||||
import {ProfileBadges} from '#/components/ProfileBadges'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {IS_LIQUID_GLASS, IS_WEB} from '#/env'
|
||||
import {type ConvoWithDetails} from './util'
|
||||
|
||||
const PFP_SIZE = IS_WEB ? 40 : Layout.HEADER_SLOT_SIZE
|
||||
|
||||
export function MessagesListHeader({
|
||||
convo,
|
||||
profile,
|
||||
moderation,
|
||||
}: {
|
||||
convo?: ConvoWithDetails | null
|
||||
profile?: Shadow<AppBskyActorDefs.ProfileViewDetailed>
|
||||
moderation?: ModerationDecision | null
|
||||
}) {
|
||||
const t = useTheme()
|
||||
|
||||
const convoState = useConvo()
|
||||
const isGroupChat = convoState?.isGroup?.()
|
||||
const isGroupChat = convo?.kind === 'group'
|
||||
|
||||
const blockInfo = useMemo(() => {
|
||||
if (!moderation) return
|
||||
@@ -65,17 +61,17 @@ export function MessagesListHeader({
|
||||
<View style={[{minHeight: PFP_SIZE}, a.justify_center]}>
|
||||
<Layout.Header.BackButton />
|
||||
</View>
|
||||
{isConvoActive(convoState) ? (
|
||||
{convo ? (
|
||||
moderation && blockInfo && profile && !isGroupChat ? (
|
||||
<ProfileHeaderReady
|
||||
convoState={convoState}
|
||||
convo={convo}
|
||||
profile={profile}
|
||||
moderation={moderation}
|
||||
blockInfo={blockInfo}
|
||||
/>
|
||||
) : (
|
||||
<GroupHeaderReady
|
||||
convoState={convoState}
|
||||
convo={convo}
|
||||
profile={profile}
|
||||
moderation={moderation}
|
||||
/>
|
||||
@@ -111,12 +107,12 @@ export function MessagesListHeader({
|
||||
}
|
||||
|
||||
function ProfileHeaderReady({
|
||||
convoState,
|
||||
convo,
|
||||
profile,
|
||||
moderation,
|
||||
blockInfo,
|
||||
}: {
|
||||
convoState: ActiveConvoStates
|
||||
convo: ConvoWithDetails
|
||||
profile: Shadow<AppBskyActorDefs.ProfileViewDetailed>
|
||||
moderation: ModerationDecision
|
||||
blockInfo: {
|
||||
@@ -132,15 +128,10 @@ function ProfileHeaderReady({
|
||||
? l`Deleted Account`
|
||||
: createSanitizedDisplayName(profile, true, moderation.ui('displayName'))
|
||||
|
||||
const latestMessageFromOther = convoState.items.findLast(
|
||||
(item: ConvoItem) =>
|
||||
item.type === 'message' &&
|
||||
item.message.sender.did !== currentAccount?.did,
|
||||
)
|
||||
|
||||
const latestReportableMessage =
|
||||
latestMessageFromOther?.type === 'message'
|
||||
? latestMessageFromOther.message
|
||||
ChatBskyConvoDefs.isMessageView(convo.view.lastMessage) &&
|
||||
convo.view.lastMessage.sender?.did !== currentAccount?.did
|
||||
? convo.view.lastMessage
|
||||
: undefined
|
||||
|
||||
return (
|
||||
@@ -164,28 +155,26 @@ function ProfileHeaderReady({
|
||||
</View>
|
||||
</Link>
|
||||
}
|
||||
muted={convoState.convo?.muted}
|
||||
muted={convo.view.muted}
|
||||
settings={
|
||||
isConvoActive(convoState) ? (
|
||||
<ConvoMenu
|
||||
convo={convoState.convo}
|
||||
profile={profile}
|
||||
currentScreen="conversation"
|
||||
blockInfo={blockInfo}
|
||||
latestReportableMessage={latestReportableMessage}
|
||||
/>
|
||||
) : null
|
||||
<ConvoMenu
|
||||
convo={convo.view}
|
||||
profile={profile}
|
||||
currentScreen="conversation"
|
||||
blockInfo={blockInfo}
|
||||
latestReportableMessage={latestReportableMessage}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function GroupHeaderReady({
|
||||
convoState,
|
||||
convo,
|
||||
profile,
|
||||
moderation,
|
||||
}: {
|
||||
convoState: ActiveConvoStates
|
||||
convo: ConvoWithDetails
|
||||
profile?: Shadow<AppBskyActorDefs.ProfileViewDetailed>
|
||||
moderation?: ModerationDecision | null
|
||||
}) {
|
||||
@@ -193,7 +182,7 @@ function GroupHeaderReady({
|
||||
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
|
||||
const groupInfo = convoState.getGroupInfo?.()
|
||||
const groupInfo = convo.kind === 'group' ? convo.details : undefined
|
||||
|
||||
const isDeletedAccount = profile?.handle === 'missing.invalid'
|
||||
const displayName = isDeletedAccount
|
||||
@@ -206,40 +195,33 @@ function GroupHeaderReady({
|
||||
(displayName ? l`${displayName}’s group chat` : l`Group chat`)
|
||||
|
||||
const handleNavigateToSettings = () => {
|
||||
const convoId = convoState.convo?.id
|
||||
if (convoId) {
|
||||
navigation.navigate('MessagesConversationSettings', {
|
||||
conversation: convoId,
|
||||
})
|
||||
} else {
|
||||
logger.error(`handleNavigateToSettings: missing convo ID`)
|
||||
}
|
||||
navigation.navigate('MessagesConversationSettings', {
|
||||
conversation: convo.view.id,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
heading={
|
||||
<>
|
||||
<AvatarBubbles size="small" profiles={convoState.recipients ?? []} />
|
||||
<AvatarBubbles size="small" profiles={convo.members} />
|
||||
<Text style={[a.text_md, a.font_semi_bold]} numberOfLines={1}>
|
||||
{groupName}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
muted={convoState.convo?.muted}
|
||||
muted={convo.view.muted}
|
||||
settings={
|
||||
isConvoActive(convoState) ? (
|
||||
<Button
|
||||
label={l`Open group chat settings`}
|
||||
size="small"
|
||||
color="secondary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
style={[a.bg_transparent]}
|
||||
onPress={handleNavigateToSettings}>
|
||||
<ButtonIcon icon={DotsHorizontalIcon} size="md" />
|
||||
</Button>
|
||||
) : null
|
||||
<Button
|
||||
label={l`Open group chat settings`}
|
||||
size="small"
|
||||
color="secondary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
style={[a.bg_transparent]}
|
||||
onPress={handleNavigateToSettings}>
|
||||
<ButtonIcon icon={DotsHorizontalIcon} size="md" />
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -35,6 +35,7 @@ import {ConvoStatus} from '#/state/messages/convo/types'
|
||||
import {useCurrentConvoId} from '#/state/messages/current-convo-id'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {MessagesList} from '#/screens/Messages/components/MessagesList'
|
||||
import {atoms as a, useTheme, web} from '#/alf'
|
||||
@@ -46,6 +47,7 @@ import {
|
||||
} from '#/components/dialogs/EmailDialog'
|
||||
import {MessagesListBlockedFooter} from '#/components/dms/MessagesListBlockedFooter'
|
||||
import {MessagesListHeader} from '#/components/dms/MessagesListHeader'
|
||||
import {type ConvoWithDetails, parseConvoView} from '#/components/dms/util'
|
||||
import {Error} from '#/components/Error'
|
||||
import * as Layout from '#/components/Layout'
|
||||
import {Loader} from '#/components/Loader'
|
||||
@@ -104,9 +106,14 @@ function Inner() {
|
||||
const t = useTheme()
|
||||
const convoState = useConvo()
|
||||
const {_} = useLingui()
|
||||
const {currentAccount} = useSession()
|
||||
const isFocused = useIsFocused()
|
||||
const {top: topInset} = useSafeAreaInsets()
|
||||
|
||||
const convo = convoState.convo
|
||||
? parseConvoView(convoState.convo, currentAccount?.did)
|
||||
: null
|
||||
|
||||
const moderationOpts = useModerationOpts()
|
||||
const {data: recipientUnshadowed} = useProfileQuery({
|
||||
did: convoState.getPrimaryMember?.()?.did,
|
||||
@@ -144,9 +151,13 @@ function Inner() {
|
||||
<Layout.Center
|
||||
style={[a.w_full, IS_LIQUID_GLASS && {paddingTop: topInset}]}>
|
||||
{moderation ? (
|
||||
<MessagesListHeader profile={recipient} moderation={moderation} />
|
||||
<MessagesListHeader
|
||||
convo={convo}
|
||||
profile={recipient}
|
||||
moderation={moderation}
|
||||
/>
|
||||
) : (
|
||||
<MessagesListHeader />
|
||||
<MessagesListHeader convo={convo} />
|
||||
)}
|
||||
</Layout.Center>
|
||||
<Error
|
||||
@@ -166,9 +177,13 @@ function Inner() {
|
||||
{!readyToShow && (
|
||||
<View style={IS_LIQUID_GLASS && {paddingTop: topInset}}>
|
||||
{moderation ? (
|
||||
<MessagesListHeader profile={recipient} moderation={moderation} />
|
||||
<MessagesListHeader
|
||||
convo={convo}
|
||||
profile={recipient}
|
||||
moderation={moderation}
|
||||
/>
|
||||
) : (
|
||||
<MessagesListHeader />
|
||||
<MessagesListHeader convo={convo} />
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
@@ -178,6 +193,9 @@ function Inner() {
|
||||
recipient={recipient}
|
||||
hasScrolled={hasScrolled}
|
||||
setHasScrolled={setHasScrolled}
|
||||
convo={convo}
|
||||
isActive={isConvoActive(convoState)}
|
||||
hasMessages={isConvoActive(convoState) && convoState.items.length > 0}
|
||||
/>
|
||||
{!readyToShow && (
|
||||
<View
|
||||
@@ -205,13 +223,18 @@ function InnerReady({
|
||||
recipient,
|
||||
hasScrolled,
|
||||
setHasScrolled,
|
||||
convo,
|
||||
isActive,
|
||||
hasMessages,
|
||||
}: {
|
||||
moderation: ModerationDecision | null
|
||||
recipient: Shadow<AppBskyActorDefs.ProfileViewDetailed> | undefined
|
||||
hasScrolled: boolean
|
||||
setHasScrolled: React.Dispatch<React.SetStateAction<boolean>>
|
||||
convo: ConvoWithDetails | null
|
||||
isActive: boolean
|
||||
hasMessages: boolean
|
||||
}) {
|
||||
const convoState = useConvo()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {top: topInset} = useSafeAreaInsets()
|
||||
const [headerHeight, setHeaderHeight] = useState(0)
|
||||
@@ -262,7 +285,11 @@ function InnerReady({
|
||||
}, [maybeBlockForEmailVerification])
|
||||
|
||||
const header = (
|
||||
<MessagesListHeader profile={recipient} moderation={moderation} />
|
||||
<MessagesListHeader
|
||||
convo={convo}
|
||||
profile={recipient}
|
||||
moderation={moderation}
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
@@ -277,7 +304,7 @@ function InnerReady({
|
||||
) : (
|
||||
header
|
||||
)}
|
||||
{isConvoActive(convoState) && (
|
||||
{isActive && (
|
||||
<MessagesList
|
||||
hasScrolled={hasScrolled}
|
||||
setHasScrolled={setHasScrolled}
|
||||
@@ -285,11 +312,11 @@ function InnerReady({
|
||||
hasAcceptOverride={!!params.accept}
|
||||
transparentHeaderHeight={IS_LIQUID_GLASS ? headerHeight : 0}
|
||||
footer={
|
||||
moderation && recipient ? (
|
||||
moderation && recipient && convo ? (
|
||||
<MessagesListBlockedFooter
|
||||
recipient={recipient}
|
||||
convoId={convoState.convo.id}
|
||||
hasMessages={convoState.items.length > 0}
|
||||
convoId={convo.view.id}
|
||||
hasMessages={hasMessages}
|
||||
moderation={moderation}
|
||||
/>
|
||||
) : null
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {useMemo, useState} from 'react'
|
||||
import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native'
|
||||
import {type ChatBskyConvoDefs, moderateProfile} from '@atproto/api'
|
||||
import {moderateProfile} from '@atproto/api'
|
||||
import {plural} from '@lingui/core/macro'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
import {StackActions, useNavigation} from '@react-navigation/native'
|
||||
@@ -34,6 +34,7 @@ import {AvatarBubbles} from '#/components/AvatarBubbles'
|
||||
import {Button, type ButtonColor, ButtonIcon} from '#/components/Button'
|
||||
import * as Dialog from '#/components/Dialog'
|
||||
import {AddMembersFlow} from '#/components/dms/AddMembersFlow'
|
||||
import {type ConvoWithDetails, parseConvoView} from '#/components/dms/util'
|
||||
import {Error} from '#/components/Error'
|
||||
import * as TextField from '#/components/forms/TextField'
|
||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||
@@ -126,9 +127,14 @@ function SettingsInner() {
|
||||
|
||||
const convoState = useConvo()
|
||||
const {currentAccount} = useSession()
|
||||
const primaryMember = convoState?.getPrimaryMember?.()
|
||||
|
||||
const data: bsky.profile.AnyProfileView[] = convoState.convo?.members ?? []
|
||||
const convo = convoState.convo
|
||||
? parseConvoView(convoState.convo, currentAccount?.did)
|
||||
: null
|
||||
const primaryMember = convo?.primaryMember
|
||||
const isOwner = !!primaryMember && primaryMember.did === currentAccount?.did
|
||||
|
||||
const data: bsky.profile.AnyProfileView[] = convo?.members ?? []
|
||||
const invites: string[] = []
|
||||
|
||||
const items = [
|
||||
@@ -163,11 +169,23 @@ function SettingsInner() {
|
||||
function renderItem({item}: {item: Item}) {
|
||||
switch (item.type) {
|
||||
case 'MEMBERS_AND_REQUESTS':
|
||||
return <MembersAndRequests memberCount={data.length} requestCount={5} />
|
||||
return (
|
||||
<MembersAndRequests
|
||||
memberCount={data.length}
|
||||
requestCount={5}
|
||||
isOwner={isOwner}
|
||||
/>
|
||||
)
|
||||
case 'ADD_MEMBERS_LINK':
|
||||
return <AddMembersLink />
|
||||
return <AddMembersLink isOwner={isOwner} />
|
||||
case 'CHAT_MEMBER':
|
||||
return <Member profile={item.profile} status={item.status} />
|
||||
return (
|
||||
<Member
|
||||
profile={item.profile}
|
||||
status={item.status}
|
||||
isOwner={isOwner}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
return null
|
||||
}
|
||||
@@ -194,8 +212,8 @@ function SettingsInner() {
|
||||
initialNumToRender={initialNumToRender}
|
||||
keyExtractor={keyExtractor}
|
||||
ListHeaderComponent={
|
||||
convoState.convo ? (
|
||||
<SettingsHeader convo={convoState.convo} profiles={data} />
|
||||
convo ? (
|
||||
<SettingsHeader convo={convo} isOwner={isOwner} />
|
||||
) : (
|
||||
<SettingsHeaderPlaceholder />
|
||||
)
|
||||
@@ -211,21 +229,15 @@ function SettingsInner() {
|
||||
function MembersAndRequests({
|
||||
memberCount,
|
||||
requestCount,
|
||||
isOwner,
|
||||
}: {
|
||||
memberCount: number
|
||||
requestCount: number
|
||||
isOwner: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const convoState = useConvo()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const isOwner =
|
||||
currentAccount?.did == null
|
||||
? false
|
||||
: convoState.getPrimaryMember?.()?.did === currentAccount.did
|
||||
|
||||
return (
|
||||
<View style={[a.flex_row, a.justify_between, a.mx_xl, a.mt_lg, a.mb_sm]}>
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
@@ -254,20 +266,12 @@ function MembersAndRequests({
|
||||
)
|
||||
}
|
||||
|
||||
function AddMembersLink() {
|
||||
function AddMembersLink({isOwner}: {isOwner: boolean}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const convoState = useConvo()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const addMembersControl = Dialog.useDialogControl()
|
||||
|
||||
const isOwner =
|
||||
currentAccount?.did == null
|
||||
? false
|
||||
: convoState.getPrimaryMember?.()?.did === currentAccount.did
|
||||
|
||||
if (!isOwner) {
|
||||
return null
|
||||
}
|
||||
@@ -354,9 +358,11 @@ function AddMembersLink() {
|
||||
function Member({
|
||||
profile,
|
||||
status,
|
||||
isOwner,
|
||||
}: {
|
||||
profile: Shadow<bsky.profile.AnyProfileView>
|
||||
status: 'owner' | 'member' | 'invited'
|
||||
isOwner: boolean
|
||||
}) {
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const t = useTheme()
|
||||
@@ -388,7 +394,9 @@ function Member({
|
||||
break
|
||||
}
|
||||
} else {
|
||||
statusBadge = <MemberMenu profile={profile} type={status} />
|
||||
statusBadge = (
|
||||
<MemberMenu profile={profile} type={status} isOwner={isOwner} />
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -496,9 +504,11 @@ function StatusButton({
|
||||
function MemberMenu({
|
||||
profile,
|
||||
type,
|
||||
isOwner,
|
||||
}: {
|
||||
profile: Shadow<bsky.profile.AnyProfileView>
|
||||
type: 'owner' | 'member' | 'invited'
|
||||
isOwner: boolean
|
||||
}) {
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const t = useTheme()
|
||||
@@ -506,16 +516,9 @@ function MemberMenu({
|
||||
const ax = useAnalytics()
|
||||
|
||||
const requireEmailVerification = useRequireEmailVerification()
|
||||
const convoState = useConvo()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const blockMemberPrompt = Prompt.usePromptControl()
|
||||
|
||||
const isOwner =
|
||||
currentAccount?.did == null
|
||||
? false
|
||||
: convoState.getPrimaryMember?.()?.did === currentAccount.did
|
||||
|
||||
const {data: convoAvailability} = useGetConvoAvailabilityQuery(profile.did)
|
||||
const {mutate: initiateConvo} = useGetConvoForMembers({
|
||||
onSuccess: ({convo}) => {
|
||||
@@ -706,29 +709,22 @@ function MemberMenu({
|
||||
|
||||
function SettingsHeader({
|
||||
convo,
|
||||
profiles,
|
||||
isOwner,
|
||||
}: {
|
||||
convo: ChatBskyConvoDefs.ConvoView
|
||||
profiles: bsky.profile.AnyProfileView[]
|
||||
convo: ConvoWithDetails
|
||||
isOwner: boolean
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const convoState = useConvo()
|
||||
const {currentAccount} = useSession()
|
||||
|
||||
const groupName = convoState.getGroupInfo?.()?.name ?? ''
|
||||
const groupName = convo.kind === 'group' ? convo.details.name : ''
|
||||
const [newGroupName, setNewGroupName] = useState(groupName)
|
||||
|
||||
const [isLocked, setIsLocked] = useState(false)
|
||||
|
||||
const isOwner =
|
||||
currentAccount?.did == null
|
||||
? false
|
||||
: convoState.getPrimaryMember?.()?.did === currentAccount.did
|
||||
|
||||
const {mutate: editGroupName} = useEditGroupName(convo.id, {
|
||||
const {mutate: editGroupName} = useEditGroupName(convo.view.id, {
|
||||
onError: e => {
|
||||
setNewGroupName(groupName)
|
||||
logger.error('Failed to edit group chat name', {message: e})
|
||||
@@ -738,7 +734,7 @@ function SettingsHeader({
|
||||
},
|
||||
})
|
||||
|
||||
const {mutate: muteConvo} = useMuteConvo(convo.id, {
|
||||
const {mutate: muteConvo} = useMuteConvo(convo.view.id, {
|
||||
onSuccess: data => {
|
||||
if (data.convo.muted) {
|
||||
Toast.show(l({message: 'Group chat muted', context: 'toast'}))
|
||||
@@ -754,7 +750,7 @@ function SettingsHeader({
|
||||
},
|
||||
})
|
||||
|
||||
const {mutate: leaveConvo} = useLeaveConvo(convo.id, {
|
||||
const {mutate: leaveConvo} = useLeaveConvo(convo.view.id, {
|
||||
onMutate: () => {
|
||||
navigation.dispatch(StackActions.pop(2))
|
||||
},
|
||||
@@ -772,7 +768,7 @@ function SettingsHeader({
|
||||
const leaveChatPrompt = Prompt.usePromptControl()
|
||||
|
||||
const handleToggleMute = () => {
|
||||
muteConvo({mute: !convo?.muted})
|
||||
muteConvo({mute: !convo.view.muted})
|
||||
}
|
||||
|
||||
const handleLeaveChat = () => {
|
||||
@@ -815,7 +811,7 @@ function SettingsHeader({
|
||||
<View
|
||||
style={[a.px_xl, a.py_4xl, a.border_b, t.atoms.border_contrast_low]}>
|
||||
<View style={[a.align_center, a.justify_center]}>
|
||||
<AvatarBubbles profiles={profiles} />
|
||||
<AvatarBubbles profiles={convo.members} />
|
||||
</View>
|
||||
<Text
|
||||
style={[
|
||||
@@ -846,12 +842,14 @@ function SettingsHeader({
|
||||
a.pt_2xl,
|
||||
]}>
|
||||
<SettingsButton
|
||||
color={convo?.muted ? 'negative_subtle' : 'secondary'}
|
||||
icon={convo?.muted ? BellOffIcon : BellIcon}
|
||||
color={convo.view.muted ? 'negative_subtle' : 'secondary'}
|
||||
icon={convo.view.muted ? BellOffIcon : BellIcon}
|
||||
label={
|
||||
convo?.muted ? l`Unmute this group chat` : l`Mute this group chat`
|
||||
convo.view.muted
|
||||
? l`Unmute this group chat`
|
||||
: l`Mute this group chat`
|
||||
}
|
||||
text={convo?.muted ? l`Muted` : l`Mute`}
|
||||
text={convo.view.muted ? l`Muted` : l`Mute`}
|
||||
onPress={handleToggleMute}
|
||||
/>
|
||||
{isOwner ? (
|
||||
|
||||
Reference in New Issue
Block a user