diff --git a/src/components/dms/dialogs/NewChatDialog.tsx b/src/components/dms/dialogs/NewChatDialog.tsx
index 4ab5a16421..84b1d3346f 100644
--- a/src/components/dms/dialogs/NewChatDialog.tsx
+++ b/src/components/dms/dialogs/NewChatDialog.tsx
@@ -10,6 +10,7 @@ import {isNetworkError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {useCreateGroupChat} from '#/state/queries/messages/create-group-chat'
import {useGetConvoForMembers} from '#/state/queries/messages/get-convo-for-members'
+import {useChatActorStatusQuery} from '#/state/queries/messages/get-status'
import {FAB} from '#/view/com/util/fab/FAB'
import {useTheme} from '#/alf'
import * as Dialog from '#/components/Dialog'
@@ -30,6 +31,8 @@ export function NewChat({
const {t: l} = useLingui()
const ax = useAnalytics()
const requireEmailVerification = useRequireEmailVerification()
+ const {data: chatStatus} = useChatActorStatusQuery()
+ const chatDisabled = !!chatStatus?.chatDisabled
const isGroupChatEnabled = ax.features.enabled(ax.features.GroupChatsEnable)
@@ -153,14 +156,16 @@ export function NewChat({
return (
<>
- }
- accessibilityRole="button"
- accessibilityLabel={l`New chat`}
- accessibilityHint=""
- />
+ {!chatDisabled && (
+ }
+ accessibilityRole="button"
+ accessibilityLabel={l`New chat`}
+ accessibilityHint=""
+ />
+ )}
@@ -171,8 +180,8 @@ export function MessagesScreenInner({navigation, route}: Props) {
return (
-
-
+
+
)
@@ -181,9 +190,11 @@ export function MessagesScreenInner({navigation, route}: Props) {
export function ChatList({
selectedChat,
newChatControl,
+ chatStatus,
}: {
selectedChat?: string
newChatControl: DialogControlProps
+ chatStatus: ChatStatus | undefined
}) {
const t = useTheme()
const {t: l} = useLingui()
@@ -362,14 +373,18 @@ export function ChatList({
textStyle={t.atoms.text}
iconColor={t.atoms.text.color}
iconSize="4xl"
- button={{
- label: l`New chat`,
- text: l`New chat`,
- onPress: wrappedOpenChatControl,
- size: 'small',
- color: 'primary',
- icon: MessagePlusIcon,
- }}
+ button={
+ chatStatus?.chatDisabled
+ ? undefined
+ : {
+ label: l`New chat`,
+ text: l`New chat`,
+ onPress: wrappedOpenChatControl,
+ size: 'small',
+ color: 'primary',
+ icon: MessagePlusIcon,
+ }
+ }
style={[a.h_full, {paddingTop: '20%'}]}
/>
)}
@@ -388,6 +403,11 @@ export function ChatList({
refreshing={isPTRing}
onRefresh={() => void onRefresh()}
onEndReached={() => void onEndReached()}
+ ListHeaderComponent={
+ chatStatus?.chatDisabled ? (
+
+ ) : undefined
+ }
ListFooterComponent={
)
}
-export function Header({newChatControl}: {newChatControl: DialogControlProps}) {
+export function Header({
+ newChatControl,
+ chatStatus,
+}: {
+ newChatControl: DialogControlProps
+ chatStatus: ChatStatus | undefined
+}) {
const {t: l} = useLingui()
const {gtMobile} = useBreakpoints()
const requireEmailVerification = useRequireEmailVerification()
@@ -476,14 +504,16 @@ export function Header({newChatControl}: {newChatControl: DialogControlProps}) {
style={[a.justify_center]}>
-
+ {!chatStatus?.chatDisabled && (
+
+ )}
>
) : (
diff --git a/src/screens/Messages/components/ChatDisabled.tsx b/src/screens/Messages/components/ChatDisabled.tsx
index 866f0029d7..8095c1e0b9 100644
--- a/src/screens/Messages/components/ChatDisabled.tsx
+++ b/src/screens/Messages/components/ChatDisabled.tsx
@@ -1,5 +1,5 @@
import {useCallback, useState} from 'react'
-import {View} from 'react-native'
+import {type StyleProp, View, type ViewStyle} from 'react-native'
import {ToolsOzoneReportDefs} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro'
import {useMutation} from '@tanstack/react-query'
@@ -15,19 +15,23 @@ import {Loader} from '#/components/Loader'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
-export function ChatDisabled() {
+export function ChatDisabled({
+ shape = 'pill',
+ style,
+}: {
+ shape?: 'pill' | 'banner'
+ style?: StyleProp
+}) {
const t = useTheme()
return (
-
+
}
-function MessagesSplitViewLayout({children, navigation, route}: LayoutProps) {
- const {rightNavVisible, centerColumnOffset} = useLayoutBreakpoints()
+function MessagesSplitViewLayout({children, ...props}: LayoutProps) {
+ const {rightNavVisible} = useLayoutBreakpoints()
+ const aa = useAgeAssurance()
+
+ if (!IS_WEB || !rightNavVisible || aa.state.access !== aa.Access.Full) {
+ return children
+ }
+
+ return (
+
+ {children}
+
+ )
+}
+
+function MessagesSplitViewLayoutInner({
+ children,
+ navigation,
+ route,
+}: LayoutProps) {
+ const {centerColumnOffset} = useLayoutBreakpoints()
const newChatControl = useDialogControl()
const t = useTheme()
- const aa = useAgeAssurance()
const isFocused = useIsFocused()
+ const {data: chatStatus} = useChatActorStatusQuery()
const onLeftColumnScroll = useCallback((e: ReanimatedScrollEvent) => {
'worklet'
splitViewLeftScroll.current = e.contentOffset.y
}, [])
- if (!IS_WEB || !rightNavVisible || aa.state.access !== aa.Access.Full) {
- return children
- }
-
const onNewChat = (conversation: string) =>
navigation.navigate('MessagesConversation', {conversation})
@@ -102,11 +118,15 @@ function MessagesSplitViewLayout({children, navigation, route}: LayoutProps) {
t.atoms.border_contrast_low,
{width: leftColumnWidth},
]}>
-
+
diff --git a/src/state/queries/messages/get-status.ts b/src/state/queries/messages/get-status.ts
new file mode 100644
index 0000000000..2bfb12550a
--- /dev/null
+++ b/src/state/queries/messages/get-status.ts
@@ -0,0 +1,27 @@
+import {useQuery} from '@tanstack/react-query'
+
+import {DM_SERVICE_HEADERS} from '#/lib/constants'
+import {useAgent} from '#/state/session'
+import {STALE} from '..'
+import {createQueryKey} from '../util'
+
+const chatActorStatusQueryKey = () =>
+ createQueryKey('chat-actor-status', {}, {persistedVersion: 1})
+
+export function useChatActorStatusQuery() {
+ const agent = useAgent()
+
+ return useQuery({
+ queryKey: chatActorStatusQueryKey(),
+ queryFn: async () => {
+ const {data} = await agent.chat.bsky.actor.getStatus(
+ {},
+ {headers: DM_SERVICE_HEADERS},
+ )
+
+ return data
+ },
+ staleTime: STALE.INFINITY,
+ gcTime: STALE.INFINITY,
+ })
+}