Migrate all search to v2 and remove v1 (#11125)
This commit is contained in:
Vendored
+1
-1
@@ -13,7 +13,7 @@ import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} f
|
||||
import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed'
|
||||
import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed'
|
||||
import {findAllPostsInQueryData as findAllPostsInQuoteQueryData} from '#/state/queries/post-quotes'
|
||||
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts'
|
||||
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts-v2'
|
||||
import {findAllPostsInQueryData as findAllPostsInThreadV2QueryData} from '#/state/queries/usePostThread/queryCache'
|
||||
import {castAsShadow, type Shadow} from './types'
|
||||
export type {Shadow} from './types'
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import {useCallback, useMemo, useRef} from 'react'
|
||||
import {type AppBskyFeedSearchPostsV2, moderatePost} from '@atproto/api'
|
||||
import {
|
||||
type AppBskyFeedDefs,
|
||||
type AppBskyFeedSearchPostsV2,
|
||||
AtUri,
|
||||
moderatePost,
|
||||
} from '@atproto/api'
|
||||
import {
|
||||
type InfiniteData,
|
||||
type QueryClient,
|
||||
type QueryKey,
|
||||
useInfiniteQuery,
|
||||
} from '@tanstack/react-query'
|
||||
@@ -13,14 +19,12 @@ import {
|
||||
buildSearchPostsV2Filters,
|
||||
extractSearchPostsParams,
|
||||
} from './search-posts-params'
|
||||
import {
|
||||
didOrHandleUriMatches,
|
||||
embedViewRecordToPostView,
|
||||
getEmbeddedPost,
|
||||
} from './util'
|
||||
|
||||
/**
|
||||
* V2 search shares the `'search-posts'` query-key root with the original hook
|
||||
* (src/state/queries/search-posts.ts) so the shadow-cache generators there -
|
||||
* findAllPostsInQueryData / findAllProfilesInQueryData - discover V2 results
|
||||
* too. This module is only used behind the AdvancedSearchV2Enable gate; the
|
||||
* original hook is unchanged.
|
||||
*/
|
||||
const searchPostsQueryKeyRoot = 'search-posts'
|
||||
const searchPostsV2QueryKey = ({
|
||||
query,
|
||||
@@ -164,3 +168,33 @@ export function useSearchPostsV2Query({
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
export function* findAllPostsInQueryData(
|
||||
queryClient: QueryClient,
|
||||
uri: string,
|
||||
): Generator<AppBskyFeedDefs.PostView, undefined> {
|
||||
const queryDatas = queryClient.getQueriesData<
|
||||
InfiniteData<AppBskyFeedSearchPostsV2.OutputSchema>
|
||||
>({
|
||||
queryKey: [searchPostsQueryKeyRoot],
|
||||
})
|
||||
const atUri = new AtUri(uri)
|
||||
|
||||
for (const [_queryKey, queryData] of queryDatas) {
|
||||
if (!queryData?.pages) {
|
||||
continue
|
||||
}
|
||||
for (const page of queryData?.pages) {
|
||||
for (const post of page.posts) {
|
||||
if (didOrHandleUriMatches(atUri, post)) {
|
||||
yield post
|
||||
}
|
||||
|
||||
const quotedPost = getEmbeddedPost(post.embed)
|
||||
if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
|
||||
yield embedViewRecordToPostView(quotedPost)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
import {useCallback, useMemo, useRef} from 'react'
|
||||
import {
|
||||
type AppBskyActorDefs,
|
||||
type AppBskyFeedDefs,
|
||||
type AppBskyFeedSearchPosts,
|
||||
AtUri,
|
||||
moderatePost,
|
||||
} from '@atproto/api'
|
||||
import {
|
||||
type InfiniteData,
|
||||
type QueryClient,
|
||||
type QueryKey,
|
||||
useInfiniteQuery,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {useAgent} from '#/state/session'
|
||||
import {
|
||||
didOrHandleUriMatches,
|
||||
embedViewRecordToPostView,
|
||||
getEmbeddedPost,
|
||||
} from './util'
|
||||
|
||||
const searchPostsQueryKeyRoot = 'search-posts'
|
||||
const searchPostsQueryKey = ({
|
||||
query,
|
||||
sort,
|
||||
author,
|
||||
}: {
|
||||
query: string
|
||||
sort?: string
|
||||
author?: string
|
||||
}) => [searchPostsQueryKeyRoot, query, sort, author]
|
||||
|
||||
export function useSearchPostsQuery({
|
||||
query,
|
||||
sort,
|
||||
enabled,
|
||||
author,
|
||||
}: {
|
||||
query: string
|
||||
sort?: 'top' | 'latest'
|
||||
enabled?: boolean
|
||||
author?: string
|
||||
}) {
|
||||
const agent = useAgent()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const selectArgs = useMemo(
|
||||
() => ({
|
||||
isSearchingSpecificUser: !!author || /from:(\w+)/.test(query),
|
||||
moderationOpts,
|
||||
}),
|
||||
[query, author, moderationOpts],
|
||||
)
|
||||
const lastRun = useRef<{
|
||||
data: InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
|
||||
args: typeof selectArgs
|
||||
result: InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
|
||||
} | null>(null)
|
||||
|
||||
return useInfiniteQuery<
|
||||
AppBskyFeedSearchPosts.OutputSchema,
|
||||
Error,
|
||||
InfiniteData<AppBskyFeedSearchPosts.OutputSchema>,
|
||||
QueryKey,
|
||||
string | undefined
|
||||
>({
|
||||
queryKey: searchPostsQueryKey({query, sort, author}),
|
||||
queryFn: async ({pageParam}) => {
|
||||
const res = await agent.app.bsky.feed.searchPosts({
|
||||
q: query,
|
||||
limit: 25,
|
||||
cursor: pageParam,
|
||||
sort,
|
||||
author,
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
initialPageParam: undefined,
|
||||
getNextPageParam: lastPage => lastPage.cursor,
|
||||
enabled: enabled ?? !!moderationOpts,
|
||||
select: useCallback(
|
||||
(data: InfiniteData<AppBskyFeedSearchPosts.OutputSchema>) => {
|
||||
const {moderationOpts, isSearchingSpecificUser} = selectArgs
|
||||
|
||||
/*
|
||||
* If a user applies the `from:<user>` filter, don't apply any
|
||||
* moderation. Note that if we add any more filtering logic below, we
|
||||
* may need to adjust this.
|
||||
*/
|
||||
if (isSearchingSpecificUser) {
|
||||
return data
|
||||
}
|
||||
|
||||
// Keep track of the last run and whether we can reuse
|
||||
// some already selected pages from there.
|
||||
let reusedPages = []
|
||||
if (lastRun.current) {
|
||||
const {
|
||||
data: lastData,
|
||||
args: lastArgs,
|
||||
result: lastResult,
|
||||
} = lastRun.current
|
||||
let canReuse = true
|
||||
for (let key in selectArgs) {
|
||||
if (selectArgs.hasOwnProperty(key)) {
|
||||
if (
|
||||
(selectArgs as Record<string, unknown>)[key] !==
|
||||
(lastArgs as Record<string, unknown>)[key]
|
||||
) {
|
||||
// Can't do reuse anything if any input has changed.
|
||||
canReuse = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canReuse) {
|
||||
for (let i = 0; i < data.pages.length; i++) {
|
||||
if (data.pages[i] && lastData.pages[i] === data.pages[i]) {
|
||||
reusedPages.push(lastResult.pages[i])
|
||||
continue
|
||||
}
|
||||
// Stop as soon as pages stop matching up.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = {
|
||||
...data,
|
||||
pages: [
|
||||
...reusedPages,
|
||||
...data.pages.slice(reusedPages.length).map(page => {
|
||||
return {
|
||||
...page,
|
||||
posts: page.posts.filter(post => {
|
||||
const mod = moderatePost(post, moderationOpts!)
|
||||
return !mod.ui('contentList').filter
|
||||
}),
|
||||
}
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
||||
lastRun.current = {data, result, args: selectArgs}
|
||||
|
||||
return result
|
||||
},
|
||||
[selectArgs],
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
export function* findAllPostsInQueryData(
|
||||
queryClient: QueryClient,
|
||||
uri: string,
|
||||
): Generator<AppBskyFeedDefs.PostView, undefined> {
|
||||
const queryDatas = queryClient.getQueriesData<
|
||||
InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
|
||||
>({
|
||||
queryKey: [searchPostsQueryKeyRoot],
|
||||
})
|
||||
const atUri = new AtUri(uri)
|
||||
|
||||
for (const [_queryKey, queryData] of queryDatas) {
|
||||
if (!queryData?.pages) {
|
||||
continue
|
||||
}
|
||||
for (const page of queryData?.pages) {
|
||||
for (const post of page.posts) {
|
||||
if (didOrHandleUriMatches(atUri, post)) {
|
||||
yield post
|
||||
}
|
||||
|
||||
const quotedPost = getEmbeddedPost(post.embed)
|
||||
if (quotedPost && didOrHandleUriMatches(atUri, quotedPost)) {
|
||||
yield embedViewRecordToPostView(quotedPost)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function* findAllProfilesInQueryData(
|
||||
queryClient: QueryClient,
|
||||
did: string,
|
||||
): Generator<AppBskyActorDefs.ProfileViewBasic, undefined> {
|
||||
const queryDatas = queryClient.getQueriesData<
|
||||
InfiniteData<AppBskyFeedSearchPosts.OutputSchema>
|
||||
>({
|
||||
queryKey: [searchPostsQueryKeyRoot],
|
||||
})
|
||||
for (const [_queryKey, queryData] of queryDatas) {
|
||||
if (!queryData?.pages) {
|
||||
continue
|
||||
}
|
||||
for (const page of queryData?.pages) {
|
||||
for (const post of page.posts) {
|
||||
if (post.author.did === did) {
|
||||
yield post.author
|
||||
}
|
||||
const quotedPost = getEmbeddedPost(post.embed)
|
||||
if (quotedPost?.author.did === did) {
|
||||
yield quotedPost.author
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} f
|
||||
import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed'
|
||||
import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed'
|
||||
import {findAllPostsInQueryData as findAllPostsInQuoteQueryData} from '#/state/queries/post-quotes'
|
||||
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts'
|
||||
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts-v2'
|
||||
import {usePostThreadContext} from '#/state/queries/usePostThread'
|
||||
import {getBranch} from '#/state/queries/usePostThread/traversal'
|
||||
import {
|
||||
|
||||
Reference in New Issue
Block a user