Refactor onboarding suggested follows (#1897)

* Refactor onboarding suggested follows

* Fix error state, track call

* Remove todo

* Use flatmap

* Add additional try catch

* Remove todo
This commit is contained in:
Eric Bailey 2023-11-14 11:25:37 -06:00 committed by GitHub
parent a81c4b68fa
commit 4355f0fd9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 227 additions and 63 deletions

View file

@ -1,9 +1,7 @@
import React from 'react'
import {View, StyleSheet, ActivityIndicator} from 'react-native'
import {AppBskyActorDefs, moderateProfile} from '@atproto/api'
import {observer} from 'mobx-react-lite'
import {useStores} from 'state/index'
import {FollowButton} from 'view/com/profile/FollowButton'
import {ProfileModeration} from '@atproto/api'
import {Button} from '#/view/com/util/forms/Button'
import {usePalette} from 'lib/hooks/usePalette'
import {SuggestedActor} from 'state/models/discovery/suggested-actors'
import {sanitizeDisplayName} from 'lib/strings/display-names'
@ -15,19 +13,32 @@ import Animated, {FadeInRight} from 'react-native-reanimated'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {useAnalytics} from 'lib/analytics/analytics'
import {Trans} from '@lingui/macro'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {
useProfileFollowMutation,
useProfileUnfollowMutation,
} from '#/state/queries/profile'
import {logger} from '#/logger'
type Props = {
item: SuggestedActor
index: number
insertSuggestionsByActor: (did: string, index: number) => Promise<void>
profile: SuggestedActor
dataUpdatedAt: number
moderation: ProfileModeration
onFollowStateChange: (props: {
did: string
following: boolean
}) => Promise<void>
}
export const RecommendedFollowsItem: React.FC<Props> = ({
item,
index,
insertSuggestionsByActor,
}) => {
export function RecommendedFollowsItem({
profile,
dataUpdatedAt,
moderation,
onFollowStateChange,
}: React.PropsWithChildren<Props>) {
const pal = usePalette('default')
const {isMobile} = useWebMediaQueries()
const shadowedProfile = useProfileShadow(profile, dataUpdatedAt)
return (
<Animated.View
@ -42,30 +53,57 @@ export const RecommendedFollowsItem: React.FC<Props> = ({
},
]}>
<ProfileCard
key={item.did}
profile={item}
index={index}
insertSuggestionsByActor={insertSuggestionsByActor}
key={profile.did}
profile={shadowedProfile}
onFollowStateChange={onFollowStateChange}
moderation={moderation}
/>
</Animated.View>
)
}
export const ProfileCard = observer(function ProfileCardImpl({
export function ProfileCard({
profile,
index,
insertSuggestionsByActor,
}: {
profile: AppBskyActorDefs.ProfileViewBasic
index: number
insertSuggestionsByActor: (did: string, index: number) => Promise<void>
}) {
onFollowStateChange,
moderation,
}: Omit<Props, 'dataUpdatedAt'>) {
const {track} = useAnalytics()
const store = useStores()
const pal = usePalette('default')
const moderation = moderateProfile(profile, store.preferences.moderationOpts)
const [addingMoreSuggestions, setAddingMoreSuggestions] =
React.useState(false)
const {mutateAsync: follow} = useProfileFollowMutation()
const {mutateAsync: unfollow} = useProfileUnfollowMutation()
const onToggleFollow = React.useCallback(async () => {
try {
if (
profile.viewer?.following &&
profile.viewer?.following !== 'pending'
) {
await unfollow({did: profile.did, followUri: profile.viewer.following})
} else if (
!profile.viewer?.following &&
profile.viewer?.following !== 'pending'
) {
setAddingMoreSuggestions(true)
await follow({did: profile.did})
await onFollowStateChange({did: profile.did, following: true})
setAddingMoreSuggestions(false)
track('Onboarding:SuggestedFollowFollowed')
}
} catch (e) {
logger.error('RecommendedFollows: failed to toggle following', {error: e})
} finally {
setAddingMoreSuggestions(false)
}
}, [
profile,
follow,
unfollow,
setAddingMoreSuggestions,
track,
onFollowStateChange,
])
return (
<View style={styles.card}>
@ -93,17 +131,12 @@ export const ProfileCard = observer(function ProfileCardImpl({
</Text>
</View>
<FollowButton
profile={profile}
<Button
type={profile.viewer?.following ? 'default' : 'inverted'}
labelStyle={styles.followButton}
onToggleFollow={async isFollow => {
if (isFollow) {
setAddingMoreSuggestions(true)
await insertSuggestionsByActor(profile.did, index)
setAddingMoreSuggestions(false)
track('Onboarding:SuggestedFollowFollowed')
}
}}
onPress={onToggleFollow}
label={profile.viewer?.following ? 'Unfollow' : 'Follow'}
withLoading={true}
/>
</View>
{profile.description ? (
@ -123,7 +156,7 @@ export const ProfileCard = observer(function ProfileCardImpl({
) : null}
</View>
)
})
}
const styles = StyleSheet.create({
cardContainer: {