about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/dms/MessageMenu.tsx12
-rw-r--r--src/screens/Messages/Conversation/MessageListError.tsx2
-rw-r--r--src/screens/Messages/Conversation/MessagesList.tsx22
-rw-r--r--src/screens/Messages/Conversation/index.tsx28
-rw-r--r--src/state/messages/convo/agent.ts (renamed from src/state/messages/convo.ts)183
-rw-r--r--src/state/messages/convo/index.tsx75
-rw-r--r--src/state/messages/convo/types.ts178
-rw-r--r--src/state/messages/index.tsx74
8 files changed, 296 insertions, 278 deletions
diff --git a/src/components/dms/MessageMenu.tsx b/src/components/dms/MessageMenu.tsx
index d2a7d147d..3a5fa54d8 100644
--- a/src/components/dms/MessageMenu.tsx
+++ b/src/components/dms/MessageMenu.tsx
@@ -5,8 +5,8 @@ import {ChatBskyConvoDefs} from '@atproto-labs/api'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
-import {useChat} from 'state/messages'
-import {ConvoStatus} from 'state/messages/convo'
+import {useConvo} from 'state/messages/convo'
+import {ConvoStatus} from 'state/messages/convo/types'
 import {useSession} from 'state/session'
 import * as Toast from '#/view/com/util/Toast'
 import {atoms as a, useTheme} from '#/alf'
@@ -33,7 +33,7 @@ export let MessageMenu = ({
   const {_} = useLingui()
   const t = useTheme()
   const {currentAccount} = useSession()
-  const chat = useChat()
+  const convo = useConvo()
   const deleteControl = usePromptControl()
   const retryDeleteControl = usePromptControl()
 
@@ -48,14 +48,14 @@ export let MessageMenu = ({
   }, [_, message.text])
 
   const onDelete = React.useCallback(() => {
-    if (chat.status !== ConvoStatus.Ready) return
+    if (convo.status !== ConvoStatus.Ready) return
 
     LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
-    chat
+    convo
       .deleteMessage(message.id)
       .then(() => Toast.show(_(msg`Message deleted`)))
       .catch(() => retryDeleteControl.open())
-  }, [_, chat, message.id, retryDeleteControl])
+  }, [_, convo, message.id, retryDeleteControl])
 
   const onReport = React.useCallback(() => {
     // TODO report the message
diff --git a/src/screens/Messages/Conversation/MessageListError.tsx b/src/screens/Messages/Conversation/MessageListError.tsx
index 7c6fd02c1..5f5df4fc9 100644
--- a/src/screens/Messages/Conversation/MessageListError.tsx
+++ b/src/screens/Messages/Conversation/MessageListError.tsx
@@ -3,7 +3,7 @@ import {View} from 'react-native'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
-import {ConvoItem, ConvoItemError} from '#/state/messages/convo'
+import {ConvoItem, ConvoItemError} from '#/state/messages/convo/types'
 import {atoms as a, useTheme} from '#/alf'
 import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
 import {InlineLinkText} from '#/components/Link'
diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx
index 1dc26d6c3..49e780aa2 100644
--- a/src/screens/Messages/Conversation/MessagesList.tsx
+++ b/src/screens/Messages/Conversation/MessagesList.tsx
@@ -11,8 +11,8 @@ import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 
 import {isIOS} from '#/platform/detection'
-import {useChat} from '#/state/messages'
-import {ConvoItem, ConvoStatus} from '#/state/messages/convo'
+import {useConvo} from '#/state/messages/convo'
+import {ConvoItem, ConvoStatus} from '#/state/messages/convo/types'
 import {ScrollProvider} from 'lib/ScrollContext'
 import {isWeb} from 'platform/detection'
 import {List} from 'view/com/util/List'
@@ -86,7 +86,7 @@ function onScrollToIndexFailed() {
 }
 
 export function MessagesList() {
-  const chat = useChat()
+  const convo = useConvo()
   const flatListRef = useRef<FlatList>(null)
 
   // We need to keep track of when the scroll offset is at the bottom of the list to know when to scroll as new items
@@ -153,20 +153,20 @@ export function MessagesList() {
   // The check for `hasInitiallyScrolled` prevents an initial fetch on mount. FlatList triggers `onStartReached`
   // immediately on mount, since we are in fact at an offset of zero, so we have to ignore those initial calls.
   const onStartReached = useCallback(() => {
-    if (chat.status === ConvoStatus.Ready && hasInitiallyScrolled) {
-      chat.fetchMessageHistory()
+    if (convo.status === ConvoStatus.Ready && hasInitiallyScrolled) {
+      convo.fetchMessageHistory()
     }
-  }, [chat, hasInitiallyScrolled])
+  }, [convo, hasInitiallyScrolled])
 
   const onSendMessage = useCallback(
     (text: string) => {
-      if (chat.status === ConvoStatus.Ready) {
-        chat.sendMessage({
+      if (convo.status === ConvoStatus.Ready) {
+        convo.sendMessage({
           text,
         })
       }
     },
-    [chat],
+    [convo],
   )
 
   const onScroll = React.useCallback(
@@ -229,7 +229,7 @@ export function MessagesList() {
       <ScrollProvider onScroll={onScroll} onMomentumEnd={onMomentumEnd}>
         <List
           ref={flatListRef}
-          data={chat.items}
+          data={convo.items}
           renderItem={renderItem}
           keyExtractor={keyExtractor}
           disableVirtualization={true}
@@ -248,7 +248,7 @@ export function MessagesList() {
           onScrollToIndexFailed={onScrollToIndexFailed}
           scrollEventThrottle={100}
           ListHeaderComponent={
-            <MaybeLoader isLoading={chat.isFetchingHistory} />
+            <MaybeLoader isLoading={convo.isFetchingHistory} />
           }
         />
       </ScrollProvider>
diff --git a/src/screens/Messages/Conversation/index.tsx b/src/screens/Messages/Conversation/index.tsx
index 7b78e7e61..db22f9e31 100644
--- a/src/screens/Messages/Conversation/index.tsx
+++ b/src/screens/Messages/Conversation/index.tsx
@@ -13,8 +13,8 @@ import {useGate} from '#/lib/statsig/statsig'
 import {useCurrentConvoId} from '#/state/messages/current-convo-id'
 import {BACK_HITSLOP} from 'lib/constants'
 import {isWeb} from 'platform/detection'
-import {ChatProvider, useChat} from 'state/messages'
-import {ConvoStatus} from 'state/messages/convo'
+import {ConvoProvider, useConvo} from 'state/messages/convo'
+import {ConvoStatus} from 'state/messages/convo/types'
 import {PreviewableUserAvatar} from 'view/com/util/UserAvatar'
 import {CenteredView} from 'view/com/util/Views'
 import {MessagesList} from '#/screens/Messages/Conversation/MessagesList'
@@ -46,23 +46,23 @@ export function MessagesConversationScreen({route}: Props) {
   if (!gate('dms')) return <ClipClopGate />
 
   return (
-    <ChatProvider convoId={convoId}>
+    <ConvoProvider convoId={convoId}>
       <Inner />
-    </ChatProvider>
+    </ConvoProvider>
   )
 }
 
 function Inner() {
-  const chat = useChat()
+  const convo = useConvo()
 
   if (
-    chat.status === ConvoStatus.Uninitialized ||
-    chat.status === ConvoStatus.Initializing
+    convo.status === ConvoStatus.Uninitialized ||
+    convo.status === ConvoStatus.Initializing
   ) {
     return <ListMaybePlaceholder isLoading />
   }
 
-  if (chat.status === ConvoStatus.Error) {
+  if (convo.status === ConvoStatus.Error) {
     // TODO
     return (
       <View>
@@ -71,7 +71,7 @@ function Inner() {
           <Button
             label="Retry"
             onPress={() => {
-              chat.error.retry()
+              convo.error.retry()
             }}>
             <ButtonText>Retry</ButtonText>
           </Button>
@@ -81,13 +81,13 @@ function Inner() {
   }
 
   /*
-   * Any other chat states (atm) are "ready" states
+   * Any other convo states (atm) are "ready" states
    */
 
   return (
     <KeyboardProvider>
       <CenteredView style={{flex: 1}} sideBorders>
-        <Header profile={chat.recipients[0]} />
+        <Header profile={convo.recipients[0]} />
         <MessagesList />
       </CenteredView>
     </KeyboardProvider>
@@ -103,7 +103,7 @@ let Header = ({
   const {_} = useLingui()
   const {gtTablet} = useBreakpoints()
   const navigation = useNavigation<NavigationProp>()
-  const chat = useChat()
+  const convo = useConvo()
 
   const onPressBack = useCallback(() => {
     if (isWeb) {
@@ -157,9 +157,9 @@ let Header = ({
           {profile.displayName}
         </Text>
       </View>
-      {chat.status === ConvoStatus.Ready ? (
+      {convo.status === ConvoStatus.Ready ? (
         <ConvoMenu
-          convo={chat.convo}
+          convo={convo.convo}
           profile={profile}
           onUpdateConvo={onUpdateConvo}
           currentScreen="conversation"
diff --git a/src/state/messages/convo.ts b/src/state/messages/convo/agent.ts
index de21ef396..38a3f5e62 100644
--- a/src/state/messages/convo.ts
+++ b/src/state/messages/convo/agent.ts
@@ -9,178 +9,16 @@ import {nanoid} from 'nanoid/non-secure'
 
 import {logger} from '#/logger'
 import {isNative} from '#/platform/detection'
-
-export type ConvoParams = {
-  convoId: string
-  agent: BskyAgent
-  __tempFromUserDid: string
-}
-
-export enum ConvoStatus {
-  Uninitialized = 'uninitialized',
-  Initializing = 'initializing',
-  Ready = 'ready',
-  Error = 'error',
-  Backgrounded = 'backgrounded',
-  Suspended = 'suspended',
-}
-
-export enum ConvoItemError {
-  HistoryFailed = 'historyFailed',
-  PollFailed = 'pollFailed',
-  Network = 'network',
-}
-
-export enum ConvoErrorCode {
-  InitFailed = 'initFailed',
-}
-
-export type ConvoError = {
-  code: ConvoErrorCode
-  exception?: Error
-  retry: () => void
-}
-
-export enum ConvoDispatchEvent {
-  Init = 'init',
-  Ready = 'ready',
-  Resume = 'resume',
-  Background = 'background',
-  Suspend = 'suspend',
-  Error = 'error',
-}
-
-export type ConvoDispatch =
-  | {
-      event: ConvoDispatchEvent.Init
-    }
-  | {
-      event: ConvoDispatchEvent.Ready
-    }
-  | {
-      event: ConvoDispatchEvent.Resume
-    }
-  | {
-      event: ConvoDispatchEvent.Background
-    }
-  | {
-      event: ConvoDispatchEvent.Suspend
-    }
-  | {
-      event: ConvoDispatchEvent.Error
-      payload: ConvoError
-    }
-
-export type ConvoItem =
-  | {
-      type: 'message' | 'pending-message'
-      key: string
-      message: ChatBskyConvoDefs.MessageView
-      nextMessage:
-        | ChatBskyConvoDefs.MessageView
-        | ChatBskyConvoDefs.DeletedMessageView
-        | null
-    }
-  | {
-      type: 'deleted-message'
-      key: string
-      message: ChatBskyConvoDefs.DeletedMessageView
-      nextMessage:
-        | ChatBskyConvoDefs.MessageView
-        | ChatBskyConvoDefs.DeletedMessageView
-        | null
-    }
-  | {
-      type: 'pending-retry'
-      key: string
-      retry: () => void
-    }
-  | {
-      type: 'error-recoverable'
-      key: string
-      code: ConvoItemError
-      retry: () => void
-    }
-
-export type ConvoState =
-  | {
-      status: ConvoStatus.Uninitialized
-      items: []
-      convo: undefined
-      error: undefined
-      sender: undefined
-      recipients: undefined
-      isFetchingHistory: false
-      deleteMessage: undefined
-      sendMessage: undefined
-      fetchMessageHistory: undefined
-    }
-  | {
-      status: ConvoStatus.Initializing
-      items: []
-      convo: undefined
-      error: undefined
-      sender: undefined
-      recipients: undefined
-      isFetchingHistory: boolean
-      deleteMessage: undefined
-      sendMessage: undefined
-      fetchMessageHistory: undefined
-    }
-  | {
-      status: ConvoStatus.Ready
-      items: ConvoItem[]
-      convo: ChatBskyConvoDefs.ConvoView
-      error: undefined
-      sender: AppBskyActorDefs.ProfileViewBasic
-      recipients: AppBskyActorDefs.ProfileViewBasic[]
-      isFetchingHistory: boolean
-      deleteMessage: (messageId: string) => Promise<void>
-      sendMessage: (
-        message: ChatBskyConvoSendMessage.InputSchema['message'],
-      ) => void
-      fetchMessageHistory: () => void
-    }
-  | {
-      status: ConvoStatus.Suspended
-      items: ConvoItem[]
-      convo: ChatBskyConvoDefs.ConvoView
-      error: undefined
-      sender: AppBskyActorDefs.ProfileViewBasic
-      recipients: AppBskyActorDefs.ProfileViewBasic[]
-      isFetchingHistory: boolean
-      deleteMessage: (messageId: string) => Promise<void>
-      sendMessage: (
-        message: ChatBskyConvoSendMessage.InputSchema['message'],
-      ) => Promise<void>
-      fetchMessageHistory: () => Promise<void>
-    }
-  | {
-      status: ConvoStatus.Backgrounded
-      items: ConvoItem[]
-      convo: ChatBskyConvoDefs.ConvoView
-      error: undefined
-      sender: AppBskyActorDefs.ProfileViewBasic
-      recipients: AppBskyActorDefs.ProfileViewBasic[]
-      isFetchingHistory: boolean
-      deleteMessage: (messageId: string) => Promise<void>
-      sendMessage: (
-        message: ChatBskyConvoSendMessage.InputSchema['message'],
-      ) => Promise<void>
-      fetchMessageHistory: () => Promise<void>
-    }
-  | {
-      status: ConvoStatus.Error
-      items: []
-      convo: undefined
-      error: any
-      sender: undefined
-      recipients: undefined
-      isFetchingHistory: false
-      deleteMessage: undefined
-      sendMessage: undefined
-      fetchMessageHistory: undefined
-    }
+import {
+  ConvoDispatch,
+  ConvoDispatchEvent,
+  ConvoErrorCode,
+  ConvoItem,
+  ConvoItemError,
+  ConvoParams,
+  ConvoState,
+  ConvoStatus,
+} from '#/state/messages/convo/types'
 
 const ACTIVE_POLL_INTERVAL = 1e3
 const BACKGROUND_POLL_INTERVAL = 10e3
@@ -235,7 +73,6 @@ export class Convo {
   private headerItems: Map<string, ConvoItem> = new Map()
 
   private isProcessingPendingMessages = false
-  private pendingPoll: Promise<void> | undefined
   private nextPoll: NodeJS.Timeout | undefined
 
   convoId: string
diff --git a/src/state/messages/convo/index.tsx b/src/state/messages/convo/index.tsx
new file mode 100644
index 000000000..c4fe71d30
--- /dev/null
+++ b/src/state/messages/convo/index.tsx
@@ -0,0 +1,75 @@
+import React, {useContext, useState, useSyncExternalStore} from 'react'
+import {AppState} from 'react-native'
+import {BskyAgent} from '@atproto-labs/api'
+import {useFocusEffect, useIsFocused} from '@react-navigation/native'
+
+import {Convo} from '#/state/messages/convo/agent'
+import {ConvoParams, ConvoState} from '#/state/messages/convo/types'
+import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
+import {useAgent} from '#/state/session'
+import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage'
+
+const ChatContext = React.createContext<ConvoState | null>(null)
+
+export function useConvo() {
+  const ctx = useContext(ChatContext)
+  if (!ctx) {
+    throw new Error('useConvo must be used within a ConvoProvider')
+  }
+  return ctx
+}
+
+export function ConvoProvider({
+  children,
+  convoId,
+}: Pick<ConvoParams, 'convoId'> & {children: React.ReactNode}) {
+  const isScreenFocused = useIsFocused()
+  const {serviceUrl} = useDmServiceUrlStorage()
+  const {getAgent} = useAgent()
+  const [convo] = useState(
+    () =>
+      new Convo({
+        convoId,
+        agent: new BskyAgent({
+          service: serviceUrl,
+        }),
+        __tempFromUserDid: getAgent().session?.did!,
+      }),
+  )
+  const service = useSyncExternalStore(convo.subscribe, convo.getSnapshot)
+  const {mutate: markAsRead} = useMarkAsReadMutation()
+
+  useFocusEffect(
+    React.useCallback(() => {
+      convo.resume()
+      markAsRead({convoId})
+
+      return () => {
+        convo.background()
+        markAsRead({convoId})
+      }
+    }, [convo, convoId, markAsRead]),
+  )
+
+  React.useEffect(() => {
+    const handleAppStateChange = (nextAppState: string) => {
+      if (isScreenFocused) {
+        if (nextAppState === 'active') {
+          convo.resume()
+        } else {
+          convo.background()
+        }
+
+        markAsRead({convoId})
+      }
+    }
+
+    const sub = AppState.addEventListener('change', handleAppStateChange)
+
+    return () => {
+      sub.remove()
+    }
+  }, [convoId, convo, isScreenFocused, markAsRead])
+
+  return <ChatContext.Provider value={service}>{children}</ChatContext.Provider>
+}
diff --git a/src/state/messages/convo/types.ts b/src/state/messages/convo/types.ts
new file mode 100644
index 000000000..cfbde6d7e
--- /dev/null
+++ b/src/state/messages/convo/types.ts
@@ -0,0 +1,178 @@
+import {AppBskyActorDefs} from '@atproto/api'
+import {
+  BskyAgent,
+  ChatBskyConvoDefs,
+  ChatBskyConvoSendMessage,
+} from '@atproto-labs/api'
+
+export type ConvoParams = {
+  convoId: string
+  agent: BskyAgent
+  __tempFromUserDid: string
+}
+
+export enum ConvoStatus {
+  Uninitialized = 'uninitialized',
+  Initializing = 'initializing',
+  Ready = 'ready',
+  Error = 'error',
+  Backgrounded = 'backgrounded',
+  Suspended = 'suspended',
+}
+
+export enum ConvoItemError {
+  HistoryFailed = 'historyFailed',
+  PollFailed = 'pollFailed',
+  Network = 'network',
+}
+
+export enum ConvoErrorCode {
+  InitFailed = 'initFailed',
+}
+
+export type ConvoError = {
+  code: ConvoErrorCode
+  exception?: Error
+  retry: () => void
+}
+
+export enum ConvoDispatchEvent {
+  Init = 'init',
+  Ready = 'ready',
+  Resume = 'resume',
+  Background = 'background',
+  Suspend = 'suspend',
+  Error = 'error',
+}
+
+export type ConvoDispatch =
+  | {
+      event: ConvoDispatchEvent.Init
+    }
+  | {
+      event: ConvoDispatchEvent.Ready
+    }
+  | {
+      event: ConvoDispatchEvent.Resume
+    }
+  | {
+      event: ConvoDispatchEvent.Background
+    }
+  | {
+      event: ConvoDispatchEvent.Suspend
+    }
+  | {
+      event: ConvoDispatchEvent.Error
+      payload: ConvoError
+    }
+
+export type ConvoItem =
+  | {
+      type: 'message' | 'pending-message'
+      key: string
+      message: ChatBskyConvoDefs.MessageView
+      nextMessage:
+        | ChatBskyConvoDefs.MessageView
+        | ChatBskyConvoDefs.DeletedMessageView
+        | null
+    }
+  | {
+      type: 'deleted-message'
+      key: string
+      message: ChatBskyConvoDefs.DeletedMessageView
+      nextMessage:
+        | ChatBskyConvoDefs.MessageView
+        | ChatBskyConvoDefs.DeletedMessageView
+        | null
+    }
+  | {
+      type: 'pending-retry'
+      key: string
+      retry: () => void
+    }
+  | {
+      type: 'error-recoverable'
+      key: string
+      code: ConvoItemError
+      retry: () => void
+    }
+
+export type ConvoState =
+  | {
+      status: ConvoStatus.Uninitialized
+      items: []
+      convo: undefined
+      error: undefined
+      sender: undefined
+      recipients: undefined
+      isFetchingHistory: false
+      deleteMessage: undefined
+      sendMessage: undefined
+      fetchMessageHistory: undefined
+    }
+  | {
+      status: ConvoStatus.Initializing
+      items: []
+      convo: undefined
+      error: undefined
+      sender: undefined
+      recipients: undefined
+      isFetchingHistory: boolean
+      deleteMessage: undefined
+      sendMessage: undefined
+      fetchMessageHistory: undefined
+    }
+  | {
+      status: ConvoStatus.Ready
+      items: ConvoItem[]
+      convo: ChatBskyConvoDefs.ConvoView
+      error: undefined
+      sender: AppBskyActorDefs.ProfileViewBasic
+      recipients: AppBskyActorDefs.ProfileViewBasic[]
+      isFetchingHistory: boolean
+      deleteMessage: (messageId: string) => Promise<void>
+      sendMessage: (
+        message: ChatBskyConvoSendMessage.InputSchema['message'],
+      ) => void
+      fetchMessageHistory: () => void
+    }
+  | {
+      status: ConvoStatus.Suspended
+      items: ConvoItem[]
+      convo: ChatBskyConvoDefs.ConvoView
+      error: undefined
+      sender: AppBskyActorDefs.ProfileViewBasic
+      recipients: AppBskyActorDefs.ProfileViewBasic[]
+      isFetchingHistory: boolean
+      deleteMessage: (messageId: string) => Promise<void>
+      sendMessage: (
+        message: ChatBskyConvoSendMessage.InputSchema['message'],
+      ) => Promise<void>
+      fetchMessageHistory: () => Promise<void>
+    }
+  | {
+      status: ConvoStatus.Backgrounded
+      items: ConvoItem[]
+      convo: ChatBskyConvoDefs.ConvoView
+      error: undefined
+      sender: AppBskyActorDefs.ProfileViewBasic
+      recipients: AppBskyActorDefs.ProfileViewBasic[]
+      isFetchingHistory: boolean
+      deleteMessage: (messageId: string) => Promise<void>
+      sendMessage: (
+        message: ChatBskyConvoSendMessage.InputSchema['message'],
+      ) => Promise<void>
+      fetchMessageHistory: () => Promise<void>
+    }
+  | {
+      status: ConvoStatus.Error
+      items: []
+      convo: undefined
+      error: any
+      sender: undefined
+      recipients: undefined
+      isFetchingHistory: false
+      deleteMessage: undefined
+      sendMessage: undefined
+      fetchMessageHistory: undefined
+    }
diff --git a/src/state/messages/index.tsx b/src/state/messages/index.tsx
index 60538615a..205d17e8c 100644
--- a/src/state/messages/index.tsx
+++ b/src/state/messages/index.tsx
@@ -1,79 +1,7 @@
-import React, {useContext, useState, useSyncExternalStore} from 'react'
-import {AppState} from 'react-native'
-import {BskyAgent} from '@atproto-labs/api'
-import {useFocusEffect, useIsFocused} from '@react-navigation/native'
+import React from 'react'
 
-import {Convo, ConvoParams, ConvoState} from '#/state/messages/convo'
 import {CurrentConvoIdProvider} from '#/state/messages/current-convo-id'
 import {MessagesEventBusProvider} from '#/state/messages/events'
-import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
-import {useAgent} from '#/state/session'
-import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage'
-
-const ChatContext = React.createContext<ConvoState | null>(null)
-
-export function useChat() {
-  const ctx = useContext(ChatContext)
-  if (!ctx) {
-    throw new Error('useChat must be used within a ChatProvider')
-  }
-  return ctx
-}
-
-export function ChatProvider({
-  children,
-  convoId,
-}: Pick<ConvoParams, 'convoId'> & {children: React.ReactNode}) {
-  const isScreenFocused = useIsFocused()
-  const {serviceUrl} = useDmServiceUrlStorage()
-  const {getAgent} = useAgent()
-  const [convo] = useState(
-    () =>
-      new Convo({
-        convoId,
-        agent: new BskyAgent({
-          service: serviceUrl,
-        }),
-        __tempFromUserDid: getAgent().session?.did!,
-      }),
-  )
-  const service = useSyncExternalStore(convo.subscribe, convo.getSnapshot)
-  const {mutate: markAsRead} = useMarkAsReadMutation()
-
-  useFocusEffect(
-    React.useCallback(() => {
-      convo.resume()
-      markAsRead({convoId})
-
-      return () => {
-        convo.background()
-        markAsRead({convoId})
-      }
-    }, [convo, convoId, markAsRead]),
-  )
-
-  React.useEffect(() => {
-    const handleAppStateChange = (nextAppState: string) => {
-      if (isScreenFocused) {
-        if (nextAppState === 'active') {
-          convo.resume()
-        } else {
-          convo.background()
-        }
-
-        markAsRead({convoId})
-      }
-    }
-
-    const sub = AppState.addEventListener('change', handleAppStateChange)
-
-    return () => {
-      sub.remove()
-    }
-  }, [convoId, convo, isScreenFocused, markAsRead])
-
-  return <ChatContext.Provider value={service}>{children}</ChatContext.Provider>
-}
 
 export function MessagesProvider({children}: {children: React.ReactNode}) {
   return (