Remove old onboarding (#4224)

* Hardcode onboarding_v2 to true, rm dead code

* Rm initialState, use initialStateReduced

* Rm dead code

* Drop *reduced prefix in code

* Prettier
This commit is contained in:
dan
2024-05-28 16:56:06 +01:00
committed by GitHub
parent 9bd411c151
commit adbbded003
17 changed files with 27 additions and 1986 deletions
@@ -1,188 +0,0 @@
import React from 'react'
import {View, ViewStyle} from 'react-native'
import {AppBskyActorDefs, moderateProfile} from '@atproto/api'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {UserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, flatten, useTheme} from '#/alf'
import {useItemContext} from '#/components/forms/Toggle'
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
import {RichText} from '#/components/RichText'
import {Text} from '#/components/Typography'
export function SuggestedAccountCard({
profile,
moderationOpts,
}: {
profile: AppBskyActorDefs.ProfileViewDetailed
moderationOpts: ReturnType<typeof useModerationOpts>
}) {
const t = useTheme()
const ctx = useItemContext()
const moderation = moderateProfile(profile, moderationOpts!)
const styles = React.useMemo(() => {
const light = t.name === 'light'
const base: ViewStyle[] = [t.atoms.bg_contrast_50]
const hover: ViewStyle[] = [t.atoms.bg_contrast_25]
const selected: ViewStyle[] = [
{
backgroundColor: light ? t.palette.primary_50 : t.palette.primary_950,
},
]
const selectedHover: ViewStyle[] = [
{
backgroundColor: light ? t.palette.primary_25 : t.palette.primary_975,
},
]
const checkboxBase: ViewStyle[] = [t.atoms.bg]
const checkboxSelected: ViewStyle[] = [
{
backgroundColor: t.palette.primary_500,
},
]
const avatarBase: ViewStyle[] = [t.atoms.bg_contrast_100]
const avatarSelected: ViewStyle[] = [
{
backgroundColor: light ? t.palette.primary_100 : t.palette.primary_900,
},
]
return {
base,
hover: flatten(hover),
selected: flatten(selected),
selectedHover: flatten(selectedHover),
checkboxBase: flatten(checkboxBase),
checkboxSelected: flatten(checkboxSelected),
avatarBase: flatten(avatarBase),
avatarSelected: flatten(avatarSelected),
}
}, [t])
return (
<View
style={[
a.w_full,
a.p_md,
a.pr_lg,
a.gap_md,
a.rounded_md,
styles.base,
(ctx.hovered || ctx.focused || ctx.pressed) && styles.hover,
ctx.selected && styles.selected,
ctx.selected &&
(ctx.hovered || ctx.focused || ctx.pressed) &&
styles.selectedHover,
]}>
<View style={[a.flex_row, a.align_center, a.justify_between, a.gap_lg]}>
<View style={[a.flex_row, a.flex_1, a.align_center, a.gap_md]}>
<View
style={[
{width: 48, height: 48},
a.relative,
a.rounded_full,
styles.avatarBase,
ctx.selected && styles.avatarSelected,
]}>
<UserAvatar
size={48}
avatar={profile.avatar}
moderation={moderation.ui('avatar')}
/>
</View>
<View style={[a.flex_1]}>
<Text style={[a.font_bold, a.text_md, a.pb_xs]} numberOfLines={1}>
{profile.displayName}
</Text>
<Text style={[t.atoms.text_contrast_medium]}>{profile.handle}</Text>
</View>
</View>
<View
style={[
a.justify_center,
a.align_center,
a.rounded_sm,
styles.checkboxBase,
ctx.selected && styles.checkboxSelected,
{
width: 28,
height: 28,
},
]}>
{ctx.selected && <Check size="sm" fill={t.palette.white} />}
</View>
</View>
{profile.description && (
<>
<View
style={[
{
opacity: ctx.selected ? 0.3 : 1,
borderTopWidth: 1,
},
a.w_full,
t.atoms.border_contrast_low,
ctx.selected && {
borderTopColor: t.palette.primary_200,
},
]}
/>
<RichText
value={profile.description}
disableLinks
numberOfLines={2}
/>
</>
)}
</View>
)
}
export function SuggestedAccountCardPlaceholder() {
const t = useTheme()
return (
<View
style={[
a.w_full,
a.flex_row,
a.justify_between,
a.align_center,
a.p_md,
a.pr_lg,
a.gap_xl,
a.rounded_md,
t.atoms.bg_contrast_25,
]}>
<View style={[a.flex_row, a.align_center, a.gap_md]}>
<View
style={[
{width: 48, height: 48},
a.relative,
a.rounded_full,
t.atoms.bg_contrast_100,
]}
/>
<View style={[a.gap_xs]}>
<View
style={[
{width: 100, height: 16},
a.rounded_sm,
t.atoms.bg_contrast_100,
]}
/>
<View
style={[
{width: 60, height: 12},
a.rounded_sm,
t.atoms.bg_contrast_100,
]}
/>
</View>
</View>
</View>
)
}
@@ -1,210 +0,0 @@
import React from 'react'
import {View} from 'react-native'
import {AppBskyActorDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useAnalytics} from '#/lib/analytics/analytics'
import {logEvent} from '#/lib/statsig/statsig'
import {capitalize} from '#/lib/strings/capitalize'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useProfilesQuery} from '#/state/queries/profile'
import {
DescriptionText,
OnboardingControls,
TitleText,
} from '#/screens/Onboarding/Layout'
import {Context} from '#/screens/Onboarding/state'
import {
SuggestedAccountCard,
SuggestedAccountCardPlaceholder,
} from '#/screens/Onboarding/StepSuggestedAccounts/SuggestedAccountCard'
import {aggregateInterestItems} from '#/screens/Onboarding/util'
import {atoms as a, useBreakpoints} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Toggle from '#/components/forms/Toggle'
import {IconCircle} from '#/components/IconCircle'
import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
import {Loader} from '#/components/Loader'
import {Text} from '#/components/Typography'
export function Inner({
profiles,
onSelect,
moderationOpts,
}: {
profiles: AppBskyActorDefs.ProfileViewDetailed[]
onSelect: (dids: string[]) => void
moderationOpts: ReturnType<typeof useModerationOpts>
}) {
const {_} = useLingui()
const [dids, setDids] = React.useState<string[]>(profiles.map(p => p.did))
React.useEffect(() => {
onSelect(dids)
}, [dids, onSelect])
return (
<Toggle.Group
values={dids}
onChange={setDids}
label={_(msg`Select some accounts below to follow`)}>
<View style={[a.gap_md]}>
{profiles.map(profile => (
<Toggle.Item
key={profile.did}
name={profile.did}
label={_(msg`Follow ${profile.handle}`)}>
<SuggestedAccountCard
profile={profile}
moderationOpts={moderationOpts}
/>
</Toggle.Item>
))}
</View>
</Toggle.Group>
)
}
export function StepSuggestedAccounts() {
const {_} = useLingui()
const {gtMobile} = useBreakpoints()
const {track} = useAnalytics()
const {state, dispatch, interestsDisplayNames} = React.useContext(Context)
const suggestedDids = React.useMemo(() => {
return aggregateInterestItems(
state.interestsStepResults.selectedInterests,
state.interestsStepResults.apiResponse.suggestedAccountDids,
state.interestsStepResults.apiResponse.suggestedAccountDids.default || [],
)
}, [state.interestsStepResults])
const moderationOpts = useModerationOpts()
const {
isLoading: isProfilesLoading,
isError,
data,
error,
} = useProfilesQuery({
handles: suggestedDids,
})
const [dids, setDids] = React.useState<string[]>([])
const [saving, setSaving] = React.useState(false)
const interestsText = React.useMemo(() => {
const i = state.interestsStepResults.selectedInterests.map(
i => interestsDisplayNames[i] || capitalize(i),
)
return i.join(', ')
}, [state.interestsStepResults.selectedInterests, interestsDisplayNames])
const handleContinue = React.useCallback(async () => {
setSaving(true)
if (dids.length) {
dispatch({type: 'setSuggestedAccountsStepResults', accountDids: dids})
}
setSaving(false)
dispatch({type: 'next'})
track('OnboardingV2:StepSuggestedAccounts:End', {
selectedAccountsLength: dids.length,
})
logEvent('onboarding:suggestedAccounts:nextPressed', {
selectedAccountsLength: dids.length,
skipped: false,
})
}, [dids, setSaving, dispatch, track])
const handleSkip = React.useCallback(() => {
// if a user comes back and clicks skip, erase follows
dispatch({type: 'setSuggestedAccountsStepResults', accountDids: []})
dispatch({type: 'next'})
logEvent('onboarding:suggestedAccounts:nextPressed', {
selectedAccountsLength: 0,
skipped: true,
})
}, [dispatch])
const isLoading = isProfilesLoading && moderationOpts
React.useEffect(() => {
track('OnboardingV2:StepSuggestedAccounts:Start')
}, [track])
return (
<View style={[a.align_start]}>
<IconCircle icon={At} style={[a.mb_2xl]} />
<TitleText>
<Trans>Here are some accounts for you to follow</Trans>
</TitleText>
<DescriptionText>
{state.interestsStepResults.selectedInterests.length ? (
<Trans>Based on your interest in {interestsText}</Trans>
) : (
<Trans>These are popular accounts you might like:</Trans>
)}
</DescriptionText>
<View style={[a.w_full, a.pt_xl]}>
{isLoading ? (
<View style={[a.gap_md]}>
{Array(10)
.fill(0)
.map((_, i) => (
<SuggestedAccountCardPlaceholder key={i} />
))}
</View>
) : isError || !data ? (
<Text>{error?.toString()}</Text>
) : (
<Inner
profiles={data.profiles}
onSelect={setDids}
moderationOpts={moderationOpts}
/>
)}
</View>
<OnboardingControls.Portal>
<View
style={[
a.gap_md,
gtMobile ? {flexDirection: 'row-reverse'} : a.flex_col,
]}>
<Button
disabled={dids.length === 0}
variant="gradient"
color="gradient_sky"
size="large"
label={_(
msg`Follow selected accounts and continue to the next step`,
)}
onPress={handleContinue}>
<ButtonText>
{dids.length === 20 ? (
<Trans>Follow All</Trans>
) : (
<Trans>Follow</Trans>
)}
</ButtonText>
<ButtonIcon icon={saving ? Loader : Plus} position="right" />
</Button>
<Button
variant="solid"
color="secondary"
size="large"
label={_(
msg`Continue to the next step without following any accounts`,
)}
onPress={handleSkip}>
<ButtonText>
<Trans>Skip</Trans>
</ButtonText>
</Button>
</View>
</OnboardingControls.Portal>
</View>
)
}