[@next] Profile handling, migrate ProfileCard (#7347)

* Introduce new utils for profiles, migrate old ProfileCard

* Rename, reorg
This commit is contained in:
Eric Bailey
2025-01-06 14:17:49 -06:00
committed by GitHub
parent 1f5830f7fe
commit e851b3de41
5 changed files with 105 additions and 29 deletions
+1
View File
@@ -0,0 +1 @@
export * as profile from '#/types/atproto/profile'
+67
View File
@@ -0,0 +1,67 @@
import {AppBskyActorDefs} from '@atproto/api'
export {
/**
* Renamed to clarify source of this util, but directly aliases the original.
* {@link AppBskyActorDefs.isProfileViewBasic}
*/
isProfileViewBasic as isBasicView,
/**
* Renamed to clarify source of this util, but directly aliases the original.
* {@link AppBskyActorDefs.isProfileViewDetailed}
*/
isProfileViewDetailed as isDetailedView,
/**
* Renamed to clarify source of this util, but directly aliases the original.
* {@link AppBskyActorDefs.isProfileView}
*/
isProfileView as isView,
} from '@atproto/api/dist/client/types/app/bsky/actor/defs'
/**
* Matches any profile view exported by our SDK
*/
export type AnyProfileView =
| AppBskyActorDefs.ProfileViewBasic
| AppBskyActorDefs.ProfileView
| AppBskyActorDefs.ProfileViewDetailed
/**
* Maps any profile view type to `ProfileViewBasic`.
*/
export function anyToBasic(
view: AnyProfileView,
): AppBskyActorDefs.ProfileViewBasic {
return {
$type: 'app.bsky.actor.defs#profileViewBasic',
did: view.did,
handle: view.handle,
displayName: view.displayName,
avatar: view.avatar,
associated: view.associated,
viewer: view.viewer,
labels: view.labels,
createdAt: view.createdAt,
}
}
/**
* Maps `ProfileViewDetailed` to `ProfileView`.
*/
export function detailedToView(
view: AppBskyActorDefs.ProfileViewDetailed,
): AppBskyActorDefs.ProfileView {
return {
$type: 'app.bsky.actor.defs#profileView',
did: view.did,
handle: view.handle,
displayName: view.displayName,
avatar: view.avatar,
associated: view.associated,
viewer: view.viewer,
labels: view.labels,
createdAt: view.createdAt,
description: view.description,
indexedAt: view.indexedAt,
}
}
+4 -3
View File
@@ -1,6 +1,6 @@
import React, {useCallback} from 'react'
import {Dimensions, StyleProp, View, ViewStyle} from 'react-native'
import {AppBskyActorDefs, AppBskyGraphDefs} from '@atproto/api'
import {AppBskyGraphDefs} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -11,6 +11,7 @@ import {useModalControls} from '#/state/modals'
import {useListMembersQuery} from '#/state/queries/list-members'
import {useSession} from '#/state/session'
import {ListFooter} from '#/components/Lists'
import * as atp from '#/types/atproto'
import {ProfileCard} from '../profile/ProfileCard'
import {ErrorMessage} from '../util/error/ErrorMessage'
import {Button} from '../util/forms/Button'
@@ -116,7 +117,7 @@ export function ListMembers({
}, [fetchNextPage])
const onPressEditMembership = React.useCallback(
(profile: AppBskyActorDefs.ProfileViewBasic) => {
(profile: atp.profile.AnyProfileView) => {
openModal({
name: 'user-add-remove-lists',
subject: profile.did,
@@ -131,7 +132,7 @@ export function ListMembers({
// =
const renderMemberButton = React.useCallback(
(profile: AppBskyActorDefs.ProfileViewBasic) => {
(profile: atp.profile.AnyProfileView) => {
if (!isOwner) {
return null
}
+2 -2
View File
@@ -1,10 +1,10 @@
import {StyleProp, TextStyle, View} from 'react-native'
import {AppBskyActorDefs} from '@atproto/api'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {Shadow} from '#/state/cache/types'
import {useProfileFollowMutationQueue} from '#/state/queries/profile'
import * as atp from '#/types/atproto'
import {Button, ButtonType} from '../util/forms/Button'
import * as Toast from '../util/Toast'
@@ -17,7 +17,7 @@ export function FollowButton({
}: {
unfollowedType?: ButtonType
followedType?: ButtonType
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>
profile: Shadow<atp.profile.AnyProfileView>
labelStyle?: StyleProp<TextStyle>
logContext: 'ProfileCard' | 'StarterPackProfilesList'
}) {
+31 -24
View File
@@ -24,6 +24,7 @@ import {
shouldShowKnownFollowers,
} from '#/components/KnownFollowers'
import * as Pills from '#/components/Pills'
import * as atp from '#/types/atproto'
import {Link} from '../util/Link'
import {Text} from '../util/text/Text'
import {PreviewableUserAvatar} from '../util/UserAvatar'
@@ -41,12 +42,12 @@ export function ProfileCard({
showKnownFollowers,
}: {
testID?: string
profile: Omit<AppBskyActorDefs.ProfileViewBasic, '$type'>
profile: atp.profile.AnyProfileView
noModFilter?: boolean
noBg?: boolean
noBorder?: boolean
renderButton?: (
profile: Shadow<AppBskyActorDefs.ProfileViewBasic>,
profile: Shadow<atp.profile.AnyProfileView>,
) => React.ReactNode
onPress?: () => void
style?: StyleProp<ViewStyle>
@@ -60,7 +61,7 @@ export function ProfileCard({
const onBeforePress = React.useCallback(() => {
onPress?.()
precacheProfile(queryClient, profile)
precacheProfile(queryClient, atp.profile.anyToBasic(profile))
}, [onPress, profile, queryClient])
if (!moderationOpts) {
@@ -126,29 +127,35 @@ export function ProfileCard({
<View style={styles.layoutButton}>{renderButton(profile)}</View>
) : undefined}
</View>
{profile.description || knownFollowersVisible ? (
<View style={styles.details}>
{profile.description ? (
<Text emoji style={pal.text} numberOfLines={4}>
{profile.description as string}
</Text>
) : null}
{knownFollowersVisible ? (
<View
style={[
a.flex_row,
a.align_center,
a.gap_sm,
!!profile.description && a.mt_md,
]}>
<KnownFollowers
minimal
profile={profile}
moderationOpts={moderationOpts}
/>
{atp.profile.isView(profile) || atp.profile.isDetailedView(profile) ? (
<>
{profile.description || knownFollowersVisible ? (
<View style={styles.details}>
{profile.description ? (
<Text emoji style={pal.text} numberOfLines={4}>
{profile.description as string}
</Text>
) : null}
{knownFollowersVisible ? (
<View
style={[
a.flex_row,
a.align_center,
a.gap_sm,
!!profile.description && a.mt_md,
]}>
{atp.profile.isDetailedView(profile) && (
<KnownFollowers
minimal
profile={profile}
moderationOpts={moderationOpts}
/>
)}
</View>
) : null}
</View>
) : null}
</View>
</>
) : null}
</Link>
)