Merge the suggested actors model with the general suggestion system (#343)

zio/stable
Paul Frazee 2023-03-21 19:18:15 -05:00 committed by GitHub
parent f20fb92dc3
commit 4f814207bc
6 changed files with 54 additions and 84 deletions

View File

@ -1,7 +1,7 @@
import {makeAutoObservable, runInAction} from 'mobx'
import {AppBskyActorProfile as Profile} from '@atproto/api'
import shuffle from 'lodash.shuffle'
import {RootStoreModel} from './root-store'
import {RootStoreModel} from '../root-store'
import {cleanError} from 'lib/strings/errors'
import {bundleAsync} from 'lib/async/bundle'
import {SUGGESTED_FOLLOWS} from 'lib/constants'
@ -10,7 +10,7 @@ const PAGE_SIZE = 30
export type SuggestedActor = Profile.ViewBasic | Profile.View
export class SuggestedActorsViewModel {
export class SuggestedActorsModel {
// state
pageSize = PAGE_SIZE
isLoading = false

View File

@ -11,7 +11,11 @@ export const SuggestedFollows = ({
suggestions,
}: {
title: string
suggestions: (AppBskyActorRef.WithInfo | RefWithInfoAndFollowers)[]
suggestions: (
| AppBskyActorRef.WithInfo
| RefWithInfoAndFollowers
| AppBskyActorProfile.View
)[]
}) => {
const pal = usePalette('default')
return (
@ -30,7 +34,11 @@ export const SuggestedFollows = ({
avatar={item.avatar}
noBg
noBorder
description=""
description={
item.description
? (item as AppBskyActorProfile.View).description
: ''
}
followers={
item.followers
? (item.followers as AppBskyActorProfile.View[])

View File

@ -1,66 +0,0 @@
import React from 'react'
import {ActivityIndicator, StyleSheet, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {useStores} from 'state/index'
import {SuggestedActorsViewModel} from 'state/models/suggested-actors-view'
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
import {Text} from '../util/text/Text'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
export const WhoToFollow = observer(() => {
const pal = usePalette('default')
const store = useStores()
const suggestedActorsView = React.useMemo<SuggestedActorsViewModel>(
() => new SuggestedActorsViewModel(store, {pageSize: 15}),
[store],
)
React.useEffect(() => {
suggestedActorsView.loadMore(true)
}, [store, suggestedActorsView])
return (
<>
{(suggestedActorsView.hasContent || suggestedActorsView.isLoading) && (
<Text type="title" style={[styles.heading, pal.text]}>
Who to follow
</Text>
)}
{suggestedActorsView.hasContent && (
<>
<View style={[pal.border, styles.bottomBorder]}>
{suggestedActorsView.suggestions.map(item => (
<ProfileCardWithFollowBtn
key={item.did}
did={item.did}
declarationCid={item.declaration.cid}
handle={item.handle}
displayName={item.displayName}
avatar={item.avatar}
description={item.description}
/>
))}
</View>
</>
)}
{suggestedActorsView.isLoading && (
<View style={s.mt10}>
<ActivityIndicator />
</View>
)}
</>
)
})
const styles = StyleSheet.create({
heading: {
fontWeight: 'bold',
paddingHorizontal: 12,
paddingBottom: 8,
},
bottomBorder: {
borderBottomWidth: 1,
},
})

View File

@ -2,15 +2,21 @@ import React from 'react'
import {StyleSheet, View} from 'react-native'
import {observer} from 'mobx-react-lite'
import {FoafsModel} from 'state/models/discovery/foafs'
import {WhoToFollow} from 'view/com/discover/WhoToFollow'
import {SuggestedActorsModel} from 'state/models/discovery/suggested-actors'
import {SuggestedFollows} from 'view/com/discover/SuggestedFollows'
import {ProfileCardFeedLoadingPlaceholder} from 'view/com/util/LoadingPlaceholder'
export const Suggestions = observer(({foafs}: {foafs: FoafsModel}) => {
if (foafs.isLoading) {
return <ProfileCardFeedLoadingPlaceholder />
}
if (foafs.hasContent) {
export const Suggestions = observer(
({
foafs,
suggestedActors,
}: {
foafs: FoafsModel
suggestedActors: SuggestedActorsModel
}) => {
if (foafs.isLoading || suggestedActors.isLoading) {
return <ProfileCardFeedLoadingPlaceholder />
}
return (
<>
{foafs.popular.length > 0 && (
@ -21,7 +27,14 @@ export const Suggestions = observer(({foafs}: {foafs: FoafsModel}) => {
/>
</View>
)}
<WhoToFollow />
{suggestedActors.hasContent && (
<View style={styles.suggestions}>
<SuggestedFollows
title="Suggested follows"
suggestions={suggestedActors.suggestions}
/>
</View>
)}
{foafs.sources.map((source, i) => {
const item = foafs.foafs.get(source)
if (!item || item.follows.length === 0) {
@ -38,9 +51,8 @@ export const Suggestions = observer(({foafs}: {foafs: FoafsModel}) => {
})}
</>
)
}
return <WhoToFollow />
})
},
)
const styles = StyleSheet.create({
suggestions: {

View File

@ -19,6 +19,7 @@ import {useStores} from 'state/index'
import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view'
import {SearchUIModel} from 'state/models/ui/search'
import {FoafsModel} from 'state/models/discovery/foafs'
import {SuggestedActorsModel} from 'state/models/discovery/suggested-actors'
import {HeaderWithInput} from 'view/com/search/HeaderWithInput'
import {Suggestions} from 'view/com/search/Suggestions'
import {SearchResults} from 'view/com/search/SearchResults'
@ -44,6 +45,10 @@ export const SearchScreen = withAuthRequired(
() => new FoafsModel(store),
[store],
)
const suggestedActors = React.useMemo<SuggestedActorsModel>(
() => new SuggestedActorsModel(store),
[store],
)
const [searchUIModel, setSearchUIModel] = React.useState<
SearchUIModel | undefined
>()
@ -65,9 +70,12 @@ export const SearchScreen = withAuthRequired(
if (!foafs.hasData) {
foafs.fetch()
}
if (!suggestedActors.hasLoaded) {
suggestedActors.loadMore(true)
}
return cleanup
}, [store, autocompleteView, foafs]),
}, [store, autocompleteView, foafs, suggestedActors]),
)
const onChangeQuery = React.useCallback(
@ -163,7 +171,7 @@ export const SearchScreen = withAuthRequired(
</Text>
</View>
) : (
<Suggestions foafs={foafs} />
<Suggestions foafs={foafs} suggestedActors={suggestedActors} />
)}
<View style={s.footerSpacer} />
</ScrollView>

View File

@ -2,6 +2,7 @@ import React from 'react'
import {StyleSheet, View} from 'react-native'
import {SearchUIModel} from 'state/models/ui/search'
import {FoafsModel} from 'state/models/discovery/foafs'
import {SuggestedActorsModel} from 'state/models/discovery/suggested-actors'
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
import {ScrollView} from 'view/com/util/Views'
import {Suggestions} from 'view/com/search/Suggestions'
@ -24,6 +25,10 @@ export const SearchScreen = withAuthRequired(
() => new FoafsModel(store),
[store],
)
const suggestedActors = React.useMemo<SuggestedActorsModel>(
() => new SuggestedActorsModel(store),
[store],
)
const searchUIModel = React.useMemo<SearchUIModel | undefined>(
() => (route.params.q ? new SearchUIModel(store) : undefined),
[route.params.q, store],
@ -36,7 +41,10 @@ export const SearchScreen = withAuthRequired(
if (!foafs.hasData) {
foafs.fetch()
}
}, [foafs, searchUIModel, route.params.q])
if (!suggestedActors.hasLoaded) {
suggestedActors.loadMore(true)
}
}, [foafs, suggestedActors, searchUIModel, route.params.q])
if (searchUIModel) {
return <SearchResults model={searchUIModel} />
@ -47,7 +55,7 @@ export const SearchScreen = withAuthRequired(
testID="searchScrollView"
style={[pal.view, styles.container]}
scrollEventThrottle={100}>
<Suggestions foafs={foafs} />
<Suggestions foafs={foafs} suggestedActors={suggestedActors} />
<View style={s.footerSpacer} />
</ScrollView>
)