Add new search results tab for starter packs (#11226)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import {memo, useCallback, useMemo, useState} from 'react'
|
||||
import {ActivityIndicator, View} from 'react-native'
|
||||
import {type AppBskyFeedDefs} from '@atproto/api'
|
||||
import {type AppBskyFeedDefs, type AppBskyGraphDefs} from '@atproto/api'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {urls} from '#/lib/constants'
|
||||
@@ -15,6 +15,7 @@ import {augmentSearchQuery} from '#/lib/strings/helpers'
|
||||
import {useActorSearch} from '#/state/queries/actor-search'
|
||||
import {usePopularFeedsSearch} from '#/state/queries/feed'
|
||||
import {useSearchPostsV2Query} from '#/state/queries/search-posts-v2'
|
||||
import {useStarterPackSearch} from '#/state/queries/starter-pack-search'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useCloseAllActiveElements} from '#/state/util'
|
||||
@@ -23,6 +24,7 @@ import {TabBar} from '#/view/com/pager/TabBar'
|
||||
import {Post} from '#/view/com/post/Post'
|
||||
import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard'
|
||||
import {List} from '#/view/com/util/List'
|
||||
import {StarterPackCard} from '#/screens/Search/components/StarterPackCard'
|
||||
import {
|
||||
hasPostOnlyFilters,
|
||||
type SearchFilters,
|
||||
@@ -106,6 +108,15 @@ let SearchResults = ({
|
||||
<SearchScreenFeedsResults query={query} active={activePage === 3} />
|
||||
),
|
||||
},
|
||||
noFilters && {
|
||||
title: l`Starter packs`,
|
||||
component: (
|
||||
<SearchScreenStarterPackResults
|
||||
query={query}
|
||||
active={activePage === 4}
|
||||
/>
|
||||
),
|
||||
},
|
||||
].filter(Boolean) as {
|
||||
title: string
|
||||
component: React.ReactNode
|
||||
@@ -692,3 +703,123 @@ function SearchFeedCard({
|
||||
|
||||
return <FeedCard.Default view={view} onPress={handleOnPress} />
|
||||
}
|
||||
|
||||
let SearchScreenStarterPackResults = ({
|
||||
query,
|
||||
active,
|
||||
}: {
|
||||
query: string
|
||||
active: boolean
|
||||
}): React.ReactNode => {
|
||||
const ax = useAnalytics()
|
||||
const {t: l} = useLingui()
|
||||
const [isPTR, setIsPTR] = useState(false)
|
||||
|
||||
const {
|
||||
isFetched,
|
||||
data: results,
|
||||
isFetching,
|
||||
error,
|
||||
refetch,
|
||||
fetchNextPage,
|
||||
isFetchingNextPage,
|
||||
hasNextPage,
|
||||
} = useStarterPackSearch({
|
||||
query,
|
||||
enabled: active,
|
||||
})
|
||||
|
||||
const onPullToRefresh = useCallback(async () => {
|
||||
setIsPTR(true)
|
||||
await refetch()
|
||||
setIsPTR(false)
|
||||
}, [setIsPTR, refetch])
|
||||
const onEndReached = useCallback(() => {
|
||||
if (isFetching || !hasNextPage || error) return
|
||||
void fetchNextPage()
|
||||
}, [isFetching, error, hasNextPage, fetchNextPage])
|
||||
const starterPacks = useMemo(() => {
|
||||
return results?.pages.flatMap(page => page.starterPacks) || []
|
||||
}, [results])
|
||||
|
||||
const fireTracking = useCallOnce(() => {
|
||||
ax.metric('search:results:loaded', {
|
||||
tab: 'starterPacks',
|
||||
initialCount: starterPacks.length,
|
||||
})
|
||||
})
|
||||
if (isFetched) {
|
||||
fireTracking()
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<EmptyState
|
||||
messageText={
|
||||
shouldRetryError(error) || isNetworkError(error)
|
||||
? l`We’re sorry, but your search could not be completed. Please try again in a few minutes.`
|
||||
: l`We’re sorry, but your search could not be completed.`
|
||||
}
|
||||
error={cleanError(error)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return isFetched ? (
|
||||
<>
|
||||
{starterPacks.length ? (
|
||||
<List
|
||||
data={starterPacks}
|
||||
renderItem={({
|
||||
item,
|
||||
index,
|
||||
}: {
|
||||
item: AppBskyGraphDefs.StarterPackView
|
||||
index: number
|
||||
}) => (
|
||||
<View style={[a.px_lg, a.pb_lg, index === 0 && a.pt_lg]}>
|
||||
<SearchStarterPack position={index} view={item} />
|
||||
</View>
|
||||
)}
|
||||
keyExtractor={(item: AppBskyGraphDefs.StarterPackView) => item.uri}
|
||||
refreshing={isPTR}
|
||||
onRefresh={() => void onPullToRefresh()}
|
||||
onEndReached={onEndReached}
|
||||
desktopFixedHeight
|
||||
ListFooterComponent={
|
||||
<ListFooter
|
||||
hasNextPage={hasNextPage}
|
||||
isFetchingNextPage={isFetchingNextPage}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<EmptyState messageText={<NoResultsText query={query} />} />
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Loader />
|
||||
)
|
||||
}
|
||||
SearchScreenStarterPackResults = memo(SearchScreenStarterPackResults)
|
||||
|
||||
function SearchStarterPack({
|
||||
position,
|
||||
view,
|
||||
}: {
|
||||
position: number
|
||||
view: AppBskyGraphDefs.StarterPackView
|
||||
}) {
|
||||
const ax = useAnalytics()
|
||||
|
||||
const handleOnPress = () => {
|
||||
ax.metric('search:result:press', {
|
||||
tab: 'starterPacks',
|
||||
resultType: 'starterPack',
|
||||
position,
|
||||
uri: view.uri,
|
||||
})
|
||||
}
|
||||
|
||||
return <StarterPackCard view={view} onPress={handleOnPress} />
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ import * as bsky from '#/types/bsky'
|
||||
|
||||
export function StarterPackCard({
|
||||
view,
|
||||
onPress,
|
||||
}: {
|
||||
view: AppBskyGraphDefs.StarterPackView
|
||||
onPress?: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
@@ -55,7 +57,10 @@ export function StarterPackCard({
|
||||
to={link.to}
|
||||
label={link.label}
|
||||
onHoverIn={link.precache}
|
||||
onPress={link.precache}>
|
||||
onPress={() => {
|
||||
link.precache()
|
||||
onPress?.()
|
||||
}}>
|
||||
{s => (
|
||||
<>
|
||||
<SubtleHover hover={s.hovered || s.pressed} />
|
||||
@@ -111,7 +116,10 @@ export function StarterPackCard({
|
||||
to={link.to}
|
||||
label={link.label}
|
||||
onHoverIn={link.precache}
|
||||
onPress={link.precache}
|
||||
onPress={() => {
|
||||
link.precache()
|
||||
onPress?.()
|
||||
}}
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
size="small"
|
||||
|
||||
Reference in New Issue
Block a user