about summary refs log tree commit diff
path: root/src/screens/Messages
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens/Messages')
-rw-r--r--src/screens/Messages/ChatList.tsx15
-rw-r--r--src/screens/Messages/Conversation.tsx61
-rw-r--r--src/screens/Messages/components/RequestButtons.tsx34
-rw-r--r--src/screens/Messages/components/RequestListItem.tsx2
4 files changed, 87 insertions, 25 deletions
diff --git a/src/screens/Messages/ChatList.tsx b/src/screens/Messages/ChatList.tsx
index 2846ed828..9fd54f1b0 100644
--- a/src/screens/Messages/ChatList.tsx
+++ b/src/screens/Messages/ChatList.tsx
@@ -9,6 +9,7 @@ import {type NativeStackScreenProps} from '@react-navigation/native-stack'
 
 import {useAppState} from '#/lib/hooks/useAppState'
 import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
+import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
 import {type MessagesTabNavigatorParams} from '#/lib/routes/types'
 import {cleanError} from '#/lib/strings/errors'
 import {logger} from '#/logger'
@@ -321,6 +322,18 @@ export function MessagesScreen({navigation, route}: Props) {
 function Header({newChatControl}: {newChatControl: DialogControlProps}) {
   const {_} = useLingui()
   const {gtMobile} = useBreakpoints()
+  const requireEmailVerification = useRequireEmailVerification()
+
+  const openChatControl = useCallback(() => {
+    newChatControl.open()
+  }, [newChatControl])
+  const wrappedOpenChatControl = requireEmailVerification(openChatControl, {
+    instructions: [
+      <Trans key="new-chat">
+        Before you can message another user, you must first verify your email.
+      </Trans>,
+    ],
+  })
 
   const settingsLink = (
     <Link
@@ -352,7 +365,7 @@ function Header({newChatControl}: {newChatControl: DialogControlProps}) {
               color="primary"
               size="small"
               variant="solid"
-              onPress={newChatControl.open}>
+              onPress={wrappedOpenChatControl}>
               <ButtonIcon icon={PlusIcon} position="left" />
               <ButtonText>
                 <Trans>New chat</Trans>
diff --git a/src/screens/Messages/Conversation.tsx b/src/screens/Messages/Conversation.tsx
index 2222084ce..90547a8d4 100644
--- a/src/screens/Messages/Conversation.tsx
+++ b/src/screens/Messages/Conversation.tsx
@@ -1,11 +1,11 @@
-import React, {useCallback} from 'react'
+import React, {useCallback, useEffect} from 'react'
 import {View} from 'react-native'
 import {
   type AppBskyActorDefs,
   moderateProfile,
   type ModerationDecision,
 } from '@atproto/api'
-import {msg} from '@lingui/macro'
+import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {
   type RouteProp,
@@ -17,6 +17,7 @@ import {type NativeStackScreenProps} from '@react-navigation/native-stack'
 
 import {useEmail} from '#/lib/hooks/useEmail'
 import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
+import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
 import {
   type CommonNavigatorParams,
   type NavigationProp,
@@ -31,8 +32,10 @@ import {useProfileQuery} from '#/state/queries/profile'
 import {useSetMinimalShellMode} from '#/state/shell'
 import {MessagesList} from '#/screens/Messages/components/MessagesList'
 import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
-import {useDialogControl} from '#/components/Dialog'
-import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
+import {
+  EmailDialogScreenID,
+  useEmailDialogControl,
+} from '#/components/dialogs/EmailDialog'
 import {MessagesListBlockedFooter} from '#/components/dms/MessagesListBlockedFooter'
 import {MessagesListHeader} from '#/components/dms/MessagesListHeader'
 import {Error} from '#/components/Error'
@@ -183,19 +186,50 @@ function InnerReady({
   hasScrolled: boolean
   setHasScrolled: React.Dispatch<React.SetStateAction<boolean>>
 }) {
-  const {_} = useLingui()
   const convoState = useConvo()
   const navigation = useNavigation<NavigationProp>()
   const {params} =
     useRoute<RouteProp<CommonNavigatorParams, 'MessagesConversation'>>()
-  const verifyEmailControl = useDialogControl()
   const {needsEmailVerification} = useEmail()
+  const emailDialogControl = useEmailDialogControl()
 
-  React.useEffect(() => {
+  /**
+   * Must be non-reactive, otherwise the update to open the global dialog will
+   * cause a re-render loop.
+   */
+  const maybeBlockForEmailVerification = useNonReactiveCallback(() => {
     if (needsEmailVerification) {
-      verifyEmailControl.open()
+      /*
+       * HACKFIX
+       *
+       * Load bearing timeout, to bump this state update until the after the
+       * `navigator.addListener('state')` handler closes elements from
+       * `shell/index.*.tsx`  - sfn & esb
+       */
+      setTimeout(() =>
+        emailDialogControl.open({
+          id: EmailDialogScreenID.Verify,
+          instructions: [
+            <Trans key="pre-compose">
+              Before you can message another user, you must first verify your
+              email.
+            </Trans>,
+          ],
+          onCloseWithoutVerifying: () => {
+            if (navigation.canGoBack()) {
+              navigation.goBack()
+            } else {
+              navigation.navigate('Messages', {animation: 'pop'})
+            }
+          },
+        }),
+      )
     }
-  }, [needsEmailVerification, verifyEmailControl])
+  })
+
+  useEffect(() => {
+    maybeBlockForEmailVerification()
+  }, [maybeBlockForEmailVerification])
 
   return (
     <>
@@ -216,15 +250,6 @@ function InnerReady({
           }
         />
       )}
-      <VerifyEmailDialog
-        reasonText={_(
-          msg`Before you may message another user, you must first verify your email.`,
-        )}
-        control={verifyEmailControl}
-        onCloseWithoutVerifying={() => {
-          navigation.navigate('Home')
-        }}
-      />
     </>
   )
 }
diff --git a/src/screens/Messages/components/RequestButtons.tsx b/src/screens/Messages/components/RequestButtons.tsx
index 62db09600..3490bec0d 100644
--- a/src/screens/Messages/components/RequestButtons.tsx
+++ b/src/screens/Messages/components/RequestButtons.tsx
@@ -1,11 +1,12 @@
 import {useCallback} from 'react'
-import {ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
+import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {StackActions, useNavigation} from '@react-navigation/native'
 import {useQueryClient} from '@tanstack/react-query'
 
-import {NavigationProp} from '#/lib/routes/types'
+import {useEmail} from '#/lib/hooks/useEmail'
+import {type NavigationProp} from '#/lib/routes/types'
 import {useProfileShadow} from '#/state/cache/profile-shadow'
 import {useAcceptConversation} from '#/state/queries/messages/accept-conversation'
 import {precacheConvoQuery} from '#/state/queries/messages/conversation'
@@ -13,8 +14,17 @@ import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
 import {useProfileBlockMutationQueue} from '#/state/queries/profile'
 import * as Toast from '#/view/com/util/Toast'
 import {atoms as a} from '#/alf'
-import {Button, ButtonIcon, ButtonProps, ButtonText} from '#/components/Button'
+import {
+  Button,
+  ButtonIcon,
+  type ButtonProps,
+  ButtonText,
+} from '#/components/Button'
 import {useDialogControl} from '#/components/Dialog'
+import {
+  EmailDialogScreenID,
+  useEmailDialogControl,
+} from '#/components/dialogs/EmailDialog'
 import {ReportDialog} from '#/components/dms/ReportDialog'
 import {CircleX_Stroke2_Corner0_Rounded} from '#/components/icons/CircleX'
 import {Flag_Stroke2_Corner0_Rounded as FlagIcon} from '#/components/icons/Flag'
@@ -186,6 +196,8 @@ export function AcceptChatButton({
   const {_} = useLingui()
   const queryClient = useQueryClient()
   const navigation = useNavigation<NavigationProp>()
+  const {needsEmailVerification} = useEmail()
+  const emailDialogControl = useEmailDialogControl()
 
   const {mutate: acceptConvo, isPending} = useAcceptConversation(convo.id, {
     onMutate: () => {
@@ -216,8 +228,20 @@ export function AcceptChatButton({
   })
 
   const onPressAccept = useCallback(() => {
-    acceptConvo()
-  }, [acceptConvo])
+    if (needsEmailVerification) {
+      emailDialogControl.open({
+        id: EmailDialogScreenID.Verify,
+        instructions: [
+          <Trans key="request-btn">
+            Before you can accept this chat request, you must first verify your
+            email.
+          </Trans>,
+        ],
+      })
+    } else {
+      acceptConvo()
+    }
+  }, [acceptConvo, needsEmailVerification, emailDialogControl])
 
   return (
     <Button
diff --git a/src/screens/Messages/components/RequestListItem.tsx b/src/screens/Messages/components/RequestListItem.tsx
index 654691a01..5e09dd2e3 100644
--- a/src/screens/Messages/components/RequestListItem.tsx
+++ b/src/screens/Messages/components/RequestListItem.tsx
@@ -1,5 +1,5 @@
 import {View} from 'react-native'
-import {ChatBskyConvoDefs} from '@atproto/api'
+import {type ChatBskyConvoDefs} from '@atproto/api'
 import {Trans} from '@lingui/macro'
 
 import {useModerationOpts} from '#/state/preferences/moderation-opts'