Suggested follows by actor (on profiles) updates (#5243)
* If fallback, return nothing * Compress size a bit * Hide on own profile * Match load state * Remove gcTime * Filter out followed users * Feedbackzio/stable^2^2
parent
47bea32061
commit
d60a8f26c4
|
@ -60,16 +60,13 @@ function CardOuter({
|
||||||
export function SuggestedFollowPlaceholder() {
|
export function SuggestedFollowPlaceholder() {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<CardOuter style={[a.gap_sm, t.atoms.border_contrast_low]}>
|
<CardOuter style={[a.gap_md, t.atoms.border_contrast_low]}>
|
||||||
<ProfileCard.Header>
|
<ProfileCard.Header>
|
||||||
<ProfileCard.AvatarPlaceholder />
|
<ProfileCard.AvatarPlaceholder />
|
||||||
|
<ProfileCard.NameAndHandlePlaceholder />
|
||||||
</ProfileCard.Header>
|
</ProfileCard.Header>
|
||||||
|
|
||||||
<View style={[a.py_xs]}>
|
<ProfileCard.DescriptionPlaceholder numberOfLines={2} />
|
||||||
<ProfileCard.NameAndHandlePlaceholder />
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<ProfileCard.DescriptionPlaceholder />
|
|
||||||
</CardOuter>
|
</CardOuter>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -176,9 +173,14 @@ function useExperimentalSuggestedUsersQuery() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SuggestedFollows({feed}: {feed: FeedDescriptor}) {
|
export function SuggestedFollows({feed}: {feed: FeedDescriptor}) {
|
||||||
const [feedType, feedUri] = feed.split('|')
|
const {currentAccount} = useSession()
|
||||||
|
const [feedType, feedUriOrDid] = feed.split('|')
|
||||||
if (feedType === 'author') {
|
if (feedType === 'author') {
|
||||||
return <SuggestedFollowsProfile did={feedUri} />
|
if (currentAccount?.did === feedUriOrDid) {
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
return <SuggestedFollowsProfile did={feedUriOrDid} />
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return <SuggestedFollowsHome />
|
return <SuggestedFollowsHome />
|
||||||
}
|
}
|
||||||
|
@ -197,6 +199,7 @@ export function SuggestedFollowsProfile({did}: {did: string}) {
|
||||||
isSuggestionsLoading={isSuggestionsLoading}
|
isSuggestionsLoading={isSuggestionsLoading}
|
||||||
profiles={data?.suggestions ?? []}
|
profiles={data?.suggestions ?? []}
|
||||||
error={error}
|
error={error}
|
||||||
|
viewContext="profile"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -212,6 +215,7 @@ export function SuggestedFollowsHome() {
|
||||||
isSuggestionsLoading={isSuggestionsLoading}
|
isSuggestionsLoading={isSuggestionsLoading}
|
||||||
profiles={profiles}
|
profiles={profiles}
|
||||||
error={error}
|
error={error}
|
||||||
|
viewContext="feed"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -220,10 +224,12 @@ export function ProfileGrid({
|
||||||
isSuggestionsLoading,
|
isSuggestionsLoading,
|
||||||
error,
|
error,
|
||||||
profiles,
|
profiles,
|
||||||
|
viewContext = 'feed',
|
||||||
}: {
|
}: {
|
||||||
isSuggestionsLoading: boolean
|
isSuggestionsLoading: boolean
|
||||||
profiles: AppBskyActorDefs.ProfileViewDetailed[]
|
profiles: AppBskyActorDefs.ProfileViewDetailed[]
|
||||||
error: Error | null
|
error: Error | null
|
||||||
|
viewContext: 'profile' | 'feed'
|
||||||
}) {
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
@ -280,7 +286,7 @@ export function ProfileGrid({
|
||||||
shape="round"
|
shape="round"
|
||||||
/>
|
/>
|
||||||
</ProfileCard.Header>
|
</ProfileCard.Header>
|
||||||
<ProfileCard.Description profile={profile} />
|
<ProfileCard.Description profile={profile} numberOfLines={2} />
|
||||||
</ProfileCard.Outer>
|
</ProfileCard.Outer>
|
||||||
</CardOuter>
|
</CardOuter>
|
||||||
)}
|
)}
|
||||||
|
@ -297,33 +303,31 @@ export function ProfileGrid({
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[a.border_t, t.atoms.border_contrast_low, t.atoms.bg_contrast_25]}>
|
style={[a.border_t, t.atoms.border_contrast_low, t.atoms.bg_contrast_25]}>
|
||||||
<View style={[a.pt_2xl, a.px_lg, a.flex_row, a.pb_xs]}>
|
<View
|
||||||
<Text
|
|
||||||
style={[
|
style={[
|
||||||
a.flex_1,
|
a.p_lg,
|
||||||
a.text_lg,
|
a.pb_xs,
|
||||||
a.font_bold,
|
a.flex_row,
|
||||||
t.atoms.text_contrast_medium,
|
a.align_center,
|
||||||
|
a.justify_between,
|
||||||
]}>
|
]}>
|
||||||
|
<Text style={[a.text_sm, a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
|
{viewContext === 'profile' ? (
|
||||||
|
<Trans>Similar accounts</Trans>
|
||||||
|
) : (
|
||||||
<Trans>Suggested for you</Trans>
|
<Trans>Suggested for you</Trans>
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
<Person fill={t.atoms.text_contrast_low.color} />
|
<Person fill={t.atoms.text_contrast_low.color} size="sm" />
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{gtMobile ? (
|
{gtMobile ? (
|
||||||
<View style={[a.flex_1, a.px_lg, a.pt_md, a.pb_xl, a.gap_md]}>
|
<View style={[a.flex_1, a.px_lg, a.pt_sm, a.pb_lg, a.gap_md]}>
|
||||||
<View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}>
|
<View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_sm]}>
|
||||||
{content}
|
{content}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View
|
<View style={[a.flex_row, a.justify_end, a.align_center, a.gap_md]}>
|
||||||
style={[
|
|
||||||
a.flex_row,
|
|
||||||
a.justify_end,
|
|
||||||
a.align_center,
|
|
||||||
a.pt_xs,
|
|
||||||
a.gap_md,
|
|
||||||
]}>
|
|
||||||
<InlineLinkText
|
<InlineLinkText
|
||||||
label={_(msg`Browse more suggestions`)}
|
label={_(msg`Browse more suggestions`)}
|
||||||
to="/search"
|
to="/search"
|
||||||
|
@ -339,7 +343,7 @@ export function ProfileGrid({
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap}
|
snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap}
|
||||||
decelerationRate="fast">
|
decelerationRate="fast">
|
||||||
<View style={[a.px_lg, a.pt_md, a.pb_xl, a.flex_row, a.gap_md]}>
|
<View style={[a.px_lg, a.pt_sm, a.pb_lg, a.flex_row, a.gap_md]}>
|
||||||
{content}
|
{content}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -220,8 +220,10 @@ export function NameAndHandlePlaceholder() {
|
||||||
|
|
||||||
export function Description({
|
export function Description({
|
||||||
profile: profileUnshadowed,
|
profile: profileUnshadowed,
|
||||||
|
numberOfLines = 3,
|
||||||
}: {
|
}: {
|
||||||
profile: AppBskyActorDefs.ProfileViewDetailed
|
profile: AppBskyActorDefs.ProfileViewDetailed
|
||||||
|
numberOfLines?: number
|
||||||
}) {
|
}) {
|
||||||
const profile = useProfileShadow(profileUnshadowed)
|
const profile = useProfileShadow(profileUnshadowed)
|
||||||
const {description} = profile
|
const {description} = profile
|
||||||
|
@ -244,31 +246,34 @@ export function Description({
|
||||||
<RichText
|
<RichText
|
||||||
value={rt}
|
value={rt}
|
||||||
style={[a.leading_snug]}
|
style={[a.leading_snug]}
|
||||||
numberOfLines={3}
|
numberOfLines={numberOfLines}
|
||||||
disableLinks
|
disableLinks
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DescriptionPlaceholder() {
|
export function DescriptionPlaceholder({
|
||||||
|
numberOfLines = 3,
|
||||||
|
}: {
|
||||||
|
numberOfLines?: number
|
||||||
|
}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<View style={[a.gap_xs]}>
|
<View style={[{gap: 8}]}>
|
||||||
<View
|
{Array(numberOfLines)
|
||||||
style={[a.rounded_xs, a.w_full, t.atoms.bg_contrast_50, {height: 12}]}
|
.fill(0)
|
||||||
/>
|
.map((_, i) => (
|
||||||
<View
|
|
||||||
style={[a.rounded_xs, a.w_full, t.atoms.bg_contrast_50, {height: 12}]}
|
|
||||||
/>
|
|
||||||
<View
|
<View
|
||||||
|
key={i}
|
||||||
style={[
|
style={[
|
||||||
a.rounded_xs,
|
a.rounded_xs,
|
||||||
a.w_full,
|
a.w_full,
|
||||||
t.atoms.bg_contrast_50,
|
t.atoms.bg_contrast_50,
|
||||||
{height: 12, width: 100},
|
{height: 12, width: i + 1 === numberOfLines ? '60%' : '100%'},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
))}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,13 +106,16 @@ export function useSuggestedFollowsQuery(options?: SuggestedFollowsOptions) {
|
||||||
export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
|
export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
return useQuery<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema, Error>({
|
return useQuery<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema, Error>({
|
||||||
gcTime: 0,
|
|
||||||
queryKey: suggestedFollowsByActorQueryKey(did),
|
queryKey: suggestedFollowsByActorQueryKey(did),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
|
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
|
||||||
actor: did,
|
actor: did,
|
||||||
})
|
})
|
||||||
return res.data
|
const data = res.data.isFallback ? {suggestions: []} : res.data
|
||||||
|
data.suggestions = data.suggestions.filter(profile => {
|
||||||
|
return !profile.viewer?.following
|
||||||
|
})
|
||||||
|
return data
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue