···11-import {STALE} from '#/state/queries'
22-import {useServiceConfigQuery} from '#/state/queries/email-verification-required'
33-import {useProfileQuery} from '#/state/queries/profile'
44-import {useSession} from '#/state/session'
55-import {BSKY_SERVICE} from '../constants'
66-import {getHostnameFromUrl} from '../strings/url-helpers'
77-88-export function useEmail() {
99- const {currentAccount} = useSession()
1010-1111- const {data: serviceConfig} = useServiceConfigQuery()
1212- const {data: profile} = useProfileQuery({
1313- did: currentAccount?.did,
1414- staleTime: STALE.INFINITY,
1515- })
1616-1717- const checkEmailConfirmed = !!serviceConfig?.checkEmailConfirmed
1818-1919- // Date set for 11 AM PST on the 18th of November
2020- const isNewEnough =
2121- !!profile?.createdAt &&
2222- Date.parse(profile.createdAt) >= Date.parse('2024-11-18T19:00:00.000Z')
2323-2424- const isSelfHost =
2525- currentAccount &&
2626- getHostnameFromUrl(currentAccount.service) !==
2727- getHostnameFromUrl(BSKY_SERVICE)
2828-2929- const needsEmailVerification =
3030- !isSelfHost &&
3131- checkEmailConfirmed &&
3232- !currentAccount?.emailConfirmed &&
3333- isNewEnough
3434-3535- return {needsEmailVerification}
3636-}
+2-2
src/lib/hooks/useOpenComposer.tsx
···22import {Trans} from '@lingui/macro'
3344import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
55-import {useOpenComposer as rootUseOpenComposer} from '#/state/shell/composer'
55+import {useOpenComposer as useRootOpenComposer} from '#/state/shell/composer'
6677export function useOpenComposer() {
88- const {openComposer} = rootUseOpenComposer()
88+ const {openComposer} = useRootOpenComposer()
99 const requireEmailVerification = useRequireEmailVerification()
1010 return useMemo(() => {
1111 return {
+1-1
src/lib/hooks/useRequireEmailVerification.tsx
···11import {useCallback} from 'react'
22import {Keyboard} from 'react-native'
3344-import {useEmail} from '#/lib/hooks/useEmail'
44+import {useEmail} from '#/state/email-verification'
55import {useRequireAuth, useSession} from '#/state/session'
66import {useCloseAllActiveElements} from '#/state/util'
77import {
+1-1
src/screens/Messages/Conversation.tsx
···1515} from '@react-navigation/native'
1616import {type NativeStackScreenProps} from '@react-navigation/native-stack'
17171818-import {useEmail} from '#/lib/hooks/useEmail'
1918import {useEnableKeyboardControllerScreen} from '#/lib/hooks/useEnableKeyboardController'
2019import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
2120import {
···2423} from '#/lib/routes/types'
2524import {isWeb} from '#/platform/detection'
2625import {type Shadow, useMaybeProfileShadow} from '#/state/cache/profile-shadow'
2626+import {useEmail} from '#/state/email-verification'
2727import {ConvoProvider, isConvoActive, useConvo} from '#/state/messages/convo'
2828import {ConvoStatus} from '#/state/messages/convo/types'
2929import {useCurrentConvoId} from '#/state/messages/current-convo-id'
+1-1
src/screens/Messages/components/MessageInput.tsx
···18181919import {HITSLOP_10, MAX_DM_GRAPHEME_LENGTH} from '#/lib/constants'
2020import {useHaptics} from '#/lib/haptics'
2121-import {useEmail} from '#/lib/hooks/useEmail'
2221import {isIOS, isWeb} from '#/platform/detection'
2222+import {useEmail} from '#/state/email-verification'
2323import {
2424 useMessageDraft,
2525 useSaveMessageDraft,
···55import {StackActions, useNavigation} from '@react-navigation/native'
66import {useQueryClient} from '@tanstack/react-query'
7788-import {useEmail} from '#/lib/hooks/useEmail'
98import {type NavigationProp} from '#/lib/routes/types'
109import {useProfileShadow} from '#/state/cache/profile-shadow'
1010+import {useEmail} from '#/state/email-verification'
1111import {useAcceptConversation} from '#/state/queries/messages/accept-conversation'
1212import {precacheConvoQuery} from '#/state/queries/messages/conversation'
1313import {useLeaveConvo} from '#/state/queries/messages/leave-conversation'
+64
src/state/email-verification.tsx
···11+import {createContext, useContext, useMemo} from 'react'
22+33+import {BSKY_SERVICE} from '#/lib/constants'
44+import {getHostnameFromUrl} from '#/lib/strings/url-helpers'
55+import {STALE} from '#/state/queries'
66+import {useProfileQuery} from '#/state/queries/profile'
77+import {useCheckEmailConfirmed} from '#/state/service-config'
88+import {useSession} from '#/state/session'
99+1010+type EmailVerificationContext = {
1111+ needsEmailVerification: boolean
1212+}
1313+1414+const EmailVerificationContext = createContext<EmailVerificationContext | null>(
1515+ null,
1616+)
1717+EmailVerificationContext.displayName = 'EmailVerificationContext'
1818+1919+export function Provider({children}: {children: React.ReactNode}) {
2020+ const {currentAccount} = useSession()
2121+2222+ const {data: profile} = useProfileQuery({
2323+ did: currentAccount?.did,
2424+ staleTime: STALE.INFINITY,
2525+ })
2626+2727+ const checkEmailConfirmed = useCheckEmailConfirmed()
2828+2929+ // Date set for 11 AM PST on the 18th of November
3030+ const isNewEnough =
3131+ !!profile?.createdAt &&
3232+ Date.parse(profile.createdAt) >= Date.parse('2024-11-18T19:00:00.000Z')
3333+3434+ const isSelfHost =
3535+ currentAccount &&
3636+ getHostnameFromUrl(currentAccount.service) !==
3737+ getHostnameFromUrl(BSKY_SERVICE)
3838+3939+ const needsEmailVerification =
4040+ !isSelfHost &&
4141+ checkEmailConfirmed &&
4242+ !currentAccount?.emailConfirmed &&
4343+ isNewEnough
4444+4545+ const value = useMemo(
4646+ () => ({needsEmailVerification}),
4747+ [needsEmailVerification],
4848+ )
4949+5050+ return (
5151+ <EmailVerificationContext.Provider value={value}>
5252+ {children}
5353+ </EmailVerificationContext.Provider>
5454+ )
5555+}
5656+Provider.displayName = 'EmailVerificationProvider'
5757+5858+export function useEmail() {
5959+ const ctx = useContext(EmailVerificationContext)
6060+ if (!ctx) {
6161+ throw new Error('useEmail must be used within a EmailVerificationProvider')
6262+ }
6363+ return ctx
6464+}