diff --git a/src/screens/Messages/Conversation/ChatDisabled.tsx b/src/screens/Messages/Conversation/ChatDisabled.tsx
new file mode 100644
index 0000000000..e7453bfd81
--- /dev/null
+++ b/src/screens/Messages/Conversation/ChatDisabled.tsx
@@ -0,0 +1,26 @@
+import React from 'react'
+import {View} from 'react-native'
+import {Trans} from '@lingui/macro'
+
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+
+export function ChatDisabled() {
+ const t = useTheme()
+ return (
+
+
+
+ Your chats have been disabled
+
+
+
+ Our moderators have reviewed reports and decided to disable your
+ access to chats on Bluesky.
+
+
+
+
+ )
+}
diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx
index ef0cc55d20..1f9147c576 100644
--- a/src/screens/Messages/Conversation/MessagesList.tsx
+++ b/src/screens/Messages/Conversation/MessagesList.tsx
@@ -16,11 +16,12 @@ import {AppBskyRichtextFacet, RichText} from '@atproto/api'
import {shortenLinks} from '#/lib/strings/rich-text-manip'
import {isIOS, isNative} from '#/platform/detection'
import {useConvoActive} from '#/state/messages/convo'
-import {ConvoItem} from '#/state/messages/convo/types'
+import {ConvoItem, ConvoStatus} from '#/state/messages/convo/types'
import {useAgent} from '#/state/session'
import {ScrollProvider} from 'lib/ScrollContext'
import {isWeb} from 'platform/detection'
import {List} from 'view/com/util/List'
+import {ChatDisabled} from '#/screens/Messages/Conversation/ChatDisabled'
import {MessageInput} from '#/screens/Messages/Conversation/MessageInput'
import {MessageListError} from '#/screens/Messages/Conversation/MessageListError'
import {atoms as a} from '#/alf'
@@ -296,10 +297,16 @@ export function MessagesList({
/>
{!blocked ? (
-
+ <>
+ {convoState.status === ConvoStatus.Disabled ? (
+
+ ) : (
+
+ )}
+ >
) : (
footer
)}
diff --git a/src/state/messages/convo/agent.ts b/src/state/messages/convo/agent.ts
index 8673c70adf..0a75401c2e 100644
--- a/src/state/messages/convo/agent.ts
+++ b/src/state/messages/convo/agent.ts
@@ -152,6 +152,7 @@ export class Convo {
fetchMessageHistory: undefined,
}
}
+ case ConvoStatus.Disabled:
case ConvoStatus.Suspended:
case ConvoStatus.Backgrounded:
case ConvoStatus.Ready: {
@@ -241,6 +242,13 @@ export class Convo {
this.withdrawRequestedPollInterval()
break
}
+ case ConvoDispatchEvent.Disable: {
+ this.status = ConvoStatus.Disabled
+ this.fetchMessageHistory() // finish init
+ this.cleanupFirehoseConnection?.()
+ this.withdrawRequestedPollInterval()
+ break
+ }
}
break
}
@@ -269,6 +277,12 @@ export class Convo {
this.withdrawRequestedPollInterval()
break
}
+ case ConvoDispatchEvent.Disable: {
+ this.status = ConvoStatus.Disabled
+ this.cleanupFirehoseConnection?.()
+ this.withdrawRequestedPollInterval()
+ break
+ }
}
break
}
@@ -303,6 +317,12 @@ export class Convo {
this.withdrawRequestedPollInterval()
break
}
+ case ConvoDispatchEvent.Disable: {
+ this.status = ConvoStatus.Disabled
+ this.cleanupFirehoseConnection?.()
+ this.withdrawRequestedPollInterval()
+ break
+ }
}
break
}
@@ -321,6 +341,10 @@ export class Convo {
this.error = action.payload
break
}
+ case ConvoDispatchEvent.Disable: {
+ this.status = ConvoStatus.Disabled
+ break
+ }
}
break
}
@@ -343,9 +367,17 @@ export class Convo {
this.error = action.payload
break
}
+ case ConvoDispatchEvent.Disable: {
+ this.status = ConvoStatus.Disabled
+ break
+ }
}
break
}
+ case ConvoStatus.Disabled: {
+ // can't do anything
+ break
+ }
default:
break
}
@@ -424,9 +456,13 @@ export class Convo {
throw new Error('Convo: could not find recipients in convo')
}
- // await new Promise(y => setTimeout(y, 2000))
- // throw new Error('UNCOMMENT TO TEST INIT FAILURE')
- this.dispatch({event: ConvoDispatchEvent.Ready})
+ const userIsDisabled = this.sender.chatDisabled as boolean
+
+ if (userIsDisabled) {
+ this.dispatch({event: ConvoDispatchEvent.Disable})
+ } else {
+ this.dispatch({event: ConvoDispatchEvent.Ready})
+ }
} catch (e: any) {
logger.error(e, {context: 'Convo: setup failed'})
@@ -829,6 +865,10 @@ export class Convo {
],
})
break
+ case 'Account is disabled':
+ this.pendingMessageFailure = 'unrecoverable'
+ this.dispatch({event: ConvoDispatchEvent.Disable})
+ break
default:
logger.warn(
`Convo handleSendMessageFailure could not handle error`,
diff --git a/src/state/messages/convo/index.tsx b/src/state/messages/convo/index.tsx
index d6648f4800..79e61f88a6 100644
--- a/src/state/messages/convo/index.tsx
+++ b/src/state/messages/convo/index.tsx
@@ -8,6 +8,7 @@ import {
ConvoParams,
ConvoState,
ConvoStateBackgrounded,
+ ConvoStateDisabled,
ConvoStateReady,
ConvoStateSuspended,
} from '#/state/messages/convo/types'
@@ -40,6 +41,7 @@ export function useConvoActive() {
| ConvoStateReady
| ConvoStateBackgrounded
| ConvoStateSuspended
+ | ConvoStateDisabled
if (!ctx) {
throw new Error('useConvo must be used within a ConvoProvider')
}
diff --git a/src/state/messages/convo/types.ts b/src/state/messages/convo/types.ts
index 25e79aba6d..6197a3b424 100644
--- a/src/state/messages/convo/types.ts
+++ b/src/state/messages/convo/types.ts
@@ -20,6 +20,7 @@ export enum ConvoStatus {
Error = 'error',
Backgrounded = 'backgrounded',
Suspended = 'suspended',
+ Disabled = 'disabled',
}
export enum ConvoItemError {
@@ -50,6 +51,7 @@ export enum ConvoDispatchEvent {
Background = 'background',
Suspend = 'suspend',
Error = 'error',
+ Disable = 'disable',
}
export type ConvoDispatch =
@@ -72,6 +74,9 @@ export type ConvoDispatch =
event: ConvoDispatchEvent.Error
payload: ConvoError
}
+ | {
+ event: ConvoDispatchEvent.Disable
+ }
export type ConvoItem =
| {
@@ -194,6 +199,18 @@ export type ConvoStateError = {
sendMessage: undefined
fetchMessageHistory: undefined
}
+export type ConvoStateDisabled = {
+ status: ConvoStatus.Disabled
+ items: ConvoItem[]
+ convo: ChatBskyConvoDefs.ConvoView
+ error: undefined
+ sender: AppBskyActorDefs.ProfileViewBasic
+ recipients: AppBskyActorDefs.ProfileViewBasic[]
+ isFetchingHistory: boolean
+ deleteMessage: DeleteMessage
+ sendMessage: SendMessage
+ fetchMessageHistory: FetchMessageHistory
+}
export type ConvoState =
| ConvoStateUninitialized
| ConvoStateInitializing
@@ -201,6 +218,7 @@ export type ConvoState =
| ConvoStateBackgrounded
| ConvoStateSuspended
| ConvoStateError
+ | ConvoStateDisabled
export type ConvoEvent = {
type: 'invalidate-block-state'
diff --git a/src/state/messages/convo/util.ts b/src/state/messages/convo/util.ts
index ffaa4104a7..200d85dfab 100644
--- a/src/state/messages/convo/util.ts
+++ b/src/state/messages/convo/util.ts
@@ -1,6 +1,7 @@
import {
ConvoState,
ConvoStateBackgrounded,
+ ConvoStateDisabled,
ConvoStateReady,
ConvoStateSuspended,
ConvoStatus,
@@ -13,10 +14,15 @@ import {
*/
export function isConvoActive(
convo: ConvoState,
-): convo is ConvoStateReady | ConvoStateBackgrounded | ConvoStateSuspended {
+): convo is
+ | ConvoStateReady
+ | ConvoStateBackgrounded
+ | ConvoStateSuspended
+ | ConvoStateDisabled {
return (
convo.status === ConvoStatus.Ready ||
convo.status === ConvoStatus.Backgrounded ||
- convo.status === ConvoStatus.Suspended
+ convo.status === ConvoStatus.Suspended ||
+ convo.status === ConvoStatus.Disabled
)
}