Search page (#1912)
* Desktop web work * Mobile search * Dedupe suggestions * Clean up and reorg * Cleanup * Cleanup * Use Pager * Delete unused code * Fix conflicts * Remove search ui model * Soft reset * Fix scrollable results, remove observer * Use correct ScrollView * Clean up layout --------- Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
parent
d5ea31920c
commit
22b76423a0
14 changed files with 742 additions and 991 deletions
|
@ -1,69 +0,0 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {searchProfiles, searchPosts} from 'lib/api/search'
|
||||
import {PostThreadModel} from '../content/post-thread'
|
||||
import {AppBskyActorDefs, AppBskyFeedDefs} from '@atproto/api'
|
||||
import {RootStoreModel} from '../root-store'
|
||||
|
||||
export class SearchUIModel {
|
||||
isPostsLoading = false
|
||||
isProfilesLoading = false
|
||||
query: string = ''
|
||||
posts: PostThreadModel[] = []
|
||||
profiles: AppBskyActorDefs.ProfileView[] = []
|
||||
|
||||
constructor(public rootStore: RootStoreModel) {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
async fetch(q: string) {
|
||||
this.posts = []
|
||||
this.profiles = []
|
||||
this.query = q
|
||||
if (!q.trim()) {
|
||||
return
|
||||
}
|
||||
|
||||
this.isPostsLoading = true
|
||||
this.isProfilesLoading = true
|
||||
|
||||
const [postsSearch, profilesSearch] = await Promise.all([
|
||||
searchPosts(q).catch(_e => []),
|
||||
searchProfiles(q).catch(_e => []),
|
||||
])
|
||||
|
||||
let posts: AppBskyFeedDefs.PostView[] = []
|
||||
if (postsSearch?.length) {
|
||||
do {
|
||||
const res = await this.rootStore.agent.app.bsky.feed.getPosts({
|
||||
uris: postsSearch
|
||||
.splice(0, 25)
|
||||
.map(p => `at://${p.user.did}/${p.tid}`),
|
||||
})
|
||||
posts = posts.concat(res.data.posts)
|
||||
} while (postsSearch.length)
|
||||
}
|
||||
runInAction(() => {
|
||||
this.posts = posts.map(post =>
|
||||
PostThreadModel.fromPostView(this.rootStore, post),
|
||||
)
|
||||
this.isPostsLoading = false
|
||||
})
|
||||
|
||||
let profiles: AppBskyActorDefs.ProfileView[] = []
|
||||
if (profilesSearch?.length) {
|
||||
do {
|
||||
const res = await this.rootStore.agent.getProfiles({
|
||||
actors: profilesSearch.splice(0, 25).map(p => p.did),
|
||||
})
|
||||
profiles = profiles.concat(res.data.profiles)
|
||||
} while (profilesSearch.length)
|
||||
}
|
||||
|
||||
this.rootStore.me.follows.hydrateMany(profiles)
|
||||
|
||||
runInAction(() => {
|
||||
this.profiles = profiles
|
||||
this.isProfilesLoading = false
|
||||
})
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ export function useActorAutocompleteFn() {
|
|||
const {data: follows} = useMyFollowsQuery()
|
||||
|
||||
return React.useCallback(
|
||||
async ({query}: {query: string}) => {
|
||||
async ({query, limit = 8}: {query: string; limit?: number}) => {
|
||||
let res
|
||||
if (query) {
|
||||
try {
|
||||
|
@ -47,7 +47,7 @@ export function useActorAutocompleteFn() {
|
|||
queryFn: () =>
|
||||
agent.searchActorsTypeahead({
|
||||
term: query,
|
||||
limit: 8,
|
||||
limit,
|
||||
}),
|
||||
})
|
||||
} catch (e) {
|
||||
|
|
32
src/state/queries/search-posts.ts
Normal file
32
src/state/queries/search-posts.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import {AppBskyFeedSearchPosts} from '@atproto/api'
|
||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||
|
||||
import {useSession} from '#/state/session'
|
||||
|
||||
const searchPostsQueryKey = ({query}: {query: string}) => [
|
||||
'search-posts',
|
||||
query,
|
||||
]
|
||||
|
||||
export function useSearchPostsQuery({query}: {query: string}) {
|
||||
const {agent} = useSession()
|
||||
|
||||
return useInfiniteQuery<
|
||||
AppBskyFeedSearchPosts.OutputSchema,
|
||||
Error,
|
||||
InfiniteData<AppBskyFeedSearchPosts.OutputSchema>,
|
||||
QueryKey,
|
||||
string | undefined
|
||||
>({
|
||||
queryKey: searchPostsQueryKey({query}),
|
||||
queryFn: async () => {
|
||||
const res = await agent.app.bsky.feed.searchPosts({
|
||||
q: query,
|
||||
limit: 25,
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
initialPageParam: undefined,
|
||||
getNextPageParam: lastPage => lastPage.cursor,
|
||||
})
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import React from 'react'
|
||||
import {
|
||||
AppBskyActorGetSuggestions,
|
||||
AppBskyGraphGetSuggestedFollowsByActor,
|
||||
|
@ -5,7 +6,7 @@ import {
|
|||
} from '@atproto/api'
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
useQuery,
|
||||
InfiniteData,
|
||||
QueryKey,
|
||||
|
@ -15,7 +16,7 @@ import {useSession} from '#/state/session'
|
|||
import {useModerationOpts} from '#/state/queries/preferences'
|
||||
|
||||
const suggestedFollowsQueryKey = ['suggested-follows']
|
||||
const suggestedFollowsByActorQuery = (did: string) => [
|
||||
const suggestedFollowsByActorQueryKey = (did: string) => [
|
||||
'suggested-follows-by-actor',
|
||||
did,
|
||||
]
|
||||
|
@ -73,7 +74,7 @@ export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
|
|||
const {agent} = useSession()
|
||||
|
||||
return useQuery<AppBskyGraphGetSuggestedFollowsByActor.OutputSchema, Error>({
|
||||
queryKey: suggestedFollowsByActorQuery(did),
|
||||
queryKey: suggestedFollowsByActorQueryKey(did),
|
||||
queryFn: async () => {
|
||||
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
|
||||
actor: did,
|
||||
|
@ -83,17 +84,26 @@ export function useSuggestedFollowsByActorQuery({did}: {did: string}) {
|
|||
})
|
||||
}
|
||||
|
||||
// TODO: Delete and replace usages with the one above.
|
||||
// TODO refactor onboarding to use above, but this is still used
|
||||
export function useGetSuggestedFollowersByActor() {
|
||||
const {agent} = useSession()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async (actor: string) => {
|
||||
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
|
||||
actor: actor,
|
||||
return React.useCallback(
|
||||
async (actor: string) => {
|
||||
const res = await queryClient.fetchQuery({
|
||||
staleTime: 60 * 1000,
|
||||
queryKey: suggestedFollowsByActorQueryKey(actor),
|
||||
queryFn: async () => {
|
||||
const res = await agent.app.bsky.graph.getSuggestedFollowsByActor({
|
||||
actor: actor,
|
||||
})
|
||||
return res.data
|
||||
},
|
||||
})
|
||||
|
||||
return res.data
|
||||
return res
|
||||
},
|
||||
})
|
||||
[agent, queryClient],
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue