Update follow buttons to the new UI
This commit is contained in:
@@ -1,24 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {View} from 'react-native'
|
|
||||||
import {AppBskyActorDefs} from '@atproto/api'
|
import {AppBskyActorDefs} from '@atproto/api'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
|
||||||
import {useLingui} from '@lingui/react'
|
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
|
||||||
import {track} from 'lib/analytics/analytics'
|
|
||||||
import {isNative, isWeb} from 'platform/detection'
|
|
||||||
import {Shadow, useProfileShadow} from 'state/cache/profile-shadow'
|
import {Shadow, useProfileShadow} from 'state/cache/profile-shadow'
|
||||||
import {
|
import {useProfileQuery} from 'state/queries/profile'
|
||||||
useProfileFollowMutationQueue,
|
import {FollowButton} from 'view/com/profile/FollowButton'
|
||||||
useProfileQuery,
|
|
||||||
} from 'state/queries/profile'
|
|
||||||
import {useRequireAuth} from 'state/session'
|
|
||||||
import * as Toast from 'view/com/util/Toast'
|
|
||||||
import {atoms as a} from '#/alf'
|
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
|
||||||
import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
|
|
||||||
import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus'
|
|
||||||
|
|
||||||
export function PostThreadFollowBtn({did}: {did: string}) {
|
export function PostThreadFollowBtn({did}: {did: string}) {
|
||||||
const {data: profile, isLoading} = useProfileQuery({did})
|
const {data: profile, isLoading} = useProfileQuery({did})
|
||||||
@@ -36,14 +22,8 @@ function PostThreadFollowBtnLoaded({
|
|||||||
profile: AppBskyActorDefs.ProfileViewDetailed
|
profile: AppBskyActorDefs.ProfileViewDetailed
|
||||||
}) {
|
}) {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const {_} = useLingui()
|
|
||||||
const profile: Shadow<AppBskyActorDefs.ProfileViewBasic> =
|
const profile: Shadow<AppBskyActorDefs.ProfileViewBasic> =
|
||||||
useProfileShadow(profileUnshadowed)
|
useProfileShadow(profileUnshadowed)
|
||||||
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
|
||||||
profile,
|
|
||||||
'PostThreadItem',
|
|
||||||
)
|
|
||||||
const requireAuth = useRequireAuth()
|
|
||||||
|
|
||||||
const isFollowing = !!profile.viewer?.following
|
const isFollowing = !!profile.viewer?.following
|
||||||
const [wasFollowing, setWasFollowing] = React.useState<boolean>(isFollowing)
|
const [wasFollowing, setWasFollowing] = React.useState<boolean>(isFollowing)
|
||||||
@@ -81,64 +61,7 @@ function PostThreadFollowBtnLoaded({
|
|||||||
}
|
}
|
||||||
}, [isFollowing, wasFollowing, navigation])
|
}, [isFollowing, wasFollowing, navigation])
|
||||||
|
|
||||||
const onPress = React.useCallback(() => {
|
|
||||||
if (!isFollowing) {
|
|
||||||
requireAuth(async () => {
|
|
||||||
try {
|
|
||||||
track('ProfileHeader:FollowButtonClicked')
|
|
||||||
await queueFollow()
|
|
||||||
} catch (e: any) {
|
|
||||||
if (e?.name !== 'AbortError') {
|
|
||||||
logger.error('Failed to follow', {message: String(e)})
|
|
||||||
Toast.show(_(msg`There was an issue! ${e.toString()}`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
requireAuth(async () => {
|
|
||||||
try {
|
|
||||||
track('ProfileHeader:UnfollowButtonClicked')
|
|
||||||
await queueUnfollow()
|
|
||||||
} catch (e: any) {
|
|
||||||
if (e?.name !== 'AbortError') {
|
|
||||||
logger.error('Failed to unfollow', {message: String(e)})
|
|
||||||
Toast.show(_(msg`There was an issue! ${e.toString()}`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [isFollowing, requireAuth, queueFollow, _, queueUnfollow])
|
|
||||||
|
|
||||||
if (!showFollowBtn) return null
|
if (!showFollowBtn) return null
|
||||||
|
|
||||||
return (
|
return <FollowButton profile={profile} logContext="PostThreadItem" />
|
||||||
<View>
|
|
||||||
<Button
|
|
||||||
testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'}
|
|
||||||
size={isNative ? 'small' : 'medium'}
|
|
||||||
color={profile.viewer?.following ? 'secondary' : 'primary'}
|
|
||||||
variant="solid"
|
|
||||||
label={
|
|
||||||
profile.viewer?.following
|
|
||||||
? _(msg`Unfollow ${profile.handle}`)
|
|
||||||
: _(msg`Follow ${profile.handle}`)
|
|
||||||
}
|
|
||||||
onPress={onPress}
|
|
||||||
style={[a.rounded_full, a.gap_xs]}>
|
|
||||||
{isWeb && (
|
|
||||||
<ButtonIcon
|
|
||||||
position="left"
|
|
||||||
icon={profile.viewer?.following ? Check : Plus}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<ButtonText>
|
|
||||||
{profile.viewer?.following ? (
|
|
||||||
<Trans>Following</Trans>
|
|
||||||
) : (
|
|
||||||
<Trans>Follow</Trans>
|
|
||||||
)}
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,32 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleProp, TextStyle, View} from 'react-native'
|
import {StyleProp, TextStyle, View} from 'react-native'
|
||||||
import {AppBskyActorDefs} from '@atproto/api'
|
import {AppBskyActorDefs} from '@atproto/api'
|
||||||
import {Button, ButtonType} from '../util/forms/Button'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import * as Toast from '../util/Toast'
|
|
||||||
import {useProfileFollowMutationQueue} from '#/state/queries/profile'
|
|
||||||
import {Shadow} from '#/state/cache/types'
|
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {msg} from '@lingui/macro'
|
|
||||||
|
import {Shadow} from '#/state/cache/types'
|
||||||
|
import {useProfileFollowMutationQueue} from '#/state/queries/profile'
|
||||||
|
import {useGate} from 'lib/statsig/statsig'
|
||||||
|
import {isNative} from 'platform/detection'
|
||||||
|
import {atoms as a} from '#/alf'
|
||||||
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
|
import * as Toast from '../util/Toast'
|
||||||
|
|
||||||
export function FollowButton({
|
export function FollowButton({
|
||||||
unfollowedType = 'inverted',
|
|
||||||
followedType = 'default',
|
|
||||||
profile,
|
profile,
|
||||||
labelStyle,
|
|
||||||
logContext,
|
logContext,
|
||||||
}: {
|
}: {
|
||||||
unfollowedType?: ButtonType
|
|
||||||
followedType?: ButtonType
|
|
||||||
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
|
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
|
||||||
labelStyle?: StyleProp<TextStyle>
|
labelStyle?: StyleProp<TextStyle>
|
||||||
logContext: 'ProfileCard'
|
logContext: 'ProfileCard' | 'PostThreadItem'
|
||||||
}) {
|
}) {
|
||||||
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue(
|
||||||
profile,
|
profile,
|
||||||
logContext,
|
logContext,
|
||||||
)
|
)
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const showFollowBackLabel =
|
||||||
|
useGate('show_follow_back_label') && logContext === 'PostThreadItem'
|
||||||
|
|
||||||
const onPressFollow = async () => {
|
const onPressFollow = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -51,23 +52,32 @@ export function FollowButton({
|
|||||||
return <View />
|
return <View />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profile.viewer.following) {
|
return (
|
||||||
return (
|
<View>
|
||||||
<Button
|
<Button
|
||||||
type={followedType}
|
testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'}
|
||||||
labelStyle={labelStyle}
|
size={isNative ? 'small' : 'medium'}
|
||||||
onPress={onPressUnfollow}
|
color={profile.viewer?.following ? 'secondary' : 'primary'}
|
||||||
label={_(msg({message: 'Unfollow', context: 'action'}))}
|
variant="solid"
|
||||||
/>
|
label={
|
||||||
)
|
profile.viewer?.following
|
||||||
} else {
|
? _(msg`Unfollow ${profile.handle}`)
|
||||||
return (
|
: _(msg`Follow ${profile.handle}`)
|
||||||
<Button
|
}
|
||||||
type={unfollowedType}
|
onPress={profile.viewer?.following ? onPressUnfollow : onPressFollow}
|
||||||
labelStyle={labelStyle}
|
style={[a.rounded_full, a.gap_xs]}>
|
||||||
onPress={onPressFollow}
|
<ButtonText>
|
||||||
label={_(msg({message: 'Follow', context: 'action'}))}
|
{!profile.viewer?.following ? (
|
||||||
/>
|
showFollowBackLabel && profile.viewer?.followedBy ? (
|
||||||
)
|
<Trans>Follow Back</Trans>
|
||||||
}
|
) : (
|
||||||
|
<Trans>Follow</Trans>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<Trans>Following</Trans>
|
||||||
|
)}
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user