From ee9fcd12f615d20615ceaac739b03507c054cfb2 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Thu, 19 Jun 2025 12:48:07 -0700 Subject: [PATCH 1/3] [PE-6262] Add fast referral signup to all platforms --- .../sign-on-screen/hooks/useFastReferral.ts | 13 ++++++++++ .../screens/AccountLoadingScreen.tsx | 21 ++++++++++++---- .../screens/FinishProfileScreen.tsx | 10 ++++++-- .../screens/PickHandleScreen.tsx | 12 ++++++++-- .../SelectArtistsScreen.tsx | 24 +++++++++++++++---- .../screens/SelectGenresScreen.tsx | 24 +++++++++++++++++-- .../sign-up-page/hooks/useFastReferral.ts | 4 +--- .../sign-up-page/pages/SelectArtistsPage.tsx | 8 +++++-- 8 files changed, 95 insertions(+), 21 deletions(-) create mode 100644 packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts diff --git a/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts b/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts new file mode 100644 index 00000000000..a93186fbc27 --- /dev/null +++ b/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts @@ -0,0 +1,13 @@ +import { useFeatureFlag } from '@audius/common/hooks' +import { FeatureFlags } from '@audius/common/services' +import { getReferrer } from 'common/store/pages/signon/selectors' +import { useSelector } from 'react-redux' + +export const useFastReferral = () => { + const hasReferrer = useSelector(getReferrer) + const { isEnabled: isFastReferralEnabled } = useFeatureFlag( + FeatureFlags.FAST_REFERRAL + ) + // Remove isMobile check to enable fast referral on all platforms + return Boolean(hasReferrer && isFastReferralEnabled) +} diff --git a/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx index 7393af2652a..ef0dde973ef 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx @@ -2,7 +2,10 @@ import { useEffect } from 'react' -import { getStatus } from '@audius/web/src/common/store/pages/signon/selectors' +import { + getStatus, + getAccountReady +} from '@audius/web/src/common/store/pages/signon/selectors' import { EditingStatus } from '@audius/web/src/common/store/pages/signon/types' import { useSelector } from 'react-redux' @@ -11,6 +14,8 @@ import LoadingSpinner from 'app/components/loading-spinner' import { useNavigation } from 'app/hooks/useNavigation' import { Heading, Page } from '../components/layout' +import { useFastReferral } from '../hooks/useFastReferral' +import type { SignOnScreenParamList } from '../types' const messages = { heading: 'Your Account is Almost Ready to Rock 🀘', @@ -19,15 +24,21 @@ const messages = { // The user just waits here until the account is created and before being shown the welcome modal on the trending page export const AccountLoadingScreen = () => { - const navigation = useNavigation() - + const navigation = useNavigation() + const isFastReferral = useFastReferral() + const accountReady = useSelector(getAccountReady) const accountCreationStatus = useSelector(getStatus) + const isAccountReady = isFastReferral + ? accountReady + : accountCreationStatus === EditingStatus.SUCCESS + useEffect(() => { - if (accountCreationStatus === EditingStatus.SUCCESS) { + if (isAccountReady) { navigation.navigate('HomeStack', { screen: 'Trending' }) } - }, [accountCreationStatus, navigation]) + // TODO: what to do in an error scenario? Any way to recover to a valid step? + }, [isAccountReady, navigation]) return ( diff --git a/packages/mobile/src/screens/sign-on-screen/screens/FinishProfileScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/FinishProfileScreen.tsx index 3fb6a14d9de..aba6928df0b 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/FinishProfileScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/FinishProfileScreen.tsx @@ -37,6 +37,7 @@ import { launchSelectImageActionSheet } from 'app/utils/launchSelectImageActionS import { AccountHeader } from '../components/AccountHeader' import { Heading, Page, PageFooter } from '../components/layout' +import { useFastReferral } from '../hooks/useFastReferral' import type { SignOnScreenParamList } from '../types' import { useTrackScreen } from '../utils/useTrackScreen' @@ -57,6 +58,7 @@ export const FinishProfileScreen = () => { const savedProfileImage = useSelector(getProfileImageField) const savedCoverPhoto = useSelector(getCoverPhotoField) const { value: savedDisplayName } = useSelector(getNameField) ?? {} + const isFastReferral = useFastReferral() useTrackScreen('FinishProfile') @@ -65,9 +67,13 @@ export const FinishProfileScreen = () => { const { displayName } = values dispatch(setValueField('name', displayName)) dispatch(signUp()) - navigation.navigate('SelectGenre') + if (isFastReferral) { + navigation.navigate('AccountLoading') + } else { + navigation.navigate('SelectGenre') + } }, - [dispatch, navigation] + [dispatch, isFastReferral, navigation] ) const initialValues = { diff --git a/packages/mobile/src/screens/sign-on-screen/screens/PickHandleScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/PickHandleScreen.tsx index b68d9637b41..dc53cbe9331 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/PickHandleScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/PickHandleScreen.tsx @@ -30,6 +30,7 @@ import { SocialMediaLoading } from '../components/SocialMediaLoading' import { SocialMediaSignUpButtons } from '../components/SocialMediaSignUpButtons' import { Heading, Page, PageFooter } from '../components/layout' import { useSocialMediaLoader } from '../components/useSocialMediaLoader' +import { useFastReferral } from '../hooks/useFastReferral' import type { SignOnScreenParamList } from '../types' import { restrictedHandles } from '../utils/restrictedHandles' import { useTrackScreen } from '../utils/useTrackScreen' @@ -96,6 +97,7 @@ export const PickHandleScreen = () => { const navigation = useNavigation() const dispatch = useDispatch() const alreadyLinkedSocial = useSelector(getIsSocialConnected) + const isFastReferral = useFastReferral() const { isWaitingForSocialLogin, handleStartSocialMediaLogin, @@ -122,9 +124,12 @@ export const PickHandleScreen = () => { (values: PickHandleValues) => { const { handle } = values dispatch(setValueField('handle', handle)) + if (isFastReferral) { + dispatch(setValueField('name', handle)) + } navigation.navigate('FinishProfile') }, - [dispatch, navigation] + [dispatch, isFastReferral, navigation] ) const handleSocialMediaLoginSuccess = useCallback( @@ -138,13 +143,16 @@ export const PickHandleScreen = () => { }) => { handleCompleteSocialMediaLogin() dispatch(setValueField('handle', handle)) + if (isFastReferral) { + dispatch(setValueField('name', handle)) + } if (requiresReview) { navigation.navigate('ReviewHandle') } else { navigation.navigate('FinishProfile') } }, - [dispatch, handleCompleteSocialMediaLogin, navigation] + [dispatch, handleCompleteSocialMediaLogin, isFastReferral, navigation] ) return ( diff --git a/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx index dc577f561a4..ed175dcbe52 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx @@ -20,6 +20,7 @@ import { useNavigation } from 'app/hooks/useNavigation' import { ReadOnlyAccountHeader } from '../../components/AccountHeader' import { Heading, PageFooter } from '../../components/layout' +import { useFastReferral } from '../../hooks/useFastReferral' import type { SignOnScreenParamList } from '../../types' import { useTrackScreen } from '../../utils/useTrackScreen' @@ -39,6 +40,7 @@ export const SelectArtistsScreen = () => { const selectedArtists = useSelector(getFollowIds) const dispatch = useDispatch() const navigation = useNavigation() + const isFastReferral = useFastReferral() useTrackScreen('SelectArtists') const accountCreationStatus = useSelector(getStatus) @@ -64,12 +66,24 @@ export const SelectArtistsScreen = () => { // Follow selected artists dispatch(addFollowArtists(selectedArtists)) dispatch(completeFollowArtists()) - // This call is what eventually triggers the RootScreen to redirect to the home page (via conditional rendering) - dispatch(finishSignUp()) - if (accountCreationStatus === EditingStatus.LOADING) { - navigation.navigate('AccountLoading') + + if (isFastReferral) { + // In fast referral mode, go directly to home screen + navigation.navigate('HomeStack', { screen: 'Trending' }) + } else { + // This call is what eventually triggers the RootScreen to redirect to the home page (via conditional rendering) + dispatch(finishSignUp()) + if (accountCreationStatus === EditingStatus.LOADING) { + navigation.navigate('AccountLoading') + } } - }, [accountCreationStatus, dispatch, navigation, selectedArtists]) + }, [ + accountCreationStatus, + dispatch, + isFastReferral, + navigation, + selectedArtists + ]) return ( diff --git a/packages/mobile/src/screens/sign-on-screen/screens/SelectGenresScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/SelectGenresScreen.tsx index 3ed1f9ffac9..0b4f802d664 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/SelectGenresScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/SelectGenresScreen.tsx @@ -11,13 +11,20 @@ import { useDispatch } from 'react-redux' import { useEffectOnce } from 'react-use' import { toFormikValidationSchema } from 'zod-formik-adapter' -import { Box, Flex, Paper, SelectablePill } from '@audius/harmony-native' +import { + Box, + Flex, + Paper, + SelectablePill, + Button +} from '@audius/harmony-native' import { useNavigation } from 'app/hooks/useNavigation' import { make, track } from 'app/services/analytics' import { EventNames } from 'app/types/analytics' import { ReadOnlyAccountHeader } from '../components/AccountHeader' import { Heading, PageFooter, gutterSize } from '../components/layout' +import { useFastReferral } from '../hooks/useFastReferral' import type { SignOnScreenParamList } from '../types' import { useTrackScreen } from '../utils/useTrackScreen' @@ -93,6 +100,7 @@ const SelectGenresFieldArray = () => { export const SelectGenresScreen = () => { const dispatch = useDispatch() const navigation = useNavigation() + const isFastReferral = useFastReferral() useEffectOnce(() => { dispatch(setFinishedPhase1(true)) @@ -107,6 +115,10 @@ export const SelectGenresScreen = () => { [dispatch, navigation] ) + const handleSkip = useCallback(() => { + navigation.navigate('SelectArtists') + }, [navigation]) + return ( { - + + Skip + + ) : null + } + /> ) diff --git a/packages/web/src/pages/sign-up-page/hooks/useFastReferral.ts b/packages/web/src/pages/sign-up-page/hooks/useFastReferral.ts index 21356657cc1..bf4bfb68c70 100644 --- a/packages/web/src/pages/sign-up-page/hooks/useFastReferral.ts +++ b/packages/web/src/pages/sign-up-page/hooks/useFastReferral.ts @@ -3,13 +3,11 @@ import { FeatureFlags } from '@audius/common/services' import { useSelector } from 'react-redux' import { getReferrer } from 'common/store/pages/signon/selectors' -import { useMedia } from 'hooks/useMedia' export const useFastReferral = () => { const hasReferrer = useSelector(getReferrer) const { isEnabled: isFastReferralEnabled } = useFeatureFlag( FeatureFlags.FAST_REFERRAL ) - const { isMobile } = useMedia() - return Boolean(hasReferrer && isFastReferralEnabled && isMobile) + return Boolean(hasReferrer && isFastReferralEnabled) } diff --git a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx index a4084d84dfb..d8b27af0f01 100644 --- a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx @@ -79,13 +79,17 @@ export const SelectArtistsPage = () => { const { selectedArtists } = values const artistsIDArray = [...selectedArtists].map((a) => Number(a)) dispatch(addFollowArtists(artistsIDArray)) - if (isMobile) { + + if (isFastReferral) { + // In fast referral mode, navigate to app CTA instead of completing sign up + navigate(SIGN_UP_APP_CTA_PAGE) + } else if (isMobile) { navigate(SIGN_UP_COMPLETED_REDIRECT) } else { navigate(SIGN_UP_APP_CTA_PAGE) } }, - [dispatch, isMobile, navigate] + [dispatch, isFastReferral, isMobile, navigate] ) const isFeaturedArtists = currentGenre === 'Featured' From 68342683ed84728a8121bfe2e5237f25cec27062 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 22 Sep 2025 18:15:04 -0700 Subject: [PATCH 2/3] Finalize --- packages/common/src/messages/sign-on/pages.ts | 4 ++ .../schemas/sign-on/finishProfileSchema.ts | 8 ++-- .../schemas/sign-on/selectArtistsSchema.ts | 2 +- .../src/schemas/sign-on/selectGenresSchema.ts | 2 +- .../suggested-follows/SuggestedFollows.tsx | 5 +-- .../sign-on-screen/components/SkipButton.tsx | 26 +++++++++++++ .../sign-on-screen/components/layout.tsx | 20 +++++++--- .../screens/AccountLoadingScreen.tsx | 18 ++------- .../screens/FinishProfileScreen.tsx | 38 +++++-------------- .../SelectArtistsScreen.tsx | 2 + .../screens/SelectGenresScreen.tsx | 25 ++---------- .../src/common/store/pages/signon/sagas.ts | 22 +++++++---- .../feed-page/components/FollowUsers.tsx | 2 +- .../sign-up-page/components/SkipButton.tsx | 12 ++++-- .../sign-up-page/pages/FinishProfilePage.tsx | 6 ++- .../sign-up-page/pages/LoadingAccountPage.tsx | 37 +++++++++++++++--- .../sign-up-page/pages/SelectArtistsPage.tsx | 2 +- .../sign-up-page/pages/SelectGenresPage.tsx | 4 +- .../utils/useDetermineAllowedRoutes.ts | 5 +-- 19 files changed, 136 insertions(+), 104 deletions(-) create mode 100644 packages/mobile/src/screens/sign-on-screen/components/SkipButton.tsx diff --git a/packages/common/src/messages/sign-on/pages.ts b/packages/common/src/messages/sign-on/pages.ts index b74db3cd866..40f3912e05a 100644 --- a/packages/common/src/messages/sign-on/pages.ts +++ b/packages/common/src/messages/sign-on/pages.ts @@ -126,3 +126,7 @@ export const welcomeModalMessages = { youreIn: "You're in! Discover music from our talented DJs, producers, and artists." } + +export const skipButtonMessages = { + skipThisStep: 'Skip this step' +} diff --git a/packages/common/src/schemas/sign-on/finishProfileSchema.ts b/packages/common/src/schemas/sign-on/finishProfileSchema.ts index 0df909a389a..f21a0bc0f4a 100644 --- a/packages/common/src/schemas/sign-on/finishProfileSchema.ts +++ b/packages/common/src/schemas/sign-on/finishProfileSchema.ts @@ -6,9 +6,11 @@ export const finishProfileSchema = z.object({ displayName: z .string({ required_error: 'Display name is required.' }) .max(MAX_DISPLAY_NAME_LENGTH, ''), - profileImage: z.object({ - url: z.string() - }), + profileImage: z + .object({ + url: z.string() + }) + .optional(), coverPhoto: z .object({ url: z.string().optional() diff --git a/packages/common/src/schemas/sign-on/selectArtistsSchema.ts b/packages/common/src/schemas/sign-on/selectArtistsSchema.ts index 99014c2dab6..8adcf91e5a4 100644 --- a/packages/common/src/schemas/sign-on/selectArtistsSchema.ts +++ b/packages/common/src/schemas/sign-on/selectArtistsSchema.ts @@ -1,5 +1,5 @@ import { z } from 'zod' export const selectArtistsSchema = z.object({ - selectedArtists: z.array(z.string()).min(3) + selectedArtists: z.array(z.string()).optional() }) diff --git a/packages/common/src/schemas/sign-on/selectGenresSchema.ts b/packages/common/src/schemas/sign-on/selectGenresSchema.ts index 0e577eb726a..0e0b503def1 100644 --- a/packages/common/src/schemas/sign-on/selectGenresSchema.ts +++ b/packages/common/src/schemas/sign-on/selectGenresSchema.ts @@ -19,5 +19,5 @@ export const selectableGenres = GENRES.filter( })) export const selectGenresSchema = z.object({ - genres: z.array(z.string()).min(1) + genres: z.array(z.string()).optional() }) diff --git a/packages/mobile/src/components/suggested-follows/SuggestedFollows.tsx b/packages/mobile/src/components/suggested-follows/SuggestedFollows.tsx index fc5824b7cb1..8d9dac7acdd 100644 --- a/packages/mobile/src/components/suggested-follows/SuggestedFollows.tsx +++ b/packages/mobile/src/components/suggested-follows/SuggestedFollows.tsx @@ -38,9 +38,8 @@ const useStyles = makeStyles(({ spacing, palette }) => ({ })) const messages = { - title: `Oops! There's nothing here.`, - instruction: - 'Tracks uploaded or reposted by people you follow will appear in your feed.' + title: `Follow users to personalize your feed`, + instruction: `Let's fix that by following some of these artists!` } export const SuggestedFollows = () => { diff --git a/packages/mobile/src/screens/sign-on-screen/components/SkipButton.tsx b/packages/mobile/src/screens/sign-on-screen/components/SkipButton.tsx new file mode 100644 index 00000000000..cb3c233cc05 --- /dev/null +++ b/packages/mobile/src/screens/sign-on-screen/components/SkipButton.tsx @@ -0,0 +1,26 @@ +import { useCallback } from 'react' + +import { skipButtonMessages } from '@audius/common/messages' +import { finishSignUp } from '@audius/web/src/common/store/pages/signon/actions' +import { useDispatch } from 'react-redux' + +import { PlainButton } from '@audius/harmony-native' +import { useNavigation } from 'app/hooks/useNavigation' + +import type { SignOnScreenParamList } from '../types' + +export const SkipButton = () => { + const navigation = useNavigation() + const dispatch = useDispatch() + + const handleSkip = useCallback(() => { + dispatch(finishSignUp()) + navigation.navigate('AccountLoading') + }, [dispatch, navigation]) + + return ( + + {skipButtonMessages.skipThisStep} + + ) +} diff --git a/packages/mobile/src/screens/sign-on-screen/components/layout.tsx b/packages/mobile/src/screens/sign-on-screen/components/layout.tsx index 673e794b569..4d0944a5b40 100644 --- a/packages/mobile/src/screens/sign-on-screen/components/layout.tsx +++ b/packages/mobile/src/screens/sign-on-screen/components/layout.tsx @@ -83,10 +83,18 @@ type PageFooterProps = { buttonProps?: Partial centered?: boolean avoidKeyboard?: boolean + requireDirty?: boolean } & Omit export const PageFooter = (props: PageFooterProps) => { - const { prefix, postfix, buttonProps, avoidKeyboard, ...other } = props + const { + prefix, + postfix, + buttonProps, + avoidKeyboard, + requireDirty = true, + ...other + } = props const insets = useSafeAreaInsets() const { spacing } = useTheme() const { handleSubmit, dirty, isValid } = useFormikContext() ?? {} @@ -118,8 +126,6 @@ export const PageFooter = (props: PageFooterProps) => { left: 0 })} > - {/* Prefixes float above the shadowed paper container */} - {prefix ? {prefix} : null} { })} {...other} > + {/* Prefixes float above the shadowed paper container */} + {prefix} - ) : null - } - /> + } /> ) diff --git a/packages/web/src/common/store/pages/signon/sagas.ts b/packages/web/src/common/store/pages/signon/sagas.ts index 56958a4da1a..517560c764e 100644 --- a/packages/web/src/common/store/pages/signon/sagas.ts +++ b/packages/web/src/common/store/pages/signon/sagas.ts @@ -805,13 +805,21 @@ function* signUp() { function* () { yield* put(signOnActions.sendWelcomeEmail(name)) yield* call(fetchAccountAsync, { shouldMarkAccountAsLoading: true }) - yield* call( - waitForValue, - getFollowIds, - null, - (value: ID[]) => value.length > 0 - ) - yield* put(signOnActions.followArtists()) + // Check if user has selected artists to follow + const selectedUserIds = yield* select(getFollowIds) + if (selectedUserIds && selectedUserIds.length > 0) { + // User has selected artists, wait for them and follow + yield* call( + waitForValue, + getFollowIds, + null, + (value: ID[]) => value.length > 0 + ) + yield* put(signOnActions.followArtists()) + } else { + // User skipped artist selection, just follow default artists + yield* put(signOnActions.followArtists()) + } yield* put(make(Name.CREATE_ACCOUNT_COMPLETE_CREATING, { handle })) yield* put(signOnActions.signUpSucceeded()) }, diff --git a/packages/web/src/pages/feed-page/components/FollowUsers.tsx b/packages/web/src/pages/feed-page/components/FollowUsers.tsx index 1b14650a71e..cc62d6d06b4 100644 --- a/packages/web/src/pages/feed-page/components/FollowUsers.tsx +++ b/packages/web/src/pages/feed-page/components/FollowUsers.tsx @@ -11,7 +11,7 @@ import { SelectArtistsPreviewContextProvider } from 'components/follow-artist-ca const messages = { cta: `Let’s fix that by following some of these artists!`, - noFollowers: `Oops! There's nothing here.` + noFollowers: `Your feed is empty` } type FollowUsersValues = { diff --git a/packages/web/src/pages/sign-up-page/components/SkipButton.tsx b/packages/web/src/pages/sign-up-page/components/SkipButton.tsx index c889236208d..10ec22bbc4c 100644 --- a/packages/web/src/pages/sign-up-page/components/SkipButton.tsx +++ b/packages/web/src/pages/sign-up-page/components/SkipButton.tsx @@ -1,17 +1,23 @@ import { useCallback } from 'react' +import { skipButtonMessages } from '@audius/common/messages' import { route } from '@audius/common/utils' import { PlainButton } from '@audius/harmony' import { useNavigateToPage } from 'hooks/useNavigateToPage' -const { SIGN_UP_LOADING_PAGE } = route +const { SIGN_UP_APP_CTA_PAGE } = route export const SkipButton = () => { const navigate = useNavigateToPage() + const handleSkip = useCallback(() => { - navigate(SIGN_UP_LOADING_PAGE) + navigate(SIGN_UP_APP_CTA_PAGE) }, [navigate]) - return Skip this step + return ( + + {skipButtonMessages.skipThisStep} + + ) } diff --git a/packages/web/src/pages/sign-up-page/pages/FinishProfilePage.tsx b/packages/web/src/pages/sign-up-page/pages/FinishProfilePage.tsx index 004f213a66f..5029fb61cee 100644 --- a/packages/web/src/pages/sign-up-page/pages/FinishProfilePage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/FinishProfilePage.tsx @@ -100,9 +100,12 @@ export const FinishProfilePage = () => { const initialValues = { profileImage: savedProfileImage || undefined, coverPhoto: savedCoverPhoto || undefined, - displayName: savedDisplayName || '' + displayName: savedDisplayName || handle.value || '' } + // Ensure display name is always set to handle if empty + const displayNameValue = savedDisplayName || handle.value || '' + const setCoverPhoto = useCallback( (value: ImageFieldValue) => { dispatch(setField('coverPhoto', value)) @@ -187,6 +190,7 @@ export const FinishProfilePage = () => { label={finishProfilePageMessages.displayName} placeholder={finishProfilePageMessages.inputPlaceholder} maxLength={MAX_DISPLAY_NAME_LENGTH} + value={displayNameValue} onChange={(e) => setDisplayName(e.currentTarget.value)} css={(theme) => ({ padding: theme.spacing.l diff --git a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx index e588b9ce817..0817c9af476 100644 --- a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx @@ -1,9 +1,10 @@ -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { route } from '@audius/common/utils' -import { Flex } from '@audius/harmony' -import { useSelector } from 'react-redux' +import { Flex, Button } from '@audius/harmony' +import { useDispatch, useSelector } from 'react-redux' +import { finishSignUp } from 'common/store/pages/signon/actions' import { getStatus, getAccountReady } from 'common/store/pages/signon/selectors' import { EditingStatus } from 'common/store/pages/signon/types' import LoadingSpinner from 'components/loading-spinner/LoadingSpinner' @@ -16,21 +17,23 @@ const { SIGN_UP_COMPLETED_REDIRECT } = route const messages = { heading: 'Your Account is Almost Ready to Rock 🀘', - description: "We're just finishing up a few things..." + description: "We're just finishing up a few things...", + continueButton: 'Continue to Audius' } // This loading page shows up when the users account is still being created either due to slow creation or a fast user // The user just waits here until the account is created and before being shown the welcome modal on the trending page export const LoadingAccountPage = () => { const navigate = useNavigateToPage() + const dispatch = useDispatch() const isFastReferral = useFastReferral() const accountReady = useSelector(getAccountReady) - const accountCreationStatus = useSelector(getStatus) + const [showContinueButton, setShowContinueButton] = useState(false) const isAccountReady = isFastReferral ? accountReady - : accountCreationStatus === EditingStatus.SUCCESS + : accountReady || accountCreationStatus === EditingStatus.SUCCESS useEffect(() => { if (isAccountReady) { @@ -39,6 +42,23 @@ export const LoadingAccountPage = () => { // TODO: what to do in an error scenario? Any way to recover to a valid step? }, [navigate, isAccountReady]) + // Show continue button after 10 seconds if account is still not ready + useEffect(() => { + const timer = setTimeout(() => { + if (!isAccountReady) { + setShowContinueButton(true) + } + }, 10000) // 10 seconds + + return () => clearTimeout(timer) + }, [isAccountReady]) + + const handleContinue = () => { + // Mark sign-up as finished so RootScreen shows HomeStack + dispatch(finishSignUp()) + navigate(SIGN_UP_COMPLETED_REDIRECT) + } + return ( @@ -48,6 +68,11 @@ export const LoadingAccountPage = () => { description={messages.description} /> + {showContinueButton && ( + + )} ) } diff --git a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx index d8b27af0f01..b4cdd0a677a 100644 --- a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx @@ -263,7 +263,7 @@ export const SelectArtistsPage = () => { disabled: !isValid || isSubmitting, isLoading: isSubmitting || isValidating }} - prefix={isFastReferral ? : null} + prefix={} postfix={ {selectArtistsPageMessages.selected}{' '} diff --git a/packages/web/src/pages/sign-up-page/pages/SelectGenresPage.tsx b/packages/web/src/pages/sign-up-page/pages/SelectGenresPage.tsx index de67194887e..1be7b8b1b7a 100644 --- a/packages/web/src/pages/sign-up-page/pages/SelectGenresPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/SelectGenresPage.tsx @@ -19,7 +19,6 @@ import { useNavigateToPage } from 'hooks/useNavigateToPage' import { AccountHeader } from '../components/AccountHeader' import { SkipButton } from '../components/SkipButton' import { Heading, Page, PageFooter, ScrollView } from '../components/layout' -import { useFastReferral } from '../hooks/useFastReferral' const { SIGN_UP_ARTISTS_PAGE } = route @@ -31,7 +30,6 @@ export const SelectGenresPage = () => { const [currentGenres, setCurrentGenres] = useState([]) const savedGenres = useSelector(getGenres) - const isFastReferral = useFastReferral() const { isMobile } = useMedia() const initialValues: SelectGenresValue = { @@ -120,7 +118,7 @@ export const SelectGenresPage = () => { centered sticky buttonProps={{ disabled: !isValid }} - prefix={isFastReferral ? : null} + prefix={} /> )} diff --git a/packages/web/src/pages/sign-up-page/utils/useDetermineAllowedRoutes.ts b/packages/web/src/pages/sign-up-page/utils/useDetermineAllowedRoutes.ts index 74b8fcc12bf..30e151d5695 100644 --- a/packages/web/src/pages/sign-up-page/utils/useDetermineAllowedRoutes.ts +++ b/packages/web/src/pages/sign-up-page/utils/useDetermineAllowedRoutes.ts @@ -67,13 +67,14 @@ export const useDetermineAllowedRoute = () => { // At this point their identity account is either fully created or being created in the background // Either way the user can't go back any more allowedRoutes = [SignUpPath.selectGenres] + // Always allow loading step as users can skip genres and artists + allowedRoutes.push(SignUpPath.loading) if (isFastReferral) { allowedRoutes.push(SignUpPath.selectArtists) allowedRoutes.push(SignUpPath.appCta) allowedRoutes.push(SignUpPath.completedRedirect) allowedRoutes.push(SignUpPath.completedReferrerRedirect) - allowedRoutes.push(SignUpPath.loading) } // TODO: These checks below here may need to fall under a different route umbrella separate from sign up @@ -90,8 +91,6 @@ export const useDetermineAllowedRoute = () => { isAccountComplete ) { allowedRoutes.push(SignUpPath.completedRedirect) - } else { - allowedRoutes.push(SignUpPath.loading) } } } From 73d1aeb3fe80b2cf9d23b9212f18c652656db2a0 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 22 Sep 2025 18:20:59 -0700 Subject: [PATCH 3/3] Finalize --- .../sign-on-screen/hooks/useFastReferral.ts | 1 - .../screens/AccountLoadingScreen.tsx | 1 - .../SelectArtistsScreen.tsx | 22 +++--------- .../sign-up-page/pages/LoadingAccountPage.tsx | 34 +++---------------- .../sign-up-page/pages/SelectArtistsPage.tsx | 9 ++--- 5 files changed, 10 insertions(+), 57 deletions(-) diff --git a/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts b/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts index a93186fbc27..a6358f46d4d 100644 --- a/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts +++ b/packages/mobile/src/screens/sign-on-screen/hooks/useFastReferral.ts @@ -8,6 +8,5 @@ export const useFastReferral = () => { const { isEnabled: isFastReferralEnabled } = useFeatureFlag( FeatureFlags.FAST_REFERRAL ) - // Remove isMobile check to enable fast referral on all platforms return Boolean(hasReferrer && isFastReferralEnabled) } diff --git a/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx index 3360866703d..6999369089d 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/AccountLoadingScreen.tsx @@ -27,7 +27,6 @@ export const AccountLoadingScreen = () => { if (isAccountReady) { navigation.navigate('HomeStack', { screen: 'Trending' }) } - // TODO: what to do in an error scenario? Any way to recover to a valid step? }, [isAccountReady, navigation]) return ( diff --git a/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx b/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx index 9b70f1b29a4..ada658c48b0 100644 --- a/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx +++ b/packages/mobile/src/screens/sign-on-screen/screens/SelectArtistScreen/SelectArtistsScreen.tsx @@ -21,7 +21,6 @@ import { useNavigation } from 'app/hooks/useNavigation' import { ReadOnlyAccountHeader } from '../../components/AccountHeader' import { SkipButton } from '../../components/SkipButton' import { Heading, PageFooter } from '../../components/layout' -import { useFastReferral } from '../../hooks/useFastReferral' import type { SignOnScreenParamList } from '../../types' import { useTrackScreen } from '../../utils/useTrackScreen' @@ -41,7 +40,6 @@ export const SelectArtistsScreen = () => { const selectedArtists = useSelector(getFollowIds) const dispatch = useDispatch() const navigation = useNavigation() - const isFastReferral = useFastReferral() useTrackScreen('SelectArtists') const accountCreationStatus = useSelector(getStatus) @@ -68,23 +66,11 @@ export const SelectArtistsScreen = () => { dispatch(addFollowArtists(selectedArtists)) dispatch(completeFollowArtists()) - if (isFastReferral) { - // In fast referral mode, go directly to home screen - navigation.navigate('HomeStack', { screen: 'Trending' }) - } else { - // This call is what eventually triggers the RootScreen to redirect to the home page (via conditional rendering) - dispatch(finishSignUp()) - if (accountCreationStatus === EditingStatus.LOADING) { - navigation.navigate('AccountLoading') - } + dispatch(finishSignUp()) + if (accountCreationStatus === EditingStatus.LOADING) { + navigation.navigate('AccountLoading') } - }, [ - accountCreationStatus, - dispatch, - isFastReferral, - navigation, - selectedArtists - ]) + }, [accountCreationStatus, dispatch, navigation, selectedArtists]) return ( diff --git a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx index 0817c9af476..d59b27b3bb2 100644 --- a/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/LoadingAccountPage.tsx @@ -1,10 +1,9 @@ -import { useEffect, useState } from 'react' +import { useEffect } from 'react' import { route } from '@audius/common/utils' -import { Flex, Button } from '@audius/harmony' -import { useDispatch, useSelector } from 'react-redux' +import { Flex } from '@audius/harmony' +import { useSelector } from 'react-redux' -import { finishSignUp } from 'common/store/pages/signon/actions' import { getStatus, getAccountReady } from 'common/store/pages/signon/selectors' import { EditingStatus } from 'common/store/pages/signon/types' import LoadingSpinner from 'components/loading-spinner/LoadingSpinner' @@ -17,19 +16,16 @@ const { SIGN_UP_COMPLETED_REDIRECT } = route const messages = { heading: 'Your Account is Almost Ready to Rock 🀘', - description: "We're just finishing up a few things...", - continueButton: 'Continue to Audius' + description: "We're just finishing up a few things..." } // This loading page shows up when the users account is still being created either due to slow creation or a fast user // The user just waits here until the account is created and before being shown the welcome modal on the trending page export const LoadingAccountPage = () => { const navigate = useNavigateToPage() - const dispatch = useDispatch() const isFastReferral = useFastReferral() const accountReady = useSelector(getAccountReady) const accountCreationStatus = useSelector(getStatus) - const [showContinueButton, setShowContinueButton] = useState(false) const isAccountReady = isFastReferral ? accountReady @@ -42,23 +38,6 @@ export const LoadingAccountPage = () => { // TODO: what to do in an error scenario? Any way to recover to a valid step? }, [navigate, isAccountReady]) - // Show continue button after 10 seconds if account is still not ready - useEffect(() => { - const timer = setTimeout(() => { - if (!isAccountReady) { - setShowContinueButton(true) - } - }, 10000) // 10 seconds - - return () => clearTimeout(timer) - }, [isAccountReady]) - - const handleContinue = () => { - // Mark sign-up as finished so RootScreen shows HomeStack - dispatch(finishSignUp()) - navigate(SIGN_UP_COMPLETED_REDIRECT) - } - return ( @@ -68,11 +47,6 @@ export const LoadingAccountPage = () => { description={messages.description} /> - {showContinueButton && ( - - )} ) } diff --git a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx index b4cdd0a677a..75c586e03dd 100644 --- a/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx +++ b/packages/web/src/pages/sign-up-page/pages/SelectArtistsPage.tsx @@ -34,7 +34,6 @@ import { PageFooter, ScrollView } from '../components/layout' -import { useFastReferral } from '../hooks/useFastReferral' const { SIGN_UP_APP_CTA_PAGE, SIGN_UP_COMPLETED_REDIRECT } = route @@ -67,7 +66,6 @@ export const SelectArtistsPage = () => { const navigate = useNavigateToPage() const { color } = useTheme() const headerContainerRef = useRef(null) - const isFastReferral = useFastReferral() const { isMobile } = useMedia() const handleChangeGenre = useCallback((e: ChangeEvent) => { @@ -80,16 +78,13 @@ export const SelectArtistsPage = () => { const artistsIDArray = [...selectedArtists].map((a) => Number(a)) dispatch(addFollowArtists(artistsIDArray)) - if (isFastReferral) { - // In fast referral mode, navigate to app CTA instead of completing sign up - navigate(SIGN_UP_APP_CTA_PAGE) - } else if (isMobile) { + if (isMobile) { navigate(SIGN_UP_COMPLETED_REDIRECT) } else { navigate(SIGN_UP_APP_CTA_PAGE) } }, - [dispatch, isFastReferral, isMobile, navigate] + [dispatch, isMobile, navigate] ) const isFeaturedArtists = currentGenre === 'Featured'