use new verify email dialog for reminder
This commit is contained in:
+38
-34
@@ -33,7 +33,6 @@ import {attachRouteToLogEvents, logEvent} from '#/lib/statsig/statsig'
|
|||||||
import {bskyTitle} from '#/lib/strings/headings'
|
import {bskyTitle} from '#/lib/strings/headings'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
import {isNative, isWeb} from '#/platform/detection'
|
||||||
import {useModalControls} from '#/state/modals'
|
|
||||||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {
|
import {
|
||||||
@@ -80,33 +79,35 @@ import {ProfileFeedScreen} from '#/screens/Profile/ProfileFeed'
|
|||||||
import {ProfileFollowersScreen} from '#/screens/Profile/ProfileFollowers'
|
import {ProfileFollowersScreen} from '#/screens/Profile/ProfileFollowers'
|
||||||
import {ProfileFollowsScreen} from '#/screens/Profile/ProfileFollows'
|
import {ProfileFollowsScreen} from '#/screens/Profile/ProfileFollows'
|
||||||
import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy'
|
import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy'
|
||||||
|
import {ProfileSearchScreen} from '#/screens/Profile/ProfileSearch'
|
||||||
import {SearchScreen} from '#/screens/Search'
|
import {SearchScreen} from '#/screens/Search'
|
||||||
|
import {AboutSettingsScreen} from '#/screens/Settings/AboutSettings'
|
||||||
|
import {AccessibilitySettingsScreen} from '#/screens/Settings/AccessibilitySettings'
|
||||||
|
import {AccountSettingsScreen} from '#/screens/Settings/AccountSettings'
|
||||||
import {AppearanceSettingsScreen} from '#/screens/Settings/AppearanceSettings'
|
import {AppearanceSettingsScreen} from '#/screens/Settings/AppearanceSettings'
|
||||||
import {AppIconSettingsScreen} from '#/screens/Settings/AppIconSettings'
|
import {AppIconSettingsScreen} from '#/screens/Settings/AppIconSettings'
|
||||||
|
import {AppPasswordsScreen} from '#/screens/Settings/AppPasswords'
|
||||||
|
import {ContentAndMediaSettingsScreen} from '#/screens/Settings/ContentAndMediaSettings'
|
||||||
|
import {ExternalMediaPreferencesScreen} from '#/screens/Settings/ExternalMediaPreferences'
|
||||||
|
import {FollowingFeedPreferencesScreen} from '#/screens/Settings/FollowingFeedPreferences'
|
||||||
|
import {LanguageSettingsScreen} from '#/screens/Settings/LanguageSettings'
|
||||||
import {NotificationSettingsScreen} from '#/screens/Settings/NotificationSettings'
|
import {NotificationSettingsScreen} from '#/screens/Settings/NotificationSettings'
|
||||||
|
import {PrivacyAndSecuritySettingsScreen} from '#/screens/Settings/PrivacyAndSecuritySettings'
|
||||||
|
import {SettingsScreen} from '#/screens/Settings/Settings'
|
||||||
import {SettingsInterests} from '#/screens/Settings/SettingsInterests'
|
import {SettingsInterests} from '#/screens/Settings/SettingsInterests'
|
||||||
|
import {ThreadPreferencesScreen} from '#/screens/Settings/ThreadPreferences'
|
||||||
import {
|
import {
|
||||||
StarterPackScreen,
|
StarterPackScreen,
|
||||||
StarterPackScreenShort,
|
StarterPackScreenShort,
|
||||||
} from '#/screens/StarterPack/StarterPackScreen'
|
} from '#/screens/StarterPack/StarterPackScreen'
|
||||||
import {Wizard} from '#/screens/StarterPack/Wizard'
|
import {Wizard} from '#/screens/StarterPack/Wizard'
|
||||||
|
import TopicScreen from '#/screens/Topic'
|
||||||
import {VideoFeed} from '#/screens/VideoFeed'
|
import {VideoFeed} from '#/screens/VideoFeed'
|
||||||
import {useTheme} from '#/alf'
|
import {useTheme} from '#/alf'
|
||||||
|
import {useDialogControl} from '#/components/Dialog'
|
||||||
|
import {VerifyEmailDialog} from '#/components/dialogs/VerifyEmailDialog'
|
||||||
import {router} from '#/routes'
|
import {router} from '#/routes'
|
||||||
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
import {Referrer} from '../modules/expo-bluesky-swiss-army'
|
||||||
import {ProfileSearchScreen} from './screens/Profile/ProfileSearch'
|
|
||||||
import {AboutSettingsScreen} from './screens/Settings/AboutSettings'
|
|
||||||
import {AccessibilitySettingsScreen} from './screens/Settings/AccessibilitySettings'
|
|
||||||
import {AccountSettingsScreen} from './screens/Settings/AccountSettings'
|
|
||||||
import {AppPasswordsScreen} from './screens/Settings/AppPasswords'
|
|
||||||
import {ContentAndMediaSettingsScreen} from './screens/Settings/ContentAndMediaSettings'
|
|
||||||
import {ExternalMediaPreferencesScreen} from './screens/Settings/ExternalMediaPreferences'
|
|
||||||
import {FollowingFeedPreferencesScreen} from './screens/Settings/FollowingFeedPreferences'
|
|
||||||
import {LanguageSettingsScreen} from './screens/Settings/LanguageSettings'
|
|
||||||
import {PrivacyAndSecuritySettingsScreen} from './screens/Settings/PrivacyAndSecuritySettings'
|
|
||||||
import {SettingsScreen} from './screens/Settings/Settings'
|
|
||||||
import {ThreadPreferencesScreen} from './screens/Settings/ThreadPreferences'
|
|
||||||
import TopicScreen from './screens/Topic'
|
|
||||||
|
|
||||||
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
const navigationRef = createNavigationContainerRef<AllNavigatorParams>()
|
||||||
|
|
||||||
@@ -736,36 +737,39 @@ const LINKING = {
|
|||||||
function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
||||||
const theme = useColorSchemeStyle(DefaultTheme, DarkTheme)
|
const theme = useColorSchemeStyle(DefaultTheme, DarkTheme)
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const {openModal} = useModalControls()
|
|
||||||
const prevLoggedRouteName = React.useRef<string | undefined>(undefined)
|
const prevLoggedRouteName = React.useRef<string | undefined>(undefined)
|
||||||
|
const verifyEmailDialogControl = useDialogControl()
|
||||||
|
|
||||||
function onReady() {
|
function onReady() {
|
||||||
prevLoggedRouteName.current = getCurrentRouteName()
|
prevLoggedRouteName.current = getCurrentRouteName()
|
||||||
if (currentAccount && shouldRequestEmailConfirmation(currentAccount)) {
|
if (currentAccount && shouldRequestEmailConfirmation(currentAccount)) {
|
||||||
openModal({name: 'verify-email', showReminder: true})
|
verifyEmailDialogControl.open()
|
||||||
snoozeEmailConfirmationPrompt()
|
snoozeEmailConfirmationPrompt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationContainer
|
<>
|
||||||
ref={navigationRef}
|
<NavigationContainer
|
||||||
linking={LINKING}
|
ref={navigationRef}
|
||||||
theme={theme}
|
linking={LINKING}
|
||||||
onStateChange={() => {
|
theme={theme}
|
||||||
logger.metric('router:navigate', {
|
onStateChange={() => {
|
||||||
from: prevLoggedRouteName.current,
|
logger.metric('router:navigate', {
|
||||||
})
|
from: prevLoggedRouteName.current,
|
||||||
prevLoggedRouteName.current = getCurrentRouteName()
|
})
|
||||||
}}
|
prevLoggedRouteName.current = getCurrentRouteName()
|
||||||
onReady={() => {
|
}}
|
||||||
attachRouteToLogEvents(getCurrentRouteName)
|
onReady={() => {
|
||||||
logModuleInitTime()
|
attachRouteToLogEvents(getCurrentRouteName)
|
||||||
onReady()
|
logModuleInitTime()
|
||||||
logger.metric('router:navigate', {})
|
onReady()
|
||||||
}}>
|
logger.metric('router:navigate', {})
|
||||||
{children}
|
}}>
|
||||||
</NavigationContainer>
|
{children}
|
||||||
|
</NavigationContainer>
|
||||||
|
<VerifyEmailDialog control={verifyEmailDialogControl} reminder />
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import {useState} from 'react'
|
||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -7,10 +7,11 @@ import {cleanError} from '#/lib/strings/errors'
|
|||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
|
||||||
import {atoms as a, useBreakpoints, web} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import * as TextField from '#/components/forms/TextField'
|
import * as TextField from '#/components/forms/TextField'
|
||||||
|
import {Envelope_Filled_Stroke2_Corner0_Rounded as EnvelopeIcon} from '#/components/icons/Envelope'
|
||||||
import {InlineLinkText} from '#/components/Link'
|
import {InlineLinkText} from '#/components/Link'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
@@ -22,6 +23,7 @@ export function VerifyEmailDialog({
|
|||||||
onCloseAfterVerifying,
|
onCloseAfterVerifying,
|
||||||
reasonText,
|
reasonText,
|
||||||
changeEmailControl,
|
changeEmailControl,
|
||||||
|
reminder,
|
||||||
}: {
|
}: {
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
onCloseWithoutVerifying?: () => void
|
onCloseWithoutVerifying?: () => void
|
||||||
@@ -33,11 +35,12 @@ export function VerifyEmailDialog({
|
|||||||
* helps reduce duplication, since these dialogs are often used together.
|
* helps reduce duplication, since these dialogs are often used together.
|
||||||
*/
|
*/
|
||||||
changeEmailControl?: Dialog.DialogControlProps
|
changeEmailControl?: Dialog.DialogControlProps
|
||||||
|
reminder?: boolean
|
||||||
}) {
|
}) {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const fallbackChangeEmailControl = Dialog.useDialogControl()
|
const fallbackChangeEmailControl = Dialog.useDialogControl()
|
||||||
|
|
||||||
const [didVerify, setDidVerify] = React.useState(false)
|
const [didVerify, setDidVerify] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -62,6 +65,7 @@ export function VerifyEmailDialog({
|
|||||||
setDidVerify={setDidVerify}
|
setDidVerify={setDidVerify}
|
||||||
reasonText={reasonText}
|
reasonText={reasonText}
|
||||||
changeEmailControl={changeEmailControl ?? fallbackChangeEmailControl}
|
changeEmailControl={changeEmailControl ?? fallbackChangeEmailControl}
|
||||||
|
reminder={reminder}
|
||||||
/>
|
/>
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
{!changeEmailControl && (
|
{!changeEmailControl && (
|
||||||
@@ -78,25 +82,34 @@ export function Inner({
|
|||||||
setDidVerify,
|
setDidVerify,
|
||||||
reasonText,
|
reasonText,
|
||||||
changeEmailControl,
|
changeEmailControl,
|
||||||
|
reminder,
|
||||||
}: {
|
}: {
|
||||||
setDidVerify: (value: boolean) => void
|
setDidVerify: (value: boolean) => void
|
||||||
reasonText?: string
|
reasonText?: string
|
||||||
changeEmailControl: Dialog.DialogControlProps
|
changeEmailControl: Dialog.DialogControlProps
|
||||||
|
reminder?: boolean
|
||||||
}) {
|
}) {
|
||||||
const control = Dialog.useDialogContext()
|
const control = Dialog.useDialogContext()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {currentAccount} = useSession()
|
const {currentAccount} = useSession()
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
const [currentStep, setCurrentStep] = React.useState<
|
const [currentStep, setCurrentStep] = useState<
|
||||||
'StepOne' | 'StepTwo' | 'StepThree'
|
'Reminder' | 'StepOne' | 'StepTwo' | 'StepThree'
|
||||||
>('StepOne')
|
>(reminder ? 'Reminder' : 'StepOne')
|
||||||
const [confirmationCode, setConfirmationCode] = React.useState('')
|
const [confirmationCode, setConfirmationCode] = useState('')
|
||||||
const [isProcessing, setIsProcessing] = React.useState(false)
|
const [isProcessing, setIsProcessing] = useState(false)
|
||||||
const [error, setError] = React.useState('')
|
const [error, setError] = useState('')
|
||||||
|
|
||||||
const uiStrings = {
|
const uiStrings = {
|
||||||
|
Reminder: {
|
||||||
|
title: _(msg`Please Verify Your Email`),
|
||||||
|
message: _(
|
||||||
|
msg`Your email has not yet been verified. This is an important security step which we recommend.`,
|
||||||
|
),
|
||||||
|
},
|
||||||
StepOne: {
|
StepOne: {
|
||||||
title: _(msg`Verify Your Email`),
|
title: _(msg`Verify Your Email`),
|
||||||
message: '',
|
message: '',
|
||||||
@@ -151,6 +164,17 @@ export function Inner({
|
|||||||
style={web({maxWidth: 450})}>
|
style={web({maxWidth: 450})}>
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
<View style={[a.gap_xl]}>
|
<View style={[a.gap_xl]}>
|
||||||
|
{currentStep === 'Reminder' && (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.rounded_sm,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_center,
|
||||||
|
{height: 150, backgroundColor: t.palette.primary_500},
|
||||||
|
]}>
|
||||||
|
<EnvelopeIcon width={64} fill="white" />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
<View style={[a.gap_sm]}>
|
<View style={[a.gap_sm]}>
|
||||||
<Text style={[a.font_heavy, a.text_2xl]}>
|
<Text style={[a.font_heavy, a.text_2xl]}>
|
||||||
{uiStrings[currentStep].title}
|
{uiStrings[currentStep].title}
|
||||||
@@ -233,7 +257,32 @@ export function Inner({
|
|||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
<View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}>
|
<View style={[a.gap_sm, gtMobile && [a.flex_row_reverse, a.ml_auto]]}>
|
||||||
{currentStep === 'StepOne' ? (
|
{currentStep === 'Reminder' ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Get started`)}
|
||||||
|
variant="solid"
|
||||||
|
color="primary"
|
||||||
|
size="large"
|
||||||
|
onPress={() => setCurrentStep('StepOne')}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Get started</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
label={_(msg`Maybe layer`)}
|
||||||
|
accessibilityHint={_(msg`Snooze reminder`)}
|
||||||
|
variant="solid"
|
||||||
|
color="secondary"
|
||||||
|
size="large"
|
||||||
|
disabled={isProcessing}
|
||||||
|
onPress={() => control.close()}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Maybe later</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
) : currentStep === 'StepOne' ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Send confirmation email`)}
|
label={_(msg`Send confirmation email`)}
|
||||||
@@ -243,7 +292,7 @@ export function Inner({
|
|||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
onPress={onSendEmail}>
|
onPress={onSendEmail}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Send Confirmation</Trans>
|
<Trans>Send confirmation</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
{isProcessing ? (
|
{isProcessing ? (
|
||||||
<Loader size="sm" style={[{color: 'white'}]} />
|
<Loader size="sm" style={[{color: 'white'}]} />
|
||||||
@@ -278,7 +327,7 @@ export function Inner({
|
|||||||
) : null}
|
) : null}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Resend Email`)}
|
label={_(msg`Resend email`)}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -288,13 +337,13 @@ export function Inner({
|
|||||||
setCurrentStep('StepOne')
|
setCurrentStep('StepOne')
|
||||||
}}>
|
}}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Resend Email</Trans>
|
<Trans>Resend email</Trans>
|
||||||
</ButtonText>
|
</ButtonText>
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : currentStep === 'StepThree' ? (
|
) : currentStep === 'StepThree' ? (
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Confirm`)}
|
label={_(msg`Close`)}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="primary"
|
color="primary"
|
||||||
size="large"
|
size="large"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
|
import * as persisted from '#/state/persisted'
|
||||||
import {clearStorage} from '#/state/persisted'
|
import {clearStorage} from '#/state/persisted'
|
||||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||||
import {useDeleteActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
import {useDeleteActorDeclaration} from '#/state/queries/messages/actor-declaration'
|
||||||
@@ -359,6 +360,16 @@ function DevOptions() {
|
|||||||
Toast.show(_(msg`Storage cleared, you need to restart the app now.`))
|
Toast.show(_(msg`Storage cleared, you need to restart the app now.`))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onPressUnsnoozeReminder = () => {
|
||||||
|
const lastEmailConfirm = new Date()
|
||||||
|
// wind back 3 days
|
||||||
|
lastEmailConfirm.setDate(lastEmailConfirm.getDate() - 3)
|
||||||
|
persisted.write('reminders', {
|
||||||
|
...persisted.get('reminders'),
|
||||||
|
lastEmailConfirm: lastEmailConfirm.toISOString(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
@@ -396,6 +407,13 @@ function DevOptions() {
|
|||||||
<Trans>Reset onboarding state</Trans>
|
<Trans>Reset onboarding state</Trans>
|
||||||
</SettingsList.ItemText>
|
</SettingsList.ItemText>
|
||||||
</SettingsList.PressableItem>
|
</SettingsList.PressableItem>
|
||||||
|
<SettingsList.PressableItem
|
||||||
|
onPress={onPressUnsnoozeReminder}
|
||||||
|
label={_(msg`Unsnooze email reminder`)}>
|
||||||
|
<SettingsList.ItemText>
|
||||||
|
<Trans>Unsnooze email reminder</Trans>
|
||||||
|
</SettingsList.ItemText>
|
||||||
|
</SettingsList.PressableItem>
|
||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
onPress={() => clearAllStorage()}
|
onPress={() => clearAllStorage()}
|
||||||
label={_(msg`Clear all storage data`)}>
|
label={_(msg`Clear all storage data`)}>
|
||||||
|
|||||||
Reference in New Issue
Block a user